aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore9
-rw-r--r--.travis.yml2
-rw-r--r--.tx/config2
-rw-r--r--Makefile.am21
-rw-r--r--README.md4
-rw-r--r--configure.ac85
-rw-r--r--contrib/debian/changelog30
-rw-r--r--contrib/debian/control7
-rw-r--r--contrib/devtools/README.md26
-rwxr-xr-xcontrib/devtools/clang-format.py62
-rwxr-xr-xcontrib/devtools/optimize-pngs.py6
-rwxr-xr-xcontrib/devtools/security-check.py181
-rwxr-xr-xcontrib/devtools/symbol-check.py30
-rwxr-xr-xcontrib/devtools/test-security-check.py60
-rw-r--r--contrib/gitian-descriptors/gitian-linux.yml2
-rw-r--r--contrib/gitian-descriptors/gitian-osx.yml2
-rw-r--r--contrib/gitian-descriptors/gitian-win.yml2
-rw-r--r--contrib/gitian-downloader/bluematt-key.pgpbin4113 -> 10324 bytes
-rw-r--r--contrib/gitian-downloader/btcdrak-key.pgp142
-rw-r--r--contrib/gitian-downloader/prab-key.pgp102
-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
-rw-r--r--depends/README.md2
-rwxr-xr-xdepends/config.guess12
-rwxr-xr-xdepends/config.sub11
-rw-r--r--depends/packages/miniupnpc.mk4
-rw-r--r--depends/packages/openssl.mk2
-rw-r--r--doc/README.md6
-rw-r--r--doc/README_osx.txt20
-rw-r--r--doc/bips.md1
-rw-r--r--doc/build-openbsd.md7
-rw-r--r--doc/build-osx.md10
-rw-r--r--doc/developer-notes.md39
-rw-r--r--doc/dnsseed-policy.md2
-rw-r--r--doc/gitian-building.md76
-rw-r--r--doc/init.md40
-rw-r--r--doc/release-notes.md39
-rw-r--r--doc/release-notes/release-notes-0.10.3.md165
-rw-r--r--doc/release-notes/release-notes-0.11.1.md172
-rw-r--r--doc/release-process.md75
-rw-r--r--doc/shared-libraries.md1
-rw-r--r--doc/tor.md11
-rw-r--r--doc/translation_process.md2
-rw-r--r--doc/translation_strings_policy.md5
-rw-r--r--doc/zmq.md16
-rwxr-xr-xqa/pull-tester/rpc-tests.py120
-rwxr-xr-xqa/pull-tester/rpc-tests.sh89
-rw-r--r--[-rwxr-xr-x]qa/pull-tester/run-bitcoind-for-test.sh.in0
-rw-r--r--[-rwxr-xr-x]qa/pull-tester/tests_config.py.in (renamed from qa/pull-tester/tests-config.sh.in)4
-rw-r--r--qa/rpc-tests/README.md10
-rwxr-xr-xqa/rpc-tests/bip65-cltv-p2p.py182
-rwxr-xr-xqa/rpc-tests/bip65-cltv.py89
-rwxr-xr-xqa/rpc-tests/blockchain.py52
-rwxr-xr-xqa/rpc-tests/fundrawtransaction.py10
-rwxr-xr-xqa/rpc-tests/httpbasics.py14
-rwxr-xr-xqa/rpc-tests/maxuploadtarget.py248
-rwxr-xr-xqa/rpc-tests/pruning.py5
-rwxr-xr-xshare/qt/make_windows_icon.sh9
-rw-r--r--src/Makefile.am34
-rw-r--r--src/Makefile.bench.include45
-rw-r--r--src/Makefile.test.include3
-rw-r--r--src/addrman.cpp8
-rw-r--r--src/addrman.h16
-rw-r--r--src/amount.h1
-rw-r--r--src/bench/.gitignore1
-rw-r--r--src/bench/Examples.cpp34
-rw-r--r--src/bench/bench.cpp70
-rw-r--r--src/bench/bench.h72
-rw-r--r--src/bench/bench_bitcoin.cpp21
-rw-r--r--src/bitcoin-cli.cpp12
-rw-r--r--src/bitcoin-tx.cpp11
-rw-r--r--src/bitcoind.cpp8
-rw-r--r--src/chainparams.cpp33
-rw-r--r--src/chainparams.h15
-rw-r--r--src/chainparamsbase.cpp47
-rw-r--r--src/chainparamsbase.h31
-rw-r--r--src/compat.h1
-rw-r--r--src/consensus/params.h1
-rw-r--r--src/dbwrapper.cpp152
-rw-r--r--src/dbwrapper.h280
-rw-r--r--src/httpserver.cpp4
-rw-r--r--src/init.cpp49
-rw-r--r--src/leveldbwrapper.cpp89
-rw-r--r--src/leveldbwrapper.h173
-rw-r--r--src/main.cpp93
-rw-r--r--src/main.h6
-rw-r--r--src/memusage.h2
-rw-r--r--src/net.cpp106
-rw-r--r--src/net.h27
-rw-r--r--src/netbase.cpp9
-rw-r--r--src/policy/policy.h9
-rw-r--r--src/pow.cpp3
-rw-r--r--src/primitives/block.h2
-rw-r--r--src/qt/bitcoin.cpp8
-rw-r--r--src/qt/bitcoinstrings.cpp42
-rw-r--r--src/qt/locale/bitcoin_en.ts179
-rw-r--r--src/rpcblockchain.cpp4
-rw-r--r--src/rpcclient.cpp1
-rw-r--r--src/rpcnet.cpp13
-rw-r--r--src/rpcrawtransaction.cpp22
-rw-r--r--src/rpcserver.cpp2
-rw-r--r--src/script/bitcoinconsensus.h7
-rw-r--r--src/script/interpreter.cpp6
-rw-r--r--src/script/script.cpp2
-rw-r--r--src/script/script.h9
-rw-r--r--src/streams.h23
-rw-r--r--src/test/README.md2
-rw-r--r--src/test/addrman_tests.cpp180
-rw-r--r--src/test/alert_tests.cpp4
-rw-r--r--src/test/data/tx_invalid.json14
-rw-r--r--src/test/data/tx_valid.json4
-rw-r--r--src/test/dbwrapper_tests.cpp207
-rw-r--r--src/test/mempool_tests.cpp199
-rw-r--r--src/test/streams_tests.cpp67
-rw-r--r--src/test/test_bitcoin.cpp7
-rw-r--r--src/test/test_bitcoin.h4
-rw-r--r--src/test/transaction_tests.cpp2
-rw-r--r--src/test/txvalidationcache_tests.cpp2
-rw-r--r--src/txdb.cpp90
-rw-r--r--src/txdb.h8
-rw-r--r--src/txmempool.cpp111
-rw-r--r--src/txmempool.h53
-rw-r--r--src/univalue/.gitignore9
-rw-r--r--src/univalue/Makefile.am10
-rw-r--r--src/univalue/build-aux/m4/.empty0
-rw-r--r--src/univalue/build-aux/m4/.gitignore1
-rw-r--r--src/univalue/lib/.gitignore8
-rw-r--r--src/univalue/test/.gitignore6
-rw-r--r--src/util.cpp18
-rw-r--r--src/util.h3
-rw-r--r--src/utiltime.cpp8
-rw-r--r--src/utiltime.h1
-rw-r--r--src/wallet/wallet.cpp2
-rw-r--r--src/wallet/walletdb.cpp7
140 files changed, 4203 insertions, 990 deletions
diff --git a/.gitignore b/.gitignore
index 9f1e522803..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/
@@ -104,9 +102,12 @@ linux-coverage-build
linux-build
win32-build
qa/pull-tester/run-bitcoind-for-test.sh
-qa/pull-tester/tests-config.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/.travis.yml b/.travis.yml
index 3e7077ab26..8e9684826f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -69,6 +69,6 @@ script:
- make $MAKEJOBS $GOAL || ( echo "Build failure. Verbose build follows." && make $GOAL V=1 ; false )
- export LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/depends/$HOST/lib
- if [ "$RUN_TESTS" = "true" ]; then make check; fi
- - if [ "$RUN_TESTS" = "true" ]; then qa/pull-tester/rpc-tests.sh; fi
+ - if [ "$RUN_TESTS" = "true" ]; then qa/pull-tester/rpc-tests.py; fi
after_script:
- if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then (echo "Upload goes here. Something like: scp -r $BASE_OUTDIR server" || echo "upload failed"); fi
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 dfde0d43ec..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.sh 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/README.md b/README.md
index 275367ebbb..5aa8c327df 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ Development Process
The `master` branch is regularly built and tested, but is not guaranteed to be
completely stable. [Tags](https://github.com/bitcoin/bitcoin/tags) are created
-regularly to indicate new official, stable release versions of Bitcoin.
+regularly to indicate new official, stable release versions of Bitcoin Core.
The contribution workflow is described in [CONTRIBUTING.md](CONTRIBUTING.md).
@@ -53,7 +53,7 @@ submit new unit tests for old code. Unit tests can be compiled and run (assuming
There are also regression and integration tests of the RPC interface, written
in Python, that are run automatically on the build server.
-These tests can be run with: `qa/pull-tester/rpc-tests.sh`
+These tests can be run with: `qa/pull-tester/rpc-tests.py`
Every pull request is built for both Windows and Linux on a dedicated server,
and unit and sanity tests are automatically run. The binaries produced may be
diff --git a/configure.ac b/configure.ac
index 0803e74ff6..1669ec03ce 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)
@@ -69,8 +70,8 @@ PKG_PROG_PKG_CONFIG
# Enable wallet
AC_ARG_ENABLE([wallet],
- [AS_HELP_STRING([--enable-wallet],
- [enable wallet (default is yes)])],
+ [AS_HELP_STRING([--disable-wallet],
+ [disable wallet (enabled by default)])],
[enable_wallet=$enableval],
[enable_wallet=yes])
@@ -87,10 +88,15 @@ AC_ARG_ENABLE([upnp-default],
[use_upnp_default=no])
AC_ARG_ENABLE(tests,
- AS_HELP_STRING([--enable-tests],[compile tests (default is yes)]),
+ AS_HELP_STRING([--disable-tests],[do not compile tests (default is to compile)]),
[use_tests=$enableval],
[use_tests=yes])
+AC_ARG_ENABLE(bench,
+ AS_HELP_STRING([--disable-bench],[do not compile benchmarks (default is to compile)]),
+ [use_bench=$enableval],
+ [use_bench=yes])
+
AC_ARG_WITH([comparison-tool],
AS_HELP_STRING([--with-comparison-tool],[path to java comparison tool (requires --enable-tests)]),
[use_comparison_tool=$withval],
@@ -101,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)])],
@@ -108,8 +119,8 @@ AC_ARG_WITH([qrencode],
[use_qr=auto])
AC_ARG_ENABLE([hardening],
- [AS_HELP_STRING([--enable-hardening],
- [attempt to harden the resulting executables (default is yes)])],
+ [AS_HELP_STRING([--disable-hardening],
+ [do not attempt to harden the resulting executables (default is to harden)])],
[use_hardening=$enableval],
[use_hardening=yes])
@@ -120,8 +131,8 @@ AC_ARG_ENABLE([reduce-exports],
[use_reduce_exports=no])
AC_ARG_ENABLE([ccache],
- [AS_HELP_STRING([--enable-ccache],
- [use ccache for building (default is yes if ccache is found)])],
+ [AS_HELP_STRING([--disable-ccache],
+ [do not use ccache for building (default is to use if found)])],
[use_ccache=$enableval],
[use_ccache=auto])
@@ -139,7 +150,7 @@ AC_ARG_ENABLE([glibc-back-compat],
AC_ARG_ENABLE([zmq],
[AS_HELP_STRING([--disable-zmq],
- [Disable ZMQ notifications])],
+ [disable ZMQ notifications])],
[use_zmq=$enableval],
[use_zmq=yes])
@@ -167,7 +178,7 @@ fi
## compatibility with the legacy buildsystem.
##
if test "x$CXXFLAGS_overridden" = "xno"; then
- CXXFLAGS="$CXXFLAGS -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter"
+ CXXFLAGS="$CXXFLAGS -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter -Wno-self-assign"
fi
CPPFLAGS="$CPPFLAGS -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS"
@@ -336,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")
@@ -346,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
@@ -676,6 +694,16 @@ if test x$use_pkgconfig = xyes; then
PKG_CHECK_MODULES([EVENT_PTHREADS], [libevent_pthreads],, [AC_MSG_ERROR(libevent_pthreads not found.)])
fi
fi
+
+ if test "x$use_zmq" = "xyes"; then
+ PKG_CHECK_MODULES([ZMQ],[libzmq >= 4],
+ [AC_DEFINE([ENABLE_ZMQ],[1],[Define to 1 to enable ZMQ functions])],
+ [AC_DEFINE([ENABLE_ZMQ],[0],[Define to 1 to enable ZMQ functions])
+ AC_MSG_WARN([libzmq version 4.x or greater not found, disabling])
+ use_zmq=no])
+ else
+ AC_DEFINE_UNQUOTED([ENABLE_ZMQ],[0],[Define to 1 to enable ZMQ functions])
+ fi
]
)
else
@@ -693,6 +721,20 @@ else
fi
fi
+ if test "x$use_zmq" = "xyes"; then
+ AC_CHECK_HEADER([zmq.h],
+ [AC_DEFINE([ENABLE_ZMQ],[1],[Define to 1 to enable ZMQ functions])],
+ [AC_MSG_WARN([zmq.h not found, disabling zmq support])
+ use_zmq=no
+ AC_DEFINE([ENABLE_ZMQ],[0],[Define to 1 to enable ZMQ functions])])
+ AC_CHECK_LIB([zmq],[zmq_ctx_shutdown],ZMQ_LIBS=-lzmq,
+ [AC_MSG_WARN([libzmq >= 4.0 not found, disabling zmq support])
+ use_zmq=no
+ AC_DEFINE([ENABLE_ZMQ],[0],[Define to 1 to enable ZMQ functions])])
+ else
+ AC_DEFINE_UNQUOTED([ENABLE_ZMQ],[0],[Define to 1 to enable ZMQ functions])
+ fi
+
BITCOIN_QT_CHECK(AC_CHECK_LIB([protobuf] ,[main],[PROTOBUF_LIBS=-lprotobuf], BITCOIN_QT_FAIL(libprotobuf not found)))
if test x$use_qr != xno; then
BITCOIN_QT_CHECK([AC_CHECK_LIB([qrencode], [main],[QR_LIBS=-lqrencode], [have_qrencode=no])])
@@ -824,20 +866,6 @@ if test x$bitcoin_enable_qt != xno; then
fi
fi
-# conditional search for and use libzmq
-AC_MSG_CHECKING([whether to build ZMQ support])
-if test "x$use_zmq" = "xyes"; then
- AC_MSG_RESULT([yes])
- PKG_CHECK_MODULES([ZMQ],[libzmq >= 4],
- [AC_DEFINE([ENABLE_ZMQ],[1],[Define to 1 to enable ZMQ functions])],
- [AC_DEFINE([ENABLE_ZMQ],[0],[Define to 1 to enable ZMQ functions])
- AC_MSG_WARN([libzmq version 4.x or greater not found, disabling])
- use_zmq=no])
-else
- AC_MSG_RESULT([no, --disable-zmq used])
- AC_DEFINE_UNQUOTED([ENABLE_ZMQ],[0],[Define to 1 to enable ZMQ functions])
-fi
-
AM_CONDITIONAL([ENABLE_ZMQ], [test "x$use_zmq" = "xyes"])
AC_MSG_CHECKING([whether to build test_bitcoin])
@@ -866,6 +894,7 @@ AM_CONDITIONAL([ENABLE_WALLET],[test x$enable_wallet = xyes])
AM_CONDITIONAL([ENABLE_TESTS],[test x$use_tests = xyes])
AM_CONDITIONAL([ENABLE_QT],[test x$bitcoin_enable_qt = xyes])
AM_CONDITIONAL([ENABLE_QT_TESTS],[test x$use_tests$bitcoin_enable_qt_test = xyesyes])
+AM_CONDITIONAL([ENABLE_BENCH],[test x$use_bench = xyes])
AM_CONDITIONAL([USE_QRCODE], [test x$use_qr = xyes])
AM_CONDITIONAL([USE_LCOV],[test x$use_lcov = xyes])
AM_CONDITIONAL([USE_COMPARISON_TOOL],[test x$use_comparison_tool != xno])
@@ -899,7 +928,7 @@ AC_SUBST(MINIUPNPC_CPPFLAGS)
AC_SUBST(MINIUPNPC_LIBS)
AC_CONFIG_FILES([Makefile src/Makefile share/setup.nsi share/qt/Info.plist src/test/buildenv.py])
AC_CONFIG_FILES([qa/pull-tester/run-bitcoind-for-test.sh],[chmod +x qa/pull-tester/run-bitcoind-for-test.sh])
-AC_CONFIG_FILES([qa/pull-tester/tests-config.sh],[chmod +x qa/pull-tester/tests-config.sh])
+AC_CONFIG_FILES([qa/pull-tester/tests_config.py],[chmod +x qa/pull-tester/tests_config.py])
dnl boost's m4 checks do something really nasty: they export these vars. As a
dnl result, they leak into secp256k1's configure and crazy things happen.
@@ -939,3 +968,11 @@ case $host in
chmod 755 libtool
;;
esac
+
+dnl Replace the BUILDDIR path with the correct Windows path if compiling on Native Windows
+case ${OS} in
+ *Windows*)
+ sed 's/BUILDDIR="\/\([[a-z]]\)/BUILDDIR="\1:/' qa/pull-tester/tests_config.py > qa/pull-tester/tests_config-2.py
+ mv qa/pull-tester/tests_config-2.py qa/pull-tester/tests_config.py
+ ;;
+esac
diff --git a/contrib/debian/changelog b/contrib/debian/changelog
index bd7ab3524c..110bfe03ef 100644
--- a/contrib/debian/changelog
+++ b/contrib/debian/changelog
@@ -1,3 +1,33 @@
+bitcoin (0.11.0-precise1) precise; urgency=medium
+
+ * New upstream release.
+
+ -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Tue, 14 Jul 2015 14:39:00 -1000
+
+bitcoin (0.10.2-precise1) precise; urgency=medium
+
+ * New upstream release.
+
+ -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Mon, 29 Jun 2015 17:33:00 -1000
+
+bitcoin (0.10.1-precise3) precise; urgency=medium
+
+ * Fix build dep (include python).
+
+ -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Tue, 5 May 2015 09:28:00 -1000
+
+bitcoin (0.10.1-precise2) precise; urgency=medium
+
+ * Fix miniupnpc dep.
+
+ -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Tue, 5 May 2015 00:33:00 -1000
+
+bitcoin (0.10.1-precise1) precise; urgency=medium
+
+ * New upstream release.
+
+ -- Matt Corallo (BlueMatt) <matt@mattcorallo.com> Tue, 5 May 2015 00:07:00 -1000
+
bitcoin (0.10.0-precise1) precise; urgency=medium
* New upstream releases.
diff --git a/contrib/debian/control b/contrib/debian/control
index 01625b8438..2fd68583ce 100644
--- a/contrib/debian/control
+++ b/contrib/debian/control
@@ -20,11 +20,12 @@ Build-Depends: debhelper,
qt4-qmake,
libqt4-dev,
libqrencode-dev,
- libprotobuf-dev, protobuf-compiler
+ libprotobuf-dev, protobuf-compiler,
+ python
Standards-Version: 3.9.2
-Homepage: http://www.bitcoin.org/
+Homepage: https://www.bitcoin.org/
Vcs-Git: git://github.com/bitcoin/bitcoin.git
-Vcs-Browser: http://github.com/bitcoin/bitcoin
+Vcs-Browser: https://github.com/bitcoin/bitcoin
Package: bitcoind
Architecture: any
diff --git a/contrib/devtools/README.md b/contrib/devtools/README.md
index f90afa7f20..278794f14c 100644
--- a/contrib/devtools/README.md
+++ b/contrib/devtools/README.md
@@ -1,9 +1,14 @@
Contents
-===========
+========
This directory contains tools for developers working on this repository.
+clang-format.py
+===============
+
+A script to format cpp source code according to [.clang-format](../../src/.clang-format). This should only be applied to new files or files which are currently not actively developed on. Also, git subtrees are not subject to formatting.
+
github-merge.sh
-==================
+===============
A small script to automate merging pull-requests securely and sign them with GPG.
@@ -37,23 +42,31 @@ Configuring the github-merge tool for the bitcoin repository is done in the foll
git config --global user.signingkey mykeyid (if you want to GPG sign)
fix-copyright-headers.py
-===========================
+========================
Every year newly updated files need to have its copyright headers updated to reflect the current year.
If you run this script from src/ it will automatically update the year on the copyright header for all
.cpp and .h files if these have a git commit from the current year.
For example a file changed in 2014 (with 2014 being the current year):
+
```// Copyright (c) 2009-2013 The Bitcoin Core developers```
would be changed to:
+
```// Copyright (c) 2009-2014 The Bitcoin Core developers```
+optimize-pngs.py
+================
+
+A script to optimize png files in the bitcoin
+repository (requires pngcrush).
+
symbol-check.py
-==================
+===============
A script to check that the (Linux) executables produced by gitian only contain
-allowed gcc, glibc and libstdc++ version symbols. This makes sure they are
+allowed gcc, glibc and libstdc++ version symbols. This makes sure they are
still compatible with the minimum supported Linux distribution versions.
Example usage after a gitian build:
@@ -70,7 +83,7 @@ If there are 'unsupported' symbols, the return value will be 1 a list like this
.../64/test_bitcoin: symbol _ZNSt8__detail15_List_nod from unsupported version GLIBCXX_3.4.15
update-translations.py
-=======================
+======================
Run this script from the root of the repository to update all translations from transifex.
It will do the following automatically:
@@ -93,4 +106,5 @@ maintained:
* for sec/leveldb: https://github.com/bitcoin/leveldb.git (branch bitcoin-fork)
Usage: git-subtree-check.sh DIR COMMIT
+
COMMIT may be omitted, in which case HEAD is used.
diff --git a/contrib/devtools/clang-format.py b/contrib/devtools/clang-format.py
new file mode 100755
index 0000000000..cee99047ac
--- /dev/null
+++ b/contrib/devtools/clang-format.py
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+'''
+Wrapper script for clang-format
+
+Copyright (c) 2015 MarcoFalke
+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.
+'''
+
+import os
+import sys
+import subprocess
+
+tested_versions = ['3.6.0', '3.6.1', '3.6.2'] # A set of versions known to produce the same output
+accepted_file_extensions = ('.h', '.cpp') # Files to format
+
+def check_clang_format_version(clang_format_exe):
+ try:
+ output = subprocess.check_output([clang_format_exe, '-version'])
+ for ver in tested_versions:
+ if ver in output:
+ print "Detected clang-format version " + ver
+ return
+ raise RuntimeError("Untested version: " + output)
+ except Exception as e:
+ print 'Could not verify version of ' + clang_format_exe + '.'
+ raise e
+
+def check_command_line_args(argv):
+ required_args = ['{clang-format-exe}', '{files}']
+ example_args = ['clang-format-3.x', 'src/main.cpp', 'src/wallet/*']
+
+ if(len(argv) < len(required_args) + 1):
+ for word in (['Usage:', argv[0]] + required_args):
+ print word,
+ print ''
+ for word in (['E.g:', argv[0]] + example_args):
+ print word,
+ print ''
+ sys.exit(1)
+
+def run_clang_format(clang_format_exe, files):
+ for target in files:
+ if os.path.isdir(target):
+ for path, dirs, files in os.walk(target):
+ run_clang_format(clang_format_exe, (os.path.join(path, f) for f in files))
+ elif target.endswith(accepted_file_extensions):
+ print "Format " + target
+ subprocess.check_call([clang_format_exe, '-i', '-style=file', target], stdout=open(os.devnull, 'wb'), stderr=subprocess.STDOUT)
+ else:
+ print "Skip " + target
+
+def main(argv):
+ check_command_line_args(argv)
+ clang_format_exe = argv[1]
+ files = argv[2:]
+ check_clang_format_version(clang_format_exe)
+ run_clang_format(clang_format_exe, files)
+
+if __name__ == "__main__":
+ main(sys.argv)
diff --git a/contrib/devtools/optimize-pngs.py b/contrib/devtools/optimize-pngs.py
index b6d6a097d6..799e0cc7d0 100755
--- a/contrib/devtools/optimize-pngs.py
+++ b/contrib/devtools/optimize-pngs.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
'''
-Run this scrip every time you change one of the png files. Using pngcrush, it will optimize the png files, remove various color profiles, remove ancillary chunks (alla) and text chunks (text).
+Run this script every time you change one of the png files. Using pngcrush, it will optimize the png files, remove various color profiles, remove ancillary chunks (alla) and text chunks (text).
#pngcrush -brute -ow -rem gAMA -rem cHRM -rem iCCP -rem sRGB -rem alla -rem text
'''
import os
@@ -18,12 +18,12 @@ def content_hash(filename):
'''Return hash of RGBA contents of image'''
i = Image.open(filename)
i = i.convert('RGBA')
- data = i.tostring()
+ data = i.tobytes()
return hashlib.sha256(data).hexdigest()
pngcrush = 'pngcrush'
git = 'git'
-folders = ["src/qt/res/movies", "src/qt/res/icons"]
+folders = ["src/qt/res/movies", "src/qt/res/icons", "share/pixmaps"]
basePath = subprocess.check_output([git, 'rev-parse', '--show-toplevel']).rstrip('\n')
totalSaveBytes = 0
noHashChange = True
diff --git a/contrib/devtools/security-check.py b/contrib/devtools/security-check.py
new file mode 100755
index 0000000000..e96eaa9c38
--- /dev/null
+++ b/contrib/devtools/security-check.py
@@ -0,0 +1,181 @@
+#!/usr/bin/python2
+'''
+Perform basic ELF security checks on a series of executables.
+Exit status will be 0 if succesful, and the program will be silent.
+Otherwise the exit status will be 1 and it will log which executables failed which checks.
+Needs `readelf` (for ELF) and `objdump` (for PE).
+'''
+from __future__ import division,print_function
+import subprocess
+import sys
+import os
+
+READELF_CMD = os.getenv('READELF', '/usr/bin/readelf')
+OBJDUMP_CMD = os.getenv('OBJDUMP', '/usr/bin/objdump')
+
+def check_ELF_PIE(executable):
+ '''
+ Check for position independent executable (PIE), allowing for address space randomization.
+ '''
+ p = subprocess.Popen([READELF_CMD, '-h', '-W', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
+ (stdout, stderr) = p.communicate()
+ if p.returncode:
+ raise IOError('Error opening file')
+
+ ok = False
+ for line in stdout.split('\n'):
+ line = line.split()
+ if len(line)>=2 and line[0] == 'Type:' and line[1] == 'DYN':
+ ok = True
+ return ok
+
+def get_ELF_program_headers(executable):
+ '''Return type and flags for ELF program headers'''
+ p = subprocess.Popen([READELF_CMD, '-l', '-W', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
+ (stdout, stderr) = p.communicate()
+ if p.returncode:
+ raise IOError('Error opening file')
+ in_headers = False
+ count = 0
+ headers = []
+ for line in stdout.split('\n'):
+ if line.startswith('Program Headers:'):
+ in_headers = True
+ if line == '':
+ in_headers = False
+ if in_headers:
+ if count == 1: # header line
+ ofs_typ = line.find('Type')
+ ofs_offset = line.find('Offset')
+ ofs_flags = line.find('Flg')
+ ofs_align = line.find('Align')
+ if ofs_typ == -1 or ofs_offset == -1 or ofs_flags == -1 or ofs_align == -1:
+ raise ValueError('Cannot parse elfread -lW output')
+ elif count > 1:
+ typ = line[ofs_typ:ofs_offset].rstrip()
+ flags = line[ofs_flags:ofs_align].rstrip()
+ headers.append((typ, flags))
+ count += 1
+ return headers
+
+def check_ELF_NX(executable):
+ '''
+ Check that no sections are writable and executable (including the stack)
+ '''
+ have_wx = False
+ have_gnu_stack = False
+ for (typ, flags) in get_ELF_program_headers(executable):
+ if typ == 'GNU_STACK':
+ have_gnu_stack = True
+ if 'W' in flags and 'E' in flags: # section is both writable and executable
+ have_wx = True
+ return have_gnu_stack and not have_wx
+
+def check_ELF_RELRO(executable):
+ '''
+ Check for read-only relocations.
+ GNU_RELRO program header must exist
+ Dynamic section must have BIND_NOW flag
+ '''
+ have_gnu_relro = False
+ for (typ, flags) in get_ELF_program_headers(executable):
+ # Note: not checking flags == 'R': here as linkers set the permission differently
+ # This does not affect security: the permission flags of the GNU_RELRO program header are ignored, the PT_LOAD header determines the effective permissions.
+ # However, the dynamic linker need to write to this area so these are RW.
+ # Glibc itself takes care of mprotecting this area R after relocations are finished.
+ # See also http://permalink.gmane.org/gmane.comp.gnu.binutils/71347
+ if typ == 'GNU_RELRO':
+ have_gnu_relro = True
+
+ have_bindnow = False
+ p = subprocess.Popen([READELF_CMD, '-d', '-W', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
+ (stdout, stderr) = p.communicate()
+ if p.returncode:
+ raise IOError('Error opening file')
+ for line in stdout.split('\n'):
+ tokens = line.split()
+ if len(tokens)>1 and tokens[1] == '(BIND_NOW)':
+ have_bindnow = True
+ return have_gnu_relro and have_bindnow
+
+def check_ELF_Canary(executable):
+ '''
+ Check for use of stack canary
+ '''
+ p = subprocess.Popen([READELF_CMD, '--dyn-syms', '-W', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
+ (stdout, stderr) = p.communicate()
+ if p.returncode:
+ raise IOError('Error opening file')
+ ok = False
+ for line in stdout.split('\n'):
+ if '__stack_chk_fail' in line:
+ ok = True
+ return ok
+
+def get_PE_dll_characteristics(executable):
+ '''
+ Get PE DllCharacteristics bits
+ '''
+ p = subprocess.Popen([OBJDUMP_CMD, '-x', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
+ (stdout, stderr) = p.communicate()
+ if p.returncode:
+ raise IOError('Error opening file')
+ for line in stdout.split('\n'):
+ tokens = line.split()
+ if len(tokens)>=2 and tokens[0] == 'DllCharacteristics':
+ return int(tokens[1],16)
+ return 0
+
+
+def check_PE_PIE(executable):
+ '''PIE: DllCharacteristics bit 0x40 signifies dynamicbase (ASLR)'''
+ return bool(get_PE_dll_characteristics(executable) & 0x40)
+
+def check_PE_NX(executable):
+ '''NX: DllCharacteristics bit 0x100 signifies nxcompat (DEP)'''
+ return bool(get_PE_dll_characteristics(executable) & 0x100)
+
+CHECKS = {
+'ELF': [
+ ('PIE', check_ELF_PIE),
+ ('NX', check_ELF_NX),
+ ('RELRO', check_ELF_RELRO),
+ ('Canary', check_ELF_Canary)
+],
+'PE': [
+ ('PIE', check_PE_PIE),
+ ('NX', check_PE_NX)
+]
+}
+
+def identify_executable(executable):
+ with open(filename, 'rb') as f:
+ magic = f.read(4)
+ if magic.startswith(b'MZ'):
+ return 'PE'
+ elif magic.startswith(b'\x7fELF'):
+ return 'ELF'
+ return None
+
+if __name__ == '__main__':
+ retval = 0
+ for filename in sys.argv[1:]:
+ try:
+ etype = identify_executable(filename)
+ if etype is None:
+ print('%s: unknown format' % filename)
+ retval = 1
+ continue
+
+ failed = []
+ for (name, func) in CHECKS[etype]:
+ if not func(filename):
+ failed.append(name)
+ if failed:
+ print('%s: failed %s' % (filename, ' '.join(failed)))
+ retval = 1
+ except IOError:
+ print('%s: cannot open' % filename)
+ retval = 1
+ exit(retval)
+
diff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py
index fad891f800..34f1ed2d17 100755
--- a/contrib/devtools/symbol-check.py
+++ b/contrib/devtools/symbol-check.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python2
# Copyright (c) 2014 Wladimir J. van der Laan
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -15,6 +15,7 @@ from __future__ import division, print_function
import subprocess
import re
import sys
+import os
# Debian 6.0.9 (Squeeze) has:
#
@@ -45,8 +46,10 @@ MAX_VERSIONS = {
IGNORE_EXPORTS = {
'_edata', '_end', '_init', '__bss_start', '_fini'
}
-READELF_CMD = '/usr/bin/readelf'
-CPPFILT_CMD = '/usr/bin/c++filt'
+READELF_CMD = os.getenv('READELF', '/usr/bin/readelf')
+CPPFILT_CMD = os.getenv('CPPFILT', '/usr/bin/c++filt')
+# Allowed NEEDED libraries
+ALLOWED_LIBRARIES = {'librt.so.1','libpthread.so.0','libanl.so.1','libm.so.6','libgcc_s.so.1','libc.so.6','ld-linux-x86-64.so.2'}
class CPPFilt(object):
'''
@@ -98,6 +101,22 @@ def check_version(max_versions, version):
return False
return ver <= max_versions[lib]
+def read_libraries(filename):
+ p = subprocess.Popen([READELF_CMD, '-d', '-W', filename], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
+ (stdout, stderr) = p.communicate()
+ if p.returncode:
+ raise IOError('Error opening file')
+ libraries = []
+ for line in stdout.split('\n'):
+ tokens = line.split()
+ if len(tokens)>2 and tokens[1] == '(NEEDED)':
+ match = re.match('^Shared library: \[(.*)\]$', ' '.join(tokens[2:]))
+ if match:
+ libraries.append(match.group(1))
+ else:
+ raise ValueError('Unparseable (NEEDED) specification')
+ return libraries
+
if __name__ == '__main__':
cppfilt = CPPFilt()
retval = 0
@@ -113,6 +132,11 @@ if __name__ == '__main__':
continue
print('%s: export of symbol %s not allowed' % (filename, cppfilt(sym)))
retval = 1
+ # Check dependency libraries
+ for library_name in read_libraries(filename):
+ if library_name not in ALLOWED_LIBRARIES:
+ print('%s: NEEDED library %s is not allowed' % (filename, library_name))
+ retval = 1
exit(retval)
diff --git a/contrib/devtools/test-security-check.py b/contrib/devtools/test-security-check.py
new file mode 100755
index 0000000000..fed7626aab
--- /dev/null
+++ b/contrib/devtools/test-security-check.py
@@ -0,0 +1,60 @@
+#!/usr/bin/python2
+'''
+Test script for security-check.py
+'''
+from __future__ import division,print_function
+import subprocess
+import sys
+import unittest
+
+def write_testcode(filename):
+ with open(filename, 'w') as f:
+ f.write('''
+ #include <stdio.h>
+ int main()
+ {
+ printf("the quick brown fox jumps over the lazy god\\n");
+ return 0;
+ }
+ ''')
+
+def call_security_check(cc, source, executable, options):
+ subprocess.check_call([cc,source,'-o',executable] + options)
+ p = subprocess.Popen(['./security-check.py',executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
+ (stdout, stderr) = p.communicate()
+ return (p.returncode, stdout.rstrip())
+
+class TestSecurityChecks(unittest.TestCase):
+ def test_ELF(self):
+ source = 'test1.c'
+ executable = 'test1'
+ cc = 'gcc'
+ write_testcode(source)
+
+ self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-zexecstack','-fno-stack-protector','-Wl,-znorelro']),
+ (1, executable+': failed PIE NX RELRO Canary'))
+ self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fno-stack-protector','-Wl,-znorelro']),
+ (1, executable+': failed PIE RELRO Canary'))
+ self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-znorelro']),
+ (1, executable+': failed PIE RELRO'))
+ self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-znorelro','-pie','-fPIE']),
+ (1, executable+': failed RELRO'))
+ self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-zrelro','-Wl,-z,now','-pie','-fPIE']),
+ (0, ''))
+
+ def test_PE(self):
+ source = 'test1.c'
+ executable = 'test1.exe'
+ cc = 'i686-w64-mingw32-gcc'
+ write_testcode(source)
+
+ self.assertEqual(call_security_check(cc, source, executable, []),
+ (1, executable+': failed PIE NX'))
+ self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat']),
+ (1, executable+': failed PIE'))
+ self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--dynamicbase']),
+ (0, ''))
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml
index 440d95a355..a98a71e2f9 100644
--- a/contrib/gitian-descriptors/gitian-linux.yml
+++ b/contrib/gitian-descriptors/gitian-linux.yml
@@ -24,7 +24,7 @@ files: []
script: |
WRAP_DIR=$HOME/wrapped
HOSTS="i686-pc-linux-gnu x86_64-unknown-linux-gnu"
- CONFIGFLAGS="--enable-upnp-default --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++"
+ CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++"
FAKETIME_HOST_PROGS=""
FAKETIME_PROGS="date ar ranlib nm strip"
diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml
index bad9a0e768..eeeb408ded 100644
--- a/contrib/gitian-descriptors/gitian-osx.yml
+++ b/contrib/gitian-descriptors/gitian-osx.yml
@@ -27,7 +27,7 @@ files:
script: |
WRAP_DIR=$HOME/wrapped
HOSTS="x86_64-apple-darwin11"
- CONFIGFLAGS="--enable-upnp-default --enable-reduce-exports GENISOIMAGE=$WRAP_DIR/genisoimage"
+ CONFIGFLAGS="--enable-reduce-exports GENISOIMAGE=$WRAP_DIR/genisoimage"
FAKETIME_HOST_PROGS=""
FAKETIME_PROGS="ar ranlib date dmg genisoimage"
diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml
index 966820ec51..5fa0db6784 100644
--- a/contrib/gitian-descriptors/gitian-win.yml
+++ b/contrib/gitian-descriptors/gitian-win.yml
@@ -26,7 +26,7 @@ files: []
script: |
WRAP_DIR=$HOME/wrapped
HOSTS="x86_64-w64-mingw32 i686-w64-mingw32"
- CONFIGFLAGS="--enable-upnp-default --enable-reduce-exports"
+ CONFIGFLAGS="--enable-reduce-exports"
FAKETIME_HOST_PROGS="g++ ar ranlib nm windres strip"
FAKETIME_PROGS="date makensis zip"
diff --git a/contrib/gitian-downloader/bluematt-key.pgp b/contrib/gitian-downloader/bluematt-key.pgp
index fb6d9eb284..2389d4657f 100644
--- a/contrib/gitian-downloader/bluematt-key.pgp
+++ b/contrib/gitian-downloader/bluematt-key.pgp
Binary files differ
diff --git a/contrib/gitian-downloader/btcdrak-key.pgp b/contrib/gitian-downloader/btcdrak-key.pgp
new file mode 100644
index 0000000000..60d76c0ec7
--- /dev/null
+++ b/contrib/gitian-downloader/btcdrak-key.pgp
@@ -0,0 +1,142 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2
+
+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
+eEaG0RH54+pi4gw=
+=fFMC
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/contrib/gitian-downloader/prab-key.pgp b/contrib/gitian-downloader/prab-key.pgp
index 0940d15c6a..0870c88b9b 100644
--- a/contrib/gitian-downloader/prab-key.pgp
+++ b/contrib/gitian-downloader/prab-key.pgp
@@ -1,29 +1,81 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2
-mQINBFI3uQUBEADRjbUQb65n7sfjT5OPnjPO8oUh5onKjNALRGHGJxWwNkwkgmT6
-mZFWjikM8B3ONEp8MfTyoOzv+MbWuBDS1GZxi0Tcb4HU323/7hhwfXV4bcHif7vq
-Sc1ahN/5LIHj0htC6Uj78IWXW+kPWjX9biRJnZ9eerfA/AatC+4KuvYTjAa9uAfa
-BnAs38EG/7ryXzxdz6M8iNB/YjHE72swSH84uTtA3LqI3huVY41eFMK6qXFBMFiq
-H6bMx4pjwKzJj78bibXEQxq88yc6TLxbURs2GF4s11dr7Iq2Y+6FHqX3PfUByZBz
-PQfbEy1Df4RbB3htCBv5puETlqZ0PVe9/B+WrcnaobxrbKEAqt0DspfoveRTIL+z
-+YDs7FuW9TFBmd+5d2nmblHrNm8eEig3DpOoVetuuXsmDy03Fwao7hGkva4P3xbP
-H4/U8GaxsfNzuLvEyy+dtd2t2C1HIxS+56r41/vdb/9rvGgEQuSr0DVpZIW9en0f
-3bek+H7/qRCbXuaiBACBvOKNror5jtTeXTvnHWMkrOItyGH9pwR2Lhhv68JQS1jk
-e3pwVRzfHBz4wQMHeLIh+blsVKCIjytBR8Rq36rsmN1q44/3HwuPW/XP61kPP90k
-dKyPF4Qa+EoPw5ON5nr3lWy8ysklM79o1NmpyqNT4UjtDDBSfJtX82ct8QARAQAB
-tB9QYXVsIFJhYmFoeSA8UFJhYmFoeUBnbWFpbC5jb20+iQI/BBMBAgApBQJSN7kF
-AhsPBQkDwdj7BwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQ0cuiohvNiPaB
-KA//Y6h6r8vUkA4/Gl2ejMgH+/DAolg9dFD+KMjQNKw16g7WzFNNS05T4RhcfZDT
-mapAW2LOUiiPVJTacmblyFp2hXCv3S+DESQjVdz15pxMHkt9fFteXGyJyrcTY5pR
-rZmjMD/9Twy2mLl5IH5ms87p0TN9HhM5Ux+B51la+Uq1wMdc1PdPWvGDeBVxCnRI
-w0224M5u1uHaMwMDGdz6sXuCuonB7CDGL9Z2+m1Al7t0peL2QdKHjv8S+SKM2rZS
-bRJyNmmTSKFQOTb9e2Ve48NNeaC0usEf8ttsygclps0mDpoa68YSY1LiuwVoIxvd
-S626eDqgmq1yyz0l3gQbYKIUv7KvRDnYhqIEkPZLCOwKirm+I5vzXvVIlfoNRoyJ
-VH3K6MJDSpBEerYNWHmUQpp7cLXIqVtako7IgmglOXQ5XVRnPvlOt5VOqQnNRTdM
-nd/FK3n1TbUyNRverODSpOS6ZxdSSwLkTycTtj1SvpLo7laW0HQ1ofJfwzVmOq8s
-8aWWTwBBC/X1UNLL/rsZMoHeUpaKHF2HSK5XzLcwqOBPRTMY0OG7vtBvj4G8clht
-A3uQmmCMr6RxsPPYPHPO3MnMpY2AK6RRnNZg5Y1Fu+/71FAuUDVTxmI402yE5XbP
-ILbJ8RgsrTVgeHdNhp9or0BdsB/wwMT5intkCaNqwb6eJag=
-=y2Va
+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
+RFdDYRHByRDDL1I=
+=dOwX
-----END PGP PUBLIC KEY BLOCK-----
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/README.md b/depends/README.md
index 2dc0b9e47e..d85e652c60 100644
--- a/depends/README.md
+++ b/depends/README.md
@@ -13,7 +13,7 @@ For example:
make HOST=x86_64-w64-mingw32 -j4
A prefix will be generated that's suitable for plugging into Bitcoin's
-configure. In the above example, a dir named i686-w64-mingw32 will be
+configure. In the above example, a dir named x86_64-w64-mingw32 will be
created. To use it for Bitcoin:
./configure --prefix=`pwd`/depends/x86_64-w64-mingw32
diff --git a/depends/config.guess b/depends/config.guess
index f357ec6c8f..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-03-04'
+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
@@ -221,7 +221,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
release='-gnu'
;;
*)
- release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2`
;;
esac
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
@@ -249,6 +249,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
*:MirBSD:*:*)
echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
exit ;;
+ *:Sortix:*:*)
+ echo ${UNAME_MACHINE}-unknown-sortix
+ exit ;;
alpha:OSF1:*:*)
case $UNAME_RELEASE in
*4.0)
@@ -962,6 +965,9 @@ EOF
ia64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
+ k1om:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
m32r*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
@@ -1038,7 +1044,7 @@ EOF
echo ${UNAME_MACHINE}-dec-linux-${LIBC}
exit ;;
x86_64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ echo ${UNAME_MACHINE}-pc-linux-${LIBC}
exit ;;
xtensa*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
diff --git a/depends/config.sub b/depends/config.sub
index 8f1229c6f7..1acc966a33 100755
--- a/depends/config.sub
+++ b/depends/config.sub
@@ -2,7 +2,7 @@
# Configuration validation subroutine script.
# Copyright 1992-2015 Free Software Foundation, Inc.
-timestamp='2015-03-08'
+timestamp='2015-08-20'
# 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
@@ -255,6 +255,7 @@ case $basic_machine in
| arc | arceb \
| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
| avr | avr32 \
+ | ba \
| be32 | be64 \
| bfin \
| c4x | c8051 | clipper \
@@ -305,7 +306,7 @@ case $basic_machine in
| riscv32 | riscv64 \
| rl78 | rx \
| score \
- | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
@@ -376,6 +377,7 @@ case $basic_machine in
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* | avr32-* \
+ | ba-* \
| be32-* | be64-* \
| bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* \
@@ -428,12 +430,13 @@ case $basic_machine in
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
| pyramid-* \
+ | riscv32-* | riscv64-* \
| rl78-* | romp-* | rs6000-* | rx-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
| sparclite-* \
- | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
| tahoe-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
| tile*-* \
@@ -1376,7 +1379,7 @@ case $os in
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
| -sym* | -kopensolaris* | -plan9* \
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
- | -aos* | -aros* | -cloudabi* \
+ | -aos* | -aros* | -cloudabi* | -sortix* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
diff --git a/depends/packages/miniupnpc.mk b/depends/packages/miniupnpc.mk
index ee1ee2f4b8..77bae10c79 100644
--- a/depends/packages/miniupnpc.mk
+++ b/depends/packages/miniupnpc.mk
@@ -1,8 +1,8 @@
package=miniupnpc
-$(package)_version=1.9.20150730
+$(package)_version=1.9.20151008
$(package)_download_path=http://miniupnp.free.fr/files
$(package)_file_name=$(package)-$($(package)_version).tar.gz
-$(package)_sha256_hash=1d64fab1fd3b4c8545139341ba197f19329a863f4f21b578fc2a228ab586a604
+$(package)_sha256_hash=e444ac3b587ce82709c4d0cfca1fe71f44f9fc433e9f946b12b9e1bfe667a633
define $(package)_set_vars
$(package)_build_opts=CC="$($(package)_cc)"
diff --git a/depends/packages/openssl.mk b/depends/packages/openssl.mk
index 22b1017ffc..687aae6682 100644
--- a/depends/packages/openssl.mk
+++ b/depends/packages/openssl.mk
@@ -10,7 +10,7 @@ $(package)_config_opts=--prefix=$(host_prefix) --openssldir=$(host_prefix)/etc/o
$(package)_config_opts+=no-krb5 no-camellia no-capieng no-cast no-cms no-dtls1 no-gost no-gmp no-heartbeats no-idea no-jpake no-md2
$(package)_config_opts+=no-mdc2 no-rc5 no-rdrand no-rfc3779 no-rsax no-sctp no-seed no-sha0 no-static_engine no-whirlpool no-rc2 no-rc4 no-ssl2 no-ssl3
$(package)_config_opts+=$($(package)_cflags) $($(package)_cppflags)
-$(package)_config_opts_linux=-fPIC
+$(package)_config_opts_linux=-fPIC -Wa,--noexecstack
$(package)_config_opts_x86_64_linux=linux-x86_64
$(package)_config_opts_i686_linux=linux-generic32
$(package)_config_opts_arm_linux=linux-generic32
diff --git a/doc/README.md b/doc/README.md
index 3e3f4a294f..08fd724355 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -7,7 +7,7 @@ Setup
Running
---------------------
-The following are some helpful notes on how to run Bitcoin on your native platform.
+The following are some helpful notes on how to run Bitcoin on your native platform.
### Unix
@@ -26,7 +26,7 @@ Unpack the files into a directory and run:
Unpack the files into a directory, and then run bitcoin-qt.exe.
-### OSX
+### OS X
Drag Bitcoin-Qt to your applications folder, and then run Bitcoin-Qt.
@@ -41,7 +41,7 @@ Building
---------------------
The following are developer notes on how to build Bitcoin on your native platform. They are not complete guides, but include notes on the necessary libraries, compile flags, etc.
-- [OSX Build Notes](build-osx.md)
+- [OS X Build Notes](build-osx.md)
- [Unix Build Notes](build-unix.md)
- [Gitian Building Guide](gitian-building.md)
diff --git a/doc/README_osx.txt b/doc/README_osx.txt
index a572c7a241..f589bfc676 100644
--- a/doc/README_osx.txt
+++ b/doc/README_osx.txt
@@ -1,12 +1,12 @@
-Deterministic OSX Dmg Notes.
+Deterministic OS X Dmg Notes.
-Working OSX DMGs are created in Linux by combining a recent clang,
+Working OS X DMGs are created in Linux by combining a recent clang,
the Apple's binutils (ld, ar, etc), and DMG authoring tools.
Apple uses clang extensively for development and has upstreamed the necessary
functionality so that a vanilla clang can take advantage. It supports the use
of -F, -target, -mmacosx-version-min, and --sysroot, which are all necessary
-when building for OSX. A pre-compiled version of 3.2 is used because it was not
+when building for OS X. A pre-compiled version of 3.2 is used because it was not
available in the Precise repositories at the time this work was started. In the
future, it can be switched to use system packages instead.
@@ -29,18 +29,18 @@ originally done in toolchain4.
To complicate things further, all builds must target an Apple SDK. These SDKs
are free to download, but not redistributable.
-To obtain it, register for a developer account, then download the XCode 6.1.1 dmg:
+To obtain it, register for a developer account, then download the Xcode 6.1.1 dmg:
https://developer.apple.com/devcenter/download.action?path=/Developer_Tools/xcode_6.1.1/xcode_6.1.1.dmg
This file is several gigabytes in size, but only a single directory inside is
needed: Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk
Unfortunately, the usual linux tools (7zip, hpmount, loopback mount) are incapable of opening this file.
-To create a tarball suitable for gitian input, mount the dmg in OSX, then create it with:
+To create a tarball suitable for Gitian input, mount the dmg in OS X, then create it with:
$ tar -C /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.9.sdk.tar.gz MacOSX10.9.sdk
-The gitian descriptors build 2 sets of files: Linux tools, then Apple binaries
+The Gitian descriptors build 2 sets of files: Linux tools, then Apple binaries
which are created using these tools. The build process has been designed to
avoid including the SDK's files in Gitian's outputs. All interim tarballs are
fully deterministic and may be freely redistributed.
@@ -64,20 +64,20 @@ Ideally, the creation could be fixed and genisoimage would no longer be necessar
Background images and other features can be added to DMG files by inserting a
.DS_Store before creation. The easiest way to create this file is to build a
-DMG without one, move it to a device running OSX, customize the layout, then
+DMG without one, move it to a device running OS X, customize the layout, then
grab the .DS_Store file for later use. That is the approach taken here.
-As of OSX Mavericks (10.9), using an Apple-blessed key to sign binaries is a
+As of OS X Mavericks (10.9), using an Apple-blessed key to sign binaries is a
requirement in order to satisfy the new Gatekeeper requirements. Because this
private key cannot be shared, we'll have to be a bit creative in order for the
build process to remain somewhat deterministic. Here's how it works:
-- Builders use gitian to create an unsigned release. This outputs an unsigned
+- Builders use Gitian to create an unsigned release. This outputs an unsigned
dmg which users may choose to bless and run. It also outputs an unsigned app
structure in the form of a tarball, which also contains all of the tools
that have been previously (deterministically) built in order to create a
final dmg.
- The Apple keyholder uses this unsigned app to create a detached signature,
using the script that is also included there.
-- Builders feed the unsigned app + detached signature back into gitian. It
+- Builders feed the unsigned app + detached signature back into Gitian. It
uses the pre-built tools to recombine the pieces into a deterministic dmg.
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-openbsd.md b/doc/build-openbsd.md
index a26b52465e..d923301467 100644
--- a/doc/build-openbsd.md
+++ b/doc/build-openbsd.md
@@ -38,7 +38,7 @@ Do not use `pkg_add boost`! The boost version installed thus is compiled using t
test_bitcoin:/usr/lib/libstdc++.so.57.0: /usr/local/lib/libestdc++.so.17.0 : WARNING: symbol(_ZN11__gnu_debug17_S_debug_me ssagesE) size mismatch, relink your program
...
- Segmentation fault (core dumped)
+ Segmentation fault (core dumped)
This makes it necessary to build boost, or at least the parts used by Bitcoin Core, manually:
@@ -57,7 +57,7 @@ tar -xjf boost_1_59_0.tar.bz2
# Boost 1.59 needs two small patches for OpenBSD
cd boost_1_59_0
# Also here: https://gist.githubusercontent.com/laanwj/bf359281dc319b8ff2e1/raw/92250de8404b97bb99d72ab898f4a8cb35ae1ea3/patch-boost_test_impl_execution_monitor_ipp.patch
-patch -p0 < /usr/ports/devel/boost/patches/patch-boost_test_impl_execution_monitor_ipp
+patch -p0 < /usr/ports/devel/boost/patches/patch-boost_test_impl_execution_monitor_ipp
# https://github.com/boostorg/filesystem/commit/90517e459681790a091566dce27ca3acabf9a70c
sed 's/__OPEN_BSD__/__OpenBSD__/g' < libs/filesystem/src/path.cpp > libs/filesystem/src/path.cpp.tmp
mv libs/filesystem/src/path.cpp.tmp libs/filesystem/src/path.cpp
@@ -92,7 +92,7 @@ tar -xzf db-4.8.30.NC.tar.gz
# Build the library and install to specified prefix
cd db-4.8.30.NC/build_unix/
# Note: Do a static build so that it can be embedded into the executable, instead of having to find a .so at runtime
-../dist/configure --enable-cxx --disable-shared --with-pic --prefix=$BDB_PREFIX CC=egcc CXX=eg++ CPP=ecpp
+../dist/configure --enable-cxx --disable-shared --with-pic --prefix=$BDB_PREFIX CC=egcc CXX=eg++ CPP=ecpp
make install
```
@@ -160,4 +160,3 @@ version installed by OpenBSD 5.7:
- https://llvm.org/bugs/show_bug.cgi?id=9758
There is no known workaround for this.
-
diff --git a/doc/build-osx.md b/doc/build-osx.md
index 201fe9522b..69c401b751 100644
--- a/doc/build-osx.md
+++ b/doc/build-osx.md
@@ -1,6 +1,6 @@
Mac OS X Build Instructions and Notes
====================================
-This guide will show you how to build bitcoind (headless client) for OSX.
+This guide will show you how to build bitcoind (headless client) for OS X.
Notes
-----
@@ -13,8 +13,8 @@ built-in one is located in `/Applications/Utilities`.
Preparation
-----------
-You need to install XCode with all the options checked so that the compiler
-and everything is available in /usr not just /Developer. XCode should be
+You need to install Xcode with all the options checked so that the compiler
+and everything is available in /usr not just /Developer. Xcode should be
available on your OS X installation media, but if not, you can get the
current version from https://developer.apple.com/xcode/. If you install
Xcode 4.3 or later, you'll need to install its command line tools. This can
@@ -38,7 +38,7 @@ NOTE: Building with Qt4 is still supported, however, could result in a broken UI
### Building `bitcoind`
-1. Clone the github tree to get the source code and go into the directory.
+1. Clone the GitHub tree to get the source code and go into the directory.
git clone https://github.com/bitcoin/bitcoin.git
cd bitcoin
@@ -62,7 +62,7 @@ Use Qt Creator as IDE
You can use Qt Creator as IDE, for debugging and for manipulating forms, etc.
Download Qt Creator from http://www.qt.io/download/. Download the "community edition" and only install Qt Creator (uncheck the rest during the installation process).
-1. Make sure you installed everything through homebrew mentioned above
+1. Make sure you installed everything through Homebrew mentioned above
2. Do a proper ./configure --with-gui=qt5 --enable-debug
3. In Qt Creator do "New Project" -> Import Project -> Import Existing Project
4. Enter "bitcoin-qt" as project name, enter src/qt as location
diff --git a/doc/developer-notes.md b/doc/developer-notes.md
index 8302a78562..7fe292f1f8 100644
--- a/doc/developer-notes.md
+++ b/doc/developer-notes.md
@@ -1,5 +1,5 @@
-Coding Standards
-================
+Developer Notes
+===============
Various coding styles have been used during the history of the codebase,
and the result is not very consistent. However, we're now trying to converge to
@@ -57,7 +57,7 @@ As Doxygen recognizes the comments by the delimiters (`/**` and `*/` in this cas
To describe a class use the same construct above the class definition:
```c++
-/**
+/**
* Alerts are for notifying old versions if they become too obsolete and
* need to upgrade. The message is displayed in the status bar.
* @see GetWarnings()
@@ -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/dnsseed-policy.md b/doc/dnsseed-policy.md
index 814ae3876a..55a5c28258 100644
--- a/doc/dnsseed-policy.md
+++ b/doc/dnsseed-policy.md
@@ -7,7 +7,7 @@ As such, DNS seeds must be run by entities which have some minimum
level of trust within the Bitcoin community.
Other implementations of Bitcoin software may also use the same
-seeds and may be more exposed. In light of this exposure, this
+seeds and may be more exposed. In light of this exposure, this
document establishes some basic expectations for operating dnsseeds.
0. A DNS seed operating organization or person is expected to follow good
diff --git a/doc/gitian-building.md b/doc/gitian-building.md
index 265fbd586d..00fdce82e8 100644
--- a/doc/gitian-building.md
+++ b/doc/gitian-building.md
@@ -1,7 +1,7 @@
Gitian building
================
-*Setup instructions for a gitian build of Bitcoin using a Debian VM or physical system.*
+*Setup instructions for a Gitian build of Bitcoin using a Debian VM or physical system.*
Gitian is the deterministic build process that is used to build the Bitcoin
Core executables. It provides a way to be reasonably sure that the
@@ -13,7 +13,7 @@ Multiple developers build the source code by following a specific descriptor
These results are compared and only if they match, the build is accepted and uploaded
to bitcoin.org.
-More independent gitian builders are needed, which is why this guide exists.
+More independent Gitian builders are needed, which is why this guide exists.
It is preferred you follow these steps yourself instead of using someone else's
VM image to avoid 'contaminating' the build.
@@ -22,9 +22,9 @@ Table of Contents
- [Create a new VirtualBox VM](#create-a-new-virtualbox-vm)
- [Connecting to the VM](#connecting-to-the-vm)
-- [Setting up Debian for gitian building](#setting-up-debian-for-gitian-building)
-- [Installing gitian](#installing-gitian)
-- [Setting up the gitian image](#setting-up-the-gitian-image)
+- [Setting up Debian for Gitian building](#setting-up-debian-for-gitian-building)
+- [Installing Gitian](#installing-gitian)
+- [Setting up the Gitian image](#setting-up-the-gitian-image)
- [Getting and building the inputs](#getting-and-building-the-inputs)
- [Building Bitcoin](#building-bitcoin)
- [Building an alternative repository](#building-an-alternative-repository)
@@ -43,7 +43,7 @@ Any kind of virtualization can be used, for example:
- [KVM](http://www.linux-kvm.org/page/Main_Page)
- [LXC](https://linuxcontainers.org/), see also [Gitian host docker container](https://github.com/gdm85/tenku/tree/master/docker/gitian-bitcoin-host/README.md).
-You can also install gitian on actual hardware instead of using virtualization.
+You can also install Gitian on actual hardware instead of using virtualization.
Create a new VirtualBox VM
---------------------------
@@ -60,18 +60,18 @@ In the VirtualBox GUI click "Create" and choose the following parameters in the
![](gitian-building/create_vm_hard_disk.png)
- Hard Disk: Create a virtual hard disk now
-
+
![](gitian-building/create_vm_hard_disk_file_type.png)
-- Hard Disk file type: Use the default, VDI (VirtualBox Disk Image)
+- Hard Disk file type: Use the default, VDI (VirtualBox Disk Image)
![](gitian-building/create_vm_storage_physical_hard_disk.png)
-
-- Storage on physical hard disk: Dynamically Allocated
-
+
+- Storage on physical hard disk: Dynamically Allocated
+
![](gitian-building/create_vm_file_location_size.png)
-- File location and size: at least 40GB; as low as 20GB *may* be possible, but better to err on the safe side
+- File location and size: at least 40GB; as low as 20GB *may* be possible, but better to err on the safe side
- Click `Create`
Get the [Debian 8.x net installer](http://cdimage.debian.org/debian-cd/8.2.0/amd64/iso-cd/debian-8.2.0-amd64-netinst.iso) (a more recent minor version should also work, see also [Debian Network installation](https://www.debian.org/CD/netinst/)).
@@ -81,7 +81,7 @@ Unixy OSes by entering the following in a terminal:
echo "d393d17ac6b3113c81186e545c416a00f28ed6e05774284bb5e8f0df39fcbcb9 debian-8.2.0-amd64-netinst.iso" | sha256sum -c
# (must return OK)
-After creating the VM, we need to configure it.
+After creating the VM, we need to configure it.
- Click the `Settings` button, then go to the `Network` tab. Adapter 1 should be attached to `NAT`.
@@ -115,8 +115,8 @@ This section will explain how to install Debian on the newly created VM.
![](gitian-building/debian_install_1_boot_menu.png)
-**Note**: Navigating in the Debian installer:
-To keep a setting at the default and proceed, just press `Enter`.
+**Note**: Navigating in the Debian installer:
+To keep a setting at the default and proceed, just press `Enter`.
To select a different button, press `Tab`.
- Choose locale and keyboard settings (doesn't matter, you can just go with the defaults or select your own information)
@@ -126,23 +126,23 @@ To select a different button, press `Tab`.
![](gitian-building/debian_install_4_configure_keyboard.png)
- The VM will detect network settings using DHCP, this should all proceed automatically
-- Configure the network:
+- Configure the network:
- Hostname `debian`.
- Leave domain name empty.
![](gitian-building/debian_install_5_configure_the_network.png)
-- Choose a root password and enter it twice (remember it for later)
+- Choose a root password and enter it twice (remember it for later)
![](gitian-building/debian_install_6a_set_up_root_password.png)
-- Name the new user `debian` (the full name doesn't matter, you can leave it empty)
+- Name the new user `debian` (the full name doesn't matter, you can leave it empty)
- Set the account username as `debian`
![](gitian-building/debian_install_7_set_up_user_fullname.png)
![](gitian-building/debian_install_8_set_up_username.png)
-- Choose a user password and enter it twice (remember it for later)
+- Choose a user password and enter it twice (remember it for later)
![](gitian-building/debian_install_9_user_password.png)
@@ -152,11 +152,11 @@ To select a different button, press `Tab`.
![](gitian-building/debian_install_10_configure_clock.png)
- Disk setup
- - Partitioning method: Guided - Use the entire disk
-
+ - Partitioning method: Guided - Use the entire disk
+
![](gitian-building/debian_install_11_partition_disks.png)
- - Select disk to partition: SCSI1 (0,0,0)
+ - Select disk to partition: SCSI1 (0,0,0)
![](gitian-building/debian_install_12_choose_disk.png)
@@ -166,7 +166,7 @@ To select a different button, press `Tab`.
![](gitian-building/debian_install_15_write_changes.png)
- The base system will be installed, this will take a minute or so
-- Choose a mirror (any will do)
+- Choose a mirror (any will do)
![](gitian-building/debian_install_16_choose_a_mirror.png)
@@ -201,7 +201,7 @@ After Installation
The next step in the guide involves logging in as root via SSH.
SSH login for root users is disabled by default, so we'll enable that now.
-Login to the VM using username `root` and the root password you choose earlier.
+Login to the VM using username `root` and the root password you chose earlier.
You'll be presented with a screen similar to this.
![](gitian-building/debian_root_login.png)
@@ -243,7 +243,7 @@ For example, to connect as `root` from a Linux command prompt use
Replace `root` with `debian` to log in as user.
-Setting up Debian for gitian building
+Setting up Debian for Gitian building
--------------------------------------
In this section we will be setting up the Debian installation for Gitian building.
@@ -260,7 +260,7 @@ Then set up LXC and the rest with the following, which is a complex jumble of se
```bash
# the version of lxc-start in Debian 7.4 needs to run as root, so make sure
-# that the build script can exectute it without providing a password
+# that the build script can execute it without providing a password
echo "%sudo ALL=NOPASSWD: /usr/bin/lxc-start" > /etc/sudoers.d/gitian-lxc
# add cgroup for LXC
echo "cgroup /sys/fs/cgroup cgroup defaults 0 0" >> /etc/fstab
@@ -280,7 +280,7 @@ reboot
At the end the VM is rebooted to make sure that the changes take effect. The steps in this
section only need to be performed once.
-Installing gitian
+Installing Gitian
------------------
Re-login as the user `debian` that was created during installation.
@@ -300,14 +300,14 @@ cd ..
**Note**: When sudo asks for a password, enter the password for the user *debian* not for *root*.
-Clone the git repositories for bitcoin and gitian.
+Clone the git repositories for bitcoin and Gitian.
```bash
git clone https://github.com/devrandom/gitian-builder.git
git clone https://github.com/bitcoin/bitcoin
```
-Setting up the gitian image
+Setting up the Gitian image
-------------------------
Gitian needs a virtual image of the operating system to build in.
@@ -333,14 +333,14 @@ Getting and building the inputs
Follow the instructions in [doc/release-process.md](release-process.md#fetch-and-build-inputs-first-time-or-when-dependency-versions-change)
in the bitcoin repository under 'Fetch and build inputs' to install sources which require
manual intervention. Also optionally follow the next step: 'Seed the Gitian sources cache
-and offline git repositories' which will fetch the remaining files required for building
+and offline git repositories' which will fetch the remaining files required for building
offline.
Building Bitcoin
----------------
-To build Bitcoin (for Linux, OSX and Windows) just follow the steps under 'perform
-gitian builds' in [doc/release-process.md](release-process.md#perform-gitian-builds) in the bitcoin repository.
+To build Bitcoin (for Linux, OS X and Windows) just follow the steps under 'perform
+Gitian builds' in [doc/release-process.md](release-process.md#perform-gitian-builds) in the bitcoin repository.
This may take some time as it will build all the dependencies needed for each descriptor.
These dependencies will be cached after a successful build to avoid rebuilding them when possible.
@@ -380,7 +380,7 @@ Building an alternative repository
-----------------------------------
If you want to do a test build of a pull on GitHub it can be useful to point
-the gitian builder at an alternative repository, using the same descriptors
+the Gitian builder at an alternative repository, using the same descriptors
and inputs.
For example:
@@ -395,9 +395,9 @@ COMMIT=2014_03_windows_unicode_path
Building fully offline
-----------------------
-For building fully offline including attaching signatures to unsigned builds, the detached-sigs repository
+For building fully offline including attaching signatures to unsigned builds, the detached-sigs repository
and the bitcoin git repository with the desired tag must both be available locally, and then gbuild must be
-told where to find them. It also requires an apt-cacher-ng which is fully-populated but set to offline mode, or
+told where to find them. It also requires an apt-cacher-ng which is fully-populated but set to offline mode, or
manually disabling gitian-builder's use of apt-get to update the VM build environment.
To configure apt-cacher-ng as an offline cacher, you will need to first populate its cache with the relevant
@@ -417,7 +417,7 @@ LXC_ARCH=amd64 LXC_SUITE=precise on-target -u root \
-e DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends -y install \
$( sed -ne '/^packages:/,/[^-] .*/ {/^- .*/{s/"//g;s/- //;p}}' ../bitcoin/contrib/gitian-descriptors/*|sort|uniq )
LXC_ARCH=amd64 LXC_SUITE=precise on-target -u root apt-get -q -y purge grub
-LXC_ARCH=amd64 LXC_SUITE=precise on-target -u root -e DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade
+LXC_ARCH=amd64 LXC_SUITE=precise on-target -u root -e DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade
```
And then set offline mode for apt-cacher-ng:
@@ -431,7 +431,7 @@ Offlinemode: 1
service apt-cacher-ng restart
```
-Then when building, override the remote URLs that gbuild would otherwise pull from the gitian descriptors::
+Then when building, override the remote URLs that gbuild would otherwise pull from the Gitian descriptors::
```bash
cd /some/root/path/
@@ -461,7 +461,7 @@ in `gitian.sigs` to your signing machine and do
```
This will create the `.sig` files that can be committed together with the `.assert` files to assert your
-gitian build.
+Gitian build.
Uploading signatures
---------------------
diff --git a/doc/init.md b/doc/init.md
index ed9ce72154..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
---------------------------------
@@ -29,25 +30,27 @@ file, however it is recommended that a strong and secure password be used
as this password is security critical to securing the wallet should the
wallet be enabled.
-If bitcoind is run with the "-server" flag (set by default), and no rpcpassword is set,
-it will use a special cookie file for authentication. The cookie is generated with random
+If bitcoind is run with the "-server" flag (set by default), and no rpcpassword is set,
+it will use a special cookie file for authentication. The cookie is generated with random
content when the daemon starts, and deleted when it exits. Read access to this file
-controls who can access it through RPC.
+controls who can access it through RPC.
-By default the cookie is stored in the data directory, but it's location can be overridden
+By default the cookie is stored in the data directory, but it's location can be overridden
with the option '-rpccookiefile'.
This allows for running bitcoind without having to do any manual configuration.
-`conf`, `pid`, and `wallet` accept relative paths which are interpreted as
+`conf`, `pid`, and `wallet` accept relative paths which are interpreted as
relative to the data directory. `wallet` *only* supports relative paths.
-For an example configuration file that describes the configuration settings,
+For an example configuration file that describes the configuration settings,
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
-----------------------------------
@@ -93,13 +103,23 @@ use old versions of Upstart and do not supply the start-stop-daemon utility.
Copy bitcoind.init to /etc/init.d/bitcoind. Test by running `service bitcoind start`.
-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
+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
-----------------------------------
Auto respawning is currently only configured for Upstart and systemd.
Reasonable defaults have been chosen but YMMV.
-
diff --git a/doc/release-notes.md b/doc/release-notes.md
index 70623a3939..fd034743e6 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -105,6 +105,16 @@ In this version, it is only enforced for peers that send protocol versions
removed. It is recommended to update SPV clients to check for the `NODE_BLOOM`
service bit for nodes that report versions newer than 70011.
+Any sequence of pushdatas in OP_RETURN outputs now allowed
+----------------------------------------------------------
+
+Previously OP_RETURN outputs with a payload were only relayed and mined if they
+had a single pushdata. This restriction has been lifted to allow any
+combination of data pushes and numeric constant opcodes (OP_1 to OP_16). The
+limit on OP_RETURN output size is now applied to the entire serialized
+scriptPubKey, 83 bytes by default. (the previous 80 byte default plus three
+bytes overhead)
+
Merkle branches removed from wallet
-----------------------------------
@@ -114,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
=================
@@ -171,7 +208,7 @@ configured specifically to process scriptPubKey and not scriptSig scripts.
- Removed bitrpc.py from contrib
-Addition of ZMQ-based Notifcations
+Addition of ZMQ-based Notifications
==================================
Bitcoind can now (optionally) asynchronously notify clients through a
diff --git a/doc/release-notes/release-notes-0.10.3.md b/doc/release-notes/release-notes-0.10.3.md
new file mode 100644
index 0000000000..8a110e562c
--- /dev/null
+++ b/doc/release-notes/release-notes-0.10.3.md
@@ -0,0 +1,165 @@
+Bitcoin Core version 0.10.3 is now available from:
+
+ <https://bitcoin.org/bin/bitcoin-core-0.10.3/>
+
+This is a new minor version release, bringing security fixes and translation
+updates. It is recommended to upgrade to this version as soon as possible.
+
+Please report bugs using the issue tracker at github:
+
+ <https://github.com/bitcoin/bitcoin/issues>
+
+Upgrading and downgrading
+=========================
+
+How to Upgrade
+--------------
+
+If you are running an older version, shut it down. Wait until it has completely
+shut down (which might take a few minutes for older versions), then run the
+installer (on Windows) or just copy over /Applications/Bitcoin-Qt (on Mac) or
+bitcoind/bitcoin-qt (on Linux).
+
+Downgrade warning
+------------------
+
+Because release 0.10.0 and later makes use of headers-first synchronization and
+parallel block download (see further), the block files and databases are not
+backwards-compatible with pre-0.10 versions of Bitcoin Core or other software:
+
+* Blocks will be stored on disk out of order (in the order they are
+received, really), which makes it incompatible with some tools or
+other programs. Reindexing using earlier versions will also not work
+anymore as a result of this.
+
+* The block index database will now hold headers for which no block is
+stored on disk, which earlier versions won't support.
+
+If you want to be able to downgrade smoothly, make a backup of your entire data
+directory. Without this your node will need start syncing (or importing from
+bootstrap.dat) anew afterwards. It is possible that the data from a completely
+synchronised 0.10 node may be usable in older versions as-is, but this is not
+supported and may break as soon as the older version attempts to reindex.
+
+This does not affect wallet forward or backward compatibility.
+
+Notable changes
+===============
+
+Fix buffer overflow in bundled upnp
+------------------------------------
+
+Bundled miniupnpc was updated to 1.9.20151008. This fixes a buffer overflow in
+the XML parser during initial network discovery.
+
+Details can be found here: http://talosintel.com/reports/TALOS-2015-0035/
+
+This applies to the distributed executables only, not when building from source or
+using distribution provided packages.
+
+Additionally, upnp has been disabled by default. This may result in a lower
+number of reachable nodes on IPv4, however this prevents future libupnpc
+vulnerabilities from being a structural risk to the network
+(see https://github.com/bitcoin/bitcoin/pull/6795).
+
+Test for LowS signatures before relaying
+-----------------------------------------
+
+Make the node require the canonical 'low-s' encoding for ECDSA signatures when
+relaying or mining. This removes a nuisance malleability vector.
+
+Consensus behavior is unchanged.
+
+If widely deployed this change would eliminate the last remaining known vector
+for nuisance malleability on SIGHASH_ALL P2PKH transactions. On the down-side
+it will block most transactions made by sufficiently out of date software.
+
+Unlike the other avenues to change txids on transactions this
+one was randomly violated by all deployed bitcoin software prior to
+its discovery. So, while other malleability vectors where made
+non-standard as soon as they were discovered, this one has remained
+permitted. Even BIP62 did not propose applying this rule to
+old version transactions, but conforming implementations have become
+much more common since BIP62 was initially written.
+
+Bitcoin Core has produced compatible signatures since a28fb70e in
+September 2013, but this didn't make it into a release until 0.9
+in March 2014; Bitcoinj has done so for a similar span of time.
+Bitcoinjs and electrum have been more recently updated.
+
+This does not replace the need for BIP62 or similar, as miners can
+still cooperate to break transactions. Nor does it replace the
+need for wallet software to handle malleability sanely[1]. This
+only eliminates the cheap and irritating DOS attack.
+
+[1] On the Malleability of Bitcoin Transactions
+Marcin Andrychowicz, Stefan Dziembowski, Daniel Malinowski, Łukasz Mazurek
+http://fc15.ifca.ai/preproceedings/bitcoin/paper_9.pdf
+
+Minimum relay fee default increase
+-----------------------------------
+
+The default for the `-minrelaytxfee` setting has been increased from `0.00001`
+to `0.00005`.
+
+This is necessitated by the current transaction flooding, causing
+outrageous memory usage on nodes due to the mempool ballooning. This is a
+temporary measure, bridging the time until a dynamic method for determining
+this fee is merged (which will be in 0.12).
+
+(see https://github.com/bitcoin/bitcoin/pull/6793, as well as the 0.11.0
+release notes, in which this value was suggested)
+
+0.10.3 Change log
+=================
+
+Detailed release notes follow. This overview includes changes that affect external
+behavior, not code moves, refactors or string updates.
+
+- #6186 `e4a7d51` Fix two problems in CSubnet parsing
+- #6153 `ebd7d8d` Parameter interaction: disable upnp if -proxy set
+- #6203 `ecc96f5` Remove P2SH coinbase flag, no longer interesting
+- #6226 `181771b` json: fail read_string if string contains trailing garbage
+- #6244 `09334e0` configure: Detect (and reject) LibreSSL
+- #6276 `0fd8464` Fix getbalance * 0
+- #6274 `be64204` Add option `-alerts` to opt out of alert system
+- #6319 `3f55638` doc: update mailing list address
+- #6438 `7e66e9c` openssl: avoid config file load/race
+- #6439 `255eced` Updated URL location of netinstall for Debian
+- #6412 `0739e6e` Test whether created sockets are select()able
+- #6694 `f696ea1` [QT] fix thin space word wrap line brake issue
+- #6704 `743cc9e` Backport bugfixes to 0.10
+- #6769 `1cea6b0` Test LowS in standardness, removes nuisance malleability vector.
+- #6789 `093d7b5` Update miniupnpc to 1.9.20151008
+- #6795 `f2778e0` net: Disable upnp by default
+- #6797 `91ef4d9` Do not store more than 200 timedata samples
+- #6793 `842c48d` Bump minrelaytxfee default
+
+Credits
+=======
+
+Thanks to everyone who directly contributed to this release:
+
+- Adam Weiss
+- Alex Morcos
+- Casey Rodarmor
+- Cory Fields
+- fanquake
+- Gregory Maxwell
+- Jonas Schnelli
+- J Ross Nicoll
+- Luke Dashjr
+- Pavel Vasin
+- Pieter Wuille
+- randy-waterhouse
+- ฿tcDrak
+- Tom Harding
+- Veres Lajos
+- Wladimir J. van der Laan
+
+And all those who contributed additional code review and/or security research:
+
+- timothy on IRC for reporting the issue
+- Vulnerability in miniupnp discovered by Aleksandar Nikolic of Cisco Talos
+
+As well as everyone that helped translating on [Transifex](https://www.transifex.com/projects/p/bitcoin/).
diff --git a/doc/release-notes/release-notes-0.11.1.md b/doc/release-notes/release-notes-0.11.1.md
new file mode 100644
index 0000000000..799205691e
--- /dev/null
+++ b/doc/release-notes/release-notes-0.11.1.md
@@ -0,0 +1,172 @@
+Bitcoin Core version 0.11.1 is now available from:
+
+ <https://bitcoin.org/bin/bitcoin-core-0.11.1/>
+
+This is a new minor version release, bringing security fixes. It is recommended
+to upgrade to this version as soon as possible.
+
+Please report bugs using the issue tracker at github:
+
+ <https://github.com/bitcoin/bitcoin/issues>
+
+Upgrading and downgrading
+=========================
+
+How to Upgrade
+--------------
+
+If you are running an older version, shut it down. Wait until it has completely
+shut down (which might take a few minutes for older versions), then run the
+installer (on Windows) or just copy over /Applications/Bitcoin-Qt (on Mac) or
+bitcoind/bitcoin-qt (on Linux).
+
+Downgrade warning
+------------------
+
+Because release 0.10.0 and later makes use of headers-first synchronization and
+parallel block download (see further), the block files and databases are not
+backwards-compatible with pre-0.10 versions of Bitcoin Core or other software:
+
+* Blocks will be stored on disk out of order (in the order they are
+received, really), which makes it incompatible with some tools or
+other programs. Reindexing using earlier versions will also not work
+anymore as a result of this.
+
+* The block index database will now hold headers for which no block is
+stored on disk, which earlier versions won't support.
+
+If you want to be able to downgrade smoothly, make a backup of your entire data
+directory. Without this your node will need start syncing (or importing from
+bootstrap.dat) anew afterwards. It is possible that the data from a completely
+synchronised 0.10 node may be usable in older versions as-is, but this is not
+supported and may break as soon as the older version attempts to reindex.
+
+This does not affect wallet forward or backward compatibility. There are no
+known problems when downgrading from 0.11.x to 0.10.x.
+
+Notable changes
+===============
+
+Fix buffer overflow in bundled upnp
+------------------------------------
+
+Bundled miniupnpc was updated to 1.9.20151008. This fixes a buffer overflow in
+the XML parser during initial network discovery.
+
+Details can be found here: http://talosintel.com/reports/TALOS-2015-0035/
+
+This applies to the distributed executables only, not when building from source or
+using distribution provided packages.
+
+Additionally, upnp has been disabled by default. This may result in a lower
+number of reachable nodes on IPv4, however this prevents future libupnpc
+vulnerabilities from being a structural risk to the network
+(see https://github.com/bitcoin/bitcoin/pull/6795).
+
+Test for LowS signatures before relaying
+-----------------------------------------
+
+Make the node require the canonical 'low-s' encoding for ECDSA signatures when
+relaying or mining. This removes a nuisance malleability vector.
+
+Consensus behavior is unchanged.
+
+If widely deployed this change would eliminate the last remaining known vector
+for nuisance malleability on SIGHASH_ALL P2PKH transactions. On the down-side
+it will block most transactions made by sufficiently out of date software.
+
+Unlike the other avenues to change txids on transactions this
+one was randomly violated by all deployed bitcoin software prior to
+its discovery. So, while other malleability vectors where made
+non-standard as soon as they were discovered, this one has remained
+permitted. Even BIP62 did not propose applying this rule to
+old version transactions, but conforming implementations have become
+much more common since BIP62 was initially written.
+
+Bitcoin Core has produced compatible signatures since a28fb70e in
+September 2013, but this didn't make it into a release until 0.9
+in March 2014; Bitcoinj has done so for a similar span of time.
+Bitcoinjs and electrum have been more recently updated.
+
+This does not replace the need for BIP62 or similar, as miners can
+still cooperate to break transactions. Nor does it replace the
+need for wallet software to handle malleability sanely[1]. This
+only eliminates the cheap and irritating DOS attack.
+
+[1] On the Malleability of Bitcoin Transactions
+Marcin Andrychowicz, Stefan Dziembowski, Daniel Malinowski, Łukasz Mazurek
+http://fc15.ifca.ai/preproceedings/bitcoin/paper_9.pdf
+
+Minimum relay fee default increase
+-----------------------------------
+
+The default for the `-minrelaytxfee` setting has been increased from `0.00001`
+to `0.00005`.
+
+This is necessitated by the current transaction flooding, causing
+outrageous memory usage on nodes due to the mempool ballooning. This is a
+temporary measure, bridging the time until a dynamic method for determining
+this fee is merged (which will be in 0.12).
+
+(see https://github.com/bitcoin/bitcoin/pull/6793, as well as the 0.11
+release notes, in which this value was suggested)
+
+0.11.1 Change log
+=================
+
+Detailed release notes follow. This overview includes changes that affect
+behavior, not code moves, refactors and string updates. For convenience in locating
+the code changes and accompanying discussion, both the pull request and
+git merge commit are mentioned.
+
+- #6438 `2531438` openssl: avoid config file load/race
+- #6439 `980f820` Updated URL location of netinstall for Debian
+- #6384 `8e5a969` qt: Force TLS1.0+ for SSL connections
+- #6471 `92401c2` Depends: bump to qt 5.5
+- #6224 `93b606a` Be even stricter in processing unrequested blocks
+- #6571 `100ac4e` libbitcoinconsensus: avoid a crash in multi-threaded environments
+- #6545 `649f5d9` Do not store more than 200 timedata samples.
+- #6694 `834e299` [QT] fix thin space word wrap line break issue
+- #6703 `1cd7952` Backport bugfixes to 0.11
+- #6750 `5ed8d0b` Recent rejects backport to v0.11
+- #6769 `71cc9d9` Test LowS in standardness, removes nuisance malleability vector.
+- #6789 `b4ad73f` Update miniupnpc to 1.9.20151008
+- #6785 `b4dc33e` Backport to v0.11: In (strCommand == "tx"), return if AlreadyHave()
+- #6412 `0095b9a` Test whether created sockets are select()able
+- #6795 `4dbcec0` net: Disable upnp by default
+- #6793 `e7bcc4a` Bump minrelaytxfee default
+
+Credits
+=======
+
+Thanks to everyone who directly contributed to this release:
+
+- Adam Weiss
+- Alex Morcos
+- Casey Rodarmor
+- Cory Fields
+- fanquake
+- Gregory Maxwell
+- Jonas Schnelli
+- J Ross Nicoll
+- Luke Dashjr
+- Pavel Janík
+- Pavel Vasin
+- Peter Todd
+- Pieter Wuille
+- randy-waterhouse
+- Ross Nicoll
+- Suhas Daftuar
+- tailsjoin
+- ฿tcDrak
+- Tom Harding
+- Veres Lajos
+- Wladimir J. van der Laan
+
+And those who contributed additional code review and/or security research:
+
+- timothy on IRC for reporting the issue
+- Vulnerability in miniupnp discovered by Aleksandar Nikolic of Cisco Talos
+
+As well as everyone that helped translating on [Transifex](https://www.transifex.com/projects/p/bitcoin/).
+
diff --git a/doc/release-process.md b/doc/release-process.md
index 1bfdb8fabd..9a2362cb85 100644
--- a/doc/release-process.md
+++ b/doc/release-process.md
@@ -1,19 +1,21 @@
Release Process
====================
-* update translations (ping wumpus, Diapolo or tcatm on IRC)
-* see https://github.com/bitcoin/bitcoin/blob/master/doc/translation_process.md#syncing-with-transifex
+* Update translations (ping wumpus, Diapolo or tcatm on IRC) see [translation_process.md](https://github.com/bitcoin/bitcoin/blob/master/doc/translation_process.md#syncing-with-transifex)
+* Update [bips.md](bips.md) to account for changes since the last release.
* * *
-###first time only or for new builders, check out the source in the following directory hierarchy
+###First time / New builders
+Check out the source code in the following directory hierarchy.
cd /path/to/your/toplevel/build
git clone https://github.com/bitcoin/gitian.sigs.git
+ git clone https://github.com/bitcoin/bitcoin-detached-sigs.git
git clone https://github.com/devrandom/gitian-builder.git
git clone https://github.com/bitcoin/bitcoin.git
-###for bitcoin maintainers/release engineers, update (commit) version in sources
+###Bitcoin maintainers/release engineers, update (commit) version in sources
pushd ./bitcoin
contrib/verifysfbinaries/verify.sh
@@ -21,72 +23,68 @@ Release Process
share/setup.nsi
src/clientversion.h (change CLIENT_VERSION_IS_RELEASE to true)
-###for bitcoin maintainers/release engineers, tag version in git
+ # tag version in git
git tag -s v(new version, e.g. 0.8.0)
-###for bitcoin maintainers/release engineers, write release notes. git shortlog helps a lot, for example:
+ # write release notes. git shortlog helps a lot, for example:
git shortlog --no-merges v(current version, e.g. 0.7.2)..v(new version, e.g. 0.8.0)
popd
* * *
-###update gitian, gitian.sigs, checkout bitcoin version, and perform gitian builds
+###Setup and perform Gitian builds
+
+ Setup Gitian descriptors:
- To ensure your gitian descriptors are accurate for direct reference for gbuild, below, run the following from a directory containing the bitcoin source:
-
pushd ./bitcoin
- export SIGNER=(your gitian key, ie bluematt, sipa, etc)
+ export SIGNER=(your Gitian key, ie bluematt, sipa, etc)
export VERSION=(new version, e.g. 0.8.0)
git checkout v${VERSION}
popd
- Ensure your gitian.sigs are up-to-date if you wish to gverify your builds against other gitian signatures:
+ Ensure your gitian.sigs are up-to-date if you wish to gverify your builds against other Gitian signatures.
pushd ./gitian.sigs
git pull
popd
- Ensure your gitian-builder sources are up-to-date to take advantage of the new caching features of gitian (`e9741525c` or later is recommended)
+ Ensure gitian-builder is up-to-date to take advantage of new caching features (`e9741525c` or later is recommended).
pushd ./gitian-builder
git pull
-###fetch and create inputs: (first time, or when dependency versions change)
-
+###Fetch and create inputs: (first time, or when dependency versions change)
+
mkdir -p inputs
wget -P inputs https://bitcoincore.org/cfields/osslsigncode-Backports-to-1.7.1.patch
wget -P inputs http://downloads.sourceforge.net/project/osslsigncode/osslsigncode/osslsigncode-1.7.1.tar.gz
- Register and download the Apple SDK: (see OSX Readme for details)
-
+ Register and download the Apple SDK: see [OS X readme](README_osx.txt) for details.
+
https://developer.apple.com/devcenter/download.action?path=/Developer_Tools/xcode_6.1.1/xcode_6.1.1.dmg
-
+
Using a Mac, create a tarball for the 10.9 SDK and copy it to the inputs directory:
-
+
tar -C /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.9.sdk.tar.gz MacOSX10.9.sdk
###Optional: Seed the Gitian sources cache and offline git repositories
-By default, gitian will fetch source files as needed. To cache them ahead of time:
+By default, Gitian will fetch source files as needed. To cache them ahead of time:
make -C ../bitcoin/depends download SOURCES_PATH=`pwd`/cache/common
Only missing files will be fetched, so this is safe to re-run for each build.
-Clone the detached-sigs repository:
-
- popd
- git clone https://github.com/bitcoin/bitcoin-detached-sigs.git
- pushd ./bitcoin-builder
-
-NOTE: Offline builds must use the --url flag to ensure gitian fetches only from local URLs.
-For example: ./bin/bguild --url bitcoin=/path/to/bitcoin,signature=/path/to/sigs {rest of arguments}
-The following gbuild invocations DO NOT DO THIS by default.
+NOTE: Offline builds must use the --url flag to ensure Gitian fetches only from local URLs. For example:
+```
+./bin/gbuild --url bitcoin=/path/to/bitcoin,signature=/path/to/sigs {rest of arguments}
+```
+The gbuild invocations below <b>DO NOT DO THIS</b> by default.
###Build (and optionally verify) Bitcoin Core for Linux, Windows, and OS X:
-
+
./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml
./bin/gsign --signer $SIGNER --release ${VERSION}-linux --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml
./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-linux ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml
@@ -110,8 +108,8 @@ The following gbuild invocations DO NOT DO THIS by default.
1. source tarball (bitcoin-${VERSION}.tar.gz)
2. linux 32-bit and 64-bit dist tarballs (bitcoin-${VERSION}-linux[32|64].tar.gz)
3. windows 32-bit and 64-bit unsigned installers and dist zips (bitcoin-${VERSION}-win[32|64]-setup-unsigned.exe, bitcoin-${VERSION}-win[32|64].zip)
- 4. OSX unsigned installer and dist tarball (bitcoin-${VERSION}-osx-unsigned.dmg, bitcoin-${VERSION}-osx64.tar.gz)
- 5. Gitian signatures (in gitian.sigs/${VERSION}-<linux|{win,osx}-unsigned>/(your gitian key)/
+ 4. OS X unsigned installer and dist tarball (bitcoin-${VERSION}-osx-unsigned.dmg, bitcoin-${VERSION}-osx64.tar.gz)
+ 5. Gitian signatures (in gitian.sigs/${VERSION}-<linux|{win,osx}-unsigned>/(your Gitian key)/
###Next steps:
@@ -125,11 +123,12 @@ Commit your signature to gitian.sigs:
git push # Assuming you can push to the gitian.sigs tree
popd
- Wait for Windows/OSX detached signatures:
- Once the Windows/OSX builds each have 3 matching signatures, they will be signed with their respective release keys.
- Detached signatures will then be committed to the bitcoin-detached-sigs repository, which can be combined with the unsigned apps to create signed binaries.
+ Wait for Windows/OS X detached signatures:
+
+ Once the Windows/OS X builds each have 3 matching signatures, they will be signed with their respective release keys.
+ Detached signatures will then be committed to the [bitcoin-detached-sigs](https://github.com/bitcoin/bitcoin-detached-sigs) repository, which can be combined with the unsigned apps to create signed binaries.
- Create (and optionally verify) the signed OSX binary:
+ Create (and optionally verify) the signed OS X binary:
pushd ./gitian-builder
./bin/gbuild -i --commit signature=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml
@@ -148,7 +147,7 @@ Commit your signature to gitian.sigs:
mv build/out/bitcoin-*win32-setup.exe ../bitcoin-${VERSION}-win32-setup.exe
popd
-Commit your signature for the signed OSX/Windows binaries:
+Commit your signature for the signed OS X/Windows binaries:
pushd gitian.sigs
git add ${VERSION}-osx-signed/${SIGNER}
@@ -176,14 +175,14 @@ Note: check that SHA256SUMS itself doesn't end up in SHA256SUMS, which is a spur
- Update bitcoin.org version
- First, check to see if the Bitcoin.org maintainers have prepared a
- release: https://github.com/bitcoin/bitcoin.org/labels/Releases
+ release: https://github.com/bitcoin-dot-org/bitcoin.org/labels/Releases
- If they have, it will have previously failed their Travis CI
checks because the final release files weren't uploaded.
Trigger a Travis CI rebuild---if it passes, merge.
- If they have not prepared a release, follow the Bitcoin.org release
- instructions: https://github.com/bitcoin/bitcoin.org#release-notes
+ instructions: https://github.com/bitcoin-dot-org/bitcoin.org#release-notes
- After the pull request is merged, the website will automatically show the newest version within 15 minutes, as well
as update the OS download links. Ping @saivann/@harding (saivann/harding on Freenode) in case anything goes wrong
diff --git a/doc/shared-libraries.md b/doc/shared-libraries.md
index f1448f7258..f4ff53d6e9 100644
--- a/doc/shared-libraries.md
+++ b/doc/shared-libraries.md
@@ -41,3 +41,4 @@ The interface is defined in the C header `bitcoinconsensus.h` located in `src/s
- [NBitcoin](https://github.com/NicolasDorier/NBitcoin/blob/master/NBitcoin/Script.cs#L814) (.NET Bindings)
- [node-libbitcoinconsensus](https://github.com/bitpay/node-libbitcoinconsensus) (Node.js Bindings)
- [java-libbitcoinconsensus](https://github.com/dexX7/java-libbitcoinconsensus) (Java Bindings)
+- [bitcoinconsensus-php](https://github.com/Bit-Wasp/bitcoinconsensus-php) (PHP Bindings)
diff --git a/doc/tor.md b/doc/tor.md
index f8b94d19d1..594897f896 100644
--- a/doc/tor.md
+++ b/doc/tor.md
@@ -15,15 +15,15 @@ outgoing connections be anonymized, but more is possible.
-proxy=ip:port Set the proxy server. If SOCKS5 is selected (default), this proxy
server will be used to try to reach .onion addresses as well.
-
+
-onion=ip:port Set the proxy server to use for tor hidden services. You do not
need to set this if it's the same as -proxy. You can use -noonion
to explicitly disable access to hidden service.
-
+
-listen When using -proxy, listening is disabled by default. If you want
to run a hidden service (see next section), you'll need to enable
it explicitly.
-
+
-connect=X When behind a Tor proxy, you can specify .onion addresses instead
-addnode=X of IP addresses or hostnames in these parameters. It requires
-seednode=X SOCKS5. In Tor mode, such addresses can also be exchanged with
@@ -55,10 +55,10 @@ your bitcoind's P2P listen port (8333 by default).
preference for your node to advertize itself with, for connections
coming from unroutable addresses (such as 127.0.0.1, where the
Tor proxy typically runs).
-
+
-listen You'll need to enable listening for incoming connections, as this
is off by default behind a proxy.
-
+
-discover When -externalip is specified, no attempt is made to discover local
IPv4 or IPv6 addresses. If you want to run a dual stack, reachable
from both Tor and IPv4 (or IPv6), you'll need to either pass your
@@ -87,4 +87,3 @@ If you only want to use Tor to reach onion addresses, but not use it as a proxy
for normal IPv4/IPv6 communication, use:
./bitcoin -onion=127.0.0.1:9050 -externalip=57qr3yd1nyntf5k.onion -discover
-
diff --git a/doc/translation_process.md b/doc/translation_process.md
index b06975e1d8..6389c5aced 100644
--- a/doc/translation_process.md
+++ b/doc/translation_process.md
@@ -1,7 +1,7 @@
Translations
============
-The Bitcoin-Core project has been designed to support multiple localisations. This makes adding new phrases, and completely new languages easily achievable. For managing all application translations, Bitcoin-Core makes use of the Transifex online translation management tool.
+The Bitcoin-Core project has been designed to support multiple localisations. This makes adding new phrases, and completely new languages easily achievable. For managing all application translations, Bitcoin-Core makes use of the Transifex online translation management tool.
### Helping to translate (using Transifex)
Transifex is setup to monitor the Github repo for updates, and when code containing new translations is found, Transifex will process any changes. It may take several hours after a pull-request has been merged, to appear in the Transifex web interface.
diff --git a/doc/translation_strings_policy.md b/doc/translation_strings_policy.md
index cf72a55b20..b95259cdc9 100644
--- a/doc/translation_strings_policy.md
+++ b/doc/translation_strings_policy.md
@@ -1,7 +1,7 @@
Translation Strings Policy
===========================
-This document provides guidelines for internationalization of the Bitcoin Core software.
+This document provides guidelines for internationalization of the Bitcoin Core software.
How to translate?
------------------
@@ -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
@@ -107,4 +107,3 @@ The second example reduces the number of pluralized words that translators have
During a string freeze (often before a major release), no translation strings are to be added, modified or removed.
This can be checked by executing `make translate` in the `src` directory, then verifying that `bitcoin_en.ts` remains unchanged.
-
diff --git a/doc/zmq.md b/doc/zmq.md
index 358d29d046..902d1124c7 100644
--- a/doc/zmq.md
+++ b/doc/zmq.md
@@ -2,7 +2,7 @@
[ZeroMQ](http://zeromq.org/) is a lightweight wrapper around TCP
connections, inter-process communication, and shared-memory,
-providing various message-oriented semantics such as publish/subcribe,
+providing various message-oriented semantics such as publish/subscribe,
request/reply, and push/pull.
The Bitcoin Core daemon can be configured to act as a trusted "border
@@ -43,14 +43,14 @@ operation.
## Enabling
-By default, the ZeroMQ port functionality is enabled. Two steps are
-required to enable--compiling in the ZeroMQ code, and configuring
-runtime operation on the command-line or configuration file.
+By default, the ZeroMQ feature is automatically compiled in if the
+necessary prerequisites are found. To disable, use --disable-zmq
+during the *configure* step of building bitcoind:
- $ ./configure --enable-zmq (other options)
+ $ ./configure --disable-zmq (other options)
-This will produce a binary that is capable of providing the ZeroMQ
-facility, but will not do so until also configured properly.
+To actually enable operation, one must set the appropriate options on
+the commandline or in the configuration file.
## Usage
@@ -78,7 +78,7 @@ bytes).
These options can also be provided in bitcoin.conf.
ZeroMQ endpoint specifiers for TCP (and others) are documented in the
-[ZeroMQ API](http://api.zeromq.org).
+[ZeroMQ API](http://api.zeromq.org/4-0:_start).
Client side, then, the ZeroMQ subscriber socket must have the
ZMQ_SUBSCRIBE option set to one or either of these prefixes (for
diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py
new file mode 100755
index 0000000000..3059fee426
--- /dev/null
+++ b/qa/pull-tester/rpc-tests.py
@@ -0,0 +1,120 @@
+#!/usr/bin/env python2
+# Copyright (c) 2014 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#
+# Run Regression Test Suite
+#
+
+import os
+import sys
+import subprocess
+import re
+from tests_config import *
+from sets import Set
+
+#If imported values are not defined then set to zero (or disabled)
+if not vars().has_key('ENABLE_WALLET'):
+ ENABLE_WALLET=0
+if not vars().has_key('ENABLE_BITCOIND'):
+ ENABLE_BITCOIND=0
+if not vars().has_key('ENABLE_UTILS'):
+ ENABLE_UTILS=0
+if not vars().has_key('ENABLE_ZMQ'):
+ ENABLE_ZMQ=0
+
+#Create a set to store arguments and create the passOn string
+opts = Set()
+passOn = ""
+p = re.compile("^--")
+for i in range(1,len(sys.argv)):
+ if (p.match(sys.argv[i]) or sys.argv[i] == "-h"):
+ passOn += " " + sys.argv[i]
+ else:
+ opts.add(sys.argv[i])
+
+#Set env vars
+buildDir = BUILDDIR
+os.environ["BITCOIND"] = buildDir + '/src/bitcoind' + EXEEXT
+os.environ["BITCOINCLI"] = buildDir + '/src/bitcoin-cli' + EXEEXT
+
+#Disable Windows tests by default
+if EXEEXT == ".exe" and "-win" not in opts:
+ print "Win tests currently disabled. Use -win option to enable"
+ sys.exit(0)
+
+#Tests
+testScripts = [
+ 'wallet.py',
+ 'listtransactions.py',
+ 'mempool_resurrect_test.py',
+ 'txn_doublespend.py --mineblock',
+ 'txn_clone.py',
+ 'getchaintips.py',
+ 'rawtransactions.py',
+ 'rest.py',
+ 'mempool_spendcoinbase.py',
+ 'mempool_coinbase_spends.py',
+ 'httpbasics.py',
+ 'zapwallettxes.py',
+ 'proxy_test.py',
+ 'merkle_blocks.py',
+ 'fundrawtransaction.py',
+ 'signrawtransactions.py',
+ 'walletbackup.py',
+ 'nodehandling.py',
+ 'reindex.py',
+ 'decodescript.py',
+ 'p2p-fullblocktest.py',
+ 'blockchain.py',
+]
+testScriptsExt = [
+ 'bip65-cltv.py',
+ 'bip65-cltv-p2p.py',
+ 'bipdersig-p2p.py',
+ 'bipdersig.py',
+ 'getblocktemplate_longpoll.py',
+ 'getblocktemplate_proposals.py',
+ 'txn_doublespend.py',
+ 'txn_clone.py --mineblock',
+ 'pruning.py',
+ 'forknotify.py',
+ 'invalidateblock.py',
+ 'keypool.py',
+ 'receivedby.py',
+# 'rpcbind_test.py', #temporary, bug in libevent, see #6655
+# '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
+if ENABLE_ZMQ == 1:
+ testScripts.append('zmq_test.py')
+
+if(ENABLE_WALLET == 1 and ENABLE_UTILS == 1 and ENABLE_BITCOIND == 1):
+ rpcTestDir = buildDir + '/qa/rpc-tests/'
+ #Run Tests
+ for i in range(len(testScripts)):
+ if (len(opts) == 0 or (len(opts) == 1 and "-win" in opts ) or '-extended' in opts
+ or testScripts[i] in opts or re.sub(".py$", "", testScripts[i]) in opts ):
+ print "Running testscript " + testScripts[i] + "..."
+ subprocess.check_call(rpcTestDir + testScripts[i] + " --srcdir " + buildDir + '/src ' + passOn,shell=True)
+ #exit if help is called so we print just one set of instructions
+ p = re.compile(" -h| --help")
+ if p.match(passOn):
+ sys.exit(0)
+
+ #Run Extended Tests
+ for i in range(len(testScriptsExt)):
+ if ('-extended' in opts or testScriptsExt[i] in opts
+ or re.sub(".py$", "", testScriptsExt[i]) in opts):
+ print "Running 2nd level testscript " + testScriptsExt[i] + "..."
+ subprocess.check_call(rpcTestDir + testScriptsExt[i] + " --srcdir " + buildDir + '/src ' + passOn,shell=True)
+else:
+ print "No rpc tests to run. Wallet, utils, and bitcoind must all be enabled"
diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh
deleted file mode 100755
index 7e1d2e8e50..0000000000
--- a/qa/pull-tester/rpc-tests.sh
+++ /dev/null
@@ -1,89 +0,0 @@
-#!/bin/bash
-set -e
-
-CURDIR=$(cd $(dirname "$0"); pwd)
-# Get BUILDDIR and REAL_BITCOIND
-. "${CURDIR}/tests-config.sh"
-
-export BITCOIND=${REAL_BITCOIND}
-export BITCOINCLI=${REAL_BITCOINCLI}
-
-if [ "x${EXEEXT}" = "x.exe" ]; then
- echo "Win tests currently disabled"
- exit 0
-fi
-
-#Run the tests
-
-testScripts=(
- 'wallet.py'
- 'listtransactions.py'
- 'mempool_resurrect_test.py'
- 'txn_doublespend.py --mineblock'
- 'txn_clone.py'
- 'getchaintips.py'
- 'rawtransactions.py'
- 'rest.py'
- 'mempool_spendcoinbase.py'
- 'mempool_coinbase_spends.py'
- 'httpbasics.py'
- 'zapwallettxes.py'
- 'proxy_test.py'
- 'merkle_blocks.py'
- 'fundrawtransaction.py'
- 'signrawtransactions.py'
- 'walletbackup.py'
- 'nodehandling.py'
- 'reindex.py'
- 'decodescript.py'
- 'p2p-fullblocktest.py'
-);
-testScriptsExt=(
- 'bipdersig-p2p.py'
- 'bipdersig.py'
- 'getblocktemplate_longpoll.py'
- 'getblocktemplate_proposals.py'
- 'txn_doublespend.py'
- 'txn_clone.py --mineblock'
- 'pruning.py'
- 'forknotify.py'
- 'invalidateblock.py'
- 'keypool.py'
- 'receivedby.py'
- 'rpcbind_test.py'
-# 'script_test.py'
- 'smartfees.py'
- 'maxblocksinflight.py'
- 'invalidblockrequest.py'
-# 'forknotify.py'
- 'p2p-acceptblock.py'
- 'mempool_packages.py'
-);
-
-if [ "x$ENABLE_ZMQ" = "x1" ]; then
- testScripts+=('zmq_test.py')
-fi
-
-extArg="-extended"
-passOn=${@#$extArg}
-
-if [ "x${ENABLE_BITCOIND}${ENABLE_UTILS}${ENABLE_WALLET}" = "x111" ]; then
- for (( i = 0; i < ${#testScripts[@]}; i++ ))
- do
- if [ -z "$1" ] || [ "${1:0:1}" == "-" ] || [ "$1" == "${testScripts[$i]}" ] || [ "$1.py" == "${testScripts[$i]}" ]
- then
- echo -e "Running testscript \033[1m${testScripts[$i]}...\033[0m"
- ${BUILDDIR}/qa/rpc-tests/${testScripts[$i]} --srcdir "${BUILDDIR}/src" ${passOn}
- fi
- done
- for (( i = 0; i < ${#testScriptsExt[@]}; i++ ))
- do
- if [ "$1" == $extArg ] || [ "$1" == "${testScriptsExt[$i]}" ] || [ "$1.py" == "${testScriptsExt[$i]}" ]
- then
- echo -e "Running \033[1m2nd level\033[0m testscript \033[1m${testScriptsExt[$i]}...\033[0m"
- ${BUILDDIR}/qa/rpc-tests/${testScriptsExt[$i]} --srcdir "${BUILDDIR}/src" ${passOn}
- fi
- done
-else
- echo "No rpc tests to run. Wallet, utils, and bitcoind must all be enabled"
-fi
diff --git a/qa/pull-tester/run-bitcoind-for-test.sh.in b/qa/pull-tester/run-bitcoind-for-test.sh.in
index 14ae08e4e5..14ae08e4e5 100755..100644
--- a/qa/pull-tester/run-bitcoind-for-test.sh.in
+++ b/qa/pull-tester/run-bitcoind-for-test.sh.in
diff --git a/qa/pull-tester/tests-config.sh.in b/qa/pull-tester/tests_config.py.in
index e881a95110..937b4231f1 100755..100644
--- a/qa/pull-tester/tests-config.sh.in
+++ b/qa/pull-tester/tests_config.py.in
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env python2
# Copyright (c) 2013-2014 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -12,6 +12,4 @@ EXEEXT="@EXEEXT@"
@BUILD_BITCOIND_TRUE@ENABLE_BITCOIND=1
@ENABLE_ZMQ_TRUE@ENABLE_ZMQ=1
-REAL_BITCOIND="$BUILDDIR/src/bitcoind${EXEEXT}"
-REAL_BITCOINCLI="$BUILDDIR/src/bitcoin-cli${EXEEXT}"
diff --git a/qa/rpc-tests/README.md b/qa/rpc-tests/README.md
index c6d1721282..d2db00362f 100644
--- a/qa/rpc-tests/README.md
+++ b/qa/rpc-tests/README.md
@@ -37,9 +37,13 @@ Helper functions for creating blocks and transactions.
Notes
=====
-You can run a single test by calling `qa/pull-tester/rpc-tests.sh <testname>`.
+You can run any single test by calling `qa/pull-tester/rpc-tests.py <testname>`.
-Run all possible tests with `qa/pull-tester/rpc-tests.sh -extended`.
+Or you can run any combination of tests by calling `qa/pull-tester/rpc-tests.py <testname1> <testname2> <testname3> ...`
+
+Run the regression test suite with `qa/pull-tester/rpc-tests.py`
+
+Run all possible tests with `qa/pull-tester/rpc-tests.py -extended`
Possible options:
@@ -53,7 +57,7 @@ Possible options:
--tracerpc Print out all RPC calls as they are made
```
-If you set the environment variable `PYTHON_DEBUG=1` you will get some debug output (example: `PYTHON_DEBUG=1 qa/pull-tester/rpc-tests.sh wallet`).
+If you set the environment variable `PYTHON_DEBUG=1` you will get some debug output (example: `PYTHON_DEBUG=1 qa/pull-tester/rpc-tests.py wallet`).
A 200-block -regtest blockchain and wallets for four nodes
is created the first time a regression test is run and
diff --git a/qa/rpc-tests/bip65-cltv-p2p.py b/qa/rpc-tests/bip65-cltv-p2p.py
new file mode 100755
index 0000000000..9ca5c69f16
--- /dev/null
+++ b/qa/rpc-tests/bip65-cltv-p2p.py
@@ -0,0 +1,182 @@
+#!/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.test_framework import ComparisonTestFramework
+from test_framework.util import *
+from test_framework.mininode import CTransaction, NetworkThread
+from test_framework.blocktools import create_coinbase, create_block
+from test_framework.comptool import TestInstance, TestManager
+from test_framework.script import CScript, OP_1NEGATE, OP_NOP2, OP_DROP
+from binascii import hexlify, unhexlify
+import cStringIO
+import time
+
+def cltv_invalidate(tx):
+ '''Modify the signature in vin 0 of the tx to fail CLTV
+
+ Prepends -1 CLTV DROP in the scriptSig itself.
+ '''
+ tx.vin[0].scriptSig = CScript([OP_1NEGATE, OP_NOP2, OP_DROP] +
+ list(CScript(tx.vin[0].scriptSig)))
+
+'''
+This test is meant to exercise BIP65 (CHECKLOCKTIMEVERIFY)
+Connect to a single node.
+Mine 2 (version 3) blocks (save the coinbases for later).
+Generate 98 more version 3 blocks, verify the node accepts.
+Mine 749 version 4 blocks, verify the node accepts.
+Check that the new CLTV rules are not enforced on the 750th version 4 block.
+Check that the new CLTV rules are enforced on the 751st version 4 block.
+Mine 199 new version blocks.
+Mine 1 old-version block.
+Mine 1 new version block.
+Mine 1 old version block, see that the node rejects.
+'''
+
+class BIP65Test(ComparisonTestFramework):
+
+ def __init__(self):
+ self.num_nodes = 1
+
+ def setup_network(self):
+ # Must set the blockversion for this test
+ self.nodes = start_nodes(1, self.options.tmpdir,
+ extra_args=[['-debug', '-whitelist=127.0.0.1', '-blockversion=3']],
+ binary=[self.options.testbinary])
+
+ def run_test(self):
+ test = TestManager(self, self.options.tmpdir)
+ test.add_all_connections(self.nodes)
+ NetworkThread().start() # Start up network handling in another thread
+ test.run()
+
+ def create_transaction(self, node, coinbase, to_address, amount):
+ from_txid = node.getblock(coinbase)['tx'][0]
+ inputs = [{ "txid" : from_txid, "vout" : 0}]
+ outputs = { to_address : amount }
+ rawtx = node.createrawtransaction(inputs, outputs)
+ signresult = node.signrawtransaction(rawtx)
+ tx = CTransaction()
+ f = cStringIO.StringIO(unhexlify(signresult['hex']))
+ tx.deserialize(f)
+ return tx
+
+ 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()
+
+ ''' 98 more version 3 blocks '''
+ test_blocks = []
+ for i in xrange(98):
+ 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(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)
+
+ '''
+ Check that the new CLTV rules are not enforced in the 750th
+ version 3 block.
+ '''
+ spendtx = self.create_transaction(self.nodes[0],
+ self.coinbase_blocks[0], self.nodeaddress, 1.0)
+ cltv_invalidate(spendtx)
+ spendtx.rehash()
+
+ 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()
+ block.rehash()
+ block.solve()
+
+ self.last_block_time += 1
+ self.tip = block.sha256
+ height += 1
+ yield TestInstance([[block, True]])
+
+ '''
+ Check that the new CLTV rules are enforced in the 751st version 4
+ block.
+ '''
+ spendtx = self.create_transaction(self.nodes[0],
+ self.coinbase_blocks[1], self.nodeaddress, 1.0)
+ cltv_invalidate(spendtx)
+ spendtx.rehash()
+
+ 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()
+ block.rehash()
+ block.solve()
+ self.last_block_time += 1
+ yield TestInstance([[block, False]])
+
+ ''' Mine 199 new version blocks on last valid tip '''
+ test_blocks = []
+ for i in xrange(199):
+ 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(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(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(height), self.last_block_time + 1)
+ block.nVersion = 3
+ block.rehash()
+ block.solve()
+ self.last_block_time += 1
+ yield TestInstance([[block, False]])
+
+if __name__ == '__main__':
+ BIP65Test().main()
diff --git a/qa/rpc-tests/bip65-cltv.py b/qa/rpc-tests/bip65-cltv.py
new file mode 100755
index 0000000000..e90e11e6a7
--- /dev/null
+++ b/qa/rpc-tests/bip65-cltv.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python2
+# 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.
+
+#
+# Test the CHECKLOCKTIMEVERIFY (BIP65) soft-fork logic
+#
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
+import os
+import shutil
+
+class BIP65Test(BitcoinTestFramework):
+
+ def setup_network(self):
+ self.nodes = []
+ self.nodes.append(start_node(0, self.options.tmpdir, []))
+ self.nodes.append(start_node(1, self.options.tmpdir, ["-blockversion=3"]))
+ self.nodes.append(start_node(2, self.options.tmpdir, ["-blockversion=4"]))
+ connect_nodes(self.nodes[1], 0)
+ connect_nodes(self.nodes[2], 0)
+ self.is_network_split = False
+ self.sync_all()
+
+ def run_test(self):
+ cnt = self.nodes[0].getblockcount()
+
+ # Mine some old-version blocks
+ self.nodes[1].generate(100)
+ self.sync_all()
+ if (self.nodes[0].getblockcount() != cnt + 100):
+ raise AssertionError("Failed to mine 100 version=3 blocks")
+
+ # Mine 750 new-version blocks
+ for i in xrange(15):
+ self.nodes[2].generate(50)
+ self.sync_all()
+ if (self.nodes[0].getblockcount() != cnt + 850):
+ raise AssertionError("Failed to mine 750 version=4 blocks")
+
+ # TODO: check that new CHECKLOCKTIMEVERIFY rules are not enforced
+
+ # Mine 1 new-version block
+ self.nodes[2].generate(1)
+ self.sync_all()
+ if (self.nodes[0].getblockcount() != cnt + 851):
+ raise AssertionFailure("Failed to mine a version=4 blocks")
+
+ # TODO: check that new CHECKLOCKTIMEVERIFY rules are enforced
+
+ # Mine 198 new-version blocks
+ for i in xrange(2):
+ self.nodes[2].generate(99)
+ self.sync_all()
+ if (self.nodes[0].getblockcount() != cnt + 1049):
+ raise AssertionError("Failed to mine 198 version=4 blocks")
+
+ # Mine 1 old-version block
+ self.nodes[1].generate(1)
+ self.sync_all()
+ if (self.nodes[0].getblockcount() != cnt + 1050):
+ raise AssertionError("Failed to mine a version=3 block after 949 version=4 blocks")
+
+ # Mine 1 new-version blocks
+ self.nodes[2].generate(1)
+ self.sync_all()
+ if (self.nodes[0].getblockcount() != cnt + 1051):
+ raise AssertionError("Failed to mine a version=4 block")
+
+ # Mine 1 old-version blocks
+ try:
+ self.nodes[1].generate(1)
+ raise AssertionError("Succeeded to mine a version=3 block after 950 version=4 blocks")
+ except JSONRPCException:
+ pass
+ self.sync_all()
+ if (self.nodes[0].getblockcount() != cnt + 1051):
+ raise AssertionError("Accepted a version=3 block after 950 version=4 blocks")
+
+ # Mine 1 new-version blocks
+ self.nodes[2].generate(1)
+ self.sync_all()
+ if (self.nodes[0].getblockcount() != cnt + 1052):
+ raise AssertionError("Failed to mine a version=4 block")
+
+if __name__ == '__main__':
+ BIP65Test().main()
diff --git a/qa/rpc-tests/blockchain.py b/qa/rpc-tests/blockchain.py
new file mode 100755
index 0000000000..b7bfe36285
--- /dev/null
+++ b/qa/rpc-tests/blockchain.py
@@ -0,0 +1,52 @@
+#!/usr/bin/env python2
+# Copyright (c) 2014 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#
+# Test RPC calls related to blockchain state.
+#
+
+import decimal
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ initialize_chain,
+ assert_equal,
+ start_nodes,
+ connect_nodes_bi,
+)
+
+class BlockchainTest(BitcoinTestFramework):
+ """
+ Test blockchain-related RPC calls:
+
+ - gettxoutsetinfo
+
+ """
+
+ def setup_chain(self):
+ print("Initializing test directory " + self.options.tmpdir)
+ initialize_chain(self.options.tmpdir)
+
+ def setup_network(self, split=False):
+ self.nodes = start_nodes(2, self.options.tmpdir)
+ connect_nodes_bi(self.nodes, 0, 1)
+ self.is_network_split = False
+ self.sync_all()
+
+ def run_test(self):
+ node = self.nodes[0]
+ res = node.gettxoutsetinfo()
+
+ assert_equal(res[u'total_amount'], decimal.Decimal('8725.00000000'))
+ assert_equal(res[u'transactions'], 200)
+ assert_equal(res[u'height'], 200)
+ assert_equal(res[u'txouts'], 200)
+ assert_equal(res[u'bytes_serialized'], 13924),
+ assert_equal(len(res[u'bestblock']), 64)
+ assert_equal(len(res[u'hash_serialized']), 64)
+
+
+if __name__ == '__main__':
+ BlockchainTest().main()
diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py
index fc29789218..93d13faa06 100755
--- a/qa/rpc-tests/fundrawtransaction.py
+++ b/qa/rpc-tests/fundrawtransaction.py
@@ -28,7 +28,15 @@ class RawTransactionsTest(BitcoinTestFramework):
def run_test(self):
print "Mining blocks..."
- feeTolerance = Decimal(0.00000002) #if the fee's positive delta is higher than this value tests will fail, neg. delta always fail the tests
+
+ min_relay_tx_fee = self.nodes[0].getnetworkinfo()['relayfee']
+ # if the fee's positive delta is higher than this value tests will fail,
+ # neg. delta always fail the tests.
+ # The size of the signature of every input may be at most 2 bytes larger
+ # than a minimum sized signature.
+
+ # = 2 bytes * minRelayTxFeePerByte
+ feeTolerance = 2 * min_relay_tx_fee/1000
self.nodes[2].generate(1)
self.sync_all()
diff --git a/qa/rpc-tests/httpbasics.py b/qa/rpc-tests/httpbasics.py
index b66533543d..7888114c54 100755
--- a/qa/rpc-tests/httpbasics.py
+++ b/qa/rpc-tests/httpbasics.py
@@ -97,5 +97,19 @@ class HTTPBasicsTest (BitcoinTestFramework):
assert_equal('"error":null' in out1, True)
assert_equal(conn.sock!=None, True) #connection must be closed because bitcoind should use keep-alive by default
+ # Check excessive request size
+ conn = httplib.HTTPConnection(urlNode2.hostname, urlNode2.port)
+ conn.connect()
+ conn.request('GET', '/' + ('x'*1000), '', headers)
+ out1 = conn.getresponse()
+ assert_equal(out1.status, httplib.NOT_FOUND)
+
+ conn = httplib.HTTPConnection(urlNode2.hostname, urlNode2.port)
+ conn.connect()
+ conn.request('GET', '/' + ('x'*10000), '', headers)
+ out1 = conn.getresponse()
+ assert_equal(out1.status, httplib.BAD_REQUEST)
+
+
if __name__ == '__main__':
HTTPBasicsTest ().main ()
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/qa/rpc-tests/pruning.py b/qa/rpc-tests/pruning.py
index 2824c51ce7..21f8d69382 100755
--- a/qa/rpc-tests/pruning.py
+++ b/qa/rpc-tests/pruning.py
@@ -61,6 +61,9 @@ class PruneTest(BitcoinTestFramework):
self.address[0] = self.nodes[0].getnewaddress()
self.address[1] = self.nodes[1].getnewaddress()
+ # Determine default relay fee
+ self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"]
+
connect_nodes(self.nodes[0], 1)
connect_nodes(self.nodes[1], 2)
connect_nodes(self.nodes[2], 0)
@@ -239,7 +242,7 @@ class PruneTest(BitcoinTestFramework):
outputs = {}
t = self.utxo.pop()
inputs.append({ "txid" : t["txid"], "vout" : t["vout"]})
- remchange = t["amount"] - Decimal("0.001000")
+ remchange = t["amount"] - 100*self.relayfee # Fee must be above min relay rate for 66kb tx
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 #
diff --git a/share/qt/make_windows_icon.sh b/share/qt/make_windows_icon.sh
deleted file mode 100755
index bf607b1c62..0000000000
--- a/share/qt/make_windows_icon.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-# create multiresolution windows icon
-ICON_SRC=../../src/qt/res/icons/bitcoin.png
-ICON_DST=../../src/qt/res/icons/bitcoin.ico
-convert ${ICON_SRC} -resize 16x16 bitcoin-16.png
-convert ${ICON_SRC} -resize 32x32 bitcoin-32.png
-convert ${ICON_SRC} -resize 48x48 bitcoin-48.png
-convert bitcoin-16.png bitcoin-32.png bitcoin-48.png ${ICON_DST}
-
diff --git a/src/Makefile.am b/src/Makefile.am
index 462774389a..f35b9dc898 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -31,13 +31,13 @@ LIBBITCOIN_UTIL=libbitcoin_util.a
LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a
LIBBITCOINQT=qt/libbitcoinqt.a
LIBSECP256K1=secp256k1/libsecp256k1.la
-LIBUNIVALUE=univalue/lib/libunivalue.la
+LIBUNIVALUE=univalue/libunivalue.la
$(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*)
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F)
-$(LIBUNIVALUE): $(wildcard univalue/lib/*)
- $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C univalue/
+$(LIBUNIVALUE): $(wildcard univalue/lib/*) $(wildcard univalue/include/*)
+ $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F)
# Make is not made aware of per-object dependencies to avoid limiting building parallelization
# But to build the less dependent modules first, we manually select their order here:
@@ -64,6 +64,7 @@ endif
bin_PROGRAMS =
TESTS =
+BENCHMARKS =
if BUILD_BITCOIND
bin_PROGRAMS += bitcoind
@@ -109,7 +110,7 @@ BITCOIN_CORE_H = \
init.h \
key.h \
keystore.h \
- leveldbwrapper.h \
+ dbwrapper.h \
limitedmap.h \
main.h \
memusage.h \
@@ -187,7 +188,7 @@ libbitcoin_server_a_SOURCES = \
httprpc.cpp \
httpserver.cpp \
init.cpp \
- leveldbwrapper.cpp \
+ dbwrapper.cpp \
main.cpp \
merkleblock.cpp \
miner.cpp \
@@ -213,7 +214,7 @@ libbitcoin_server_a_SOURCES = \
if ENABLE_ZMQ
LIBBITCOIN_ZMQ=libbitcoin_zmq.a
-libbitcoin_zmq_a_CPPFLAGS = $(BITCOIN_INCLUDES)
+libbitcoin_zmq_a_CPPFLAGS = $(BITCOIN_INCLUDES) $(ZMQ_CFLAGS)
libbitcoin_zmq_a_SOURCES = \
zmq/zmqabstractnotifier.cpp \
zmq/zmqnotificationinterface.cpp \
@@ -411,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
@@ -420,7 +433,8 @@ EXTRA_DIST = leveldb
clean-local:
-$(MAKE) -C leveldb clean
-$(MAKE) -C secp256k1 clean
- rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno
+ -$(MAKE) -C univalue clean
+ -rm -f leveldb/*/*.gcda leveldb/*/*.gcno leveldb/helpers/memenv/*.gcda leveldb/helpers/memenv/*.gcno
-rm -f config.h
.rc.o:
@@ -439,6 +453,10 @@ if ENABLE_TESTS
include Makefile.test.include
endif
+if ENABLE_BENCH
+include Makefile.bench.include
+endif
+
if ENABLE_QT
include Makefile.qt.include
endif
diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include
new file mode 100644
index 0000000000..61fe9e287d
--- /dev/null
+++ b/src/Makefile.bench.include
@@ -0,0 +1,45 @@
+bin_PROGRAMS += bench/bench_bitcoin
+BENCH_SRCDIR = bench
+BENCH_BINARY = bench/bench_bitcoin$(EXEEXT)
+
+
+bench_bench_bitcoin_SOURCES = \
+ bench/bench_bitcoin.cpp \
+ bench/bench.cpp \
+ bench/bench.h \
+ bench/Examples.cpp
+
+bench_bench_bitcoin_CPPFLAGS = $(BITCOIN_INCLUDES) $(EVENT_CLFAGS) $(EVENT_PTHREADS_CFLAGS) -I$(builddir)/bench/
+bench_bench_bitcoin_LDADD = \
+ $(LIBBITCOIN_SERVER) \
+ $(LIBBITCOIN_COMMON) \
+ $(LIBBITCOIN_UNIVALUE) \
+ $(LIBBITCOIN_UTIL) \
+ $(LIBBITCOIN_CRYPTO) \
+ $(LIBLEVELDB) \
+ $(LIBMEMENV) \
+ $(LIBSECP256K1)
+
+if ENABLE_ZMQ
+bench_bench_bitcoin_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS)
+endif
+
+if ENABLE_WALLET
+bench_bench_bitcoin_LDADD += $(LIBBITCOIN_WALLET)
+endif
+
+bench_bench_bitcoin_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
+bench_bench_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
+
+
+CLEAN_BITCOIN_BENCH = bench/*.gcda bench/*.gcno
+
+CLEANFILES += $(CLEAN_BITCOIN_BENCH)
+
+bitcoin_bench: $(BENCH_BINARY)
+
+bench: $(BENCH_BINARY) FORCE
+ $(BENCH_BINARY)
+
+bitcoin_bench_clean : FORCE
+ rm -f $(CLEAN_BITCOIN_BENCH) $(bench_bench_bitcoin_OBJECTS) $(BENCH_BINARY)
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 9a6e43631b..f23a8f41fc 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -36,6 +36,7 @@ GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.r
BITCOIN_TESTS =\
test/arith_uint256_tests.cpp \
test/bignum.h \
+ test/addrman_tests.cpp \
test/alert_tests.cpp \
test/allocator_tests.cpp \
test/base32_tests.cpp \
@@ -53,6 +54,7 @@ BITCOIN_TESTS =\
test/hash_tests.cpp \
test/key_tests.cpp \
test/limitedmap_tests.cpp \
+ test/dbwrapper_tests.cpp \
test/main_tests.cpp \
test/mempool_tests.cpp \
test/miner_tests.cpp \
@@ -73,6 +75,7 @@ BITCOIN_TESTS =\
test/sighash_tests.cpp \
test/sigopcount_tests.cpp \
test/skiplist_tests.cpp \
+ test/streams_tests.cpp \
test/test_bitcoin.cpp \
test/test_bitcoin.h \
test/timedata_tests.cpp \
diff --git a/src/addrman.cpp b/src/addrman.cpp
index ff1f7e9187..078b9e1681 100644
--- a/src/addrman.cpp
+++ b/src/addrman.cpp
@@ -329,13 +329,17 @@ void CAddrMan::Attempt_(const CService& addr, int64_t nTime)
info.nAttempts++;
}
-CAddrInfo CAddrMan::Select_()
+CAddrInfo CAddrMan::Select_(bool newOnly)
{
if (size() == 0)
return CAddrInfo();
+ if (newOnly && nNew == 0)
+ return CAddrInfo();
+
// Use a 50% chance for choosing between tried and new table entries.
- if (nTried > 0 && (nNew == 0 || GetRandInt(2) == 0)) {
+ if (!newOnly &&
+ (nTried > 0 && (nNew == 0 || GetRandInt(2) == 0))) {
// use a tried node
double fChanceFactor = 1.0;
while (1) {
diff --git a/src/addrman.h b/src/addrman.h
index 384b6cfdb9..1123caabfa 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -22,6 +22,8 @@
*/
class CAddrInfo : public CAddress
{
+
+
public:
//! last try whatsoever by us (memory only)
int64_t nLastTry;
@@ -230,8 +232,8 @@ protected:
//! Mark an entry as attempted to connect.
void Attempt_(const CService &addr, int64_t nTime);
- //! Select an address to connect to.
- CAddrInfo Select_();
+ //! Select an address to connect to, if newOnly is set to true, only the new table is selected from.
+ CAddrInfo Select_(bool newOnly);
#ifdef DEBUG_ADDRMAN
//! Perform consistency check. Returns an error code or zero.
@@ -532,13 +534,13 @@ public:
/**
* Choose an address to connect to.
*/
- CAddrInfo Select()
+ CAddrInfo Select(bool newOnly = false)
{
CAddrInfo addrRet;
{
LOCK(cs);
Check();
- addrRet = Select_();
+ addrRet = Select_(newOnly);
Check();
}
return addrRet;
@@ -567,6 +569,12 @@ public:
Check();
}
}
+
+ //! Ensure that bucket placement is always the same for testing purposes.
+ void MakeDeterministic(){
+ nKey.SetNull(); //Do not use outside of tests.
+ }
+
};
#endif // BITCOIN_ADDRMAN_H
diff --git a/src/amount.h b/src/amount.h
index 90e6b5aa8e..a4c7764cda 100644
--- a/src/amount.h
+++ b/src/amount.h
@@ -51,6 +51,7 @@ public:
friend bool operator==(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK == b.nSatoshisPerK; }
friend bool operator<=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK <= b.nSatoshisPerK; }
friend bool operator>=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK >= b.nSatoshisPerK; }
+ CFeeRate& operator+=(const CFeeRate& a) { nSatoshisPerK += a.nSatoshisPerK; return *this; }
std::string ToString() const;
ADD_SERIALIZE_METHODS;
diff --git a/src/bench/.gitignore b/src/bench/.gitignore
new file mode 100644
index 0000000000..e231fe4cab
--- /dev/null
+++ b/src/bench/.gitignore
@@ -0,0 +1 @@
+bench_bitcoin
diff --git a/src/bench/Examples.cpp b/src/bench/Examples.cpp
new file mode 100644
index 0000000000..b6b020a971
--- /dev/null
+++ b/src/bench/Examples.cpp
@@ -0,0 +1,34 @@
+// 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 "main.h"
+#include "utiltime.h"
+
+// Sanity test: this should loop ten times, and
+// min/max/average should be close to 100ms.
+static void Sleep100ms(benchmark::State& state)
+{
+ while (state.KeepRunning()) {
+ MilliSleep(100);
+ }
+}
+
+BENCHMARK(Sleep100ms);
+
+// Extremely fast-running benchmark:
+#include <math.h>
+
+volatile double sum = 0.0; // volatile, global so not optimized away
+
+static void Trig(benchmark::State& state)
+{
+ double d = 0.01;
+ while (state.KeepRunning()) {
+ sum += sin(d);
+ d += 0.000001;
+ }
+}
+
+BENCHMARK(Trig);
diff --git a/src/bench/bench.cpp b/src/bench/bench.cpp
new file mode 100644
index 0000000000..6ee3cdc27a
--- /dev/null
+++ b/src/bench/bench.cpp
@@ -0,0 +1,70 @@
+// 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>
+
+using namespace benchmark;
+
+std::map<std::string, BenchFunction> BenchRunner::benchmarks;
+
+static double gettimedouble(void) {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return tv.tv_usec * 0.000001 + tv.tv_sec;
+}
+
+BenchRunner::BenchRunner(std::string name, BenchFunction func)
+{
+ benchmarks.insert(std::make_pair(name, func));
+}
+
+void
+BenchRunner::RunAll(double elapsedTimeForOne)
+{
+ std::cout << "Benchmark" << "," << "count" << "," << "min" << "," << "max" << "," << "average" << "\n";
+
+ for (std::map<std::string,BenchFunction>::iterator it = benchmarks.begin();
+ it != benchmarks.end(); ++it) {
+
+ State state(it->first, elapsedTimeForOne);
+ BenchFunction& func = it->second;
+ func(state);
+ }
+}
+
+bool State::KeepRunning()
+{
+ double now;
+ if (count == 0) {
+ beginTime = now = gettimedouble();
+ }
+ else {
+ // timeCheckCount is used to avoid calling gettime most of the time,
+ // so benchmarks that run very quickly get consistent results.
+ if ((count+1)%timeCheckCount != 0) {
+ ++count;
+ return true; // keep going
+ }
+ now = gettimedouble();
+ double elapsedOne = (now - lastTime)/timeCheckCount;
+ if (elapsedOne < minTime) minTime = elapsedOne;
+ if (elapsedOne > maxTime) maxTime = elapsedOne;
+ if (elapsedOne*timeCheckCount < maxElapsed/16) timeCheckCount *= 2;
+ }
+ lastTime = now;
+ ++count;
+
+ if (now - beginTime < maxElapsed) return true; // Keep going
+
+ --count;
+
+ // Output results
+ double average = (now-beginTime)/count;
+ std::cout << name << "," << count << "," << minTime << "," << maxTime << "," << average << "\n";
+
+ return false;
+}
diff --git a/src/bench/bench.h b/src/bench/bench.h
new file mode 100644
index 0000000000..5ce13c642b
--- /dev/null
+++ b/src/bench/bench.h
@@ -0,0 +1,72 @@
+// 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_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)
+// Wny not use the Google Benchmark framework? Because adding Yet Another Dependency
+// (that uses cmake as its build system and has lots of features we don't need) isn't
+// worth it.
+
+/*
+ * Usage:
+
+static void CODE_TO_TIME(benchmark::State& state)
+{
+ ... do any setup needed...
+ while (state.KeepRunning()) {
+ ... do stuff you want to time...
+ }
+ ... do any cleanup needed...
+}
+
+BENCHMARK(CODE_TO_TIME);
+
+ */
+
+namespace benchmark {
+
+ class State {
+ std::string name;
+ double maxElapsed;
+ double beginTime;
+ double lastTime, minTime, maxTime;
+ int64_t count;
+ int64_t timeCheckCount;
+ public:
+ State(std::string _name, double _maxElapsed) : name(_name), maxElapsed(_maxElapsed), count(0) {
+ minTime = std::numeric_limits<double>::max();
+ maxTime = std::numeric_limits<double>::min();
+ timeCheckCount = 1;
+ }
+ bool KeepRunning();
+ };
+
+ typedef boost::function<void(State&)> BenchFunction;
+
+ class BenchRunner
+ {
+ static std::map<std::string, BenchFunction> benchmarks;
+
+ public:
+ BenchRunner(std::string name, BenchFunction func);
+
+ static void RunAll(double elapsedTimeForOne=1.0);
+ };
+}
+
+// BENCHMARK(foo) expands to: benchmark::BenchRunner bench_11foo("foo", foo);
+#define BENCHMARK(n) \
+ benchmark::BenchRunner BOOST_PP_CAT(bench_, BOOST_PP_CAT(__LINE__, n))(BOOST_PP_STRINGIZE(n), n);
+
+#endif // BITCOIN_BENCH_BENCH_H
diff --git a/src/bench/bench_bitcoin.cpp b/src/bench/bench_bitcoin.cpp
new file mode 100644
index 0000000000..db1402216d
--- /dev/null
+++ b/src/bench/bench_bitcoin.cpp
@@ -0,0 +1,21 @@
+// 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 "key.h"
+#include "main.h"
+#include "util.h"
+
+int
+main(int argc, char** argv)
+{
+ ECC_Start();
+ SetupEnvironment();
+ fPrintToDebugLog = false; // don't want to write to debug.log file
+
+ benchmark::BenchRunner::RunAll();
+
+ ECC_Stop();
+}
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index e0fe6aa5bf..9564573657 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -31,9 +31,7 @@ std::string HelpMessageCli()
strUsage += HelpMessageOpt("-?", _("This help message"));
strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file (default: %s)"), "bitcoin.conf"));
strUsage += HelpMessageOpt("-datadir=<dir>", _("Specify data directory"));
- strUsage += HelpMessageOpt("-testnet", _("Use the test network"));
- strUsage += HelpMessageOpt("-regtest", _("Enter regression test mode, which uses a special chain in which blocks can be "
- "solved instantly. This is intended for regression testing tools and app development."));
+ AppendParamsHelpMessages(strUsage);
strUsage += HelpMessageOpt("-rpcconnect=<ip>", strprintf(_("Send commands to node running on <ip> (default: %s)"), "127.0.0.1"));
strUsage += HelpMessageOpt("-rpcport=<port>", strprintf(_("Connect to JSON-RPC on <port> (default: %u or testnet: %u)"), 8332, 18332));
strUsage += HelpMessageOpt("-rpcwait", _("Wait for RPC server to start"));
@@ -69,7 +67,7 @@ static bool AppInitRPC(int argc, char* argv[])
// Parameters
//
ParseParameters(argc, argv);
- if (argc<2 || mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version")) {
+ if (argc<2 || mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help") || mapArgs.count("-version")) {
std::string strUsage = _("Bitcoin Core RPC client version") + " " + FormatFullVersion() + "\n";
if (!mapArgs.count("-version")) {
strUsage += "\n" + _("Usage:") + "\n" +
@@ -94,8 +92,10 @@ static bool AppInitRPC(int argc, char* argv[])
return false;
}
// Check for -testnet or -regtest parameter (BaseParams() calls are only valid after this clause)
- if (!SelectBaseParamsFromCommandLine()) {
- fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n");
+ try {
+ SelectBaseParams(ChainNameFromCommandLine());
+ } catch (const std::exception& e) {
+ fprintf(stderr, "Error: %s\n", e.what());
return false;
}
if (GetBoolArg("-rpcssl", false))
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index f7518fab5d..48033cd8ad 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -35,14 +35,16 @@ static bool AppInitRawTx(int argc, char* argv[])
ParseParameters(argc, argv);
// Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
- if (!SelectParamsFromCommandLine()) {
- fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n");
+ try {
+ SelectParams(ChainNameFromCommandLine());
+ } catch (const std::exception& e) {
+ fprintf(stderr, "Error: %s\n", e.what());
return false;
}
fCreateBlank = GetBoolArg("-create", false);
- if (argc<2 || mapArgs.count("-?") || mapArgs.count("-help"))
+ if (argc<2 || mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help"))
{
// First part of help message is specific to this utility
std::string strUsage = _("Bitcoin Core bitcoin-tx utility version") + " " + FormatFullVersion() + "\n\n" +
@@ -58,8 +60,7 @@ static bool AppInitRawTx(int argc, char* argv[])
strUsage += HelpMessageOpt("-create", _("Create new, empty TX."));
strUsage += HelpMessageOpt("-json", _("Select JSON output"));
strUsage += HelpMessageOpt("-txid", _("Output only the hex-encoded transaction id of the resultant transaction."));
- strUsage += HelpMessageOpt("-regtest", _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly."));
- strUsage += HelpMessageOpt("-testnet", _("Use the test network"));
+ AppendParamsHelpMessages(strUsage);
fprintf(stdout, "%s", strUsage.c_str());
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index b512f74c22..addf0e6a26 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -72,7 +72,7 @@ bool AppInit(int argc, char* argv[])
ParseParameters(argc, argv);
// Process help and version before taking care about datadir
- if (mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version"))
+ if (mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help") || mapArgs.count("-version"))
{
std::string strUsage = _("Bitcoin Core Daemon") + " " + _("version") + " " + FormatFullVersion() + "\n";
@@ -107,8 +107,10 @@ bool AppInit(int argc, char* argv[])
return false;
}
// Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
- if (!SelectParamsFromCommandLine()) {
- fprintf(stderr, "Error: Invalid combination of -regtest and -testnet.\n");
+ try {
+ SelectParams(ChainNameFromCommandLine());
+ } catch (const std::exception& e) {
+ fprintf(stderr, "Error: %s\n", e.what());
return false;
}
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 430b75683b..dd26c3b31a 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -5,6 +5,7 @@
#include "chainparams.h"
+#include "tinyformat.h"
#include "util.h"
#include "utilstrencodings.h"
@@ -76,6 +77,7 @@ public:
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
consensus.nPowTargetSpacing = 10 * 60;
consensus.fPowAllowMinDifficultyBlocks = false;
+ consensus.fPowNoRetargeting = false;
/**
* The message start string is designed to be unlikely to occur in normal data.
* The characters are rarely used upper ASCII, not valid as UTF-8, and produce
@@ -155,6 +157,7 @@ public:
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
consensus.nPowTargetSpacing = 10 * 60;
consensus.fPowAllowMinDifficultyBlocks = true;
+ consensus.fPowNoRetargeting = false;
pchMessageStart[0] = 0x0b;
pchMessageStart[1] = 0x11;
pchMessageStart[2] = 0x09;
@@ -217,6 +220,7 @@ public:
consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
consensus.nPowTargetSpacing = 10 * 60;
consensus.fPowAllowMinDifficultyBlocks = true;
+ consensus.fPowNoRetargeting = true;
pchMessageStart[0] = 0xfa;
pchMessageStart[1] = 0xbf;
@@ -263,31 +267,20 @@ const CChainParams &Params() {
return *pCurrentParams;
}
-CChainParams &Params(CBaseChainParams::Network network) {
- switch (network) {
- case CBaseChainParams::MAIN:
+CChainParams& Params(const std::string& chain)
+{
+ if (chain == CBaseChainParams::MAIN)
return mainParams;
- case CBaseChainParams::TESTNET:
+ else if (chain == CBaseChainParams::TESTNET)
return testNetParams;
- case CBaseChainParams::REGTEST:
+ else if (chain == CBaseChainParams::REGTEST)
return regTestParams;
- default:
- assert(false && "Unimplemented network");
- return mainParams;
- }
+ else
+ throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain));
}
-void SelectParams(CBaseChainParams::Network network) {
+void SelectParams(const std::string& network)
+{
SelectBaseParams(network);
pCurrentParams = &Params(network);
}
-
-bool SelectParamsFromCommandLine()
-{
- CBaseChainParams::Network network = NetworkIdFromCommandLine();
- if (network == CBaseChainParams::MAX_NETWORK_TYPES)
- return false;
-
- SelectParams(network);
- return true;
-}
diff --git a/src/chainparams.h b/src/chainparams.h
index 342bccb12f..cb061d596e 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -105,16 +105,15 @@ protected:
*/
const CChainParams &Params();
-/** Return parameters for the given network. */
-CChainParams &Params(CBaseChainParams::Network network);
-
-/** Sets the params returned by Params() to those for the given network. */
-void SelectParams(CBaseChainParams::Network network);
+/**
+ * @returns CChainParams for the given BIP70 chain name.
+ */
+CChainParams& Params(const std::string& chain);
/**
- * Looks for -regtest or -testnet and then calls SelectParams as appropriate.
- * Returns false if an invalid combination is given.
+ * Sets the params returned by Params() to those for the given BIP70 chain name.
+ * @throws std::runtime_error when the chain is not supported.
*/
-bool SelectParamsFromCommandLine();
+void SelectParams(const std::string& chain);
#endif // BITCOIN_CHAINPARAMS_H
diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp
index 9c87bf2154..db2dc751f5 100644
--- a/src/chainparamsbase.cpp
+++ b/src/chainparamsbase.cpp
@@ -5,10 +5,25 @@
#include "chainparamsbase.h"
+#include "tinyformat.h"
#include "util.h"
#include <assert.h>
+const std::string CBaseChainParams::MAIN = "main";
+const std::string CBaseChainParams::TESTNET = "test";
+const std::string CBaseChainParams::REGTEST = "regtest";
+
+void AppendParamsHelpMessages(std::string& strUsage, bool debugHelp)
+{
+ strUsage += HelpMessageGroup(_("Chain selection options:"));
+ strUsage += HelpMessageOpt("-testnet", _("Use the test chain"));
+ if (debugHelp) {
+ strUsage += HelpMessageOpt("-regtest", "Enter regression test mode, which uses a special chain in which blocks can be solved instantly. "
+ "This is intended for regression testing tools and app development.");
+ }
+}
+
/**
* Main network
*/
@@ -71,31 +86,25 @@ const CBaseChainParams& BaseParams()
return *pCurrentBaseParams;
}
-void SelectBaseParams(CBaseChainParams::Network network)
+void SelectBaseParams(const std::string& chain)
{
- switch (network) {
- case CBaseChainParams::MAIN:
+ if (chain == CBaseChainParams::MAIN)
pCurrentBaseParams = &mainParams;
- break;
- case CBaseChainParams::TESTNET:
+ else if (chain == CBaseChainParams::TESTNET)
pCurrentBaseParams = &testNetParams;
- break;
- case CBaseChainParams::REGTEST:
+ else if (chain == CBaseChainParams::REGTEST)
pCurrentBaseParams = &regTestParams;
- break;
- default:
- assert(false && "Unimplemented network");
- return;
- }
+ else
+ throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain));
}
-CBaseChainParams::Network NetworkIdFromCommandLine()
+std::string ChainNameFromCommandLine()
{
bool fRegTest = GetBoolArg("-regtest", false);
bool fTestNet = GetBoolArg("-testnet", false);
if (fTestNet && fRegTest)
- return CBaseChainParams::MAX_NETWORK_TYPES;
+ throw std::runtime_error("Invalid combination of -regtest and -testnet.");
if (fRegTest)
return CBaseChainParams::REGTEST;
if (fTestNet)
@@ -103,16 +112,6 @@ CBaseChainParams::Network NetworkIdFromCommandLine()
return CBaseChainParams::MAIN;
}
-bool SelectBaseParamsFromCommandLine()
-{
- CBaseChainParams::Network network = NetworkIdFromCommandLine();
- if (network == CBaseChainParams::MAX_NETWORK_TYPES)
- return false;
-
- SelectBaseParams(network);
- return true;
-}
-
bool AreBaseParamsConfigured()
{
return pCurrentBaseParams != NULL;
diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h
index 4369d0aef7..095c4cbdcb 100644
--- a/src/chainparamsbase.h
+++ b/src/chainparamsbase.h
@@ -15,13 +15,10 @@
class CBaseChainParams
{
public:
- enum Network {
- MAIN,
- TESTNET,
- REGTEST,
-
- MAX_NETWORK_TYPES
- };
+ /** BIP70 chain name strings (main, test or regtest) */
+ static const std::string MAIN;
+ static const std::string TESTNET;
+ static const std::string REGTEST;
const std::string& DataDir() const { return strDataDir; }
int RPCPort() const { return nRPCPort; }
@@ -34,25 +31,25 @@ protected:
};
/**
+ * Append the help messages for the chainparams options to the
+ * parameter string.
+ */
+void AppendParamsHelpMessages(std::string& strUsage, bool debugHelp=true);
+
+/**
* Return the currently selected parameters. This won't change after app
* startup, except for unit tests.
*/
const CBaseChainParams& BaseParams();
/** Sets the params returned by Params() to those for the given network. */
-void SelectBaseParams(CBaseChainParams::Network network);
-
-/**
- * Looks for -regtest or -testnet and returns the appropriate Network ID.
- * Returns MAX_NETWORK_TYPES if an invalid combination is given.
- */
-CBaseChainParams::Network NetworkIdFromCommandLine();
+void SelectBaseParams(const std::string& chain);
/**
- * Calls NetworkIdFromCommandLine() and then calls SelectParams as appropriate.
- * Returns false if an invalid combination is given.
+ * Looks for -regtest, -testnet and returns the appropriate BIP70 chain name.
+ * @return CBaseChainParams::MAX_NETWORK_TYPES if an invalid combination is given. CBaseChainParams::MAIN by default.
*/
-bool SelectBaseParamsFromCommandLine();
+std::string ChainNameFromCommandLine();
/**
* Return true if SelectBaseParamsFromCommandLine() has been called to select
diff --git a/src/compat.h b/src/compat.h
index 5378c2c761..20c2a25143 100644
--- a/src/compat.h
+++ b/src/compat.h
@@ -38,6 +38,7 @@
#include <sys/types.h>
#include <net/if.h>
#include <netinet/in.h>
+#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <limits.h>
diff --git a/src/consensus/params.h b/src/consensus/params.h
index c480a1cce1..efbbbed352 100644
--- a/src/consensus/params.h
+++ b/src/consensus/params.h
@@ -22,6 +22,7 @@ struct Params {
/** Proof of work parameters */
uint256 powLimit;
bool fPowAllowMinDifficultyBlocks;
+ bool fPowNoRetargeting;
int64_t nPowTargetSpacing;
int64_t nPowTargetTimespan;
int64_t DifficultyAdjustmentInterval() const { return nPowTargetTimespan / nPowTargetSpacing; }
diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp
new file mode 100644
index 0000000000..b6307cf0bf
--- /dev/null
+++ b/src/dbwrapper.cpp
@@ -0,0 +1,152 @@
+// Copyright (c) 2012-2014 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 "dbwrapper.h"
+
+#include "util.h"
+#include "random.h"
+
+#include <boost/filesystem.hpp>
+
+#include <leveldb/cache.h>
+#include <leveldb/env.h>
+#include <leveldb/filter_policy.h>
+#include <memenv.h>
+#include <stdint.h>
+
+void HandleError(const leveldb::Status& status) throw(dbwrapper_error)
+{
+ if (status.ok())
+ return;
+ LogPrintf("%s\n", status.ToString());
+ if (status.IsCorruption())
+ throw dbwrapper_error("Database corrupted");
+ if (status.IsIOError())
+ throw dbwrapper_error("Database I/O error");
+ if (status.IsNotFound())
+ throw dbwrapper_error("Database entry missing");
+ throw dbwrapper_error("Unknown database error");
+}
+
+static leveldb::Options GetOptions(size_t nCacheSize)
+{
+ leveldb::Options options;
+ options.block_cache = leveldb::NewLRUCache(nCacheSize / 2);
+ options.write_buffer_size = nCacheSize / 4; // up to two write buffers may be held in memory simultaneously
+ options.filter_policy = leveldb::NewBloomFilterPolicy(10);
+ options.compression = leveldb::kNoCompression;
+ options.max_open_files = 64;
+ if (leveldb::kMajorVersion > 1 || (leveldb::kMajorVersion == 1 && leveldb::kMinorVersion >= 16)) {
+ // LevelDB versions before 1.16 consider short writes to be corruption. Only trigger error
+ // on corruption in later versions.
+ options.paranoid_checks = true;
+ }
+ return options;
+}
+
+CDBWrapper::CDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate)
+{
+ penv = NULL;
+ readoptions.verify_checksums = true;
+ iteroptions.verify_checksums = true;
+ iteroptions.fill_cache = false;
+ syncoptions.sync = true;
+ options = GetOptions(nCacheSize);
+ options.create_if_missing = true;
+ if (fMemory) {
+ penv = leveldb::NewMemEnv(leveldb::Env::Default());
+ options.env = penv;
+ } else {
+ if (fWipe) {
+ LogPrintf("Wiping LevelDB in %s\n", path.string());
+ leveldb::Status result = leveldb::DestroyDB(path.string(), options);
+ HandleError(result);
+ }
+ TryCreateDirectory(path);
+ LogPrintf("Opening LevelDB in %s\n", path.string());
+ }
+ leveldb::Status status = leveldb::DB::Open(options, path.string(), &pdb);
+ HandleError(status);
+ LogPrintf("Opened LevelDB successfully\n");
+
+ // The base-case obfuscation key, which is a noop.
+ obfuscate_key = std::vector<unsigned char>(OBFUSCATE_KEY_NUM_BYTES, '\000');
+
+ bool key_exists = Read(OBFUSCATE_KEY_KEY, obfuscate_key);
+
+ if (!key_exists && obfuscate && IsEmpty()) {
+ // Initialize non-degenerate obfuscation if it won't upset
+ // existing, non-obfuscated data.
+ std::vector<unsigned char> new_key = CreateObfuscateKey();
+
+ // Write `new_key` so we don't obfuscate the key with itself
+ Write(OBFUSCATE_KEY_KEY, new_key);
+ obfuscate_key = new_key;
+
+ LogPrintf("Wrote new obfuscate key for %s: %s\n", path.string(), GetObfuscateKeyHex());
+ }
+
+ LogPrintf("Using obfuscation key for %s: %s\n", path.string(), GetObfuscateKeyHex());
+}
+
+CDBWrapper::~CDBWrapper()
+{
+ delete pdb;
+ pdb = NULL;
+ delete options.filter_policy;
+ options.filter_policy = NULL;
+ delete options.block_cache;
+ options.block_cache = NULL;
+ delete penv;
+ options.env = NULL;
+}
+
+bool CDBWrapper::WriteBatch(CDBBatch& batch, bool fSync) throw(dbwrapper_error)
+{
+ leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch);
+ HandleError(status);
+ return true;
+}
+
+// Prefixed with null character to avoid collisions with other keys
+//
+// We must use a string constructor which specifies length so that we copy
+// past the null-terminator.
+const std::string CDBWrapper::OBFUSCATE_KEY_KEY("\000obfuscate_key", 14);
+
+const unsigned int CDBWrapper::OBFUSCATE_KEY_NUM_BYTES = 8;
+
+/**
+ * Returns a string (consisting of 8 random bytes) suitable for use as an
+ * obfuscating XOR key.
+ */
+std::vector<unsigned char> CDBWrapper::CreateObfuscateKey() const
+{
+ unsigned char buff[OBFUSCATE_KEY_NUM_BYTES];
+ GetRandBytes(buff, OBFUSCATE_KEY_NUM_BYTES);
+ return std::vector<unsigned char>(&buff[0], &buff[OBFUSCATE_KEY_NUM_BYTES]);
+
+}
+
+bool CDBWrapper::IsEmpty()
+{
+ boost::scoped_ptr<CDBIterator> it(NewIterator());
+ it->SeekToFirst();
+ return !(it->Valid());
+}
+
+const std::vector<unsigned char>& CDBWrapper::GetObfuscateKey() const
+{
+ return obfuscate_key;
+}
+
+std::string CDBWrapper::GetObfuscateKeyHex() const
+{
+ return HexStr(obfuscate_key);
+}
+
+CDBIterator::~CDBIterator() { delete piter; }
+bool CDBIterator::Valid() { return piter->Valid(); }
+void CDBIterator::SeekToFirst() { piter->SeekToFirst(); }
+void CDBIterator::Next() { piter->Next(); }
diff --git a/src/dbwrapper.h b/src/dbwrapper.h
new file mode 100644
index 0000000000..1d31ab8ae5
--- /dev/null
+++ b/src/dbwrapper.h
@@ -0,0 +1,280 @@
+// Copyright (c) 2012-2014 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_DBWRAPPER_H
+#define BITCOIN_DBWRAPPER_H
+
+#include "clientversion.h"
+#include "serialize.h"
+#include "streams.h"
+#include "util.h"
+#include "utilstrencodings.h"
+#include "version.h"
+
+#include <boost/filesystem/path.hpp>
+
+#include <leveldb/db.h>
+#include <leveldb/write_batch.h>
+
+class dbwrapper_error : public std::runtime_error
+{
+public:
+ dbwrapper_error(const std::string& msg) : std::runtime_error(msg) {}
+};
+
+void HandleError(const leveldb::Status& status) throw(dbwrapper_error);
+
+/** Batch of changes queued to be written to a CDBWrapper */
+class CDBBatch
+{
+ friend class CDBWrapper;
+
+private:
+ leveldb::WriteBatch batch;
+ const std::vector<unsigned char> *obfuscate_key;
+
+public:
+ /**
+ * @param[in] obfuscate_key If passed, XOR data with this key.
+ */
+ CDBBatch(const std::vector<unsigned char> *obfuscate_key) : obfuscate_key(obfuscate_key) { };
+
+ template <typename K, typename V>
+ void Write(const K& key, const V& value)
+ {
+ CDataStream ssKey(SER_DISK, CLIENT_VERSION);
+ ssKey.reserve(ssKey.GetSerializeSize(key));
+ ssKey << key;
+ leveldb::Slice slKey(&ssKey[0], ssKey.size());
+
+ CDataStream ssValue(SER_DISK, CLIENT_VERSION);
+ ssValue.reserve(ssValue.GetSerializeSize(value));
+ ssValue << value;
+ ssValue.Xor(*obfuscate_key);
+ leveldb::Slice slValue(&ssValue[0], ssValue.size());
+
+ batch.Put(slKey, slValue);
+ }
+
+ template <typename K>
+ void Erase(const K& key)
+ {
+ CDataStream ssKey(SER_DISK, CLIENT_VERSION);
+ ssKey.reserve(ssKey.GetSerializeSize(key));
+ ssKey << key;
+ leveldb::Slice slKey(&ssKey[0], ssKey.size());
+
+ batch.Delete(slKey);
+ }
+};
+
+class CDBIterator
+{
+private:
+ leveldb::Iterator *piter;
+ const std::vector<unsigned char> *obfuscate_key;
+
+public:
+
+ /**
+ * @param[in] piterIn The original leveldb iterator.
+ * @param[in] obfuscate_key If passed, XOR data with this key.
+ */
+ CDBIterator(leveldb::Iterator *piterIn, const std::vector<unsigned char>* obfuscate_key) :
+ piter(piterIn), obfuscate_key(obfuscate_key) { };
+ ~CDBIterator();
+
+ bool Valid();
+
+ void SeekToFirst();
+
+ template<typename K> void Seek(const K& key) {
+ CDataStream ssKey(SER_DISK, CLIENT_VERSION);
+ ssKey.reserve(ssKey.GetSerializeSize(key));
+ ssKey << key;
+ leveldb::Slice slKey(&ssKey[0], ssKey.size());
+ piter->Seek(slKey);
+ }
+
+ void Next();
+
+ template<typename K> bool GetKey(K& key) {
+ leveldb::Slice slKey = piter->key();
+ try {
+ CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION);
+ ssKey >> key;
+ } catch (const std::exception&) {
+ return false;
+ }
+ return true;
+ }
+
+ unsigned int GetKeySize() {
+ return piter->key().size();
+ }
+
+ template<typename V> bool GetValue(V& value) {
+ leveldb::Slice slValue = piter->value();
+ try {
+ CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
+ ssValue.Xor(*obfuscate_key);
+ ssValue >> value;
+ } catch (const std::exception&) {
+ return false;
+ }
+ return true;
+ }
+
+ unsigned int GetValueSize() {
+ return piter->value().size();
+ }
+
+};
+
+class CDBWrapper
+{
+private:
+ //! custom environment this database is using (may be NULL in case of default environment)
+ leveldb::Env* penv;
+
+ //! database options used
+ leveldb::Options options;
+
+ //! options used when reading from the database
+ leveldb::ReadOptions readoptions;
+
+ //! options used when iterating over values of the database
+ leveldb::ReadOptions iteroptions;
+
+ //! options used when writing to the database
+ leveldb::WriteOptions writeoptions;
+
+ //! options used when sync writing to the database
+ leveldb::WriteOptions syncoptions;
+
+ //! the database itself
+ leveldb::DB* pdb;
+
+ //! a key used for optional XOR-obfuscation of the database
+ std::vector<unsigned char> obfuscate_key;
+
+ //! the key under which the obfuscation key is stored
+ static const std::string OBFUSCATE_KEY_KEY;
+
+ //! the length of the obfuscate key in number of bytes
+ static const unsigned int OBFUSCATE_KEY_NUM_BYTES;
+
+ std::vector<unsigned char> CreateObfuscateKey() const;
+
+public:
+ /**
+ * @param[in] path Location in the filesystem where leveldb data will be stored.
+ * @param[in] nCacheSize Configures various leveldb cache settings.
+ * @param[in] fMemory If true, use leveldb's memory environment.
+ * @param[in] fWipe If true, remove all existing data.
+ * @param[in] obfuscate If true, store data obfuscated via simple XOR. If false, XOR
+ * with a zero'd byte array.
+ */
+ CDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory = false, bool fWipe = false, bool obfuscate = false);
+ ~CDBWrapper();
+
+ template <typename K, typename V>
+ bool Read(const K& key, V& value) const throw(dbwrapper_error)
+ {
+ CDataStream ssKey(SER_DISK, CLIENT_VERSION);
+ ssKey.reserve(ssKey.GetSerializeSize(key));
+ ssKey << key;
+ leveldb::Slice slKey(&ssKey[0], ssKey.size());
+
+ std::string strValue;
+ leveldb::Status status = pdb->Get(readoptions, slKey, &strValue);
+ if (!status.ok()) {
+ if (status.IsNotFound())
+ return false;
+ LogPrintf("LevelDB read failure: %s\n", status.ToString());
+ HandleError(status);
+ }
+ try {
+ CDataStream ssValue(strValue.data(), strValue.data() + strValue.size(), SER_DISK, CLIENT_VERSION);
+ ssValue.Xor(obfuscate_key);
+ ssValue >> value;
+ } catch (const std::exception&) {
+ return false;
+ }
+ return true;
+ }
+
+ template <typename K, typename V>
+ bool Write(const K& key, const V& value, bool fSync = false) throw(dbwrapper_error)
+ {
+ CDBBatch batch(&obfuscate_key);
+ batch.Write(key, value);
+ return WriteBatch(batch, fSync);
+ }
+
+ template <typename K>
+ bool Exists(const K& key) const throw(dbwrapper_error)
+ {
+ CDataStream ssKey(SER_DISK, CLIENT_VERSION);
+ ssKey.reserve(ssKey.GetSerializeSize(key));
+ ssKey << key;
+ leveldb::Slice slKey(&ssKey[0], ssKey.size());
+
+ std::string strValue;
+ leveldb::Status status = pdb->Get(readoptions, slKey, &strValue);
+ if (!status.ok()) {
+ if (status.IsNotFound())
+ return false;
+ LogPrintf("LevelDB read failure: %s\n", status.ToString());
+ HandleError(status);
+ }
+ return true;
+ }
+
+ template <typename K>
+ bool Erase(const K& key, bool fSync = false) throw(dbwrapper_error)
+ {
+ CDBBatch batch(&obfuscate_key);
+ batch.Erase(key);
+ return WriteBatch(batch, fSync);
+ }
+
+ bool WriteBatch(CDBBatch& batch, bool fSync = false) throw(dbwrapper_error);
+
+ // not available for LevelDB; provide for compatibility with BDB
+ bool Flush()
+ {
+ return true;
+ }
+
+ bool Sync() throw(dbwrapper_error)
+ {
+ CDBBatch batch(&obfuscate_key);
+ return WriteBatch(batch, true);
+ }
+
+ CDBIterator *NewIterator()
+ {
+ return new CDBIterator(pdb->NewIterator(iteroptions), &obfuscate_key);
+ }
+
+ /**
+ * Return true if the database managed by this class contains no entries.
+ */
+ bool IsEmpty();
+
+ /**
+ * Accessor for obfuscate_key.
+ */
+ const std::vector<unsigned char>& GetObfuscateKey() const;
+
+ /**
+ * Return the obfuscate_key as a hex-formatted string.
+ */
+ std::string GetObfuscateKeyHex() const;
+
+};
+
+#endif // BITCOIN_DBWRAPPER_H
+
diff --git a/src/httpserver.cpp b/src/httpserver.cpp
index 0a7f903e9f..8698abb900 100644
--- a/src/httpserver.cpp
+++ b/src/httpserver.cpp
@@ -38,6 +38,9 @@
#include <boost/foreach.hpp>
#include <boost/scoped_ptr.hpp>
+/** Maximum size of http request (request line + headers) */
+static const size_t MAX_HEADERS_SIZE = 8192;
+
/** HTTP request work item */
class HTTPWorkItem : public HTTPClosure
{
@@ -414,6 +417,7 @@ bool InitHTTPServer()
}
evhttp_set_timeout(http, GetArg("-rpcservertimeout", DEFAULT_HTTP_SERVER_TIMEOUT));
+ evhttp_set_max_headers_size(http, MAX_HEADERS_SIZE);
evhttp_set_max_body_size(http, MAX_SIZE);
evhttp_set_gencb(http, http_request_cb, NULL);
diff --git a/src/init.cpp b/src/init.cpp
index 3c8a9a08ff..d0f73a632b 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -320,6 +320,8 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-dbcache=<n>", strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache));
strUsage += HelpMessageOpt("-loadblock=<file>", _("Imports blocks from external blk000??.dat file") + " " + _("on startup"));
strUsage += HelpMessageOpt("-maxorphantx=<n>", strprintf(_("Keep at most <n> unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS));
+ strUsage += HelpMessageOpt("-maxmempool=<n>", strprintf(_("Keep the transaction memory pool below <n> megabytes (default: %u)"), DEFAULT_MAX_MEMPOOL_SIZE));
+ strUsage += HelpMessageOpt("-mempoolexpiry=<n>", strprintf(_("Do not keep transactions in the mempool longer than <n> hours (default: %u)"), DEFAULT_MEMPOOL_EXPIRY));
strUsage += HelpMessageOpt("-par=<n>", strprintf(_("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)"),
-GetNumCores(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS));
#ifndef WIN32
@@ -367,6 +369,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:"));
@@ -432,6 +435,7 @@ std::string HelpMessage(HelpMessageMode mode)
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));
@@ -443,11 +447,10 @@ std::string HelpMessage(HelpMessageMode mode)
{
strUsage += HelpMessageOpt("-printpriority", strprintf("Log transaction priority and fee per kB when mining blocks (default: %u)", 0));
strUsage += HelpMessageOpt("-privdb", strprintf("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)", 1));
- strUsage += HelpMessageOpt("-regtest", "Enter regression test mode, which uses a special chain in which blocks can be solved instantly. "
- "This is intended for regression testing tools and app development.");
}
strUsage += HelpMessageOpt("-shrinkdebugfile", _("Shrink debug.log file on client startup (default: 1 when no -debug)"));
- strUsage += HelpMessageOpt("-testnet", _("Use the test network"));
+
+ AppendParamsHelpMessages(strUsage, showDebug);
strUsage += HelpMessageGroup(_("Node relay options:"));
if (showDebug)
@@ -693,13 +696,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);
@@ -730,6 +733,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");
@@ -829,22 +833,31 @@ 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);
+ // -mempoollimit limits
+ 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(_("-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);
if (nScriptCheckThreads <= 0)
@@ -912,7 +925,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)
{
@@ -926,7 +939,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)
{
@@ -1053,12 +1066,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));
}
@@ -1171,6 +1184,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
RegisterValidationInterface(pzmqNotificationInterface);
}
#endif
+ if (mapArgs.count("-maxuploadtarget")) {
+ CNode::SetMaxOutboundTarget(GetArg("-maxuploadtarget", 0)*1024*1024);
+ }
// ********************************************************* Step 7: load block chain
@@ -1379,9 +1395,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";
@@ -1502,10 +1517,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
// if pruning, unset the service bit and perform the initial blockstore prune
// after any wallet rescanning has taken place.
if (fPruneMode) {
- uiInterface.InitMessage(_("Pruning blockstore..."));
LogPrintf("Unsetting NODE_NETWORK on prune mode\n");
nLocalServices &= ~NODE_NETWORK;
if (!fReindex) {
+ uiInterface.InitMessage(_("Pruning blockstore..."));
PruneAndFlush();
}
}
diff --git a/src/leveldbwrapper.cpp b/src/leveldbwrapper.cpp
deleted file mode 100644
index 26cacf95ae..0000000000
--- a/src/leveldbwrapper.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright (c) 2012-2014 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 "leveldbwrapper.h"
-
-#include "util.h"
-
-#include <boost/filesystem.hpp>
-
-#include <leveldb/cache.h>
-#include <leveldb/env.h>
-#include <leveldb/filter_policy.h>
-#include <memenv.h>
-
-void HandleError(const leveldb::Status& status) throw(leveldb_error)
-{
- if (status.ok())
- return;
- LogPrintf("%s\n", status.ToString());
- if (status.IsCorruption())
- throw leveldb_error("Database corrupted");
- if (status.IsIOError())
- throw leveldb_error("Database I/O error");
- if (status.IsNotFound())
- throw leveldb_error("Database entry missing");
- throw leveldb_error("Unknown database error");
-}
-
-static leveldb::Options GetOptions(size_t nCacheSize)
-{
- leveldb::Options options;
- options.block_cache = leveldb::NewLRUCache(nCacheSize / 2);
- options.write_buffer_size = nCacheSize / 4; // up to two write buffers may be held in memory simultaneously
- options.filter_policy = leveldb::NewBloomFilterPolicy(10);
- options.compression = leveldb::kNoCompression;
- options.max_open_files = 64;
- if (leveldb::kMajorVersion > 1 || (leveldb::kMajorVersion == 1 && leveldb::kMinorVersion >= 16)) {
- // LevelDB versions before 1.16 consider short writes to be corruption. Only trigger error
- // on corruption in later versions.
- options.paranoid_checks = true;
- }
- return options;
-}
-
-CLevelDBWrapper::CLevelDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory, bool fWipe)
-{
- penv = NULL;
- readoptions.verify_checksums = true;
- iteroptions.verify_checksums = true;
- iteroptions.fill_cache = false;
- syncoptions.sync = true;
- options = GetOptions(nCacheSize);
- options.create_if_missing = true;
- if (fMemory) {
- penv = leveldb::NewMemEnv(leveldb::Env::Default());
- options.env = penv;
- } else {
- if (fWipe) {
- LogPrintf("Wiping LevelDB in %s\n", path.string());
- leveldb::Status result = leveldb::DestroyDB(path.string(), options);
- HandleError(result);
- }
- TryCreateDirectory(path);
- LogPrintf("Opening LevelDB in %s\n", path.string());
- }
- leveldb::Status status = leveldb::DB::Open(options, path.string(), &pdb);
- HandleError(status);
- LogPrintf("Opened LevelDB successfully\n");
-}
-
-CLevelDBWrapper::~CLevelDBWrapper()
-{
- delete pdb;
- pdb = NULL;
- delete options.filter_policy;
- options.filter_policy = NULL;
- delete options.block_cache;
- options.block_cache = NULL;
- delete penv;
- options.env = NULL;
-}
-
-bool CLevelDBWrapper::WriteBatch(CLevelDBBatch& batch, bool fSync) throw(leveldb_error)
-{
- leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch);
- HandleError(status);
- return true;
-}
diff --git a/src/leveldbwrapper.h b/src/leveldbwrapper.h
deleted file mode 100644
index c65e842704..0000000000
--- a/src/leveldbwrapper.h
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright (c) 2012-2014 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_LEVELDBWRAPPER_H
-#define BITCOIN_LEVELDBWRAPPER_H
-
-#include "clientversion.h"
-#include "serialize.h"
-#include "streams.h"
-#include "util.h"
-#include "version.h"
-
-#include <boost/filesystem/path.hpp>
-
-#include <leveldb/db.h>
-#include <leveldb/write_batch.h>
-
-class leveldb_error : public std::runtime_error
-{
-public:
- leveldb_error(const std::string& msg) : std::runtime_error(msg) {}
-};
-
-void HandleError(const leveldb::Status& status) throw(leveldb_error);
-
-/** Batch of changes queued to be written to a CLevelDBWrapper */
-class CLevelDBBatch
-{
- friend class CLevelDBWrapper;
-
-private:
- leveldb::WriteBatch batch;
-
-public:
- template <typename K, typename V>
- void Write(const K& key, const V& value)
- {
- CDataStream ssKey(SER_DISK, CLIENT_VERSION);
- ssKey.reserve(ssKey.GetSerializeSize(key));
- ssKey << key;
- leveldb::Slice slKey(&ssKey[0], ssKey.size());
-
- CDataStream ssValue(SER_DISK, CLIENT_VERSION);
- ssValue.reserve(ssValue.GetSerializeSize(value));
- ssValue << value;
- leveldb::Slice slValue(&ssValue[0], ssValue.size());
-
- batch.Put(slKey, slValue);
- }
-
- template <typename K>
- void Erase(const K& key)
- {
- CDataStream ssKey(SER_DISK, CLIENT_VERSION);
- ssKey.reserve(ssKey.GetSerializeSize(key));
- ssKey << key;
- leveldb::Slice slKey(&ssKey[0], ssKey.size());
-
- batch.Delete(slKey);
- }
-};
-
-class CLevelDBWrapper
-{
-private:
- //! custom environment this database is using (may be NULL in case of default environment)
- leveldb::Env* penv;
-
- //! database options used
- leveldb::Options options;
-
- //! options used when reading from the database
- leveldb::ReadOptions readoptions;
-
- //! options used when iterating over values of the database
- leveldb::ReadOptions iteroptions;
-
- //! options used when writing to the database
- leveldb::WriteOptions writeoptions;
-
- //! options used when sync writing to the database
- leveldb::WriteOptions syncoptions;
-
- //! the database itself
- leveldb::DB* pdb;
-
-public:
- CLevelDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory = false, bool fWipe = false);
- ~CLevelDBWrapper();
-
- template <typename K, typename V>
- bool Read(const K& key, V& value) const throw(leveldb_error)
- {
- CDataStream ssKey(SER_DISK, CLIENT_VERSION);
- ssKey.reserve(ssKey.GetSerializeSize(key));
- ssKey << key;
- leveldb::Slice slKey(&ssKey[0], ssKey.size());
-
- std::string strValue;
- leveldb::Status status = pdb->Get(readoptions, slKey, &strValue);
- if (!status.ok()) {
- if (status.IsNotFound())
- return false;
- LogPrintf("LevelDB read failure: %s\n", status.ToString());
- HandleError(status);
- }
- try {
- CDataStream ssValue(strValue.data(), strValue.data() + strValue.size(), SER_DISK, CLIENT_VERSION);
- ssValue >> value;
- } catch (const std::exception&) {
- return false;
- }
- return true;
- }
-
- template <typename K, typename V>
- bool Write(const K& key, const V& value, bool fSync = false) throw(leveldb_error)
- {
- CLevelDBBatch batch;
- batch.Write(key, value);
- return WriteBatch(batch, fSync);
- }
-
- template <typename K>
- bool Exists(const K& key) const throw(leveldb_error)
- {
- CDataStream ssKey(SER_DISK, CLIENT_VERSION);
- ssKey.reserve(ssKey.GetSerializeSize(key));
- ssKey << key;
- leveldb::Slice slKey(&ssKey[0], ssKey.size());
-
- std::string strValue;
- leveldb::Status status = pdb->Get(readoptions, slKey, &strValue);
- if (!status.ok()) {
- if (status.IsNotFound())
- return false;
- LogPrintf("LevelDB read failure: %s\n", status.ToString());
- HandleError(status);
- }
- return true;
- }
-
- template <typename K>
- bool Erase(const K& key, bool fSync = false) throw(leveldb_error)
- {
- CLevelDBBatch batch;
- batch.Erase(key);
- return WriteBatch(batch, fSync);
- }
-
- bool WriteBatch(CLevelDBBatch& batch, bool fSync = false) throw(leveldb_error);
-
- // not available for LevelDB; provide for compatibility with BDB
- bool Flush()
- {
- return true;
- }
-
- bool Sync() throw(leveldb_error)
- {
- CLevelDBBatch batch;
- return WriteBatch(batch, true);
- }
-
- // not exactly clean encapsulation, but it's easiest for now
- leveldb::Iterator* NewIterator()
- {
- return pdb->NewIterator(iteroptions);
- }
-};
-
-#endif // BITCOIN_LEVELDBWRAPPER_H
diff --git a/src/main.cpp b/src/main.cpp
index 5cfb05b0d2..26a22ae6fd 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -740,17 +740,14 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
return true;
}
-CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree)
+CAmount GetMinRelayFee(const CTransaction& tx, const CTxMemPool& pool, unsigned int nBytes, bool fAllowFree)
{
- {
- LOCK(mempool.cs);
- uint256 hash = tx.GetHash();
- double dPriorityDelta = 0;
- CAmount nFeeDelta = 0;
- mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta);
- if (dPriorityDelta > 0 || nFeeDelta > 0)
- return 0;
- }
+ uint256 hash = tx.GetHash();
+ double dPriorityDelta = 0;
+ CAmount nFeeDelta = 0;
+ pool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta);
+ if (dPriorityDelta > 0 || nFeeDelta > 0)
+ return 0;
CAmount nMinFee = ::minRelayTxFee.GetFee(nBytes);
@@ -779,7 +776,7 @@ static std::string FormatStateMessage(const CValidationState &state)
}
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
- bool* pfMissingInputs, bool fRejectAbsurdFee)
+ bool* pfMissingInputs, bool fOverrideMempoolLimit, bool fRejectAbsurdFee)
{
AssertLockHeld(cs_main);
if (pfMissingInputs)
@@ -879,17 +876,20 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
CAmount nFees = nValueIn-nValueOut;
double dPriority = view.GetPriority(tx, chainActive.Height());
- CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), mempool.HasNoInputsOf(tx));
+ CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), pool.HasNoInputsOf(tx));
unsigned int nSize = entry.GetTxSize();
// Don't accept it if it can't get into a block
- CAmount txMinFee = GetMinRelayFee(tx, nSize, true);
+ CAmount txMinFee = GetMinRelayFee(tx, pool, nSize, true);
if (fLimitFree && nFees < txMinFee)
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "insufficient fee", false,
strprintf("%d < %d", nFees, txMinFee));
- // Require that free transactions have sufficient priority to be mined in the next block.
- if (GetBoolArg("-relaypriority", true) && nFees < ::minRelayTxFee.GetFee(nSize) && !AllowFree(view.GetPriority(tx, chainActive.Height() + 1))) {
+ CAmount mempoolRejectFee = pool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFee(nSize);
+ if (mempoolRejectFee > 0 && nFees < mempoolRejectFee) {
+ return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "mempool min fee not met", false, strprintf("%d < %d", nFees, mempoolRejectFee));
+ } else if (GetBoolArg("-relaypriority", true) && nFees < ::minRelayTxFee.GetFee(nSize) && !AllowFree(view.GetPriority(tx, chainActive.Height() + 1))) {
+ // Require that free transactions have sufficient priority to be mined in the next block.
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "insufficient priority");
}
@@ -954,6 +954,17 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
// Store transaction in memory
pool.addUnchecked(hash, entry, setAncestors, !IsInitialBlockDownload());
+
+ // trim mempool and check if tx was trimmed
+ if (!fOverrideMempoolLimit) {
+ int expired = pool.Expire(GetTime() - GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60);
+ if (expired != 0)
+ LogPrint("mempool", "Expired %i transactions from the memory pool\n", expired);
+
+ pool.TrimToSize(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000);
+ if (!pool.exists(tx.GetHash()))
+ return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "mempool full");
+ }
}
SyncWithWallets(tx, NULL);
@@ -1740,11 +1751,18 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
unsigned int flags = fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE;
- // Start enforcing the DERSIG (BIP66) rules, for block.nVersion=3 blocks, when 75% of the network has upgraded:
+ // Start enforcing the DERSIG (BIP66) rules, for block.nVersion=3 blocks,
+ // when 75% of the network has upgraded:
if (block.nVersion >= 3 && IsSuperMajority(3, pindex->pprev, chainparams.GetConsensus().nMajorityEnforceBlockUpgrade, chainparams.GetConsensus())) {
flags |= SCRIPT_VERIFY_DERSIG;
}
+ // Start enforcing CHECKLOCKTIMEVERIFY, (BIP65) for block.nVersion=4
+ // blocks, when 75% of the network has upgraded:
+ if (block.nVersion >= 4 && IsSuperMajority(4, pindex->pprev, chainparams.GetConsensus().nMajorityEnforceBlockUpgrade, chainparams.GetConsensus())) {
+ flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
+ }
+
CBlockUndo blockundo;
CCheckQueueControl<CScriptCheck> control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : NULL);
@@ -1881,7 +1899,7 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) {
std::set<int> setFilesToPrune;
bool fFlushForPrune = false;
try {
- if (fPruneMode && fCheckForPruning) {
+ if (fPruneMode && fCheckForPruning && !fReindex) {
FindFilesToPrune(setFilesToPrune);
fCheckForPruning = false;
if (!setFilesToPrune.empty()) {
@@ -2020,7 +2038,7 @@ void static UpdateTip(CBlockIndex *pindexNew) {
}
}
-/** Disconnect chainActive's tip. */
+/** Disconnect chainActive's tip. You want to manually re-limit mempool size after this */
bool static DisconnectTip(CValidationState &state) {
CBlockIndex *pindexDelete = chainActive.Tip();
assert(pindexDelete);
@@ -2047,7 +2065,7 @@ bool static DisconnectTip(CValidationState &state) {
// ignore validation errors in resurrected transactions
list<CTransaction> removed;
CValidationState stateDummy;
- if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL)) {
+ if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL, true)) {
mempool.remove(tx, removed, true);
} else if (mempool.exists(tx.GetHash())) {
vHashUpdate.push_back(tx.GetHash());
@@ -2220,9 +2238,11 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
const CBlockIndex *pindexFork = chainActive.FindFork(pindexMostWork);
// Disconnect active blocks which are no longer in the best chain.
+ bool fBlocksDisconnected = false;
while (chainActive.Tip() && chainActive.Tip() != pindexFork) {
if (!DisconnectTip(state))
return false;
+ fBlocksDisconnected = true;
}
// Build list of new blocks to connect.
@@ -2268,6 +2288,9 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
}
}
+ if (fBlocksDisconnected)
+ mempool.TrimToSize(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000);
+
// Callbacks/notifications for a new best chain.
if (fInvalidFound)
CheckForkWarningConditionsOnNewFork(vpindexToConnect.back());
@@ -2354,6 +2377,8 @@ bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) {
}
}
+ mempool.TrimToSize(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000);
+
// The resulting new best tip may not be in setBlockIndexCandidates anymore, so
// add it again.
BlockMap::iterator it = mapBlockIndex.begin();
@@ -2684,6 +2709,11 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
return state.Invalid(error("%s : rejected nVersion=2 block", __func__),
REJECT_OBSOLETE, "bad-version");
+ // Reject block.nVersion=3 blocks when 95% (75% on testnet) of the network has upgraded:
+ if (block.nVersion < 4 && IsSuperMajority(4, pindexPrev, consensusParams.nMajorityRejectBlockOutdated, consensusParams))
+ return state.Invalid(error("%s : rejected nVersion=3 block", __func__),
+ REJECT_OBSOLETE, "bad-version");
+
return true;
}
@@ -3775,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))
@@ -4290,10 +4330,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
RelayTransaction(tx);
vWorkQueue.push_back(inv.hash);
- LogPrint("mempool", "AcceptToMemoryPool: peer=%d: accepted %s (poolsz %u)\n",
+ LogPrint("mempool", "AcceptToMemoryPool: peer=%d: accepted %s (poolsz %u txn, %u kB)\n",
pfrom->id,
tx.GetHash().ToString(),
- mempool.size());
+ mempool.size(), mempool.DynamicMemoryUsage() / 1000);
// Recursively process any orphan transactions that depended on this one
set<NodeId> setMisbehaving;
@@ -4955,7 +4995,16 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
if ((nSyncStarted == 0 && fFetch) || pindexBestHeader->GetBlockTime() > GetAdjustedTime() - 24 * 60 * 60) {
state.fSyncStarted = true;
nSyncStarted++;
- CBlockIndex *pindexStart = pindexBestHeader->pprev ? pindexBestHeader->pprev : pindexBestHeader;
+ const CBlockIndex *pindexStart = pindexBestHeader;
+ /* If possible, start at the block preceding the currently
+ best known header. This ensures that we always get a
+ non-empty list of headers back as long as the peer
+ is up-to-date. With a non-empty response, we can initialise
+ the peer's known best block. This wouldn't be possible
+ if we requested starting at pindexBestHeader and
+ got back an empty response. */
+ if (pindexStart->pprev)
+ pindexStart = pindexStart->pprev;
LogPrint("net", "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->nHeight, pto->id, pto->nStartingHeight);
pto->PushMessage("getheaders", chainActive.GetLocator(pindexStart), uint256());
}
diff --git a/src/main.h b/src/main.h
index 7fe004c3a1..c3874be663 100644
--- a/src/main.h
+++ b/src/main.h
@@ -51,6 +51,10 @@ static const unsigned int DEFAULT_ANCESTOR_SIZE_LIMIT = 900;
static const unsigned int DEFAULT_DESCENDANT_LIMIT = 1000;
/** Default for -limitdescendantsize, maximum kilobytes of in-mempool descendants */
static const unsigned int DEFAULT_DESCENDANT_SIZE_LIMIT = 2500;
+/** Default for -maxmempool, maximum megabytes of mempool memory usage */
+static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE = 300;
+/** Default for -mempoolexpiry, expiration time for mempool transactions in hours */
+static const unsigned int DEFAULT_MEMPOOL_EXPIRY = 72;
/** The maximum size of a blk?????.dat file (since 0.8) */
static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB
/** The pre-allocation chunk size for blk?????.dat files (since 0.8) */
@@ -228,7 +232,7 @@ void PruneAndFlush();
/** (try to) add transaction to memory pool **/
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
- bool* pfMissingInputs, bool fRejectAbsurdFee=false);
+ bool* pfMissingInputs, bool fOverrideMempoolLimit=false, bool fRejectAbsurdFee=false);
struct CNodeStateStats {
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/net.cpp b/src/net.cpp
index 87c4f0af0a..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);
@@ -963,6 +969,15 @@ static void AcceptConnection(const ListenSocket& hListenSocket) {
return;
}
+ // According to the internet TCP_NODELAY is not carried into accepted sockets
+ // on all platforms. Set it again here just to be sure.
+ int set = 1;
+#ifdef WIN32
+ setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&set, sizeof(int));
+#else
+ setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (void*)&set, sizeof(int));
+#endif
+
if (CNode::IsBanned(addr) && !whitelisted)
{
LogPrintf("connection from %s dropped (banned)\n", addr.ToString());
@@ -1790,8 +1805,11 @@ bool BindListenPort(const CService &addrBind, string& strError, bool fWhiteliste
// Allow binding if the port is still in TIME_WAIT state after
// the program was closed and restarted.
setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
+ // Disable Nagle's algorithm
+ setsockopt(hListenSocket, IPPROTO_TCP, TCP_NODELAY, (void*)&nOne, sizeof(int));
#else
setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&nOne, sizeof(int));
+ setsockopt(hListenSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&nOne, sizeof(int));
#endif
// Set to non-blocking, incoming connections will also inherit this
@@ -2071,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/netbase.cpp b/src/netbase.cpp
index c3d56d9184..f5316965ce 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -444,12 +444,19 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
if (hSocket == INVALID_SOCKET)
return false;
-#ifdef SO_NOSIGPIPE
int set = 1;
+#ifdef SO_NOSIGPIPE
// Different way of disabling SIGPIPE on BSD
setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
#endif
+ //Disable Nagle's algorithm
+#ifdef WIN32
+ setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&set, sizeof(int));
+#else
+ setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (void*)&set, sizeof(int));
+#endif
+
// Set to non-blocking
if (!SetSocketNonBlocking(hSocket, true))
return error("ConnectSocketDirectly: Setting socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError()));
diff --git a/src/policy/policy.h b/src/policy/policy.h
index 1551aecde8..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"
@@ -37,7 +37,8 @@ static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY
SCRIPT_VERIFY_NULLDUMMY |
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS |
SCRIPT_VERIFY_CLEANSTACK |
- SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
+ SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY |
+ SCRIPT_VERIFY_LOW_S;
/** For convenience, standard but not mandatory verify flags. */
static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS;
@@ -55,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/pow.cpp b/src/pow.cpp
index bb53ad204b..5ace3fbc9b 100644
--- a/src/pow.cpp
+++ b/src/pow.cpp
@@ -52,6 +52,9 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params)
{
+ if (params.fPowNoRetargeting)
+ return pindexLast->nBits;
+
// Limit adjustment step
int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime;
LogPrintf(" nActualTimespan = %d before bounds\n", nActualTimespan);
diff --git a/src/primitives/block.h b/src/primitives/block.h
index 86106098f5..54731ff557 100644
--- a/src/primitives/block.h
+++ b/src/primitives/block.h
@@ -21,7 +21,7 @@ class CBlockHeader
{
public:
// header
- static const int32_t CURRENT_VERSION=3;
+ static const int32_t CURRENT_VERSION=4;
int32_t nVersion;
uint256 hashPrevBlock;
uint256 hashMerkleRoot;
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index ea7f86d18e..bda8acff15 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -563,7 +563,7 @@ int main(int argc, char *argv[])
// Show help message immediately after parsing command-line options (for "-lang") and setting locale,
// but before showing splash screen.
- if (mapArgs.count("-?") || mapArgs.count("-help") || mapArgs.count("-version"))
+ if (mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help") || mapArgs.count("-version"))
{
HelpMessageDialog help(NULL, mapArgs.count("-version"));
help.showOrPrint();
@@ -597,8 +597,10 @@ int main(int argc, char *argv[])
// - Needs to be done before createOptionsModel
// Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
- if (!SelectParamsFromCommandLine()) {
- QMessageBox::critical(0, QObject::tr("Bitcoin Core"), QObject::tr("Error: Invalid combination of -regtest and -testnet."));
+ try {
+ SelectParams(ChainNameFromCommandLine());
+ } catch(std::exception &e) {
+ QMessageBox::critical(0, QObject::tr("Bitcoin Core"), QObject::tr("Error: %1").arg(e.what()));
return 1;
}
#ifdef ENABLE_WALLET
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/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/rpcblockchain.cpp b/src/rpcblockchain.cpp
index 58f49f9f56..146eb3905a 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -648,6 +648,7 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp)
UniValue softforks(UniValue::VARR);
softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams));
softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams));
+ softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams));
obj.push_back(Pair("softforks", softforks));
if (fPruneMode)
@@ -772,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/rpcclient.cpp b/src/rpcclient.cpp
index 4064c2fee3..343b6234d4 100644
--- a/src/rpcclient.cpp
+++ b/src/rpcclient.cpp
@@ -76,6 +76,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "getrawtransaction", 1 },
{ "createrawtransaction", 0 },
{ "createrawtransaction", 1 },
+ { "createrawtransaction", 2 },
{ "signrawtransaction", 1 },
{ "signrawtransaction", 2 },
{ "sendrawtransaction", 1 },
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/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index 4dec53396d..5f3363d097 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -316,9 +316,9 @@ UniValue verifytxoutproof(const UniValue& params, bool fHelp)
UniValue createrawtransaction(const UniValue& params, bool fHelp)
{
- if (fHelp || params.size() != 2)
+ if (fHelp || params.size() < 2 || params.size() > 3)
throw runtime_error(
- "createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] {\"address\":amount,\"data\":\"hex\",...}\n"
+ "createrawtransaction [{\"txid\":\"id\",\"vout\":n},...] {\"address\":amount,\"data\":\"hex\",...} ( locktime )\n"
"\nCreate a transaction spending the given inputs and creating new outputs.\n"
"Outputs can be addresses or data.\n"
"Returns hex-encoded raw transaction.\n"
@@ -340,6 +340,7 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp)
" \"data\": \"hex\", (string, required) The key is \"data\", the value is hex encoded data\n"
" ...\n"
" }\n"
+ "3. locktime (numeric, optional, default=0) Raw locktime. Non-0 value also locktime-activates inputs\n"
"\nResult:\n"
"\"transaction\" (string) hex string of the transaction\n"
@@ -351,13 +352,22 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp)
);
LOCK(cs_main);
- RPCTypeCheck(params, boost::assign::list_of(UniValue::VARR)(UniValue::VOBJ));
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VARR)(UniValue::VOBJ)(UniValue::VNUM), true);
+ if (params[0].isNull() || params[1].isNull())
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, arguments 1 and 2 must be non-null");
UniValue inputs = params[0].get_array();
UniValue sendTo = params[1].get_obj();
CMutableTransaction rawTx;
+ if (params.size() > 2 && !params[2].isNull()) {
+ int64_t nLockTime = params[2].get_int64();
+ if (nLockTime < 0 || nLockTime > std::numeric_limits<uint32_t>::max())
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, locktime out of range");
+ rawTx.nLockTime = nLockTime;
+ }
+
for (unsigned int idx = 0; idx < inputs.size(); idx++) {
const UniValue& input = inputs[idx];
const UniValue& o = input.get_obj();
@@ -371,7 +381,9 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp)
if (nOutput < 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
- CTxIn in(COutPoint(txid, nOutput));
+ uint32_t nSequence = (rawTx.nLockTime ? std::numeric_limits<uint32_t>::max() - 1 : std::numeric_limits<uint32_t>::max());
+ CTxIn in(COutPoint(txid, nOutput), CScript(), nSequence);
+
rawTx.vin.push_back(in);
}
@@ -809,7 +821,7 @@ UniValue sendrawtransaction(const UniValue& params, bool fHelp)
// push to local node and sync with wallets
CValidationState state;
bool fMissingInputs;
- if (!AcceptToMemoryPool(mempool, state, tx, false, &fMissingInputs, !fOverrideFees)) {
+ if (!AcceptToMemoryPool(mempool, state, tx, false, &fMissingInputs, false, !fOverrideFees)) {
if (state.IsInvalid()) {
throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
} else {
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/script/bitcoinconsensus.h b/src/script/bitcoinconsensus.h
index 0320577797..a48ff1e18d 100644
--- a/src/script/bitcoinconsensus.h
+++ b/src/script/bitcoinconsensus.h
@@ -44,9 +44,10 @@ typedef enum bitcoinconsensus_error_t
/** Script verification flags */
enum
{
- bitcoinconsensus_SCRIPT_FLAGS_VERIFY_NONE = 0,
- bitcoinconsensus_SCRIPT_FLAGS_VERIFY_P2SH = (1U << 0), // evaluate P2SH (BIP16) subscripts
- bitcoinconsensus_SCRIPT_FLAGS_VERIFY_DERSIG = (1U << 2), // enforce strict DER (BIP66) compliance
+ bitcoinconsensus_SCRIPT_FLAGS_VERIFY_NONE = 0,
+ bitcoinconsensus_SCRIPT_FLAGS_VERIFY_P2SH = (1U << 0), // evaluate P2SH (BIP16) subscripts
+ bitcoinconsensus_SCRIPT_FLAGS_VERIFY_DERSIG = (1U << 2), // enforce strict DER (BIP66) compliance
+ bitcoinconsensus_SCRIPT_FLAGS_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9), // enable CHECKLOCKTIMEVERIFY (BIP65)
};
/// Returns 1 if the input nIn of the serialized transaction pointed to by
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index d3aec26020..6a20d497c0 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -273,7 +273,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
return set_error(serror, SCRIPT_ERR_PUSH_SIZE);
// Note how OP_RESERVED does not count towards the opcode limit.
- if (opcode > OP_16 && ++nOpCount > 201)
+ if (opcode > OP_16 && ++nOpCount > MAX_OPS_PER_SCRIPT)
return set_error(serror, SCRIPT_ERR_OP_COUNT);
if (opcode == OP_CAT ||
@@ -869,10 +869,10 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
int nKeysCount = CScriptNum(stacktop(-i), fRequireMinimal).getint();
- if (nKeysCount < 0 || nKeysCount > 20)
+ if (nKeysCount < 0 || nKeysCount > MAX_PUBKEYS_PER_MULTISIG)
return set_error(serror, SCRIPT_ERR_PUBKEY_COUNT);
nOpCount += nKeysCount;
- if (nOpCount > 201)
+ if (nOpCount > MAX_OPS_PER_SCRIPT)
return set_error(serror, SCRIPT_ERR_OP_COUNT);
int ikey = ++i;
i += nKeysCount;
diff --git a/src/script/script.cpp b/src/script/script.cpp
index 9a0c067a33..263c89defe 100644
--- a/src/script/script.cpp
+++ b/src/script/script.cpp
@@ -170,7 +170,7 @@ unsigned int CScript::GetSigOpCount(bool fAccurate) const
if (fAccurate && lastOpcode >= OP_1 && lastOpcode <= OP_16)
n += DecodeOP_N(lastOpcode);
else
- n += 20;
+ n += MAX_PUBKEYS_PER_MULTISIG;
}
lastOpcode = opcode;
}
diff --git a/src/script/script.h b/src/script/script.h
index cdc9a71bb2..a38d33a189 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -17,7 +17,14 @@
#include <string>
#include <vector>
-static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes
+// Maximum number of bytes pushable to the stack
+static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520;
+
+// Maximum number of non-push operations per script
+static const int MAX_OPS_PER_SCRIPT = 201;
+
+// Maximum number of public keys per multisig
+static const int MAX_PUBKEYS_PER_MULTISIG = 20;
// Threshold for nLockTime: below this value it is interpreted as block number,
// otherwise as UNIX timestamp.
diff --git a/src/streams.h b/src/streams.h
index fa1e18defe..8610e4d18e 100644
--- a/src/streams.h
+++ b/src/streams.h
@@ -296,6 +296,29 @@ public:
data.insert(data.end(), begin(), end());
clear();
}
+
+ /**
+ * XOR the contents of this stream with a certain key.
+ *
+ * @param[in] key The key used to XOR the data in this stream.
+ */
+ void Xor(const std::vector<unsigned char>& key)
+ {
+ if (key.size() == 0) {
+ return;
+ }
+
+ for (size_type i = 0, j = 0; i != size(); i++) {
+ vch[i] ^= key[j++];
+
+ // This potentially acts on very many bytes of data, so it's
+ // important that we calculate `j`, i.e. the `key` index in this
+ // way instead of doing a %, which would effectively be a division
+ // for each byte Xor'd -- much slower than need be.
+ if (j == key.size())
+ j = 0;
+ }
+ }
};
diff --git a/src/test/README.md b/src/test/README.md
index e36112bd4f..b2d6be14f1 100644
--- a/src/test/README.md
+++ b/src/test/README.md
@@ -16,6 +16,8 @@ their tests in a test suite called "<source_filename>_tests". For an
examples of this pattern, examine uint160_tests.cpp and
uint256_tests.cpp.
+Add the source files to /src/Makefile.test.include to add them to the build.
+
For further reading, I found the following website to be helpful in
explaining how the boost unit test framework works:
[http://www.alittlemadness.com/2009/03/31/c-unit-testing-with-boosttest/](http://www.alittlemadness.com/2009/03/31/c-unit-testing-with-boosttest/).
diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp
new file mode 100644
index 0000000000..cfcdd9abb2
--- /dev/null
+++ b/src/test/addrman_tests.cpp
@@ -0,0 +1,180 @@
+// Copyright (c) 2012-2013 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 "addrman.h"
+#include "test/test_bitcoin.h"
+#include <string>
+#include <boost/test/unit_test.hpp>
+
+#include "random.h"
+
+using namespace std;
+
+class CAddrManTest : public CAddrMan{};
+
+BOOST_FIXTURE_TEST_SUITE(addrman_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(addrman_simple)
+{
+ CAddrManTest addrman;
+
+ // Set addrman addr placement to be deterministic.
+ addrman.MakeDeterministic();
+
+ CNetAddr source = CNetAddr("252.2.2.2:8333");
+
+ // Test 1: Does Addrman respond correctly when empty.
+ BOOST_CHECK(addrman.size() == 0);
+ CAddrInfo addr_null = addrman.Select();
+ BOOST_CHECK(addr_null.ToString() == "[::]:0");
+
+ // Test 2: Does Addrman::Add work as expected.
+ CService addr1 = CService("250.1.1.1:8333");
+ addrman.Add(CAddress(addr1), source);
+ BOOST_CHECK(addrman.size() == 1);
+ CAddrInfo addr_ret1 = addrman.Select();
+ BOOST_CHECK(addr_ret1.ToString() == "250.1.1.1:8333");
+
+ // Test 3: Does IP address deduplication work correctly.
+ // Expected dup IP should not be added.
+ CService addr1_dup = CService("250.1.1.1:8333");
+ addrman.Add(CAddress(addr1_dup), source);
+ BOOST_CHECK(addrman.size() == 1);
+
+
+ // Test 5: New table has one addr and we add a diff addr we should
+ // have two addrs.
+ CService addr2 = CService("250.1.1.2:8333");
+ addrman.Add(CAddress(addr2), source);
+ BOOST_CHECK(addrman.size() == 2);
+
+ // Test 6: AddrMan::Clear() should empty the new table.
+ addrman.Clear();
+ BOOST_CHECK(addrman.size() == 0);
+ CAddrInfo addr_null2 = addrman.Select();
+ BOOST_CHECK(addr_null2.ToString() == "[::]:0");
+}
+
+BOOST_AUTO_TEST_CASE(addrman_ports)
+{
+ CAddrManTest addrman;
+
+ // Set addrman addr placement to be deterministic.
+ addrman.MakeDeterministic();
+
+ CNetAddr source = CNetAddr("252.2.2.2:8333");
+
+ BOOST_CHECK(addrman.size() == 0);
+
+ // Test 7; Addr with same IP but diff port does not replace existing addr.
+ CService addr1 = CService("250.1.1.1:8333");
+ addrman.Add(CAddress(addr1), source);
+ BOOST_CHECK(addrman.size() == 1);
+
+ CService addr1_port = CService("250.1.1.1:8334");
+ addrman.Add(CAddress(addr1_port), source);
+ BOOST_CHECK(addrman.size() == 1);
+ CAddrInfo addr_ret2 = addrman.Select();
+ BOOST_CHECK(addr_ret2.ToString() == "250.1.1.1:8333");
+
+ // Test 8: Add same IP but diff port to tried table, it doesn't get added.
+ // Perhaps this is not ideal behavior but it is the current behavior.
+ addrman.Good(CAddress(addr1_port));
+ BOOST_CHECK(addrman.size() == 1);
+ bool newOnly = true;
+ CAddrInfo addr_ret3 = addrman.Select(newOnly);
+ BOOST_CHECK(addr_ret3.ToString() == "250.1.1.1:8333");
+}
+
+
+BOOST_AUTO_TEST_CASE(addrman_select)
+{
+ CAddrManTest addrman;
+
+ // Set addrman addr placement to be deterministic.
+ addrman.MakeDeterministic();
+
+ CNetAddr source = CNetAddr("252.2.2.2:8333");
+
+ // Test 9: Select from new with 1 addr in new.
+ CService addr1 = CService("250.1.1.1:8333");
+ addrman.Add(CAddress(addr1), source);
+ BOOST_CHECK(addrman.size() == 1);
+
+ bool newOnly = true;
+ CAddrInfo addr_ret1 = addrman.Select(newOnly);
+ BOOST_CHECK(addr_ret1.ToString() == "250.1.1.1:8333");
+
+
+ // Test 10: move addr to tried, select from new expected nothing returned.
+ addrman.Good(CAddress(addr1));
+ BOOST_CHECK(addrman.size() == 1);
+ CAddrInfo addr_ret2 = addrman.Select(newOnly);
+ BOOST_CHECK(addr_ret2.ToString() == "[::]:0");
+
+ CAddrInfo addr_ret3 = addrman.Select();
+ BOOST_CHECK(addr_ret3.ToString() == "250.1.1.1:8333");
+}
+
+BOOST_AUTO_TEST_CASE(addrman_new_collisions)
+{
+ CAddrManTest addrman;
+
+ // Set addrman addr placement to be deterministic.
+ addrman.MakeDeterministic();
+
+ CNetAddr source = CNetAddr("252.2.2.2:8333");
+
+ BOOST_CHECK(addrman.size() == 0);
+
+ for (unsigned int i = 1; i < 4; i++){
+ CService addr = CService("250.1.1."+boost::to_string(i));
+ addrman.Add(CAddress(addr), source);
+
+ //Test 11: No collision in new table yet.
+ BOOST_CHECK(addrman.size() == i);
+ }
+
+ //Test 12: new table collision!
+ CService addr1 = CService("250.1.1.4");
+ addrman.Add(CAddress(addr1), source);
+ BOOST_CHECK(addrman.size() == 3);
+
+ CService addr2 = CService("250.1.1.5");
+ addrman.Add(CAddress(addr2), source);
+ BOOST_CHECK(addrman.size() == 4);
+}
+
+BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
+{
+ CAddrManTest addrman;
+
+ // Set addrman addr placement to be deterministic.
+ addrman.MakeDeterministic();
+
+ CNetAddr source = CNetAddr("252.2.2.2:8333");
+
+ BOOST_CHECK(addrman.size() == 0);
+
+ for (unsigned int i = 1; i < 75; i++){
+ CService addr = CService("250.1.1."+boost::to_string(i));
+ addrman.Add(CAddress(addr), source);
+ addrman.Good(CAddress(addr));
+
+ //Test 13: No collision in tried table yet.
+ BOOST_TEST_MESSAGE(addrman.size());
+ BOOST_CHECK(addrman.size() == i);
+ }
+
+ //Test 14: tried table collision!
+ CService addr1 = CService("250.1.1.76");
+ addrman.Add(CAddress(addr1), source);
+ BOOST_CHECK(addrman.size() == 74);
+
+ CService addr2 = CService("250.1.1.77");
+ addrman.Add(CAddress(addr2), source);
+ BOOST_CHECK(addrman.size() == 75);
+}
+
+
+BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file
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 5cad5af7c3..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"],
@@ -193,5 +197,9 @@
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xc5b93064159b3b2d6ab506a41b1f50463771b988 EQUAL"]],
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000030251b1000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
+["A transaction with a non-standard DER signature."],
+[[["b1dbc81696c8a9c0fccd0693ab66d7c368dbc38c0def4e800685560ddd1b2132", 0, "DUP HASH160 0x14 0x4b3bd7eba3bc0284fd3007be7f3be275e94f5826 EQUALVERIFY CHECKSIG"]],
+"010000000132211bdd0d568506804eef0d8cc3db68c3d766ab9306cdfcc0a9c89616c8dbb1000000006c493045022100c7bb0faea0522e74ff220c20c022d2cb6033f8d167fb89e75a50e237a35fd6d202203064713491b1f8ad5f79e623d0219ad32510bfaa1009ab30cbee77b59317d6e30001210237af13eb2d84e4545af287b919c2282019c9691cc509e78e196a9d8274ed1be0ffffffff0100000000000000001976a914f1b3ed2eda9a2ebe5a9374f692877cdf87c0f95b88ac00000000", "P2SH,DERSIG"],
+
["Make diffs cleaner by leaving a comment here without comma at the end"]
]
diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json
index 9744a3c848..0dfef73ae5 100644
--- a/src/test/data/tx_valid.json
+++ b/src/test/data/tx_valid.json
@@ -229,5 +229,9 @@
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xc5b93064159b3b2d6ab506a41b1f50463771b988 EQUAL"]],
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000030251b1000000000100000000000000000001000000", "P2SH,CHECKLOCKTIMEVERIFY"],
+["A transaction with a non-standard DER signature."],
+[[["b1dbc81696c8a9c0fccd0693ab66d7c368dbc38c0def4e800685560ddd1b2132", 0, "DUP HASH160 0x14 0x4b3bd7eba3bc0284fd3007be7f3be275e94f5826 EQUALVERIFY CHECKSIG"]],
+"010000000132211bdd0d568506804eef0d8cc3db68c3d766ab9306cdfcc0a9c89616c8dbb1000000006c493045022100c7bb0faea0522e74ff220c20c022d2cb6033f8d167fb89e75a50e237a35fd6d202203064713491b1f8ad5f79e623d0219ad32510bfaa1009ab30cbee77b59317d6e30001210237af13eb2d84e4545af287b919c2282019c9691cc509e78e196a9d8274ed1be0ffffffff0100000000000000001976a914f1b3ed2eda9a2ebe5a9374f692877cdf87c0f95b88ac00000000", "P2SH"],
+
["Make diffs cleaner by leaving a comment here without comma at the end"]
]
diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp
new file mode 100644
index 0000000000..8b6b0697ab
--- /dev/null
+++ b/src/test/dbwrapper_tests.cpp
@@ -0,0 +1,207 @@
+// Copyright (c) 2012-2013 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 "dbwrapper.h"
+#include "uint256.h"
+#include "random.h"
+#include "test/test_bitcoin.h"
+
+#include <boost/assign/std/vector.hpp> // for 'operator+=()'
+#include <boost/assert.hpp>
+#include <boost/test/unit_test.hpp>
+
+using namespace std;
+using namespace boost::assign; // bring 'operator+=()' into scope
+using namespace boost::filesystem;
+
+// Test if a string consists entirely of null characters
+bool is_null_key(const vector<unsigned char>& key) {
+ bool isnull = true;
+
+ for (unsigned int i = 0; i < key.size(); i++)
+ isnull &= (key[i] == '\x00');
+
+ return isnull;
+}
+
+BOOST_FIXTURE_TEST_SUITE(dbwrapper_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(dbwrapper)
+{
+ // Perform tests both obfuscated and non-obfuscated.
+ for (int i = 0; i < 2; i++) {
+ bool obfuscate = (bool)i;
+ path ph = temp_directory_path() / unique_path();
+ CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
+ char key = 'k';
+ uint256 in = GetRandHash();
+ uint256 res;
+
+ // Ensure that we're doing real obfuscation when obfuscate=true
+ BOOST_CHECK(obfuscate != is_null_key(dbw.GetObfuscateKey()));
+
+ BOOST_CHECK(dbw.Write(key, in));
+ BOOST_CHECK(dbw.Read(key, res));
+ BOOST_CHECK_EQUAL(res.ToString(), in.ToString());
+ }
+}
+
+// Test batch operations
+BOOST_AUTO_TEST_CASE(dbwrapper_batch)
+{
+ // Perform tests both obfuscated and non-obfuscated.
+ for (int i = 0; i < 2; i++) {
+ bool obfuscate = (bool)i;
+ path ph = temp_directory_path() / unique_path();
+ CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
+
+ char key = 'i';
+ uint256 in = GetRandHash();
+ char key2 = 'j';
+ uint256 in2 = GetRandHash();
+ char key3 = 'k';
+ uint256 in3 = GetRandHash();
+
+ uint256 res;
+ CDBBatch batch(&dbw.GetObfuscateKey());
+
+ batch.Write(key, in);
+ batch.Write(key2, in2);
+ batch.Write(key3, in3);
+
+ // Remove key3 before it's even been written
+ batch.Erase(key3);
+
+ dbw.WriteBatch(batch);
+
+ BOOST_CHECK(dbw.Read(key, res));
+ BOOST_CHECK_EQUAL(res.ToString(), in.ToString());
+ BOOST_CHECK(dbw.Read(key2, res));
+ BOOST_CHECK_EQUAL(res.ToString(), in2.ToString());
+
+ // key3 never should've been written
+ BOOST_CHECK(dbw.Read(key3, res) == false);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(dbwrapper_iterator)
+{
+ // Perform tests both obfuscated and non-obfuscated.
+ for (int i = 0; i < 2; i++) {
+ bool obfuscate = (bool)i;
+ path ph = temp_directory_path() / unique_path();
+ CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
+
+ // The two keys are intentionally chosen for ordering
+ char key = 'j';
+ uint256 in = GetRandHash();
+ BOOST_CHECK(dbw.Write(key, in));
+ char key2 = 'k';
+ uint256 in2 = GetRandHash();
+ BOOST_CHECK(dbw.Write(key2, in2));
+
+ boost::scoped_ptr<CDBIterator> it(const_cast<CDBWrapper*>(&dbw)->NewIterator());
+
+ // Be sure to seek past the obfuscation key (if it exists)
+ it->Seek(key);
+
+ char key_res;
+ uint256 val_res;
+
+ it->GetKey(key_res);
+ it->GetValue(val_res);
+ BOOST_CHECK_EQUAL(key_res, key);
+ BOOST_CHECK_EQUAL(val_res.ToString(), in.ToString());
+
+ it->Next();
+
+ it->GetKey(key_res);
+ it->GetValue(val_res);
+ BOOST_CHECK_EQUAL(key_res, key2);
+ BOOST_CHECK_EQUAL(val_res.ToString(), in2.ToString());
+
+ it->Next();
+ BOOST_CHECK_EQUAL(it->Valid(), false);
+ }
+}
+
+// Test that we do not obfuscation if there is existing data.
+BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate)
+{
+ // We're going to share this path between two wrappers
+ path ph = temp_directory_path() / unique_path();
+ create_directories(ph);
+
+ // Set up a non-obfuscated wrapper to write some initial data.
+ CDBWrapper* dbw = new CDBWrapper(ph, (1 << 10), false, false, false);
+ char key = 'k';
+ uint256 in = GetRandHash();
+ uint256 res;
+
+ BOOST_CHECK(dbw->Write(key, in));
+ BOOST_CHECK(dbw->Read(key, res));
+ BOOST_CHECK_EQUAL(res.ToString(), in.ToString());
+
+ // Call the destructor to free leveldb LOCK
+ delete dbw;
+
+ // Now, set up another wrapper that wants to obfuscate the same directory
+ CDBWrapper odbw(ph, (1 << 10), false, false, true);
+
+ // Check that the key/val we wrote with unobfuscated wrapper exists and
+ // is readable.
+ uint256 res2;
+ BOOST_CHECK(odbw.Read(key, res2));
+ BOOST_CHECK_EQUAL(res2.ToString(), in.ToString());
+
+ BOOST_CHECK(!odbw.IsEmpty()); // There should be existing data
+ BOOST_CHECK(is_null_key(odbw.GetObfuscateKey())); // The key should be an empty string
+
+ uint256 in2 = GetRandHash();
+ uint256 res3;
+
+ // Check that we can write successfully
+ BOOST_CHECK(odbw.Write(key, in2));
+ BOOST_CHECK(odbw.Read(key, res3));
+ BOOST_CHECK_EQUAL(res3.ToString(), in2.ToString());
+}
+
+// Ensure that we start obfuscating during a reindex.
+BOOST_AUTO_TEST_CASE(existing_data_reindex)
+{
+ // We're going to share this path between two wrappers
+ path ph = temp_directory_path() / unique_path();
+ create_directories(ph);
+
+ // Set up a non-obfuscated wrapper to write some initial data.
+ CDBWrapper* dbw = new CDBWrapper(ph, (1 << 10), false, false, false);
+ char key = 'k';
+ uint256 in = GetRandHash();
+ uint256 res;
+
+ BOOST_CHECK(dbw->Write(key, in));
+ BOOST_CHECK(dbw->Read(key, res));
+ BOOST_CHECK_EQUAL(res.ToString(), in.ToString());
+
+ // Call the destructor to free leveldb LOCK
+ delete dbw;
+
+ // Simulate a -reindex by wiping the existing data store
+ CDBWrapper odbw(ph, (1 << 10), false, true, true);
+
+ // Check that the key/val we wrote with unobfuscated wrapper doesn't exist
+ uint256 res2;
+ BOOST_CHECK(!odbw.Read(key, res2));
+ BOOST_CHECK(!is_null_key(odbw.GetObfuscateKey()));
+
+ uint256 in2 = GetRandHash();
+ uint256 res3;
+
+ // Check that we can write successfully
+ BOOST_CHECK(odbw.Write(key, in2));
+ BOOST_CHECK(odbw.Read(key, res3));
+ BOOST_CHECK_EQUAL(res3.ToString(), in2.ToString());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp
index 5bf1e98e8f..0cf906a259 100644
--- a/src/test/mempool_tests.cpp
+++ b/src/test/mempool_tests.cpp
@@ -153,11 +153,11 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
std::vector<std::string> sortedOrder;
sortedOrder.resize(5);
- sortedOrder[0] = tx2.GetHash().ToString(); // 20000
- sortedOrder[1] = tx4.GetHash().ToString(); // 15000
+ sortedOrder[0] = tx3.GetHash().ToString(); // 0
+ sortedOrder[1] = tx5.GetHash().ToString(); // 10000
sortedOrder[2] = tx1.GetHash().ToString(); // 10000
- sortedOrder[3] = tx5.GetHash().ToString(); // 10000
- sortedOrder[4] = tx3.GetHash().ToString(); // 0
+ sortedOrder[3] = tx4.GetHash().ToString(); // 15000
+ sortedOrder[4] = tx2.GetHash().ToString(); // 20000
CheckSort(pool, sortedOrder);
/* low fee but with high fee child */
@@ -169,7 +169,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
pool.addUnchecked(tx6.GetHash(), CTxMemPoolEntry(tx6, 0LL, 1, 10.0, 1, true));
BOOST_CHECK_EQUAL(pool.size(), 6);
// Check that at this point, tx6 is sorted low
- sortedOrder.push_back(tx6.GetHash().ToString());
+ sortedOrder.insert(sortedOrder.begin(), tx6.GetHash().ToString());
CheckSort(pool, sortedOrder);
CTxMemPool::setEntries setAncestors;
@@ -194,9 +194,9 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
BOOST_CHECK_EQUAL(pool.size(), 7);
// Now tx6 should be sorted higher (high fee child): tx7, tx6, tx2, ...
- sortedOrder.erase(sortedOrder.end()-1);
- sortedOrder.insert(sortedOrder.begin(), tx6.GetHash().ToString());
- sortedOrder.insert(sortedOrder.begin(), tx7.GetHash().ToString());
+ sortedOrder.erase(sortedOrder.begin());
+ sortedOrder.push_back(tx6.GetHash().ToString());
+ sortedOrder.push_back(tx7.GetHash().ToString());
CheckSort(pool, sortedOrder);
/* low fee child of tx7 */
@@ -211,7 +211,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
pool.addUnchecked(tx8.GetHash(), CTxMemPoolEntry(tx8, 0LL, 2, 10.0, 1, true), setAncestors);
// Now tx8 should be sorted low, but tx6/tx both high
- sortedOrder.push_back(tx8.GetHash().ToString());
+ sortedOrder.insert(sortedOrder.begin(), tx8.GetHash().ToString());
CheckSort(pool, sortedOrder);
/* low fee child of tx7 */
@@ -226,7 +226,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
// tx9 should be sorted low
BOOST_CHECK_EQUAL(pool.size(), 9);
- sortedOrder.push_back(tx9.GetHash().ToString());
+ sortedOrder.insert(sortedOrder.begin(), tx9.GetHash().ToString());
CheckSort(pool, sortedOrder);
std::vector<std::string> snapshotOrder = sortedOrder;
@@ -255,21 +255,21 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
* tx8 and tx9 should both now be sorted higher
* Final order after tx10 is added:
*
- * tx7 = 2.2M (4 txs)
- * tx6 = 2.2M (5 txs)
- * tx10 = 200k (1 tx)
- * tx8 = 200k (2 txs)
- * tx9 = 200k (2 txs)
- * tx2 = 20000 (1)
- * tx4 = 15000 (1)
- * tx1 = 10000 (1)
- * tx5 = 10000 (1)
* tx3 = 0 (1)
+ * tx5 = 10000 (1)
+ * tx1 = 10000 (1)
+ * tx4 = 15000 (1)
+ * tx2 = 20000 (1)
+ * tx9 = 200k (2 txs)
+ * tx8 = 200k (2 txs)
+ * tx10 = 200k (1 tx)
+ * tx6 = 2.2M (5 txs)
+ * tx7 = 2.2M (4 txs)
*/
- sortedOrder.erase(sortedOrder.end()-2, sortedOrder.end()); // take out tx8, tx9 from the end
- sortedOrder.insert(sortedOrder.begin()+2, tx10.GetHash().ToString()); // tx10 is after tx6
- sortedOrder.insert(sortedOrder.begin()+3, tx9.GetHash().ToString());
- sortedOrder.insert(sortedOrder.begin()+3, tx8.GetHash().ToString());
+ sortedOrder.erase(sortedOrder.begin(), sortedOrder.begin()+2); // take out tx9, tx8 from the beginning
+ sortedOrder.insert(sortedOrder.begin()+5, tx9.GetHash().ToString());
+ sortedOrder.insert(sortedOrder.begin()+6, tx8.GetHash().ToString());
+ sortedOrder.insert(sortedOrder.begin()+7, tx10.GetHash().ToString()); // tx10 is just before tx6
CheckSort(pool, sortedOrder);
// there should be 10 transactions in the mempool
@@ -281,4 +281,157 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
CheckSort(pool, snapshotOrder);
}
+BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
+{
+ CTxMemPool pool(CFeeRate(1000));
+
+ CMutableTransaction tx1 = CMutableTransaction();
+ tx1.vin.resize(1);
+ tx1.vin[0].scriptSig = CScript() << OP_1;
+ tx1.vout.resize(1);
+ tx1.vout[0].scriptPubKey = CScript() << OP_1 << OP_EQUAL;
+ tx1.vout[0].nValue = 10 * COIN;
+ pool.addUnchecked(tx1.GetHash(), CTxMemPoolEntry(tx1, 10000LL, 0, 10.0, 1, pool.HasNoInputsOf(tx1)));
+
+ CMutableTransaction tx2 = CMutableTransaction();
+ tx2.vin.resize(1);
+ tx2.vin[0].scriptSig = CScript() << OP_2;
+ tx2.vout.resize(1);
+ tx2.vout[0].scriptPubKey = CScript() << OP_2 << OP_EQUAL;
+ tx2.vout[0].nValue = 10 * COIN;
+ pool.addUnchecked(tx2.GetHash(), CTxMemPoolEntry(tx2, 5000LL, 0, 10.0, 1, pool.HasNoInputsOf(tx2)));
+
+ pool.TrimToSize(pool.DynamicMemoryUsage()); // should do nothing
+ BOOST_CHECK(pool.exists(tx1.GetHash()));
+ BOOST_CHECK(pool.exists(tx2.GetHash()));
+
+ pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); // should remove the lower-feerate transaction
+ BOOST_CHECK(pool.exists(tx1.GetHash()));
+ BOOST_CHECK(!pool.exists(tx2.GetHash()));
+
+ pool.addUnchecked(tx2.GetHash(), CTxMemPoolEntry(tx2, 5000LL, 0, 10.0, 1, pool.HasNoInputsOf(tx2)));
+ CMutableTransaction tx3 = CMutableTransaction();
+ tx3.vin.resize(1);
+ tx3.vin[0].prevout = COutPoint(tx2.GetHash(), 0);
+ tx3.vin[0].scriptSig = CScript() << OP_2;
+ tx3.vout.resize(1);
+ tx3.vout[0].scriptPubKey = CScript() << OP_3 << OP_EQUAL;
+ tx3.vout[0].nValue = 10 * COIN;
+ pool.addUnchecked(tx3.GetHash(), CTxMemPoolEntry(tx3, 20000LL, 0, 10.0, 1, pool.HasNoInputsOf(tx3)));
+
+ pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); // tx3 should pay for tx2 (CPFP)
+ BOOST_CHECK(!pool.exists(tx1.GetHash()));
+ BOOST_CHECK(pool.exists(tx2.GetHash()));
+ BOOST_CHECK(pool.exists(tx3.GetHash()));
+
+ pool.TrimToSize(::GetSerializeSize(CTransaction(tx1), SER_NETWORK, PROTOCOL_VERSION)); // mempool is limited to tx1's size in memory usage, so nothing fits
+ BOOST_CHECK(!pool.exists(tx1.GetHash()));
+ BOOST_CHECK(!pool.exists(tx2.GetHash()));
+ BOOST_CHECK(!pool.exists(tx3.GetHash()));
+
+ CFeeRate maxFeeRateRemoved(25000, ::GetSerializeSize(CTransaction(tx3), SER_NETWORK, PROTOCOL_VERSION) + ::GetSerializeSize(CTransaction(tx2), SER_NETWORK, PROTOCOL_VERSION));
+ BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + 1000);
+
+ CMutableTransaction tx4 = CMutableTransaction();
+ tx4.vin.resize(2);
+ tx4.vin[0].prevout.SetNull();
+ tx4.vin[0].scriptSig = CScript() << OP_4;
+ tx4.vin[1].prevout.SetNull();
+ tx4.vin[1].scriptSig = CScript() << OP_4;
+ tx4.vout.resize(2);
+ tx4.vout[0].scriptPubKey = CScript() << OP_4 << OP_EQUAL;
+ tx4.vout[0].nValue = 10 * COIN;
+ tx4.vout[1].scriptPubKey = CScript() << OP_4 << OP_EQUAL;
+ tx4.vout[1].nValue = 10 * COIN;
+
+ CMutableTransaction tx5 = CMutableTransaction();
+ tx5.vin.resize(2);
+ tx5.vin[0].prevout = COutPoint(tx4.GetHash(), 0);
+ tx5.vin[0].scriptSig = CScript() << OP_4;
+ tx5.vin[1].prevout.SetNull();
+ tx5.vin[1].scriptSig = CScript() << OP_5;
+ tx5.vout.resize(2);
+ tx5.vout[0].scriptPubKey = CScript() << OP_5 << OP_EQUAL;
+ tx5.vout[0].nValue = 10 * COIN;
+ tx5.vout[1].scriptPubKey = CScript() << OP_5 << OP_EQUAL;
+ tx5.vout[1].nValue = 10 * COIN;
+
+ CMutableTransaction tx6 = CMutableTransaction();
+ tx6.vin.resize(2);
+ tx6.vin[0].prevout = COutPoint(tx4.GetHash(), 1);
+ tx6.vin[0].scriptSig = CScript() << OP_4;
+ tx6.vin[1].prevout.SetNull();
+ tx6.vin[1].scriptSig = CScript() << OP_6;
+ tx6.vout.resize(2);
+ tx6.vout[0].scriptPubKey = CScript() << OP_6 << OP_EQUAL;
+ tx6.vout[0].nValue = 10 * COIN;
+ tx6.vout[1].scriptPubKey = CScript() << OP_6 << OP_EQUAL;
+ tx6.vout[1].nValue = 10 * COIN;
+
+ CMutableTransaction tx7 = CMutableTransaction();
+ tx7.vin.resize(2);
+ tx7.vin[0].prevout = COutPoint(tx5.GetHash(), 0);
+ tx7.vin[0].scriptSig = CScript() << OP_5;
+ tx7.vin[1].prevout = COutPoint(tx6.GetHash(), 0);
+ tx7.vin[1].scriptSig = CScript() << OP_6;
+ tx7.vout.resize(2);
+ tx7.vout[0].scriptPubKey = CScript() << OP_7 << OP_EQUAL;
+ tx7.vout[0].nValue = 10 * COIN;
+ tx7.vout[0].scriptPubKey = CScript() << OP_7 << OP_EQUAL;
+ tx7.vout[0].nValue = 10 * COIN;
+
+ pool.addUnchecked(tx4.GetHash(), CTxMemPoolEntry(tx4, 7000LL, 0, 10.0, 1, pool.HasNoInputsOf(tx4)));
+ pool.addUnchecked(tx5.GetHash(), CTxMemPoolEntry(tx5, 1000LL, 0, 10.0, 1, pool.HasNoInputsOf(tx5)));
+ pool.addUnchecked(tx6.GetHash(), CTxMemPoolEntry(tx6, 1100LL, 0, 10.0, 1, pool.HasNoInputsOf(tx6)));
+ pool.addUnchecked(tx7.GetHash(), CTxMemPoolEntry(tx7, 9000LL, 0, 10.0, 1, pool.HasNoInputsOf(tx7)));
+
+ // we only require this remove, at max, 2 txn, because its not clear what we're really optimizing for aside from that
+ pool.TrimToSize(pool.DynamicMemoryUsage() - 1);
+ BOOST_CHECK(pool.exists(tx4.GetHash()));
+ BOOST_CHECK(pool.exists(tx6.GetHash()));
+ BOOST_CHECK(!pool.exists(tx7.GetHash()));
+
+ if (!pool.exists(tx5.GetHash()))
+ pool.addUnchecked(tx5.GetHash(), CTxMemPoolEntry(tx5, 1000LL, 0, 10.0, 1, pool.HasNoInputsOf(tx5)));
+ pool.addUnchecked(tx7.GetHash(), CTxMemPoolEntry(tx7, 9000LL, 0, 10.0, 1, pool.HasNoInputsOf(tx7)));
+
+ pool.TrimToSize(pool.DynamicMemoryUsage() / 2); // should maximize mempool size by only removing 5/7
+ BOOST_CHECK(pool.exists(tx4.GetHash()));
+ BOOST_CHECK(!pool.exists(tx5.GetHash()));
+ BOOST_CHECK(pool.exists(tx6.GetHash()));
+ BOOST_CHECK(!pool.exists(tx7.GetHash()));
+
+ pool.addUnchecked(tx5.GetHash(), CTxMemPoolEntry(tx5, 1000LL, 0, 10.0, 1, pool.HasNoInputsOf(tx5)));
+ pool.addUnchecked(tx7.GetHash(), CTxMemPoolEntry(tx7, 9000LL, 0, 10.0, 1, pool.HasNoInputsOf(tx7)));
+
+ std::vector<CTransaction> vtx;
+ std::list<CTransaction> conflicts;
+ SetMockTime(42);
+ SetMockTime(42 + CTxMemPool::ROLLING_FEE_HALFLIFE);
+ BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + 1000);
+ // ... we should keep the same min fee until we get a block
+ pool.removeForBlock(vtx, 1, conflicts);
+ SetMockTime(42 + 2*CTxMemPool::ROLLING_FEE_HALFLIFE);
+ BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), (maxFeeRateRemoved.GetFeePerK() + 1000)/2);
+ // ... then feerate should drop 1/2 each halflife
+
+ SetMockTime(42 + 2*CTxMemPool::ROLLING_FEE_HALFLIFE + CTxMemPool::ROLLING_FEE_HALFLIFE/2);
+ BOOST_CHECK_EQUAL(pool.GetMinFee(pool.DynamicMemoryUsage() * 5 / 2).GetFeePerK(), (maxFeeRateRemoved.GetFeePerK() + 1000)/4);
+ // ... with a 1/2 halflife when mempool is < 1/2 its target size
+
+ SetMockTime(42 + 2*CTxMemPool::ROLLING_FEE_HALFLIFE + CTxMemPool::ROLLING_FEE_HALFLIFE/2 + CTxMemPool::ROLLING_FEE_HALFLIFE/4);
+ BOOST_CHECK_EQUAL(pool.GetMinFee(pool.DynamicMemoryUsage() * 9 / 2).GetFeePerK(), (maxFeeRateRemoved.GetFeePerK() + 1000)/8);
+ // ... with a 1/4 halflife when mempool is < 1/4 its target size
+
+ SetMockTime(42 + 7*CTxMemPool::ROLLING_FEE_HALFLIFE + CTxMemPool::ROLLING_FEE_HALFLIFE/2 + CTxMemPool::ROLLING_FEE_HALFLIFE/4);
+ BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), 1000);
+ // ... but feerate should never drop below 1000
+
+ SetMockTime(42 + 8*CTxMemPool::ROLLING_FEE_HALFLIFE + CTxMemPool::ROLLING_FEE_HALFLIFE/2 + CTxMemPool::ROLLING_FEE_HALFLIFE/4);
+ BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), 0);
+ // ... unless it has gone all the way to 0 (after getting past 1000/2)
+
+ SetMockTime(0);
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp
new file mode 100644
index 0000000000..0ed8f363d7
--- /dev/null
+++ b/src/test/streams_tests.cpp
@@ -0,0 +1,67 @@
+// Copyright (c) 2012-2013 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 "streams.h"
+#include "support/allocators/zeroafterfree.h"
+#include "test/test_bitcoin.h"
+
+#include <boost/assign/std/vector.hpp> // for 'operator+=()'
+#include <boost/assert.hpp>
+#include <boost/test/unit_test.hpp>
+
+using namespace std;
+using namespace boost::assign; // bring 'operator+=()' into scope
+
+BOOST_FIXTURE_TEST_SUITE(streams_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(streams_serializedata_xor)
+{
+ std::vector<char> in;
+ std::vector<char> expected_xor;
+ std::vector<unsigned char> key;
+ CDataStream ds(in, 0, 0);
+
+ // Degenerate case
+
+ key += '\x00','\x00';
+ ds.Xor(key);
+ BOOST_CHECK_EQUAL(
+ std::string(expected_xor.begin(), expected_xor.end()),
+ std::string(ds.begin(), ds.end()));
+
+ in += '\x0f','\xf0';
+ expected_xor += '\xf0','\x0f';
+
+ // Single character key
+
+ ds.clear();
+ ds.insert(ds.begin(), in.begin(), in.end());
+ key.clear();
+
+ key += '\xff';
+ ds.Xor(key);
+ BOOST_CHECK_EQUAL(
+ std::string(expected_xor.begin(), expected_xor.end()),
+ std::string(ds.begin(), ds.end()));
+
+ // Multi character key
+
+ in.clear();
+ expected_xor.clear();
+ in += '\xf0','\x0f';
+ expected_xor += '\x0f','\x00';
+
+ ds.clear();
+ ds.insert(ds.begin(), in.begin(), in.end());
+
+ key.clear();
+ key += '\xff','\x0f';
+
+ ds.Xor(key);
+ BOOST_CHECK_EQUAL(
+ std::string(expected_xor.begin(), expected_xor.end()),
+ std::string(ds.begin(), ds.end()));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index 8d81275a6f..23e5e66d84 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -32,13 +32,14 @@ CWallet* pwalletMain;
extern bool fPrintToConsole;
extern void noui_connect();
-BasicTestingSetup::BasicTestingSetup(CBaseChainParams::Network network)
+BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
{
ECC_Start();
SetupEnvironment();
+ SetupNetworking();
fPrintToDebugLog = false; // don't want to write to debug.log file
fCheckBlockIndex = true;
- SelectParams(network);
+ SelectParams(chainName);
noui_connect();
}
@@ -47,7 +48,7 @@ BasicTestingSetup::~BasicTestingSetup()
ECC_Stop();
}
-TestingSetup::TestingSetup(CBaseChainParams::Network network) : BasicTestingSetup(network)
+TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(chainName)
{
#ifdef ENABLE_WALLET
bitdb.MakeMock();
diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h
index b9314d0611..0bab4b6831 100644
--- a/src/test/test_bitcoin.h
+++ b/src/test/test_bitcoin.h
@@ -12,7 +12,7 @@
* This just configures logging and chain parameters.
*/
struct BasicTestingSetup {
- BasicTestingSetup(CBaseChainParams::Network network = CBaseChainParams::MAIN);
+ BasicTestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
~BasicTestingSetup();
};
@@ -25,7 +25,7 @@ struct TestingSetup: public BasicTestingSetup {
boost::filesystem::path pathTemp;
boost::thread_group threadGroup;
- TestingSetup(CBaseChainParams::Network network = CBaseChainParams::MAIN);
+ TestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
~TestingSetup();
};
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index 9847f6512e..f9423bc0de 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -345,7 +345,7 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
t.vout[0].nValue = 501; // dust
BOOST_CHECK(!IsStandardTx(t, reason));
- t.vout[0].nValue = 601; // not dust
+ t.vout[0].nValue = 2730; // not dust
BOOST_CHECK(IsStandardTx(t, reason));
t.vout[0].scriptPubKey = CScript() << OP_1;
diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp
index edad18644e..9b8e1c088b 100644
--- a/src/test/txvalidationcache_tests.cpp
+++ b/src/test/txvalidationcache_tests.cpp
@@ -23,7 +23,7 @@ ToMemPool(CMutableTransaction& tx)
LOCK(cs_main);
CValidationState state;
- return AcceptToMemoryPool(mempool, state, tx, false, NULL, false);
+ return AcceptToMemoryPool(mempool, state, tx, false, NULL, true, false);
}
BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
diff --git a/src/txdb.cpp b/src/txdb.cpp
index 21ecd65238..cd76c0155c 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -29,18 +29,8 @@ static const char DB_REINDEX_FLAG = 'R';
static const char DB_LAST_BLOCK = 'l';
-void static BatchWriteCoins(CLevelDBBatch &batch, const uint256 &hash, const CCoins &coins) {
- if (coins.IsPruned())
- batch.Erase(make_pair(DB_COINS, hash));
- else
- batch.Write(make_pair(DB_COINS, hash), coins);
-}
-
-void static BatchWriteHashBestChain(CLevelDBBatch &batch, const uint256 &hash) {
- batch.Write(DB_BEST_BLOCK, hash);
-}
-
-CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe) {
+CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe, true)
+{
}
bool CCoinsViewDB::GetCoins(const uint256 &txid, CCoins &coins) const {
@@ -59,12 +49,15 @@ uint256 CCoinsViewDB::GetBestBlock() const {
}
bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) {
- CLevelDBBatch batch;
+ CDBBatch batch(&db.GetObfuscateKey());
size_t count = 0;
size_t changed = 0;
for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
if (it->second.flags & CCoinsCacheEntry::DIRTY) {
- BatchWriteCoins(batch, it->first, it->second.coins);
+ if (it->second.coins.IsPruned())
+ batch.Erase(make_pair(DB_COINS, it->first));
+ else
+ batch.Write(make_pair(DB_COINS, it->first), it->second.coins);
changed++;
}
count++;
@@ -72,13 +65,13 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) {
mapCoins.erase(itOld);
}
if (!hashBlock.IsNull())
- BatchWriteHashBestChain(batch, hashBlock);
+ batch.Write(DB_BEST_BLOCK, hashBlock);
LogPrint("coindb", "Committing %u changed transactions (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count);
return db.WriteBatch(batch);
}
-CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
+CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) {
}
bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) {
@@ -105,8 +98,8 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const {
/* It seems that there are no "const iterators" for LevelDB. Since we
only need read operations on it, use a const-cast to get around
that restriction. */
- boost::scoped_ptr<leveldb::Iterator> pcursor(const_cast<CLevelDBWrapper*>(&db)->NewIterator());
- pcursor->SeekToFirst();
+ boost::scoped_ptr<CDBIterator> pcursor(const_cast<CDBWrapper*>(&db)->NewIterator());
+ pcursor->Seek(DB_COINS);
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
stats.hashBlock = GetBestBlock();
@@ -114,22 +107,10 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const {
CAmount nTotalAmount = 0;
while (pcursor->Valid()) {
boost::this_thread::interruption_point();
- try {
- leveldb::Slice slKey = pcursor->key();
- CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
- char chType;
- ssKey >> chType;
- if (chType == DB_COINS) {
- leveldb::Slice slValue = pcursor->value();
- CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
- CCoins coins;
- ssValue >> coins;
- uint256 txhash;
- ssKey >> txhash;
- ss << txhash;
- ss << VARINT(coins.nVersion);
- ss << (coins.fCoinBase ? 'c' : 'n');
- ss << VARINT(coins.nHeight);
+ std::pair<char, uint256> key;
+ CCoins coins;
+ if (pcursor->GetKey(key) && key.first == DB_COINS) {
+ if (pcursor->GetValue(coins)) {
stats.nTransactions++;
for (unsigned int i=0; i<coins.vout.size(); i++) {
const CTxOut &out = coins.vout[i];
@@ -140,13 +121,15 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const {
nTotalAmount += out.nValue;
}
}
- stats.nSerializedSize += 32 + slValue.size();
+ stats.nSerializedSize += 32 + pcursor->GetValueSize();
ss << VARINT(0);
+ } else {
+ return error("CCoinsViewDB::GetStats() : unable to read value");
}
- pcursor->Next();
- } catch (const std::exception& e) {
- return error("%s: Deserialize or I/O error - %s", __func__, e.what());
+ } else {
+ break;
}
+ pcursor->Next();
}
{
LOCK(cs_main);
@@ -158,7 +141,7 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const {
}
bool CBlockTreeDB::WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo) {
- CLevelDBBatch batch;
+ CDBBatch batch(&GetObfuscateKey());
for (std::vector<std::pair<int, const CBlockFileInfo*> >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) {
batch.Write(make_pair(DB_BLOCK_FILES, it->first), *it->second);
}
@@ -174,7 +157,7 @@ bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) {
}
bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >&vect) {
- CLevelDBBatch batch;
+ CDBBatch batch(&GetObfuscateKey());
for (std::vector<std::pair<uint256,CDiskTxPos> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
batch.Write(make_pair(DB_TXINDEX, it->first), it->second);
return WriteBatch(batch);
@@ -194,26 +177,17 @@ bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) {
bool CBlockTreeDB::LoadBlockIndexGuts()
{
- boost::scoped_ptr<leveldb::Iterator> pcursor(NewIterator());
+ boost::scoped_ptr<CDBIterator> pcursor(NewIterator());
- CDataStream ssKeySet(SER_DISK, CLIENT_VERSION);
- ssKeySet << make_pair(DB_BLOCK_INDEX, uint256());
- pcursor->Seek(ssKeySet.str());
+ pcursor->Seek(make_pair(DB_BLOCK_INDEX, uint256()));
// Load mapBlockIndex
while (pcursor->Valid()) {
boost::this_thread::interruption_point();
- try {
- leveldb::Slice slKey = pcursor->key();
- CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION);
- char chType;
- ssKey >> chType;
- if (chType == DB_BLOCK_INDEX) {
- leveldb::Slice slValue = pcursor->value();
- CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION);
- CDiskBlockIndex diskindex;
- ssValue >> diskindex;
-
+ std::pair<char, uint256> key;
+ if (pcursor->GetKey(key) && key.first == DB_BLOCK_INDEX) {
+ CDiskBlockIndex diskindex;
+ if (pcursor->GetValue(diskindex)) {
// Construct block index object
CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash());
pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev);
@@ -234,10 +208,10 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
pcursor->Next();
} else {
- break; // if shutdown requested or finished loading block index
+ return error("LoadBlockIndex() : failed to read value");
}
- } catch (const std::exception& e) {
- return error("%s: Deserialize or I/O error - %s", __func__, e.what());
+ } else {
+ break;
}
}
diff --git a/src/txdb.h b/src/txdb.h
index bef5dc9fd1..586ab55d0d 100644
--- a/src/txdb.h
+++ b/src/txdb.h
@@ -7,7 +7,7 @@
#define BITCOIN_TXDB_H
#include "coins.h"
-#include "leveldbwrapper.h"
+#include "dbwrapper.h"
#include <map>
#include <string>
@@ -26,11 +26,11 @@ static const int64_t nMaxDbCache = sizeof(void*) > 4 ? 16384 : 1024;
//! min. -dbcache in (MiB)
static const int64_t nMinDbCache = 4;
-/** CCoinsView backed by the LevelDB coin database (chainstate/) */
+/** CCoinsView backed by the coin database (chainstate/) */
class CCoinsViewDB : public CCoinsView
{
protected:
- CLevelDBWrapper db;
+ CDBWrapper db;
public:
CCoinsViewDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false);
@@ -42,7 +42,7 @@ public:
};
/** Access to the block database (blocks/index/) */
-class CBlockTreeDB : public CLevelDBWrapper
+class CBlockTreeDB : public CDBWrapper
{
public:
CBlockTreeDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false);
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 1370cab0c0..a772e7adea 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -13,6 +13,7 @@
#include "streams.h"
#include "util.h"
#include "utilmoneystr.h"
+#include "utiltime.h"
#include "version.h"
using namespace std;
@@ -305,15 +306,18 @@ void CTxMemPoolEntry::UpdateState(int64_t modifySize, CAmount modifyFee, int64_t
}
}
-CTxMemPool::CTxMemPool(const CFeeRate& _minRelayFee) :
+CTxMemPool::CTxMemPool(const CFeeRate& _minReasonableRelayFee) :
nTransactionsUpdated(0)
{
+ _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(_minRelayFee);
+ minerPolicyEstimator = new CBlockPolicyEstimator(_minReasonableRelayFee);
+ minReasonableRelayFee = _minReasonableRelayFee;
}
CTxMemPool::~CTxMemPool()
@@ -483,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;
@@ -508,6 +512,7 @@ void CTxMemPool::removeConflicts(const CTransaction &tx, std::list<CTransaction>
if (txConflict != tx)
{
remove(txConflict, removed, true);
+ ClearPrioritisation(txConflict.GetHash());
}
}
}
@@ -538,22 +543,35 @@ void CTxMemPool::removeForBlock(const std::vector<CTransaction>& vtx, unsigned i
}
// After the txs in the new block have been removed from the mempool, update policy estimates
minerPolicyEstimator->processBlock(nBlockHeight, entries, fCurrentEstimate);
+ lastRollingFeeUpdate = GetTime();
+ blockSinceLastRollingFeeBump = true;
}
-void CTxMemPool::clear()
+void CTxMemPool::_clear()
{
- LOCK(cs);
mapLinks.clear();
mapTx.clear();
mapNextTx.clear();
totalTxSize = 0;
cachedInnerUsage = 0;
+ lastRollingFeeUpdate = GetTime();
+ blockSinceLastRollingFeeBump = false;
+ rollingMinimumFeeRate = 0;
++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());
@@ -735,10 +753,10 @@ void CTxMemPool::PrioritiseTransaction(const uint256 hash, const string strHash,
LogPrintf("PrioritiseTransaction: %s priority += %f, fee += %d\n", strHash, dPriorityDelta, FormatMoney(nFeeDelta));
}
-void CTxMemPool::ApplyDeltas(const uint256 hash, double &dPriorityDelta, CAmount &nFeeDelta)
+void CTxMemPool::ApplyDeltas(const uint256 hash, double &dPriorityDelta, CAmount &nFeeDelta) const
{
LOCK(cs);
- std::map<uint256, std::pair<double, CAmount> >::iterator pos = mapDeltas.find(hash);
+ std::map<uint256, std::pair<double, CAmount> >::const_iterator pos = mapDeltas.find(hash);
if (pos == mapDeltas.end())
return;
const std::pair<double, CAmount> &deltas = pos->second;
@@ -792,6 +810,22 @@ void CTxMemPool::RemoveStaged(setEntries &stage) {
}
}
+int CTxMemPool::Expire(int64_t time) {
+ LOCK(cs);
+ indexed_transaction_set::nth_index<2>::type::iterator it = mapTx.get<2>().begin();
+ setEntries toremove;
+ while (it != mapTx.get<2>().end() && it->GetTime() < time) {
+ toremove.insert(mapTx.project<0>(it));
+ it++;
+ }
+ setEntries stage;
+ BOOST_FOREACH(txiter removeit, toremove) {
+ CalculateDescendants(removeit, stage);
+ }
+ RemoveStaged(stage);
+ return stage.size();
+}
+
bool CTxMemPool::addUnchecked(const uint256&hash, const CTxMemPoolEntry &entry, bool fCurrentEstimate)
{
LOCK(cs);
@@ -837,3 +871,62 @@ const CTxMemPool::setEntries & CTxMemPool::GetMemPoolChildren(txiter entry) cons
assert(it != mapLinks.end());
return it->second.children;
}
+
+CFeeRate CTxMemPool::GetMinFee(size_t sizelimit) const {
+ LOCK(cs);
+ if (!blockSinceLastRollingFeeBump || rollingMinimumFeeRate == 0)
+ return CFeeRate(rollingMinimumFeeRate);
+
+ int64_t time = GetTime();
+ if (time > lastRollingFeeUpdate + 10) {
+ double halflife = ROLLING_FEE_HALFLIFE;
+ if (DynamicMemoryUsage() < sizelimit / 4)
+ halflife /= 4;
+ else if (DynamicMemoryUsage() < sizelimit / 2)
+ halflife /= 2;
+
+ rollingMinimumFeeRate = rollingMinimumFeeRate / pow(2.0, (time - lastRollingFeeUpdate) / halflife);
+ lastRollingFeeUpdate = time;
+
+ if (rollingMinimumFeeRate < minReasonableRelayFee.GetFeePerK() / 2) {
+ rollingMinimumFeeRate = 0;
+ return CFeeRate(0);
+ }
+ }
+ return std::max(CFeeRate(rollingMinimumFeeRate), minReasonableRelayFee);
+}
+
+void CTxMemPool::trackPackageRemoved(const CFeeRate& rate) {
+ AssertLockHeld(cs);
+ if (rate.GetFeePerK() > rollingMinimumFeeRate) {
+ rollingMinimumFeeRate = rate.GetFeePerK();
+ blockSinceLastRollingFeeBump = false;
+ }
+}
+
+void CTxMemPool::TrimToSize(size_t sizelimit) {
+ LOCK(cs);
+
+ unsigned nTxnRemoved = 0;
+ CFeeRate maxFeeRateRemoved(0);
+ while (DynamicMemoryUsage() > sizelimit) {
+ indexed_transaction_set::nth_index<1>::type::iterator it = mapTx.get<1>().begin();
+
+ // We set the new mempool min fee to the feerate of the removed set, plus the
+ // "minimum reasonable fee rate" (ie some value under which we consider txn
+ // to have 0 fee). This way, we don't allow txn to enter mempool with feerate
+ // equal to txn which were removed with no block in between.
+ CFeeRate removed(it->GetFeesWithDescendants(), it->GetSizeWithDescendants());
+ removed += minReasonableRelayFee;
+ trackPackageRemoved(removed);
+ maxFeeRateRemoved = std::max(maxFeeRateRemoved, removed);
+
+ setEntries stage;
+ CalculateDescendants(mapTx.project<0>(it), stage);
+ RemoveStaged(stage);
+ nTxnRemoved += stage.size();
+ }
+
+ if (maxFeeRateRemoved > CFeeRate(0))
+ LogPrint("mempool", "Removed %u txn, rolling minimum fee bumped to %s\n", nTxnRemoved, maxFeeRateRemoved.ToString());
+}
diff --git a/src/txmempool.h b/src/txmempool.h
index c0eef0dd22..7b5843a8d0 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -83,7 +83,7 @@ public:
const CTransaction& GetTx() const { return this->tx; }
double GetPriority(unsigned int currentHeight) const;
- CAmount GetFee() const { return nFee; }
+ const CAmount& GetFee() const { return nFee; }
size_t GetTxSize() const { return nTxSize; }
int64_t GetTime() const { return nTime; }
unsigned int GetHeight() const { return nHeight; }
@@ -160,9 +160,9 @@ public:
double f2 = aSize * bFees;
if (f1 == f2) {
- return a.GetTime() < b.GetTime();
+ return a.GetTime() >= b.GetTime();
}
- return f1 > f2;
+ return f1 < f2;
}
// Calculate which feerate to use for an entry (avoiding division).
@@ -211,9 +211,10 @@ public:
*
* CTxMemPool::mapTx, and CTxMemPoolEntry bookkeeping:
*
- * mapTx is a boost::multi_index that sorts the mempool on 2 criteria:
+ * mapTx is a boost::multi_index that sorts the mempool on 3 criteria:
* - transaction hash
* - feerate [we use max(feerate of tx, feerate of tx with all descendants)]
+ * - time in mempool
*
* Note: the term "descendant" refers to in-mempool transactions that depend on
* this one, while "ancestor" refers to in-mempool transactions that a given
@@ -277,14 +278,25 @@ 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;
uint64_t totalTxSize; //! sum of all mempool tx' byte sizes
uint64_t cachedInnerUsage; //! sum of dynamic memory usage of all the map elements (NOT the maps themselves)
+ CFeeRate minReasonableRelayFee;
+
+ mutable int64_t lastRollingFeeUpdate;
+ mutable bool blockSinceLastRollingFeeBump;
+ mutable double rollingMinimumFeeRate; //! minimum fee to get into the pool, decreases exponentially
+
+ void trackPackageRemoved(const CFeeRate& rate);
+
public:
+
+ static const int ROLLING_FEE_HALFLIFE = 60 * 60 * 12; // public only for testing
+
typedef boost::multi_index_container<
CTxMemPoolEntry,
boost::multi_index::indexed_by<
@@ -294,6 +306,11 @@ public:
boost::multi_index::ordered_non_unique<
boost::multi_index::identity<CTxMemPoolEntry>,
CompareTxMemPoolEntryByFee
+ >,
+ // sorted by entry time
+ boost::multi_index::ordered_non_unique<
+ boost::multi_index::identity<CTxMemPoolEntry>,
+ CompareTxMemPoolEntryByEntryTime
>
>
> indexed_transaction_set;
@@ -328,7 +345,12 @@ public:
std::map<COutPoint, CInPoint> mapNextTx;
std::map<uint256, std::pair<double, CAmount> > mapDeltas;
- CTxMemPool(const CFeeRate& _minRelayFee);
+ /** Create a new CTxMemPool.
+ * minReasonableRelayFee should be a feerate which is, roughly, somewhere
+ * around what it "costs" to relay a transaction around the network and
+ * below which we would reasonably say a transaction has 0-effective-fee.
+ */
+ CTxMemPool(const CFeeRate& _minReasonableRelayFee);
~CTxMemPool();
/**
@@ -338,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
@@ -353,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;
@@ -365,7 +388,7 @@ public:
/** Affect CreateNewBlock prioritisation of transactions */
void PrioritiseTransaction(const uint256 hash, const std::string strHash, double dPriorityDelta, const CAmount& nFeeDelta);
- void ApplyDeltas(const uint256 hash, double &dPriorityDelta, CAmount &nFeeDelta);
+ void ApplyDeltas(const uint256 hash, double &dPriorityDelta, CAmount &nFeeDelta) const;
void ClearPrioritisation(const uint256 hash);
public:
@@ -397,6 +420,20 @@ public:
*/
bool CalculateMemPoolAncestors(const CTxMemPoolEntry &entry, setEntries &setAncestors, uint64_t limitAncestorCount, uint64_t limitAncestorSize, uint64_t limitDescendantCount, uint64_t limitDescendantSize, std::string &errString, bool fSearchForParents = true);
+ /** The minimum fee to get into the mempool, which may itself not be enough
+ * for larger-sized transactions.
+ * The minReasonableRelayFee constructor arg is used to bound the time it
+ * takes the fee rate to go back down all the way to 0. When the feerate
+ * would otherwise be half of this, it is set to 0 instead.
+ */
+ CFeeRate GetMinFee(size_t sizelimit) const;
+
+ /** Remove transactions from the mempool until its dynamic size is <= sizelimit. */
+ void TrimToSize(size_t sizelimit);
+
+ /** Expire all transaction (and their dependencies) in the mempool older than time. Return the number of removed transactions. */
+ int Expire(int64_t time);
+
unsigned long size()
{
LOCK(cs);
diff --git a/src/univalue/.gitignore b/src/univalue/.gitignore
index ca9e842348..a7a2ca9197 100644
--- a/src/univalue/.gitignore
+++ b/src/univalue/.gitignore
@@ -19,4 +19,13 @@ test-driver
libtool
ltmain.sh
+*.a
+*.la
+*.lo
+*.logs
*.o
+*.pc
+*.trs
+
+.dirstamp
+.libs
diff --git a/src/univalue/Makefile.am b/src/univalue/Makefile.am
index 2800f466dc..df9e66229c 100644
--- a/src/univalue/Makefile.am
+++ b/src/univalue/Makefile.am
@@ -5,20 +5,20 @@ ACLOCAL_AMFLAGS = -I build-aux/m4
include_HEADERS = include/univalue.h
noinst_HEADERS = lib/univalue_escapes.h
-lib_LTLIBRARIES = lib/libunivalue.la
+lib_LTLIBRARIES = libunivalue.la
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = pc/libunivalue.pc
-lib_libunivalue_la_SOURCES = \
+libunivalue_la_SOURCES = \
lib/univalue.cpp \
lib/univalue_read.cpp \
lib/univalue_write.cpp
-lib_libunivalue_la_LDFLAGS = \
+libunivalue_la_LDFLAGS = \
-version-info $(LIBUNIVALUE_CURRENT):$(LIBUNIVALUE_REVISION):$(LIBUNIVALUE_AGE) \
-no-undefined
-lib_libunivalue_la_CXXFLAGS = -I$(top_srcdir)/include
+libunivalue_la_CXXFLAGS = -I$(top_srcdir)/include
TESTS = test/unitester
@@ -38,7 +38,7 @@ noinst_PROGRAMS = $(TESTS)
TEST_DATA_DIR=test
test_unitester_SOURCES = test/unitester.cpp
-test_unitester_LDADD = lib/libunivalue.la
+test_unitester_LDADD = libunivalue.la
test_unitester_CXXFLAGS = -I$(top_srcdir)/include -DJSON_TEST_SRC=\"$(srcdir)/$(TEST_DATA_DIR)\"
test_unitester_LDFLAGS = -static $(LIBTOOL_APP_LDFLAGS)
diff --git a/src/univalue/build-aux/m4/.empty b/src/univalue/build-aux/m4/.empty
deleted file mode 100644
index e69de29bb2..0000000000
--- a/src/univalue/build-aux/m4/.empty
+++ /dev/null
diff --git a/src/univalue/build-aux/m4/.gitignore b/src/univalue/build-aux/m4/.gitignore
new file mode 100644
index 0000000000..f063686524
--- /dev/null
+++ b/src/univalue/build-aux/m4/.gitignore
@@ -0,0 +1 @@
+/*.m4
diff --git a/src/univalue/lib/.gitignore b/src/univalue/lib/.gitignore
index ca8c16dcd4..ee7fc2851c 100644
--- a/src/univalue/lib/.gitignore
+++ b/src/univalue/lib/.gitignore
@@ -1,10 +1,2 @@
-
-libunivalue-uninstalled.pc
-libunivalue.pc
-libunivalue.a
gen
-
.libs
-*.lo
-*.la
-
diff --git a/src/univalue/test/.gitignore b/src/univalue/test/.gitignore
index e4dea0df72..4afa094b10 100644
--- a/src/univalue/test/.gitignore
+++ b/src/univalue/test/.gitignore
@@ -1,7 +1 @@
-
unitester
-
-*.log
-*.trs
-
-.libs
diff --git a/src/util.cpp b/src/util.cpp
index f50d25e17a..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')
@@ -280,10 +285,13 @@ int LogPrintStr(const std::string &str)
{
int ret = 0; // Returns total number of characters written
static bool fStartedNewLine = true;
+
+ string strTimestamped = LogTimestampStr(str, &fStartedNewLine);
+
if (fPrintToConsole)
{
// print to console
- ret = fwrite(str.data(), 1, str.size(), stdout);
+ ret = fwrite(strTimestamped.data(), 1, strTimestamped.size(), stdout);
fflush(stdout);
}
else if (fPrintToDebugLog)
@@ -291,8 +299,6 @@ int LogPrintStr(const std::string &str)
boost::call_once(&DebugPrintInit, debugPrintInitFlag);
boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
- string strTimestamped = LogTimestampStr(str, &fStartedNewLine);
-
// buffer if we haven't opened the log yet
if (fileout == NULL) {
assert(vMsgsBeforeOpenLog);
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/wallet.cpp b/src/wallet/wallet.cpp
index bd3004061b..3f2d5a05f6 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -2863,6 +2863,6 @@ int CMerkleTx::GetBlocksToMaturity() const
bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectAbsurdFee)
{
CValidationState state;
- return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, fRejectAbsurdFee);
+ return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, false, fRejectAbsurdFee);
}
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++;