mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-21 15:50:07 +01:00
Compare commits
201 Commits
v26.2
...
v0.12.1rc2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
465d30915c | ||
|
|
46898e7e94 | ||
|
|
cada7c2418 | ||
|
|
4c3a00d35c | ||
|
|
90f1d246d3 | ||
|
|
4226aacdba | ||
|
|
c2106543fe | ||
|
|
a784675a32 | ||
|
|
e3341aa94e | ||
|
|
834aaef7bd | ||
|
|
640666b22f | ||
|
|
e10c044c78 | ||
|
|
c5f94f6584 | ||
|
|
869262605f | ||
|
|
4d035bcc9a | ||
|
|
c270b62cc2 | ||
|
|
ba80ceef59 | ||
|
|
caf138122d | ||
|
|
a0cea89456 | ||
|
|
26e9a05cc3 | ||
|
|
c0fe2c9e03 | ||
|
|
597494f5a9 | ||
|
|
7ffc2bd943 | ||
|
|
19866c1ffc | ||
|
|
3a99feba85 | ||
|
|
159ee3dd90 | ||
|
|
9713ed3015 | ||
|
|
648be9b442 | ||
|
|
ee40924fef | ||
|
|
6ff0b9f96e | ||
|
|
0710b303d6 | ||
|
|
8ebc6f2aac | ||
|
|
0bdaacd791 | ||
|
|
5f90d4e294 | ||
|
|
6f83cf2adb | ||
|
|
ade85e126d | ||
|
|
c8d309e4b4 | ||
|
|
6170506fdf | ||
|
|
c0c5e09fe2 | ||
|
|
197c3760ff | ||
|
|
0a79c04af3 | ||
|
|
0d09af77b7 | ||
|
|
15ba08c3b5 | ||
|
|
f04f4fd2ee | ||
|
|
ca8f160af5 | ||
|
|
a10da9aa49 | ||
|
|
00d57b4d3a | ||
|
|
35af157641 | ||
|
|
188ca9c305 | ||
|
|
ea52530906 | ||
|
|
b466264635 | ||
|
|
02d707ff37 | ||
|
|
e473c2dd02 | ||
|
|
04503f78c7 | ||
|
|
772863583c | ||
|
|
68134263e2 | ||
|
|
10be44a0bb | ||
|
|
c3faf78c0e | ||
|
|
947c4ff724 | ||
|
|
9cb31e664a | ||
|
|
889e5b3050 | ||
|
|
1329963001 | ||
|
|
00ec73e062 | ||
|
|
b46000415c | ||
|
|
3450f4cc95 | ||
|
|
d0dbb6daee | ||
|
|
827a2b6736 | ||
|
|
43484d7c08 | ||
|
|
73a0375ebe | ||
|
|
e16f5b40c2 | ||
|
|
b2f2b85ad5 | ||
|
|
b9ed8c9969 | ||
|
|
996c27d1d9 | ||
|
|
b1f031d435 | ||
|
|
a7939f8695 | ||
|
|
294f4320a2 | ||
|
|
c76bfff11e | ||
|
|
af9f564267 | ||
|
|
4ad418bc9b | ||
|
|
86755bc85a | ||
|
|
e2d9a58588 | ||
|
|
b2287a7e01 | ||
|
|
5f456a6546 | ||
|
|
e8d19ab79f | ||
|
|
1205f87d36 | ||
|
|
8e09f914f8 | ||
|
|
46dbcd4833 | ||
|
|
cb83beb375 | ||
|
|
32e3538752 | ||
|
|
8c5f90306c | ||
|
|
15c0263ff1 | ||
|
|
54d390780f | ||
|
|
a683d20d5f | ||
|
|
38bf790d70 | ||
|
|
aa26ee0101 | ||
|
|
568c32411d | ||
|
|
65d384fe82 | ||
|
|
42b521d8a0 | ||
|
|
58e3abfffc | ||
|
|
be4b474287 | ||
|
|
46d7eb6137 | ||
|
|
fe074ccb37 | ||
|
|
7c5e90e8dd | ||
|
|
1bc1d796be | ||
|
|
5df314b927 | ||
|
|
b16b5bc191 | ||
|
|
f4b2ce8ee8 | ||
|
|
7726c487f8 | ||
|
|
52b29dca76 | ||
|
|
da83ecd454 | ||
|
|
e25b158ab8 | ||
|
|
64612f1820 | ||
|
|
5bb3e263e2 | ||
|
|
621bbd88ba | ||
|
|
4b8d2bc625 | ||
|
|
cda064caa1 | ||
|
|
fa311338d2 | ||
|
|
51af87f078 | ||
|
|
236686b844 | ||
|
|
44438a192a | ||
|
|
a74fa1f06b | ||
|
|
351ffd8482 | ||
|
|
c0d2382170 | ||
|
|
d8b062d752 | ||
|
|
d04525a065 | ||
|
|
1709cc5cb0 | ||
|
|
b0cb055673 | ||
|
|
8b7a0f88cb | ||
|
|
098fcb5694 | ||
|
|
1488fc8eac | ||
|
|
2e552b04c2 | ||
|
|
5cacb8f319 | ||
|
|
fa8c497d84 | ||
|
|
d7c54c5a9d | ||
|
|
fbea2f64e2 | ||
|
|
f17b00b66f | ||
|
|
e20704ba71 | ||
|
|
6f8346db5f | ||
|
|
605de4a88a | ||
|
|
6191a9b628 | ||
|
|
6307beb09f | ||
|
|
6092ff205b | ||
|
|
82667afd78 | ||
|
|
5771b71ca5 | ||
|
|
3d5cf698d6 | ||
|
|
a06a8b4888 | ||
|
|
2a3161bf8b | ||
|
|
afe825f075 | ||
|
|
071f704a70 | ||
|
|
fd4bd5009e | ||
|
|
2c5c2154c9 | ||
|
|
fab88af4d5 | ||
|
|
a36d79bfe2 | ||
|
|
8f25d6eb0e | ||
|
|
fa0a391b35 | ||
|
|
d570a1f41b | ||
|
|
a344880e6a | ||
|
|
5b144b7113 | ||
|
|
d513405cb7 | ||
|
|
4707797df2 | ||
|
|
9265e89a77 | ||
|
|
1320300ea1 | ||
|
|
fa4ba40d8c | ||
|
|
b1a8374aaa | ||
|
|
daa8da281b | ||
|
|
fabba1c1a4 | ||
|
|
ff9b610026 | ||
|
|
1ed938b5fe | ||
|
|
333e1eaeea | ||
|
|
5cadf3eb60 | ||
|
|
bfdaa3c87f | ||
|
|
e08b7cb33c | ||
|
|
3cb066c62b | ||
|
|
a75a03a5f2 | ||
|
|
bdd0f9e286 | ||
|
|
f6c8c1242b | ||
|
|
e70fc6f842 | ||
|
|
5ba42bad6d | ||
|
|
2d6a493493 | ||
|
|
76de36fd2e | ||
|
|
453c56701a | ||
|
|
9ef7c54ef0 | ||
|
|
301f16ad1c | ||
|
|
12c469b236 | ||
|
|
eccd67106d | ||
|
|
f3ad812208 | ||
|
|
9572e4944a | ||
|
|
fa8c8d7fa6 | ||
|
|
10b88be798 | ||
|
|
06c6a58463 | ||
|
|
f43c2f9a8a | ||
|
|
8fc174aae6 | ||
|
|
44fef99e66 | ||
|
|
96e8d12033 | ||
|
|
b2d7ada372 | ||
|
|
82aff880d3 | ||
|
|
f31955d9da | ||
|
|
6ba25d2886 | ||
|
|
cfb44ce97a | ||
|
|
2985000808 | ||
|
|
45b8e278fb |
@@ -3,6 +3,12 @@
|
||||
# compiler key (which we don't use anyway). This is worked around for now by
|
||||
# replacing the "compilers" with a build name prefixed by the no-op ":"
|
||||
# command. See: https://github.com/travis-ci/travis-ci/issues/4393
|
||||
# - sudo/dist/group are set so as to get Blue Box VMs, necessary for [loopback]
|
||||
# IPv6 support
|
||||
|
||||
sudo: required
|
||||
dist: precise
|
||||
group: legacy
|
||||
|
||||
os: linux
|
||||
language: cpp
|
||||
@@ -52,7 +58,7 @@ install:
|
||||
before_script:
|
||||
- unset CC; unset CXX
|
||||
- mkdir -p depends/SDKs depends/sdk-sources
|
||||
- if [ -n "$OSX_SDK" -a ! -f depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then wget $SDK_URL/MacOSX${OSX_SDK}.sdk.tar.gz -O depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi
|
||||
- if [ -n "$OSX_SDK" -a ! -f depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then curl --location --fail $SDK_URL/MacOSX${OSX_SDK}.sdk.tar.gz -o depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi
|
||||
- if [ -n "$OSX_SDK" -a -f depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then tar -C depends/SDKs -xf depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi
|
||||
- make $MAKEJOBS -C depends HOST=$HOST $DEP_OPTS
|
||||
script:
|
||||
|
||||
@@ -95,6 +95,8 @@ Anyone may participate in peer review which is expressed by comments in the pull
|
||||
- Concept ACK means "I agree in the general principle of this pull request";
|
||||
- Nit refers to trivial, often non-blocking issues.
|
||||
|
||||
Reviewers should include the commit hash which they reviewed in their comments.
|
||||
|
||||
Project maintainers reserve the right to weigh the opinions of peer reviewers using common sense judgement and also may weight based on meritocracy: Those that have demonstrated a deeper commitment and understanding towards the project (over time) or have clear domain expertise may naturally have more weight, as one would expect in all walks of life.
|
||||
|
||||
Where a patch set affects consensus critical code, the bar will be set much higher in terms of discussion and peer review requirements, keeping in mind that mistakes could be very costly to the wider community. This includes refactoring of consensus critical code.
|
||||
|
||||
2
COPYING
2
COPYING
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2009-2015 The Bitcoin Core developers
|
||||
Copyright (c) 2009-2016 The Bitcoin Core developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -26,6 +26,9 @@ OSX_QT_TRANSLATIONS = da,de,es,hu,ru,uk,zh_CN,zh_TW
|
||||
|
||||
DIST_DOCS = $(wildcard doc/*.md) $(wildcard doc/release-notes/*.md)
|
||||
|
||||
BIN_CHECKS=$(top_srcdir)/contrib/devtools/symbol-check.py \
|
||||
$(top_srcdir)/contrib/devtools/security-check.py
|
||||
|
||||
WINDOWS_PACKAGING = $(top_srcdir)/share/pixmaps/bitcoin.ico \
|
||||
$(top_srcdir)/share/pixmaps/nsis-header.bmp \
|
||||
$(top_srcdir)/share/pixmaps/nsis-wizard.bmp \
|
||||
@@ -213,7 +216,7 @@ endif
|
||||
|
||||
dist_noinst_SCRIPTS = autogen.sh
|
||||
|
||||
EXTRA_DIST = $(top_srcdir)/share/genbuild.sh qa/pull-tester/rpc-tests.py qa/rpc-tests $(DIST_DOCS) $(WINDOWS_PACKAGING) $(OSX_PACKAGING)
|
||||
EXTRA_DIST = $(top_srcdir)/share/genbuild.sh qa/pull-tester/rpc-tests.py qa/rpc-tests $(DIST_DOCS) $(WINDOWS_PACKAGING) $(OSX_PACKAGING) $(BIN_CHECKS)
|
||||
|
||||
CLEANFILES = $(OSX_DMG) $(BITCOIN_WIN_INSTALLER)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ Bitcoin Core integration/staging tree
|
||||
|
||||
[](https://travis-ci.org/bitcoin/bitcoin)
|
||||
|
||||
https://www.bitcoin.org
|
||||
https://bitcoincore.org
|
||||
|
||||
What is Bitcoin?
|
||||
----------------
|
||||
@@ -15,13 +15,14 @@ out collectively by the network. Bitcoin Core is the name of open source
|
||||
software which enables the use of this currency.
|
||||
|
||||
For more information, as well as an immediately useable, binary version of
|
||||
the Bitcoin Core software, see https://www.bitcoin.org/en/download.
|
||||
the Bitcoin Core software, see https://bitcoin.org/en/download, or read the
|
||||
[original whitepaper](https://bitcoincore.org/bitcoin.pdf).
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
Bitcoin Core is released under the terms of the MIT license. See [COPYING](COPYING) for more
|
||||
information or see http://opensource.org/licenses/MIT.
|
||||
information or see https://opensource.org/licenses/MIT.
|
||||
|
||||
Development Process
|
||||
-------------------
|
||||
|
||||
41
configure.ac
41
configure.ac
@@ -1,11 +1,11 @@
|
||||
dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N)
|
||||
AC_PREREQ([2.60])
|
||||
define(_CLIENT_VERSION_MAJOR, 0)
|
||||
define(_CLIENT_VERSION_MINOR, 11)
|
||||
define(_CLIENT_VERSION_REVISION, 99)
|
||||
define(_CLIENT_VERSION_MINOR, 12)
|
||||
define(_CLIENT_VERSION_REVISION, 1)
|
||||
define(_CLIENT_VERSION_BUILD, 0)
|
||||
define(_CLIENT_VERSION_IS_RELEASE, false)
|
||||
define(_COPYRIGHT_YEAR, 2015)
|
||||
define(_CLIENT_VERSION_IS_RELEASE, true)
|
||||
define(_COPYRIGHT_YEAR, 2016)
|
||||
AC_INIT([Bitcoin Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[https://github.com/bitcoin/bitcoin/issues],[bitcoin])
|
||||
AC_CONFIG_SRCDIR([src/main.cpp])
|
||||
AC_CONFIG_HEADERS([src/config/bitcoin-config.h])
|
||||
@@ -64,6 +64,8 @@ AC_PATH_PROG([GIT], [git])
|
||||
AC_PATH_PROG(CCACHE,ccache)
|
||||
AC_PATH_PROG(XGETTEXT,xgettext)
|
||||
AC_PATH_PROG(HEXDUMP,hexdump)
|
||||
AC_PATH_TOOL(READELF, readelf)
|
||||
AC_PATH_TOOL(CPPFILT, c++filt)
|
||||
|
||||
dnl pkg-config check.
|
||||
PKG_PROG_PKG_CONFIG
|
||||
@@ -92,6 +94,11 @@ AC_ARG_ENABLE(tests,
|
||||
[use_tests=$enableval],
|
||||
[use_tests=yes])
|
||||
|
||||
AC_ARG_ENABLE(gui-tests,
|
||||
AS_HELP_STRING([--disable-gui-tests],[do not compile GUI tests (default is to compile if GUI and tests enabled)]),
|
||||
[use_gui_tests=$enableval],
|
||||
[use_gui_tests=$use_tests])
|
||||
|
||||
AC_ARG_ENABLE(bench,
|
||||
AS_HELP_STRING([--disable-bench],[do not compile benchmarks (default is to compile)]),
|
||||
[use_bench=$enableval],
|
||||
@@ -409,6 +416,10 @@ AX_GCC_FUNC_ATTRIBUTE([dllimport])
|
||||
|
||||
if test x$use_glibc_compat != xno; then
|
||||
|
||||
#glibc absorbed clock_gettime in 2.17. librt (its previous location) is safe to link
|
||||
#in anyway for back-compat.
|
||||
AC_CHECK_LIB([rt],[clock_gettime],, AC_MSG_ERROR(lib missing))
|
||||
|
||||
#__fdelt_chk's params and return type have changed from long unsigned int to long int.
|
||||
# See which one is present here.
|
||||
AC_MSG_CHECKING(__fdelt_chk type)
|
||||
@@ -422,7 +433,8 @@ if test x$use_glibc_compat != xno; then
|
||||
[ fdelt_type="long int"])
|
||||
AC_MSG_RESULT($fdelt_type)
|
||||
AC_DEFINE_UNQUOTED(FDELT_TYPE, $fdelt_type,[parameter and return value type for __fdelt_chk])
|
||||
|
||||
else
|
||||
AC_SEARCH_LIBS([clock_gettime],[rt])
|
||||
fi
|
||||
|
||||
if test x$TARGET_OS != xwindows; then
|
||||
@@ -489,8 +501,6 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/socket.h>]],
|
||||
[ AC_MSG_RESULT(no)]
|
||||
)
|
||||
|
||||
AC_SEARCH_LIBS([clock_gettime],[rt])
|
||||
|
||||
AC_MSG_CHECKING([for visibility attribute])
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE([
|
||||
int foo_def( void ) __attribute__((visibility("default")));
|
||||
@@ -827,8 +837,8 @@ else
|
||||
fi
|
||||
|
||||
dnl these are only used when qt is enabled
|
||||
BUILD_TEST_QT=""
|
||||
if test x$bitcoin_enable_qt != xno; then
|
||||
BUILD_QT=qt
|
||||
dnl enable dbus support
|
||||
AC_MSG_CHECKING([whether to build GUI with support for D-Bus])
|
||||
if test x$bitcoin_enable_qt_dbus != xno; then
|
||||
@@ -858,9 +868,9 @@ if test x$bitcoin_enable_qt != xno; then
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether to build test_bitcoin-qt])
|
||||
if test x$use_tests$bitcoin_enable_qt_test = xyesyes; then
|
||||
if test x$use_gui_tests$bitcoin_enable_qt_test = xyesyes; then
|
||||
AC_MSG_RESULT([yes])
|
||||
BUILD_TEST_QT="test"
|
||||
BUILD_TEST_QT="yes"
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
@@ -871,9 +881,10 @@ AM_CONDITIONAL([ENABLE_ZMQ], [test "x$use_zmq" = "xyes"])
|
||||
AC_MSG_CHECKING([whether to build test_bitcoin])
|
||||
if test x$use_tests = xyes; then
|
||||
AC_MSG_RESULT([yes])
|
||||
BUILD_TEST="test"
|
||||
BUILD_TEST="yes"
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
BUILD_TEST=""
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether to reduce exports])
|
||||
@@ -891,15 +902,16 @@ AM_CONDITIONAL([TARGET_DARWIN], [test x$TARGET_OS = xdarwin])
|
||||
AM_CONDITIONAL([BUILD_DARWIN], [test x$BUILD_OS = xdarwin])
|
||||
AM_CONDITIONAL([TARGET_WINDOWS], [test x$TARGET_OS = xwindows])
|
||||
AM_CONDITIONAL([ENABLE_WALLET],[test x$enable_wallet = xyes])
|
||||
AM_CONDITIONAL([ENABLE_TESTS],[test x$use_tests = xyes])
|
||||
AM_CONDITIONAL([ENABLE_TESTS],[test x$BUILD_TEST = 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_QT_TESTS],[test x$BUILD_TEST_QT = xyes])
|
||||
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])
|
||||
AM_CONDITIONAL([USE_COMPARISON_TOOL_REORG_TESTS],[test x$use_comparison_tool_reorg_test != xno])
|
||||
AM_CONDITIONAL([GLIBC_BACK_COMPAT],[test x$use_glibc_compat = xyes])
|
||||
AM_CONDITIONAL([HARDEN],[test x$use_hardening = xyes])
|
||||
|
||||
AC_DEFINE(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR, [Major version])
|
||||
AC_DEFINE(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR, [Minor version])
|
||||
@@ -926,9 +938,6 @@ AC_SUBST(USE_QRCODE)
|
||||
AC_SUBST(BOOST_LIBS)
|
||||
AC_SUBST(TESTDEFS)
|
||||
AC_SUBST(LEVELDB_TARGET_FLAGS)
|
||||
AC_SUBST(BUILD_TEST)
|
||||
AC_SUBST(BUILD_QT)
|
||||
AC_SUBST(BUILD_TEST_QT)
|
||||
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])
|
||||
|
||||
@@ -23,7 +23,7 @@ Build-Depends: debhelper,
|
||||
libprotobuf-dev, protobuf-compiler,
|
||||
python
|
||||
Standards-Version: 3.9.2
|
||||
Homepage: https://www.bitcoin.org/
|
||||
Homepage: https://bitcoincore.org/
|
||||
Vcs-Git: git://github.com/bitcoin/bitcoin.git
|
||||
Vcs-Browser: https://github.com/bitcoin/bitcoin
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Upstream-Contact: Satoshi Nakamoto <satoshin@gmx.com>
|
||||
Source: https://github.com/bitcoin/bitcoin
|
||||
|
||||
Files: *
|
||||
Copyright: 2009-2015, Bitcoin Core Developers
|
||||
Copyright: 2009-2016, Bitcoin Core Developers
|
||||
License: Expat
|
||||
Comment: The Bitcoin Core Developers encompasses the current developers listed on bitcoin.org,
|
||||
as well as the numerous contributors to the project.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH BITCOIN-CLI "1" "February 2015" "bitcoin-cli 0.10"
|
||||
.TH BITCOIN-CLI "1" "February 2016" "bitcoin-cli 0.12"
|
||||
.SH NAME
|
||||
bitcoin-cli \- a remote procedure call client for Bitcoin Core.
|
||||
.SH SYNOPSIS
|
||||
@@ -11,31 +11,7 @@ This manual page documents the bitcoin-cli program. bitcoin-cli is an RPC client
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
\fB\-?\fR
|
||||
Show the help message.
|
||||
.TP
|
||||
\fB\-conf=\fR<file>
|
||||
Specify configuration file (default: bitcoin.conf).
|
||||
.TP
|
||||
\fB\-datadir=\fR<dir>
|
||||
Specify data directory.
|
||||
.TP
|
||||
\fB\-testnet\fR
|
||||
Connect to a Bitcoin Core instance running in testnet mode.
|
||||
.TP
|
||||
\fB\-regtest\fR
|
||||
Connect to a Bitcoin Core instance running in regtest mode (see documentation for -regtest on bitcoind).
|
||||
.TP
|
||||
\fB\-rpcuser=\fR<user>
|
||||
Username for JSON\-RPC connections.
|
||||
.TP
|
||||
\fB\-rpcpassword=\fR<pw>
|
||||
Password for JSON\-RPC connections.
|
||||
.TP
|
||||
\fB\-rpcport=\fR<port>
|
||||
Listen for JSON\-RPC connections on <port> (default: 8332 or testnet: 18332).
|
||||
.TP
|
||||
\fB\-rpcconnect=\fR<ip>
|
||||
Send commands to node running on <ip> (default: 127.0.0.1).
|
||||
Show possible options.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
\fBbitcoind\fP, \fBbitcoin.conf\fP
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH BITCOIN-QT "1" "April 2013" "bitcoin-qt 1"
|
||||
.TH BITCOIN-QT "1" "February 2016" "bitcoin-qt 0.12"
|
||||
.SH NAME
|
||||
bitcoin-qt \- peer-to-peer network based digital currency
|
||||
.SH DESCRIPTION
|
||||
@@ -8,184 +8,6 @@ bitcoin\-qt [command\-line options]
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
\-?
|
||||
This help message
|
||||
.TP
|
||||
\fB\-conf=\fR<file>
|
||||
Specify configuration file (default: bitcoin.conf)
|
||||
.TP
|
||||
\fB\-pid=\fR<file>
|
||||
Specify pid file (default: bitcoind.pid)
|
||||
.TP
|
||||
\fB\-gen\fR
|
||||
Generate coins
|
||||
.TP
|
||||
\fB\-gen\fR=\fI0\fR
|
||||
Don't generate coins
|
||||
.TP
|
||||
\fB\-datadir=\fR<dir>
|
||||
Specify data directory
|
||||
.TP
|
||||
\fB\-dbcache=\fR<n>
|
||||
Set database cache size in megabytes (default: 25)
|
||||
.TP
|
||||
\fB\-timeout=\fR<n>
|
||||
Specify connection timeout in milliseconds (default: 5000)
|
||||
.TP
|
||||
\fB\-proxy=\fR<ip:port>
|
||||
Connect through SOCKS5 proxy
|
||||
.TP
|
||||
\fB\-tor=\fR<ip:port>
|
||||
Use proxy to reach tor hidden services (default: same as \fB\-proxy\fR)
|
||||
.TP
|
||||
\fB\-dns\fR
|
||||
Allow DNS lookups for \fB\-addnode\fR, \fB\-seednode\fR and \fB\-connect\fR
|
||||
.TP
|
||||
\fB\-port=\fR<port>
|
||||
Listen for connections on <port> (default: 8333 or testnet: 18333)
|
||||
.TP
|
||||
\fB\-maxconnections=\fR<n>
|
||||
Maintain at most <n> connections to peers (default: 125)
|
||||
.TP
|
||||
\fB\-addnode=\fR<ip>
|
||||
Add a node to connect to and attempt to keep the connection open
|
||||
.TP
|
||||
\fB\-connect=\fR<ip>
|
||||
Connect only to the specified node(s)
|
||||
.TP
|
||||
\fB\-seednode=\fR<ip>
|
||||
Connect to a node to retrieve peer addresses, and disconnect
|
||||
.TP
|
||||
\fB\-externalip=\fR<ip>
|
||||
Specify your own public address
|
||||
.TP
|
||||
\fB\-onlynet=\fR<net>
|
||||
Only connect to nodes in network <net> (IPv4, IPv6 or Tor)
|
||||
.TP
|
||||
\fB\-discover\fR
|
||||
Discover own IP address (default: 1 when listening and no \fB\-externalip\fR)
|
||||
.TP
|
||||
\fB\-checkpoints\fR
|
||||
Only accept block chain matching built\-in checkpoints (default: 1)
|
||||
.TP
|
||||
\fB\-listen\fR
|
||||
Accept connections from outside (default: 1 if no \fB\-proxy\fR or \fB\-connect\fR)
|
||||
.TP
|
||||
\fB\-bind=\fR<addr>
|
||||
Bind to given address and always listen on it. Use [host]:port notation for IPv6
|
||||
.TP
|
||||
\fB\-dnsseed\fR
|
||||
Find peers using DNS lookup (default: 1 unless \fB\-connect\fR)
|
||||
.TP
|
||||
\fB\-banscore=\fR<n>
|
||||
Threshold for disconnecting misbehaving peers (default: 100)
|
||||
.TP
|
||||
\fB\-bantime=\fR<n>
|
||||
Number of seconds to keep misbehaving peers from reconnecting (default: 86400)
|
||||
.TP
|
||||
\fB\-maxreceivebuffer=\fR<n>
|
||||
Maximum per\-connection receive buffer, <n>*1000 bytes (default: 5000)
|
||||
.TP
|
||||
\fB\-maxsendbuffer=\fR<n>
|
||||
Maximum per\-connection send buffer, <n>*1000 bytes (default: 1000)
|
||||
.TP
|
||||
\fB\-upnp\fR
|
||||
Use UPnP to map the listening port (default: 1 when listening)
|
||||
.TP
|
||||
\fB\-paytxfee=\fR<amt>
|
||||
Fee per KB to add to transactions you send
|
||||
.TP
|
||||
\fB\-server\fR
|
||||
Accept command line and JSON\-RPC commands
|
||||
.TP
|
||||
\fB\-testnet\fR
|
||||
Use the test network
|
||||
.TP
|
||||
\fB\-debug\fR
|
||||
Output extra debugging information. Implies all other \fB\-debug\fR* options
|
||||
.TP
|
||||
\fB\-debugnet\fR
|
||||
Output extra network debugging information
|
||||
.TP
|
||||
\fB\-logtimestamps\fR
|
||||
Prepend debug output with timestamp
|
||||
.TP
|
||||
\fB\-shrinkdebugfile\fR
|
||||
Shrink debug.log file on client startup (default: 1 when no \fB\-debug\fR)
|
||||
.TP
|
||||
\fB\-printtoconsole\fR
|
||||
Send trace/debug info to console instead of debug.log file
|
||||
.TP
|
||||
\fB\-rpcuser=\fR<user>
|
||||
Username for JSON\-RPC connections
|
||||
.TP
|
||||
\fB\-rpcpassword=\fR<pw>
|
||||
Password for JSON\-RPC connections
|
||||
.TP
|
||||
\fB\-rpcport=\fR<port>
|
||||
Listen for JSON\-RPC connections on <port> (default: 8332 or testnet: 18332)
|
||||
.TP
|
||||
\fB\-rpcallowip=\fR<ip>
|
||||
Allow JSON\-RPC connections from specified IP address
|
||||
.TP
|
||||
\fB\-rpcthreads=\fR<n>
|
||||
Set the number of threads to service RPC calls (default: 4)
|
||||
.TP
|
||||
\fB\-blocknotify=\fR<cmd>
|
||||
Execute command when the best block changes (%s in cmd is replaced by block hash)
|
||||
.TP
|
||||
\fB\-walletnotify=\fR<cmd>
|
||||
Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)
|
||||
.TP
|
||||
\fB\-alertnotify=\fR<cmd>
|
||||
Execute command when a relevant alert is received (%s in cmd is replaced by message)
|
||||
.TP
|
||||
\fB\-upgradewallet\fR
|
||||
Upgrade wallet to latest format
|
||||
.TP
|
||||
\fB\-keypool=\fR<n>
|
||||
Set key pool size to <n> (default: 100)
|
||||
.TP
|
||||
\fB\-rescan\fR
|
||||
Rescan the block chain for missing wallet transactions
|
||||
.TP
|
||||
\fB\-salvagewallet\fR
|
||||
Attempt to recover private keys from a corrupt wallet.dat
|
||||
.TP
|
||||
\fB\-checkblocks=\fR<n>
|
||||
How many blocks to check at startup (default: 288, 0 = all)
|
||||
.TP
|
||||
\fB\-checklevel=\fR<n>
|
||||
How thorough the block verification is (0\-4, default: 3)
|
||||
.TP
|
||||
\fB\-txindex\fR
|
||||
Maintain a full transaction index (default: 0)
|
||||
.TP
|
||||
\fB\-loadblock=\fR<file>
|
||||
Imports blocks from external blk000??.dat file
|
||||
.TP
|
||||
\fB\-reindex\fR
|
||||
Rebuild block chain index from current blk000??.dat files
|
||||
.TP
|
||||
\fB\-par=\fR<n>
|
||||
Set the number of script verification threads (1\-16, 0=auto, default: 0)
|
||||
.SS "Block creation options:"
|
||||
.TP
|
||||
\fB\-blockminsize=\fR<n>
|
||||
Set minimum block size in bytes (default: 0)
|
||||
.TP
|
||||
\fB\-blockmaxsize=\fR<n>
|
||||
Set maximum block size in bytes (default: 250000)
|
||||
.HP
|
||||
\fB\-blockprioritysize=\fR<n> Set maximum size of high\-priority/low\-fee transactions in bytes (default: 27000)
|
||||
.PP
|
||||
Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)
|
||||
.SS "UI options:"
|
||||
.TP
|
||||
\fB\-lang=\fR<lang>
|
||||
Set language, for example "de_DE" (default: system locale)
|
||||
.TP
|
||||
\fB\-min\fR
|
||||
Start minimized
|
||||
.TP
|
||||
\fB\-splash\fR
|
||||
Show splash screen on startup (default: 1)
|
||||
List options.
|
||||
.SH "SEE ALSO"
|
||||
bitcoind(1)
|
||||
|
||||
@@ -1,75 +1,15 @@
|
||||
.TH BITCOIN.CONF "5" "January 2011" "bitcoin.conf 3.19"
|
||||
.TH BITCOIN.CONF "5" "February 2016" "bitcoin.conf 0.12"
|
||||
.SH NAME
|
||||
bitcoin.conf \- bitcoin configuration file
|
||||
.SH SYNOPSIS
|
||||
All command-line options (except for '\-conf') may be specified in a configuration file, and all configuration file options may also be specified on the command line. Command-line options override values set in the configuration file.
|
||||
.TP
|
||||
The configuration file is a list of 'setting=value' pairs, one per line, with optional comments starting with the '#' character.
|
||||
The configuration file is a list of 'setting=value' pairs, one per line, with optional comments starting with the '#' character. Please refer to bitcoind(1) for a up to date list of valid options.
|
||||
.TP
|
||||
The configuration file is not automatically created; you can create it using your favorite plain-text editor. By default, bitcoind(1) will look for a file named bitcoin.conf(5) in the bitcoin data directory, but both the data directory and the configuration file path may be changed using the '\-datadir' and '\-conf' command-line arguments.
|
||||
.SH LOCATION
|
||||
bitcoin.conf should be located in $HOME/.bitcoin
|
||||
.SH NETWORK-RELATED SETTINGS
|
||||
.TP
|
||||
.TP
|
||||
\fBtestnet=\fR[\fI'1'\fR|\fI'0'\fR]
|
||||
Enable or disable run on the test network instead of the real *bitcoin* network.
|
||||
.TP
|
||||
\fBproxy=\fR\fI'127.0.0.1:9050'\fR
|
||||
Connect via a socks4 proxy.
|
||||
.TP
|
||||
\fBaddnode=\fR\fI'10.0.0.2:8333'\fR
|
||||
Use as many *addnode=* settings as you like to connect to specific peers.
|
||||
.TP
|
||||
\fBconnect=\fR\fI'10.0.0.1:8333'\fR
|
||||
Use as many *connect=* settings as you like to connect ONLY to specific peers.
|
||||
.TP
|
||||
\fRmaxconnections=\fR\fI'value'\fR
|
||||
Maximum number of inbound+outbound connections.
|
||||
.SH JSON-RPC OPTIONS
|
||||
.TP
|
||||
\fBserver=\fR[\fI'1'\fR|\fI'0'\fR]
|
||||
Tells *bitcoin* to accept or not accept JSON-RPC commands.
|
||||
.TP
|
||||
\fBrpcuser=\fR\fI'username'\fR
|
||||
You must set *rpcuser* to secure the JSON-RPC api.
|
||||
.TP
|
||||
\fBrpcpassword=\fR\fI'password'\fR
|
||||
You must set *rpcpassword* to secure the JSON-RPC api.
|
||||
.TP
|
||||
\fBrpcallowip=\fR\fI'192.168.1.*'\fR
|
||||
By default, only RPC connections from localhost are allowed. Specify as many *rpcallowip=* settings as you like to allow connections from other hosts (and you may use * as a wildcard character).
|
||||
.TP
|
||||
\fBrpcport=\fR\fI'8332'\fR
|
||||
Listen for RPC connections on this TCP port.
|
||||
.TP
|
||||
\fBrpcconnect=\fR\fI'127.0.0.1'\fR
|
||||
You can use *bitcoin* or *bitcoind(1)* to send commands to *bitcoin*/*bitcoind(1)* running on another host using this option.
|
||||
.TP
|
||||
.SH MISCELLANEOUS OPTIONS
|
||||
.TP
|
||||
\fBgen=\fR[\fI'0'\fR|\fI'1'\fR]
|
||||
Enable or disable attempt to generate bitcoins.
|
||||
.TP
|
||||
\fB4way=\fR[\fI'0'\fR|\fI'1'\fR]
|
||||
Enable or disable use SSE instructions to try to generate bitcoins faster.
|
||||
.TP
|
||||
\fBkeypool=\fR\fI'100'\fR
|
||||
Pre-generate this many public/private key pairs, so wallet backups will be valid for both prior transactions and several dozen future transactions.
|
||||
.TP
|
||||
\fBpaytxfee=\fR\fI'0.00'\fR
|
||||
Pay an optional transaction fee every time you send bitcoins. Transactions with fees are more likely than free transactions to be included in generated blocks, so may be validated sooner.
|
||||
.TP
|
||||
\fBallowreceivebyip=\fR\fI'1'\fR
|
||||
Allow direct connections for the 'pay via IP address' feature.
|
||||
.TP
|
||||
.SH USER INTERFACE OPTIONS
|
||||
.TP
|
||||
\fBmin=\fR[\fI'0'\fR|\fI'1'\fR]
|
||||
Enable or disable start bitcoind minimized.
|
||||
.TP
|
||||
\fBminimizetotray=\fR[\fI'0'\fR|\fI'1'\fR]
|
||||
Enable or disable minimize to the system tray.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
bitcoind(1)
|
||||
.SH AUTHOR
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH BITCOIND "1" "January 2011" "bitcoind 3.19"
|
||||
.TH BITCOIND "1" "February 2016" "bitcoind 0.12"
|
||||
.SH NAME
|
||||
bitcoind \- peer-to-peer network based digital currency
|
||||
.SH SYNOPSIS
|
||||
@@ -6,185 +6,20 @@ bitcoin [options] <command> [params]
|
||||
.TP
|
||||
bitcoin [options] help <command> \- Get help for a command
|
||||
.SH DESCRIPTION
|
||||
This manual page documents the bitcoind program. Bitcoin is a peer-to-peer digital currency. Peer-to-peer (P2P) means that there is no central authority to issue new money or keep track of transactions. Instead, these tasks are managed collectively by the nodes of the network. Advantages:
|
||||
|
||||
Bitcoins can be sent easily through the Internet, without having to trust middlemen. Transactions are designed to be irreversible. Be safe from instability caused by fractional reserve banking and central banks. The limited inflation of the Bitcoin system’s money supply is distributed evenly (by CPU power) throughout the network, not monopolized by banks.
|
||||
This manual page documents the bitcoind program. Bitcoin is an experimental new digital currency that enables instant payments to anyone, anywhere in the world. Bitcoin uses peer-to-peer technology to operate with no central authority: managing transactions and issuing money are carried out collectively by the network. Bitcoin Core is the name of open source software which enables the use of this currency.
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
\fB\-conf=\fR<file>
|
||||
Specify configuration file (default: bitcoin.conf)
|
||||
.TP
|
||||
\fB\-gen\fR
|
||||
Generate coins
|
||||
.TP
|
||||
\fB\-gen\fR=\fI0\fR
|
||||
Don't generate coins
|
||||
.TP
|
||||
\fB\-min\fR
|
||||
Start minimized
|
||||
.TP
|
||||
\fB\-datadir=\fR<dir>
|
||||
Specify data directory
|
||||
.TP
|
||||
\fB\-proxy=\fR<ip:port>
|
||||
Connect through SOCKS5 proxy
|
||||
.TP
|
||||
\fB\-addnode=\fR<ip>
|
||||
Add a node to connect to
|
||||
.TP
|
||||
\fB\-connect=\fR<ip>
|
||||
Connect only to the specified node
|
||||
.TP
|
||||
\fB\-paytxfee=\fR<amt>
|
||||
Fee per KB to add to transactions you send
|
||||
.TP
|
||||
\fB\-server\fR
|
||||
Accept command line and JSON\-RPC commands
|
||||
.TP
|
||||
\fB\-daemon\fR
|
||||
Run in the background as a daemon and accept commands
|
||||
.TP
|
||||
\fB\-testnet\fR
|
||||
Use the test network
|
||||
.TP
|
||||
\fB\-rpcuser=\fR<user>
|
||||
Username for JSON\-RPC connections
|
||||
.TP
|
||||
\fB\-rpcpassword=\fR<pw>
|
||||
Password for JSON\-RPC connections
|
||||
.TP
|
||||
\fB\-rpcport=\fR<port>
|
||||
Listen for JSON\-RPC connections on <port>
|
||||
.TP
|
||||
\fB\-rpcallowip=\fR<ip>
|
||||
Allow JSON\-RPC connections from specified IP address
|
||||
.TP
|
||||
\fB\-rpcconnect=\fR<ip>
|
||||
Send commands to node running on <ip>
|
||||
.TP
|
||||
\-?
|
||||
This help message
|
||||
List of possible options.
|
||||
.SH COMMANDS
|
||||
.TP
|
||||
\fBbackupwallet 'destination'\fR
|
||||
Safely copies *wallet.dat* to 'destination', which can be a directory or a path with filename.
|
||||
.TP
|
||||
\fBgetaccount 'bitcoinaddress'\fR
|
||||
DEPRECATED. Returns the account associated with the given address.
|
||||
.TP
|
||||
\fBsetaccount 'bitcoinaddress' ['account']\fR
|
||||
DEPRECATED. Sets the ['account'] associated with the given address. ['account'] may be omitted to remove an address from ['account'].
|
||||
.TP
|
||||
\fBgetaccountaddress 'account'\fR
|
||||
DEPRECATED. Returns a new bitcoin address for 'account'.
|
||||
.TP
|
||||
\fBgetaddressesbyaccount 'account'\fR
|
||||
DEPRECATED. Returns the list of addresses associated with the given 'account'.
|
||||
.TP
|
||||
\fBgetbalance 'account'\fR
|
||||
Returns the server's available balance, or the balance for 'account' (accounts are deprecated).
|
||||
.TP
|
||||
\fBgetblockcount\fR
|
||||
Returns the number of blocks in the longest block chain.
|
||||
.TP
|
||||
\fBgetblocknumber\fR
|
||||
Returns the block number of the latest block in the longest block chain.
|
||||
.TP
|
||||
\fBgetconnectioncount\fR
|
||||
Returns the number of connections to other nodes.
|
||||
.TP
|
||||
\fBgetdifficulty\fR
|
||||
Returns the proof-of-work difficulty as a multiple of the minimum difficulty.
|
||||
.TP
|
||||
\fBgetgenerate\fR
|
||||
Returns boolean true if server is trying to generate bitcoins, false otherwise.
|
||||
.TP
|
||||
\fBsetgenerate 'generate' ['genproclimit']\fR
|
||||
Generation is limited to ['genproclimit'] processors, \-1 is unlimited.
|
||||
.TP
|
||||
\fBgethashespersec\fR
|
||||
Returns a recent hashes per second performance measurement while generating.
|
||||
.TP
|
||||
\fBgetinfo\fR
|
||||
Returns an object containing server information.
|
||||
.TP
|
||||
\fBgetnewaddress 'account'\fR
|
||||
Returns a new bitcoin address for receiving payments. If 'account' is specified (deprecated), it is added to the address book so payments received with the address will be credited to 'account'.
|
||||
.TP
|
||||
\fBgetreceivedbyaccount 'account' ['minconf=1']\fR
|
||||
DEPRECATED. Returns the total amount received by addresses associated with 'account' in transactions with at least ['minconf'] confirmations.
|
||||
.TP
|
||||
\fBgetreceivedbyaddress 'bitcoinaddress' ['minconf=1']\fR
|
||||
Returns the total amount received by 'bitcoinaddress' in transactions with at least ['minconf'] confirmations.
|
||||
.TP
|
||||
\fBgettransaction 'txid'\fR
|
||||
Returns information about a specific transaction, given hexadecimal transaction ID.
|
||||
.TP
|
||||
\fBgetwork 'data'\fR
|
||||
If 'data' is specified, tries to solve the block and returns true if it was successful. If 'data' is not specified, returns formatted hash 'data' to work on:
|
||||
\fBhelp\fR
|
||||
List commands.
|
||||
|
||||
"midstate" : precomputed hash state after hashing the first half of the data.
|
||||
"data" : block data.
|
||||
"hash1" : formatted hash buffer for second hash.
|
||||
"target" : little endian hash target.
|
||||
.TP
|
||||
\fBhelp 'command'\fR
|
||||
List commands, or get help for a command.
|
||||
.TP
|
||||
\fBlistaccounts ['minconf=1']\fR
|
||||
DEPRECATED. List accounts and their current balances.
|
||||
*note: requires bitcoin 0.3.20 or later.
|
||||
.TP
|
||||
\fBlistreceivedbyaccount ['minconf=1'] ['includeempty=false']\fR
|
||||
['minconf'] is the minimum number of confirmations before payments are included. ['includeempty'] whether to include addresses that haven't received any payments. Returns an array of objects containing:
|
||||
|
||||
"account" : DEPRECATED. the account of the receiving address.
|
||||
"amount" : total amount received by the address.
|
||||
"confirmations" : number of confirmations of the most recent transaction included.
|
||||
.TP
|
||||
\fBlistreceivedbyaddress ['minconf=1'] ['includeempty=false']\fR
|
||||
['minconf'] is the minimum number of confirmations before payments are included. ['includeempty'] whether to include addresses that haven't received any payments. Returns an array of objects containing:
|
||||
|
||||
"address" : receiving address.
|
||||
"account" : DEPRECATED. the account of the receiving address.
|
||||
"amount" : total amount received by the address.
|
||||
"confirmations" : number of confirmations of the most recent transaction included.
|
||||
.TP
|
||||
\fBlisttransactions 'account' ['count=10']\fR
|
||||
Returns a list of the last ['count'] transactions for 'account' \- for all accounts if 'account' is not specified or is "*". Each entry in the list may contain:
|
||||
|
||||
"category" : will be generate, send, receive, or move.
|
||||
"amount" : amount of transaction.
|
||||
"fee" : Fee (if any) paid (only for send transactions).
|
||||
"confirmations" : number of confirmations (only for generate/send/receive).
|
||||
"txid" : transaction ID (only for generate/send/receive).
|
||||
"otheraccount" : account funds were moved to or from (only for move).
|
||||
"message" : message associated with transaction (only for send).
|
||||
"to" : message-to associated with transaction (only for send).
|
||||
|
||||
*note: requires bitcoin 0.3.20 or later.
|
||||
.TP
|
||||
\fBmove <'fromaccount'> <'toaccount'> <'amount'> ['minconf=1'] ['comment']\fR
|
||||
DEPRECATED. Moves funds between accounts.
|
||||
.TP
|
||||
\fBsendfrom* <'account'> <'bitcoinaddress'> <'amount'> ['minconf=1'] ['comment'] ['comment-to']\fR
|
||||
DEPRECATED. Sends amount from account's balance to 'bitcoinaddress'. This method will fail if there is less than amount bitcoins with ['minconf'] confirmations in the account's balance (unless account is the empty-string-named default account; it behaves like the *sendtoaddress* method). Returns transaction ID on success.
|
||||
.TP
|
||||
\fBsendtoaddress 'bitcoinaddress' 'amount' ['comment'] ['comment-to']\fR
|
||||
Sends amount from the server's available balance to 'bitcoinaddress'. amount is a real and is rounded to the nearest 0.01. Returns transaction id on success.
|
||||
.TP
|
||||
\fBstop\fR
|
||||
Stops the bitcoin server.
|
||||
.TP
|
||||
\fBvalidateaddress 'bitcoinaddress'\fR
|
||||
Checks that 'bitcoinaddress' looks like a proper bitcoin address. Returns an object containing:
|
||||
|
||||
"isvalid" : true or false.
|
||||
"ismine" : true if the address is in the server's wallet.
|
||||
"address" : bitcoinaddress.
|
||||
|
||||
*note: ismine and address are only returned if the address is valid.
|
||||
Get help for a command.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
bitcoin.conf(5)
|
||||
|
||||
@@ -11,16 +11,16 @@ 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.
|
||||
If you run this script from the root folder it will automatically update the year on the copyright header for all
|
||||
source files if these have a git commit from the current year.
|
||||
|
||||
For example a file changed in 2014 (with 2014 being the current year):
|
||||
For example a file changed in 2015 (with 2015 being the current year):
|
||||
|
||||
```// Copyright (c) 2009-2013 The Bitcoin Core developers```
|
||||
|
||||
would be changed to:
|
||||
|
||||
```// Copyright (c) 2009-2014 The Bitcoin Core developers```
|
||||
```// Copyright (c) 2009-2015 The Bitcoin Core developers```
|
||||
|
||||
git-subtree-check.sh
|
||||
====================
|
||||
|
||||
@@ -1,53 +1,46 @@
|
||||
#!/usr/bin/env python
|
||||
'''
|
||||
Run this script inside of src/ and it will look for all the files
|
||||
that were changed this year that still have the last year in the
|
||||
copyright headers, and it will fix the headers on that file using
|
||||
a perl regex one liner.
|
||||
Run this script to update all the copyright headers of files
|
||||
that were changed this year.
|
||||
|
||||
For example: if it finds something like this and we're in 2014
|
||||
For example:
|
||||
|
||||
// Copyright (c) 2009-2013 The Bitcoin Core developers
|
||||
// Copyright (c) 2009-2012 The Bitcoin Core developers
|
||||
|
||||
it will change it to
|
||||
|
||||
// Copyright (c) 2009-2014 The Bitcoin Core developers
|
||||
|
||||
It will do this for all the files in the folder and its children.
|
||||
|
||||
Author: @gubatron
|
||||
// Copyright (c) 2009-2015 The Bitcoin Core developers
|
||||
'''
|
||||
import os
|
||||
import time
|
||||
import re
|
||||
|
||||
year = time.gmtime()[0]
|
||||
last_year = year - 1
|
||||
command = "perl -pi -e 's/%s The Bitcoin/%s The Bitcoin/' %s"
|
||||
listFilesCommand = "find . | grep %s"
|
||||
CMD_GIT_DATE = 'git log --format=@%%at -1 %s | date +"%%Y" -u -f -'
|
||||
CMD_REGEX= "perl -pi -e 's/(20\d\d)(?:-20\d\d)? The Bitcoin/$1-%s The Bitcoin/' %s"
|
||||
REGEX_CURRENT= re.compile("%s The Bitcoin" % year)
|
||||
CMD_LIST_FILES= "find %s | grep %s"
|
||||
|
||||
extensions = [".cpp",".h"]
|
||||
FOLDERS = ["./qa", "./src"]
|
||||
EXTENSIONS = [".cpp",".h", ".py"]
|
||||
|
||||
def getLastGitModifiedDate(filePath):
|
||||
gitGetLastCommitDateCommand = "git log " + filePath +" | grep Date | head -n 1"
|
||||
p = os.popen(gitGetLastCommitDateCommand)
|
||||
result = ""
|
||||
for l in p:
|
||||
result = l
|
||||
break
|
||||
result = result.replace("\n","")
|
||||
return result
|
||||
def get_git_date(file_path):
|
||||
r = os.popen(CMD_GIT_DATE % file_path)
|
||||
for l in r:
|
||||
# Result is one line, so just return
|
||||
return l.replace("\n","")
|
||||
return ""
|
||||
|
||||
n=1
|
||||
for extension in extensions:
|
||||
foundFiles = os.popen(listFilesCommand % extension)
|
||||
for filePath in foundFiles:
|
||||
filePath = filePath[1:-1]
|
||||
if filePath.endswith(extension):
|
||||
filePath = os.getcwd() + filePath
|
||||
modifiedTime = getLastGitModifiedDate(filePath)
|
||||
if len(modifiedTime) > 0 and str(year) in modifiedTime:
|
||||
print n,"Last Git Modified: ", modifiedTime, " - ", filePath
|
||||
os.popen(command % (last_year,year,filePath))
|
||||
n = n + 1
|
||||
|
||||
|
||||
for folder in FOLDERS:
|
||||
for extension in EXTENSIONS:
|
||||
for file_path in os.popen(CMD_LIST_FILES % (folder, extension)):
|
||||
file_path = os.getcwd() + file_path[1:-1]
|
||||
if file_path.endswith(extension):
|
||||
git_date = get_git_date(file_path)
|
||||
if str(year) == git_date:
|
||||
# Only update if current year is not found
|
||||
if REGEX_CURRENT.search(open(file_path, "r").read()) is None:
|
||||
print n,"Last git edit", git_date, "-", file_path
|
||||
os.popen(CMD_REGEX % (year,file_path))
|
||||
n = n + 1
|
||||
|
||||
@@ -94,7 +94,7 @@ def check_ELF_RELRO(executable):
|
||||
raise IOError('Error opening file')
|
||||
for line in stdout.split('\n'):
|
||||
tokens = line.split()
|
||||
if len(tokens)>1 and tokens[1] == '(BIND_NOW)':
|
||||
if len(tokens)>1 and tokens[1] == '(BIND_NOW)' or (len(tokens)>2 and tokens[1] == '(FLAGS)' and 'BIND_NOW' in tokens[2]):
|
||||
have_bindnow = True
|
||||
return have_gnu_relro and have_bindnow
|
||||
|
||||
|
||||
@@ -42,9 +42,12 @@ MAX_VERSIONS = {
|
||||
'GLIBCXX': (3,4,13),
|
||||
'GLIBC': (2,11)
|
||||
}
|
||||
# See here for a description of _IO_stdin_used:
|
||||
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=634261#109
|
||||
|
||||
# Ignore symbols that are exported as part of every executable
|
||||
IGNORE_EXPORTS = {
|
||||
'_edata', '_end', '_init', '__bss_start', '_fini'
|
||||
'_edata', '_end', '_init', '__bss_start', '_fini', '_IO_stdin_used'
|
||||
}
|
||||
READELF_CMD = os.getenv('READELF', '/usr/bin/readelf')
|
||||
CPPFILT_CMD = os.getenv('CPPFILT', '/usr/bin/c++filt')
|
||||
|
||||
@@ -72,7 +72,7 @@ def sanitize_string(s):
|
||||
'''Sanitize string for printing'''
|
||||
return s.replace('\n',' ')
|
||||
|
||||
def check_format_specifiers(source, translation, errors):
|
||||
def check_format_specifiers(source, translation, errors, numerus):
|
||||
source_f = split_format_specifiers(find_format_specifiers(source))
|
||||
# assert that no source messages contain both Qt and strprintf format specifiers
|
||||
# if this fails, go change the source as this is hacky and confusing!
|
||||
@@ -80,10 +80,13 @@ def check_format_specifiers(source, translation, errors):
|
||||
try:
|
||||
translation_f = split_format_specifiers(find_format_specifiers(translation))
|
||||
except IndexError:
|
||||
errors.append("Parse error in translation '%s'" % sanitize_string(translation))
|
||||
errors.append("Parse error in translation for '%s': '%s'" % (sanitize_string(source), sanitize_string(translation)))
|
||||
return False
|
||||
else:
|
||||
if source_f != translation_f:
|
||||
if numerus and source_f == (set(), ['n']) and translation_f == (set(), []) and translation.find('%') == -1:
|
||||
# Allow numerus translations to omit %n specifier (usually when it only has one possible value)
|
||||
return True
|
||||
errors.append("Mismatch between '%s' and '%s'" % (sanitize_string(source), sanitize_string(translation)))
|
||||
return False
|
||||
return True
|
||||
@@ -150,7 +153,7 @@ def postprocess_translations(reduce_diff_hacks=False):
|
||||
if translation is None:
|
||||
continue
|
||||
errors = []
|
||||
valid = check_format_specifiers(source, translation, errors)
|
||||
valid = check_format_specifiers(source, translation, errors, numerus)
|
||||
|
||||
for error in errors:
|
||||
print('%s: %s' % (filename, error))
|
||||
|
||||
@@ -6,6 +6,7 @@ suites:
|
||||
architectures:
|
||||
- "amd64"
|
||||
packages:
|
||||
- "curl"
|
||||
- "g++-multilib"
|
||||
- "git-core"
|
||||
- "pkg-config"
|
||||
@@ -15,7 +16,9 @@ packages:
|
||||
- "faketime"
|
||||
- "bsdmainutils"
|
||||
- "binutils-gold"
|
||||
reference_datetime: "2015-06-01 00:00:00"
|
||||
- "ca-certificates"
|
||||
- "python"
|
||||
reference_datetime: "2016-01-01 00:00:00"
|
||||
remotes:
|
||||
- "url": "https://github.com/bitcoin/bitcoin.git"
|
||||
"dir": "bitcoin"
|
||||
@@ -23,7 +26,7 @@ files: []
|
||||
script: |
|
||||
WRAP_DIR=$HOME/wrapped
|
||||
HOSTS="i686-pc-linux-gnu x86_64-unknown-linux-gnu"
|
||||
CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++"
|
||||
CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports --disable-bench --disable-gui-tests LDFLAGS=-static-libstdc++"
|
||||
FAKETIME_HOST_PROGS=""
|
||||
FAKETIME_PROGS="date ar ranlib nm strip"
|
||||
|
||||
@@ -94,6 +97,8 @@ script: |
|
||||
|
||||
./configure --prefix=${BASEPREFIX}/${i} --bindir=${INSTALLPATH}/bin --includedir=${INSTALLPATH}/include --libdir=${INSTALLPATH}/lib --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS}
|
||||
make ${MAKEOPTS}
|
||||
make ${MAKEOPTS} -C src check-security
|
||||
make ${MAKEOPTS} -C src check-symbols
|
||||
make install-strip
|
||||
cd installed
|
||||
find . -name "lib*.la" -delete
|
||||
|
||||
@@ -5,9 +5,8 @@ suites:
|
||||
architectures:
|
||||
- "amd64"
|
||||
packages:
|
||||
- "libc6:i386"
|
||||
- "faketime"
|
||||
reference_datetime: "2015-06-01 00:00:00"
|
||||
reference_datetime: "2016-01-01 00:00:00"
|
||||
remotes:
|
||||
- "url": "https://github.com/bitcoin/bitcoin-detached-sigs.git"
|
||||
"dir": "signature"
|
||||
|
||||
@@ -6,6 +6,7 @@ suites:
|
||||
architectures:
|
||||
- "amd64"
|
||||
packages:
|
||||
- "curl"
|
||||
- "g++"
|
||||
- "git-core"
|
||||
- "pkg-config"
|
||||
@@ -18,7 +19,9 @@ packages:
|
||||
- "libcap-dev"
|
||||
- "libz-dev"
|
||||
- "libbz2-dev"
|
||||
reference_datetime: "2015-06-01 00:00:00"
|
||||
- "ca-certificates"
|
||||
- "python"
|
||||
reference_datetime: "2016-01-01 00:00:00"
|
||||
remotes:
|
||||
- "url": "https://github.com/bitcoin/bitcoin.git"
|
||||
"dir": "bitcoin"
|
||||
@@ -27,7 +30,7 @@ files:
|
||||
script: |
|
||||
WRAP_DIR=$HOME/wrapped
|
||||
HOSTS="x86_64-apple-darwin11"
|
||||
CONFIGFLAGS="--enable-reduce-exports GENISOIMAGE=$WRAP_DIR/genisoimage"
|
||||
CONFIGFLAGS="--enable-reduce-exports --disable-bench --disable-gui-tests GENISOIMAGE=$WRAP_DIR/genisoimage"
|
||||
FAKETIME_HOST_PROGS=""
|
||||
FAKETIME_PROGS="ar ranlib date dmg genisoimage"
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ architectures:
|
||||
packages:
|
||||
- "libssl-dev"
|
||||
- "autoconf"
|
||||
reference_datetime: "2015-06-01 00:00:00"
|
||||
reference_datetime: "2016-01-01 00:00:00"
|
||||
remotes:
|
||||
- "url": "https://github.com/bitcoin/bitcoin-detached-sigs.git"
|
||||
"dir": "signature"
|
||||
|
||||
@@ -6,6 +6,7 @@ suites:
|
||||
architectures:
|
||||
- "amd64"
|
||||
packages:
|
||||
- "curl"
|
||||
- "g++"
|
||||
- "git-core"
|
||||
- "pkg-config"
|
||||
@@ -18,7 +19,9 @@ packages:
|
||||
- "g++-mingw-w64"
|
||||
- "nsis"
|
||||
- "zip"
|
||||
reference_datetime: "2015-06-01 00:00:00"
|
||||
- "ca-certificates"
|
||||
- "python"
|
||||
reference_datetime: "2016-01-01 00:00:00"
|
||||
remotes:
|
||||
- "url": "https://github.com/bitcoin/bitcoin.git"
|
||||
"dir": "bitcoin"
|
||||
@@ -26,7 +29,7 @@ files: []
|
||||
script: |
|
||||
WRAP_DIR=$HOME/wrapped
|
||||
HOSTS="x86_64-w64-mingw32 i686-w64-mingw32"
|
||||
CONFIGFLAGS="--enable-reduce-exports"
|
||||
CONFIGFLAGS="--enable-reduce-exports --disable-gui-tests"
|
||||
FAKETIME_HOST_PROGS="g++ ar ranlib nm windres strip"
|
||||
FAKETIME_PROGS="date makensis zip"
|
||||
|
||||
@@ -124,6 +127,7 @@ script: |
|
||||
|
||||
./configure --prefix=${BASEPREFIX}/${i} --bindir=${INSTALLPATH}/bin --includedir=${INSTALLPATH}/include --libdir=${INSTALLPATH}/lib --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS}
|
||||
make ${MAKEOPTS}
|
||||
make ${MAKEOPTS} -C src check-security
|
||||
make deploy
|
||||
make install-strip
|
||||
cp -f bitcoin-*setup*.exe $OUTDIR/
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
Utility to generate the seeds.txt list that is compiled into the client
|
||||
(see [src/chainparamsseeds.h](/src/chainparamsseeds.h) and other utilities in [contrib/seeds](/contrib/seeds)).
|
||||
|
||||
The 512 seeds compiled into the 0.10 release were created from sipa's DNS seed data, like this:
|
||||
The seeds compiled into the release are created from sipa's DNS seed data, like this:
|
||||
|
||||
curl -s http://bitcoin.sipa.be/seeds.txt > seeds_main.txt
|
||||
python makeseeds.py < seeds_main.txt > nodes_main.txt
|
||||
python generate-seeds.py . > ../../src/chainparamsseeds.h
|
||||
|
||||
curl -s http://bitcoin.sipa.be/seeds.txt | makeseeds.py
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
### Verify SF Binaries ###
|
||||
### Verify Binaries ###
|
||||
This script attempts to download the signature file `SHA256SUMS.asc` from https://bitcoin.org.
|
||||
|
||||
It first checks if the signature passes, and then downloads the files specified in the file, and checks if the hashes of these files match those that are specified in the signature file.
|
||||
|
||||
The script returns 0 if everything passes the checks. It returns 1 if either the signature check or the hash check doesn't pass. If an error occurs the return value is 2.
|
||||
The script returns 0 if everything passes the checks. It returns 1 if either the signature check or the hash check doesn't pass. If an error occurs the return value is 2.
|
||||
|
||||
@@ -7,7 +7,7 @@ build_darwin_OTOOL: = $(shell xcrun -f otool)
|
||||
build_darwin_NM: = $(shell xcrun -f nm)
|
||||
build_darwin_INSTALL_NAME_TOOL:=$(shell xcrun -f install_name_tool)
|
||||
build_darwin_SHA256SUM = shasum -a 256
|
||||
build_darwin_DOWNLOAD = curl --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -L -o
|
||||
build_darwin_DOWNLOAD = curl --location --fail --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -o
|
||||
|
||||
#darwin host on darwin builder. overrides darwin host preferences.
|
||||
darwin_CC=$(shell xcrun -f clang) -mmacosx-version-min=$(OSX_MIN_VERSION)
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
build_linux_SHA256SUM = sha256sum
|
||||
build_linux_DOWNLOAD = wget --timeout=$(DOWNLOAD_CONNECT_TIMEOUT) --tries=$(DOWNLOAD_RETRIES) -nv -O
|
||||
build_linux_DOWNLOAD = curl --location --fail --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -o
|
||||
|
||||
5
depends/config.guess
vendored
5
depends/config.guess
vendored
@@ -2,7 +2,7 @@
|
||||
# Attempt to guess a canonical system name.
|
||||
# Copyright 1992-2015 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2015-10-21'
|
||||
timestamp='2015-11-19'
|
||||
|
||||
# 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
|
||||
@@ -1393,6 +1393,9 @@ EOF
|
||||
x86_64:VMkernel:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-esx
|
||||
exit ;;
|
||||
amd64:Isilon\ OneFS:*:*)
|
||||
echo x86_64-unknown-onefs
|
||||
exit ;;
|
||||
esac
|
||||
|
||||
cat >&2 <<EOF
|
||||
|
||||
8
depends/config.sub
vendored
8
depends/config.sub
vendored
@@ -2,7 +2,7 @@
|
||||
# Configuration validation subroutine script.
|
||||
# Copyright 1992-2015 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2015-08-20'
|
||||
timestamp='2015-11-22'
|
||||
|
||||
# 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
|
||||
@@ -53,8 +53,7 @@ timestamp='2015-08-20'
|
||||
me=`echo "$0" | sed -e 's,.*/,,'`
|
||||
|
||||
usage="\
|
||||
Usage: $0 [OPTION] CPU-MFR-OPSYS
|
||||
$0 [OPTION] ALIAS
|
||||
Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
|
||||
|
||||
Canonicalize a configuration name.
|
||||
|
||||
@@ -1399,7 +1398,8 @@ case $os in
|
||||
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
||||
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
||||
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
|
||||
| -onefs* | -tirtos*)
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-qnx*)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package=boost
|
||||
$(package)_version=1_58_0
|
||||
$(package)_download_path=http://sourceforge.net/projects/boost/files/boost/1.58.0
|
||||
$(package)_version=1_59_0
|
||||
$(package)_download_path=http://sourceforge.net/projects/boost/files/boost/1.59.0
|
||||
$(package)_file_name=$(package)_$($(package)_version).tar.bz2
|
||||
$(package)_sha256_hash=fdfc204fc33ec79c99b9a74944c3e54bd78be4f7f15e260c0e2700a36dc7d3e5
|
||||
$(package)_sha256_hash=727a932322d94287b62abb1bd2d41723eec4356a7728909e38adb65ca25241ca
|
||||
|
||||
define $(package)_set_vars
|
||||
$(package)_config_opts_release=variant=release
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package=miniupnpc
|
||||
$(package)_version=1.9.20151008
|
||||
$(package)_version=1.9.20151026
|
||||
$(package)_download_path=http://miniupnp.free.fr/files
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.gz
|
||||
$(package)_sha256_hash=e444ac3b587ce82709c4d0cfca1fe71f44f9fc433e9f946b12b9e1bfe667a633
|
||||
$(package)_sha256_hash=f3cf9a5a31588a917d4d9237e5bc50f84d00c5aa48e27ed50d9b88dfa6a25d47
|
||||
|
||||
define $(package)_set_vars
|
||||
$(package)_build_opts=CC="$($(package)_cc)"
|
||||
$(package)_build_opts_darwin=OS=Darwin
|
||||
$(package)_build_opts_darwin=OS=Darwin LIBTOOL="$($(package)_libtool)"
|
||||
$(package)_build_opts_mingw32=-f Makefile.mingw
|
||||
$(package)_build_env+=CFLAGS="$($(package)_cflags) $($(package)_cppflags)" AR="$($(package)_ar)"
|
||||
endef
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package=native_ccache
|
||||
$(package)_version=3.2.3
|
||||
$(package)_version=3.2.4
|
||||
$(package)_download_path=http://samba.org/ftp/ccache
|
||||
$(package)_file_name=ccache-$($(package)_version).tar.bz2
|
||||
$(package)_sha256_hash=b07165d4949d107d17f2f84b90b52953617bf1abbf249d5cc20636f43337c98c
|
||||
$(package)_sha256_hash=ffeb967edb549e67da0bd5f44f729a2022de9fdde65dfd80d2a7204d7f75332e
|
||||
|
||||
define $(package)_set_vars
|
||||
$(package)_config_opts=
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package=zeromq
|
||||
$(package)_version=4.0.4
|
||||
$(package)_version=4.0.7
|
||||
$(package)_download_path=http://download.zeromq.org
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.gz
|
||||
$(package)_sha256_hash=1ef71d46e94f33e27dd5a1661ed626cd39be4d2d6967792a275040e34457d399
|
||||
$(package)_sha256_hash=e00b2967e074990d0538361cc79084a0a92892df2c6e7585da34e4c61ee47b03
|
||||
|
||||
define $(package)_set_vars
|
||||
$(package)_config_opts=--without-documentation --disable-shared
|
||||
|
||||
@@ -34,7 +34,7 @@ PROJECT_NAME = Bitcoin
|
||||
# This could be handy for archiving the generated documentation or
|
||||
# if some version control system is used.
|
||||
|
||||
PROJECT_NUMBER = 0.11.99
|
||||
PROJECT_NUMBER = 0.12.1
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Bitcoin Core 0.11.99
|
||||
Bitcoin Core 0.12.1
|
||||
=====================
|
||||
|
||||
Setup
|
||||
@@ -49,7 +49,7 @@ The following are developer notes on how to build Bitcoin on your native platfor
|
||||
|
||||
Development
|
||||
---------------------
|
||||
The Bitcoin repo's [root README](https://github.com/bitcoin/bitcoin/blob/master/README.md) contains relevant information on the development process and automated testing.
|
||||
The Bitcoin repo's [root README](/README.md) contains relevant information on the development process and automated testing.
|
||||
|
||||
- [Developer Notes](developer-notes.md)
|
||||
- [Multiwallet Qt Development](multiwallet-qt.md)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Bitcoin Core 0.11.99
|
||||
Bitcoin Core 0.12.1
|
||||
=====================
|
||||
|
||||
Intro
|
||||
|
||||
@@ -18,4 +18,5 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.12.0**):
|
||||
* [`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)).
|
||||
* [`BIP 125`](https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki): Opt-in full replace-by-fee signaling honoured in mempool and mining as of **v0.12.0** ([PR 6871](https://github.com/bitcoin/bitcoin/pull/6871)).
|
||||
* [`BIP 130`](https://github.com/bitcoin/bips/blob/master/bip-0130.mediawiki): direct headers announcement is negotiated with peer versions `>=70012` as of **v0.12.0** ([PR 6494](https://github.com/bitcoin/bitcoin/pull/6494)).
|
||||
|
||||
@@ -61,7 +61,7 @@ Dependency Build Instructions: Ubuntu & Debian
|
||||
----------------------------------------------
|
||||
Build requirements:
|
||||
|
||||
sudo apt-get install build-essential libtool autotools-dev autoconf pkg-config libssl-dev libevent-dev bsdmainutils
|
||||
sudo apt-get install build-essential libtool autotools-dev automake pkg-config libssl-dev libevent-dev bsdmainutils
|
||||
|
||||
On at least Ubuntu 14.04+ and Debian 7+ there are generic names for the
|
||||
individual boost development packages, so the following can be used to only
|
||||
@@ -236,3 +236,31 @@ In this case there is no dependency on Berkeley DB 4.8.
|
||||
|
||||
Mining is also possible in disable-wallet mode, but only using the `getblocktemplate` RPC
|
||||
call not `getwork`.
|
||||
|
||||
Additional Configure Flags
|
||||
--------------------------
|
||||
A list of additional configure flags can be displayed with:
|
||||
|
||||
./configure --help
|
||||
|
||||
ARM Cross-compilation
|
||||
-------------------
|
||||
These steps can be performed on, for example, an Ubuntu VM. The depends system
|
||||
will also work on other Linux distributions, however the commands for
|
||||
installing the toolchain will be different.
|
||||
|
||||
First install the toolchain:
|
||||
|
||||
sudo apt-get install g++-arm-linux-gnueabihf
|
||||
|
||||
To build executables for ARM:
|
||||
|
||||
cd depends
|
||||
make HOST=arm-linux-gnueabihf NO_QT=1
|
||||
cd ..
|
||||
./configure --prefix=$PWD/depends/arm-linux-gnueabihf --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++
|
||||
make
|
||||
|
||||
|
||||
For further documentation on the depends system see [README.md](../depends/README.md) in the depends directory.
|
||||
>>>>>>> 3e55b3a... [doc] added depends cross compile info
|
||||
|
||||
@@ -259,15 +259,15 @@ adduser debian sudo
|
||||
Then set up LXC and the rest with the following, which is a complex jumble of settings and workarounds:
|
||||
|
||||
```bash
|
||||
# the version of lxc-start in Debian 7.4 needs to run as root, so make sure
|
||||
# the version of lxc-start in Debian needs to run as root, so make sure
|
||||
# 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
|
||||
# make /etc/rc.local script that sets up bridge between guest and host
|
||||
echo '#!/bin/sh -e' > /etc/rc.local
|
||||
echo 'brctl addbr br0' >> /etc/rc.local
|
||||
echo 'ifconfig br0 10.0.3.2/24 up' >> /etc/rc.local
|
||||
echo 'iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE' >> /etc/rc.local
|
||||
echo 'echo 1 > /proc/sys/net/ipv4/ip_forward' >> /etc/rc.local
|
||||
echo 'exit 0' >> /etc/rc.local
|
||||
# make sure that USE_LXC is always set when logging in as debian,
|
||||
# and configure LXC IP addresses
|
||||
|
||||
@@ -1,239 +1,145 @@
|
||||
(note: this is a temporary file, to be added-to by anybody, and moved to
|
||||
release-notes at release time)
|
||||
Bitcoin Core version 0.12.1 is now available from:
|
||||
|
||||
<https://bitcoin.org/bin/bitcoin-core-0.12.1/>
|
||||
|
||||
This is a new minor version release, including the BIP9, BIP68 and BIP112
|
||||
softfork, various bugfixes and updated translations.
|
||||
|
||||
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
|
||||
-----------------
|
||||
|
||||
### Downgrade to a version < 0.12.0
|
||||
|
||||
Because release 0.12.0 and later will obfuscate the chainstate on every
|
||||
fresh sync or reindex, the chainstate is not backwards-compatible with
|
||||
pre-0.12 versions of Bitcoin Core or other software.
|
||||
|
||||
If you want to downgrade after you have done a reindex with 0.12.0 or later,
|
||||
you will need to reindex when you first start Bitcoin Core version 0.11 or
|
||||
earlier.
|
||||
|
||||
Notable changes
|
||||
===============
|
||||
|
||||
SSL support for RPC dropped
|
||||
----------------------------
|
||||
First version bits BIP9 softfork deployment
|
||||
-------------------------------------------
|
||||
|
||||
SSL support for RPC, previously enabled by the option `rpcssl` has been dropped
|
||||
from both the client and the server. This was done in preparation for removing
|
||||
the dependency on OpenSSL for the daemon completely.
|
||||
This release includes a soft fork deployment to enforce [BIP68][],
|
||||
[BIP112][] and [BIP113][] using the [BIP9][] deployment mechanism.
|
||||
|
||||
Trying to use `rpcssl` will result in an error:
|
||||
The deployment sets the block version number to 0x20000001 between
|
||||
midnight 1st May 2016 and midnight 1st May 2017 to signal readiness for
|
||||
deployment. The version number consists of 0x20000000 to indicate version
|
||||
bits together with setting bit 0 to indicate support for this combined
|
||||
deployment, shown as "csv" in the `getblockchaininfo` RPC call.
|
||||
|
||||
Error: SSL mode for RPC (-rpcssl) is no longer supported.
|
||||
For more information about the soft forking change, please see
|
||||
<https://github.com/bitcoin/bitcoin/pull/7648>
|
||||
|
||||
If you are one of the few people that relies on this feature, a flexible
|
||||
migration path is to use `stunnel`. This is an utility that can tunnel
|
||||
arbitrary TCP connections inside SSL. On e.g. Ubuntu it can be installed with:
|
||||
This specific backport pull-request can be viewed at
|
||||
<https://github.com/bitcoin/bitcoin/pull/7543>
|
||||
|
||||
sudo apt-get install stunnel4
|
||||
[BIP9]: https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki
|
||||
[BIP68]: https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki
|
||||
[BIP112]: https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki
|
||||
|
||||
Then, to tunnel a SSL connection on 28332 to a RPC server bound on localhost on port 18332 do:
|
||||
BIP68 soft fork to enforce sequence locks for relative locktime
|
||||
---------------------------------------------------------------
|
||||
|
||||
stunnel -d 28332 -r 127.0.0.1:18332 -p stunnel.pem -P ''
|
||||
[BIP68][] introduces relative lock-time consensus-enforced semantics of
|
||||
the sequence number field to enable a signed transaction input to remain
|
||||
invalid for a defined period of time after confirmation of its corresponding
|
||||
outpoint.
|
||||
|
||||
It can also be set up system-wide in inetd style.
|
||||
For more information about the implementation, see
|
||||
<https://github.com/bitcoin/bitcoin/pull/7184>
|
||||
|
||||
Another way to re-attain SSL would be to setup a httpd reverse proxy. This solution
|
||||
would allow the use of different authentication, loadbalancing, on-the-fly compression and
|
||||
caching. A sample config for apache2 could look like:
|
||||
BIP112 soft fork to enforce OP_CHECKSEQUENCEVERIFY
|
||||
--------------------------------------------------
|
||||
|
||||
Listen 443
|
||||
[BIP112][] redefines the existing OP_NOP3 as OP_CHECKSEQUENCEVERIFY (CSV)
|
||||
for a new opcode in the Bitcoin scripting system that in combination with
|
||||
[BIP68][] allows execution pathways of a script to be restricted based
|
||||
on the age of the output being spent.
|
||||
|
||||
NameVirtualHost *:443
|
||||
<VirtualHost *:443>
|
||||
For more information about the implementation, see
|
||||
<https://github.com/bitcoin/bitcoin/pull/7524>
|
||||
|
||||
SSLEngine On
|
||||
SSLCertificateFile /etc/apache2/ssl/server.crt
|
||||
SSLCertificateKeyFile /etc/apache2/ssl/server.key
|
||||
|
||||
<Location /bitcoinrpc>
|
||||
ProxyPass http://127.0.0.1:8332/
|
||||
ProxyPassReverse http://127.0.0.1:8332/
|
||||
# optional enable digest auth
|
||||
# AuthType Digest
|
||||
# ...
|
||||
|
||||
# optional bypass bitcoind rpc basic auth
|
||||
# RequestHeader set Authorization "Basic <hash>"
|
||||
# get the <hash> from the shell with: base64 <<< bitcoinrpc:<password>
|
||||
</Location>
|
||||
|
||||
# Or, balance the load:
|
||||
# ProxyPass / balancer://balancer_cluster_name
|
||||
|
||||
</VirtualHost>
|
||||
|
||||
Random-cookie RPC authentication
|
||||
---------------------------------
|
||||
|
||||
When no `-rpcpassword` is specified, the daemon now uses a special 'cookie'
|
||||
file for authentication. This file is generated with random content when the
|
||||
daemon starts, and deleted when it exits. Its contents are used as
|
||||
authentication token. Read access to this file controls who can access through
|
||||
RPC. By default it is stored in the data directory but its location can be
|
||||
overridden with the option `-rpccookiefile`.
|
||||
|
||||
This is similar to Tor's CookieAuthentication: see
|
||||
https://www.torproject.org/docs/tor-manual.html.en
|
||||
|
||||
This allows running bitcoind without having to do any manual configuration.
|
||||
|
||||
Low-level RPC API changes
|
||||
--------------------------
|
||||
|
||||
- Monetary amounts can be provided as strings. This means that for example the
|
||||
argument to sendtoaddress can be "0.0001" instead of 0.0001. This can be an
|
||||
advantage if a JSON library insists on using a lossy floating point type for
|
||||
numbers, which would be dangerous for monetary amounts.
|
||||
|
||||
Option parsing behavior
|
||||
-----------------------
|
||||
|
||||
Command line options are now parsed strictly in the order in which they are
|
||||
specified. It used to be the case that `-X -noX` ends up, unintuitively, with X
|
||||
set, as `-X` had precedence over `-noX`. This is no longer the case. Like for
|
||||
other software, the last specified value for an option will hold.
|
||||
|
||||
`NODE_BLOOM` service bit
|
||||
------------------------
|
||||
|
||||
Support for the `NODE_BLOOM` service bit, as described in [BIP
|
||||
111](https://github.com/bitcoin/bips/blob/master/bip-0111.mediawiki), has been
|
||||
added to the P2P protocol code.
|
||||
|
||||
BIP 111 defines a service bit to allow peers to advertise that they support
|
||||
bloom filters (such as used by SPV clients) explicitly. It also bumps the protocol
|
||||
version to allow peers to identify old nodes which allow bloom filtering of the
|
||||
connection despite lacking the new service bit.
|
||||
|
||||
In this version, it is only enforced for peers that send protocol versions
|
||||
`>=70011`. For the next major version it is planned that this restriction will be
|
||||
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
|
||||
-----------------------------------
|
||||
|
||||
Previously, every wallet transaction stored a Merkle branch to prove its
|
||||
presence in blocks. This wasn't being used for more than an expensive
|
||||
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 0.4.3 or any version from 0.5.2 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.
|
||||
|
||||
Automatically use Tor hidden services
|
||||
BIP113 locktime enforcement soft fork
|
||||
-------------------------------------
|
||||
|
||||
Starting with Tor version 0.2.7.1 it is possible, through Tor's control socket
|
||||
API, to create and destroy 'ephemeral' hidden services programmatically.
|
||||
Bitcoin Core has been updated to make use of this.
|
||||
Bitcoin Core 0.11.2 previously introduced mempool-only locktime
|
||||
enforcement using GetMedianTimePast(). This release seeks to
|
||||
consensus enforce the rule.
|
||||
|
||||
This means that if Tor is running (and proper authorization is available),
|
||||
Bitcoin Core automatically creates a hidden service to listen on, without
|
||||
manual configuration. Bitcoin Core will also use Tor automatically to connect
|
||||
to other .onion nodes if the control socket can be successfully opened. This
|
||||
will positively affect the number of available .onion nodes and their usage.
|
||||
Bitcoin transactions currently may specify a locktime indicating when
|
||||
they may be added to a valid block. Current consensus rules require
|
||||
that blocks have a block header time greater than the locktime specified
|
||||
in any transaction in that block.
|
||||
|
||||
This new feature is enabled by default if Bitcoin Core is listening, and
|
||||
a connection to Tor can be made. It can be configured with the `-listenonion`,
|
||||
`-torcontrol` and `-torpassword` settings. To show verbose debugging
|
||||
information, pass `-debug=tor`.
|
||||
Miners get to choose what time they use for their header time, with the
|
||||
consensus rule being that no node will accept a block whose time is more
|
||||
than two hours in the future. This creates a incentive for miners to
|
||||
set their header times to future values in order to include locktimed
|
||||
transactions which weren't supposed to be included for up to two more
|
||||
hours.
|
||||
|
||||
Reduce upload traffic
|
||||
---------------------
|
||||
The consensus rules also specify that valid blocks may have a header
|
||||
time greater than that of the median of the 11 previous blocks. This
|
||||
GetMedianTimePast() time has a key feature we generally associate with
|
||||
time: it can't go backwards.
|
||||
|
||||
A major part of the outbound traffic is caused by serving historic blocks to
|
||||
other nodes in initial block download state.
|
||||
[BIP113][] specifies a soft fork enforced in this release that
|
||||
weakens this perverse incentive for individual miners to use a future
|
||||
time by requiring that valid blocks have a computed GetMedianTimePast()
|
||||
greater than the locktime specified in any transaction in that block.
|
||||
|
||||
It is now possible to reduce the total upload traffic via the `-maxuploadtarget`
|
||||
parameter. This is *not* a hard limit but a threshold to minimize the outbound
|
||||
traffic. When the limit is about to be reached, the uploaded data is cut by not
|
||||
serving historic blocks (blocks older than one week).
|
||||
Moreover, any SPV peer is disconnected when they request a filtered block.
|
||||
Mempool inclusion rules currently require transactions to be valid for
|
||||
immediate inclusion in a block in order to be accepted into the mempool.
|
||||
This release begins applying the BIP113 rule to received transactions,
|
||||
so transaction whose time is greater than the GetMedianTimePast() will
|
||||
no longer be accepted into the mempool.
|
||||
|
||||
This option can be specified in MiB per day and is turned off by default
|
||||
(`-maxuploadtarget=0`).
|
||||
The recommended minimum is 144 * MAX_BLOCK_SIZE (currently 144MB) per day.
|
||||
**Implication for miners:** you will begin rejecting transactions that
|
||||
would not be valid under BIP113, which will prevent you from producing
|
||||
invalid blocks when BIP113 is enforced on the network. Any
|
||||
transactions which are valid under the current rules but not yet valid
|
||||
under the BIP113 rules will either be mined by other miners or delayed
|
||||
until they are valid under BIP113. Note, however, that time-based
|
||||
locktime transactions are more or less unseen on the network currently.
|
||||
|
||||
Whitelisted peers will never be disconnected, although their traffic counts for
|
||||
calculating the target.
|
||||
**Implication for users:** GetMedianTimePast() always trails behind the
|
||||
current time, so a transaction locktime set to the present time will be
|
||||
rejected by nodes running this release until the median time moves
|
||||
forward. To compensate, subtract one hour (3,600 seconds) from your
|
||||
locktimes to allow those transactions to be included in mempools at
|
||||
approximately the expected time.
|
||||
|
||||
A more detailed documentation about keeping traffic low can be found in
|
||||
[/doc/reducetraffic.md](/doc/reducetraffic.md).
|
||||
For more information about the implementation, see
|
||||
<https://github.com/bitcoin/bitcoin/pull/6566>
|
||||
|
||||
Signature validation using libsecp256k1
|
||||
---------------------------------------
|
||||
Miscellaneous
|
||||
-------------
|
||||
|
||||
ECDSA signatures inside Bitcoin transactions now use validation using
|
||||
[https://github.com/bitcoin/secp256k1](libsecp256k1) instead of OpenSSL.
|
||||
The p2p alert system is off by default. To turn on, use `-alert` with
|
||||
startup configuration.
|
||||
|
||||
Depending on the platform, this means a significant speedup for raw signature
|
||||
validation speed. The advantage is largest on x86_64, where validation is over
|
||||
five times faster. In practice, this translates to a raw reindexing and new
|
||||
block validation times that are less than half of what it was before.
|
||||
|
||||
Libsecp256k1 has undergone very extensive testing and validation.
|
||||
|
||||
A side effect of this change is that libconsensus no longer depends on OpenSSL.
|
||||
|
||||
Direct headers announcement (BIP 130)
|
||||
-------------------------------------
|
||||
|
||||
Between compatible peers, BIP 130 direct headers announcement is used. This
|
||||
means that blocks are advertized by announcing their headers directly, instead
|
||||
of just announcing the hash. In a reorganization, all new headers are sent,
|
||||
instead of just the new tip. This can often prevent an extra roundtrip before
|
||||
the actual block is downloaded.
|
||||
|
||||
Negative confirmations and conflict detection
|
||||
---------------------------------------------
|
||||
|
||||
The wallet will now report a negative number for confirmations that indicates
|
||||
how deep in the block chain the conflict is found. For example, if a transaction
|
||||
A has 5 confirmations and spends the same input as a wallet transaction B, B
|
||||
will be reported as having -5 confirmations. If another wallet transaction C
|
||||
spends an output from B, it will also be reported as having -5 confirmations.
|
||||
To detect conflicts with historical transactions in the chain a one-time
|
||||
`-rescan` may be needed.
|
||||
|
||||
Unlike earlier versions, unconfirmed but non-conflicting transactions will never
|
||||
get a negative confirmation count. They are not treated as spendable unless
|
||||
they're coming from ourself (change) and accepted into our local mempool,
|
||||
however. The new "trusted" field in the `listtransactions` RPC output
|
||||
indicates whether outputs of an unconfirmed transaction are considered
|
||||
spendable.
|
||||
|
||||
0.12.0 Change log
|
||||
0.12.1 Change log
|
||||
=================
|
||||
|
||||
Detailed release notes follow. This overview includes changes that affect
|
||||
@@ -241,60 +147,51 @@ behavior, not code moves, refactors and string updates. For convenience in locat
|
||||
the code changes and accompanying discussion, both the pull request and
|
||||
git merge commit are mentioned.
|
||||
|
||||
### RPC and REST
|
||||
|
||||
Asm representations of scriptSig signatures now contain SIGHASH type decodes
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
The `asm` property of each scriptSig now contains the decoded signature hash
|
||||
type for each signature that provides a valid defined hash type.
|
||||
|
||||
The following items contain assembly representations of scriptSig signatures
|
||||
and are affected by this change:
|
||||
|
||||
- RPC `getrawtransaction`
|
||||
- RPC `decoderawtransaction`
|
||||
- REST `/rest/tx/` (JSON format)
|
||||
- REST `/rest/block/` (JSON format when including extended tx details)
|
||||
- `bitcoin-tx -json`
|
||||
|
||||
For example, the `scriptSig.asm` property of a transaction input that
|
||||
previously showed an assembly representation of:
|
||||
|
||||
304502207fa7a6d1e0ee81132a269ad84e68d695483745cde8b541e3bf630749894e342a022100c1f7ab20e13e22fb95281a870f3dcf38d782e53023ee313d741ad0cfbc0c509001
|
||||
|
||||
now shows as:
|
||||
|
||||
304502207fa7a6d1e0ee81132a269ad84e68d695483745cde8b541e3bf630749894e342a022100c1f7ab20e13e22fb95281a870f3dcf38d782e53023ee313d741ad0cfbc0c5090[ALL]
|
||||
|
||||
Note that the output of the RPC `decodescript` did not change because it is
|
||||
configured specifically to process scriptPubKey and not scriptSig scripts.
|
||||
|
||||
### Configuration and command-line options
|
||||
### RPC and other APIs
|
||||
- #7739 `7ffc2bd` Add abandoned status to listtransactions (jonasschnelli)
|
||||
|
||||
### Block and transaction handling
|
||||
- #7543 `834aaef` Backport BIP9, BIP68 and BIP112 with softfork (btcdrak)
|
||||
|
||||
### P2P protocol and network code
|
||||
- #7804 `90f1d24` Track block download times per individual block (sipa)
|
||||
- #7832 `4c3a00d` Reduce block timeout to 10 minutes (laanwj)
|
||||
|
||||
### Validation
|
||||
- #7821 `4226aac` init: allow shutdown during 'Activating best chain...' (laanwj)
|
||||
- #7835 `46898e7` Version 2 transactions remain non-standard until CSV activates (sdaftuar)
|
||||
|
||||
### Build system
|
||||
- #7487 `00d57b4` Workaround Travis-side CI issues (luke-jr)
|
||||
- #7606 `a10da9a` No need to set -L and --location for curl (MarcoFalke)
|
||||
- #7614 `ca8f160` Add curl to packages (now needed for depends) (luke-jr)
|
||||
- #7776 `a784675` Remove unnecessary executables from gitian release (laanwj)
|
||||
|
||||
### Wallet
|
||||
|
||||
### GUI
|
||||
|
||||
### Tests
|
||||
- #7715 `19866c1` Fix calculation of balances and available coins. (morcos)
|
||||
|
||||
### Miscellaneous
|
||||
- #7617 `f04f4fd` Fix markdown syntax and line terminate LogPrint (MarcoFalke)
|
||||
- #7747 `4d035bc` added depends cross compile info (accraze)
|
||||
- #7741 `a0cea89` Mark p2p alert system as deprecated (btcdrak)
|
||||
- #7780 `c5f94f6` Disable bad-chain alert (btcdrak)
|
||||
|
||||
- Removed bitrpc.py from contrib
|
||||
Credits
|
||||
=======
|
||||
|
||||
Addition of ZMQ-based Notifications
|
||||
==================================
|
||||
Thanks to everyone who directly contributed to this release:
|
||||
|
||||
- accraze
|
||||
- Alex Morcos
|
||||
- BtcDrak
|
||||
- Jonas Schnelli
|
||||
- Luke Dashjr
|
||||
- MarcoFalke
|
||||
- Mark Friedenbach
|
||||
- NicolasDorier
|
||||
- Pieter Wuille
|
||||
- Suhas Daftuar
|
||||
- Wladimir J. van der Laan
|
||||
|
||||
As well as everyone that helped translating on [Transifex](https://www.transifex.com/projects/p/bitcoin/).
|
||||
|
||||
Bitcoind can now (optionally) asynchronously notify clients through a
|
||||
ZMQ-based PUB socket of the arrival of new transactions and blocks.
|
||||
This feature requires installation of the ZMQ C API library 4.x and
|
||||
configuring its use through the command line or configuration file.
|
||||
Please see docs/zmq.md for details of operation.
|
||||
|
||||
@@ -3,6 +3,7 @@ Release Process
|
||||
|
||||
* 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.
|
||||
* Update hardcoded [seeds](/contrib/seeds)
|
||||
|
||||
* * *
|
||||
|
||||
@@ -19,8 +20,10 @@ Check out the source code in the following directory hierarchy.
|
||||
|
||||
pushd ./bitcoin
|
||||
contrib/verifysfbinaries/verify.sh
|
||||
configure.ac
|
||||
doc/README*
|
||||
share/setup.nsi
|
||||
doc/Doxyfile
|
||||
contrib/gitian-descriptors/*.yml
|
||||
src/clientversion.h (change CLIENT_VERSION_IS_RELEASE to true)
|
||||
|
||||
# tag version in git
|
||||
@@ -41,6 +44,7 @@ Check out the source code in the following directory hierarchy.
|
||||
pushd ./bitcoin
|
||||
export SIGNER=(your Gitian key, ie bluematt, sipa, etc)
|
||||
export VERSION=(new version, e.g. 0.8.0)
|
||||
git fetch
|
||||
git checkout v${VERSION}
|
||||
popd
|
||||
|
||||
@@ -83,25 +87,21 @@ NOTE: Offline builds must use the --url flag to ensure Gitian fetches only from
|
||||
```
|
||||
The gbuild invocations below <b>DO NOT DO THIS</b> by default.
|
||||
|
||||
###Build (and optionally verify) Bitcoin Core for Linux, Windows, and OS X:
|
||||
###Build and sign 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
|
||||
mv build/out/bitcoin-*.tar.gz build/out/src/bitcoin-*.tar.gz ../
|
||||
mv build/out/bitcoin-*.tar.gz build/out/src/bitcoin-*.tar.gz ../
|
||||
|
||||
./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-win.yml
|
||||
./bin/gsign --signer $SIGNER --release ${VERSION}-win-unsigned --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win.yml
|
||||
./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-win-unsigned ../bitcoin/contrib/gitian-descriptors/gitian-win.yml
|
||||
mv build/out/bitcoin-*-win-unsigned.tar.gz inputs/bitcoin-win-unsigned.tar.gz
|
||||
mv build/out/bitcoin-*.zip build/out/bitcoin-*.exe ../
|
||||
mv build/out/bitcoin-*-win-unsigned.tar.gz inputs/bitcoin-win-unsigned.tar.gz
|
||||
mv build/out/bitcoin-*.zip build/out/bitcoin-*.exe ../
|
||||
|
||||
./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml
|
||||
./bin/gsign --signer $SIGNER --release ${VERSION}-osx-unsigned --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml
|
||||
./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-osx-unsigned ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml
|
||||
mv build/out/bitcoin-*-osx-unsigned.tar.gz inputs/bitcoin-osx-unsigned.tar.gz
|
||||
mv build/out/bitcoin-*.tar.gz build/out/bitcoin-*.dmg ../
|
||||
popd
|
||||
mv build/out/bitcoin-*-osx-unsigned.tar.gz inputs/bitcoin-osx-unsigned.tar.gz
|
||||
mv build/out/bitcoin-*.tar.gz build/out/bitcoin-*.dmg ../
|
||||
|
||||
Build output expected:
|
||||
|
||||
@@ -111,6 +111,20 @@ The gbuild invocations below <b>DO NOT DO THIS</b> by default.
|
||||
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)/
|
||||
|
||||
###Verify other gitian builders signatures to your own. (Optional)
|
||||
|
||||
Add other gitian builders keys to your gpg keyring
|
||||
|
||||
gpg --import ../bitcoin/contrib/gitian-downloader/*.pgp
|
||||
|
||||
Verify the signatures
|
||||
|
||||
./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-linux ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml
|
||||
./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-win-unsigned ../bitcoin/contrib/gitian-descriptors/gitian-win.yml
|
||||
./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-osx-unsigned ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml
|
||||
|
||||
popd
|
||||
|
||||
###Next steps:
|
||||
|
||||
Commit your signature to gitian.sigs:
|
||||
@@ -124,7 +138,6 @@ Commit your signature to gitian.sigs:
|
||||
popd
|
||||
|
||||
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.
|
||||
|
||||
@@ -197,7 +210,7 @@ Note: check that SHA256SUMS itself doesn't end up in SHA256SUMS, which is a spur
|
||||
|
||||
- Optionally reddit /r/Bitcoin, ... but this will usually sort out itself
|
||||
|
||||
- Notify BlueMatt so that he can start building [https://launchpad.net/~bitcoin/+archive/ubuntu/bitcoin](the PPAs)
|
||||
- Notify BlueMatt so that he can start building [the PPAs](https://launchpad.net/~bitcoin/+archive/ubuntu/bitcoin)
|
||||
|
||||
- Add release notes for the new version to the directory `doc/release-notes` in git master
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
@@ -62,8 +62,10 @@ for arg in sys.argv[1:]:
|
||||
|
||||
#Set env vars
|
||||
buildDir = BUILDDIR
|
||||
os.environ["BITCOIND"] = buildDir + '/src/bitcoind' + EXEEXT
|
||||
os.environ["BITCOINCLI"] = buildDir + '/src/bitcoin-cli' + EXEEXT
|
||||
if "BITCOIND" not in os.environ:
|
||||
os.environ["BITCOIND"] = buildDir + '/src/bitcoind' + EXEEXT
|
||||
if "BITCOINCLI" not in os.environ:
|
||||
os.environ["BITCOINCLI"] = buildDir + '/src/bitcoin-cli' + EXEEXT
|
||||
|
||||
#Disable Windows tests by default
|
||||
if EXEEXT == ".exe" and "-win" not in opts:
|
||||
@@ -72,6 +74,7 @@ if EXEEXT == ".exe" and "-win" not in opts:
|
||||
|
||||
#Tests
|
||||
testScripts = [
|
||||
'bip68-112-113-p2p.py',
|
||||
'wallet.py',
|
||||
'listtransactions.py',
|
||||
'receivedby.py',
|
||||
@@ -83,6 +86,7 @@ testScripts = [
|
||||
'rest.py',
|
||||
'mempool_spendcoinbase.py',
|
||||
'mempool_reorg.py',
|
||||
'mempool_limit.py',
|
||||
'httpbasics.py',
|
||||
'multi_rpc.py',
|
||||
'zapwallettxes.py',
|
||||
@@ -100,10 +104,16 @@ testScripts = [
|
||||
'sendheaders.py',
|
||||
'keypool.py',
|
||||
'prioritise_transaction.py',
|
||||
'invalidblockrequest.py',
|
||||
'invalidtxrequest.py',
|
||||
'abandonconflict.py',
|
||||
'p2p-versionbits-warning.py',
|
||||
]
|
||||
testScriptsExt = [
|
||||
'bip9-softforks.py',
|
||||
'bip65-cltv.py',
|
||||
'bip65-cltv-p2p.py',
|
||||
'bip68-sequence.py',
|
||||
'bipdersig-p2p.py',
|
||||
'bipdersig.py',
|
||||
'getblocktemplate_longpoll.py',
|
||||
@@ -116,7 +126,6 @@ testScriptsExt = [
|
||||
# 'rpcbind_test.py', #temporary, bug in libevent, see #6655
|
||||
'smartfees.py',
|
||||
'maxblocksinflight.py',
|
||||
'invalidblockrequest.py',
|
||||
'p2p-acceptblock.py',
|
||||
'mempool_packages.py',
|
||||
'maxuploadtarget.py',
|
||||
|
||||
@@ -47,10 +47,7 @@ implements the test logic.
|
||||
* ```NodeConn``` is the class used to connect to a bitcoind. If you implement
|
||||
a callback class that derives from ```NodeConnCB``` and pass that to the
|
||||
```NodeConn``` object, your code will receive the appropriate callbacks when
|
||||
events of interest arrive. NOTE: be sure to call
|
||||
```self.create_callback_map()``` in your derived classes' ```__init__```
|
||||
function, so that the correct mappings are set up between p2p messages and your
|
||||
callback functions.
|
||||
events of interest arrive.
|
||||
|
||||
* You can pass the same handler to multiple ```NodeConn```'s if you like, or pass
|
||||
different ones to each -- whatever makes the most sense for your test.
|
||||
|
||||
159
qa/rpc-tests/abandonconflict.py
Executable file
159
qa/rpc-tests/abandonconflict.py
Executable file
@@ -0,0 +1,159 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
try:
|
||||
import urllib.parse as urlparse
|
||||
except ImportError:
|
||||
import urlparse
|
||||
|
||||
class AbandonConflictTest(BitcoinTestFramework):
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = []
|
||||
self.nodes.append(start_node(0, self.options.tmpdir, ["-debug","-logtimemicros","-minrelaytxfee=0.00001"]))
|
||||
self.nodes.append(start_node(1, self.options.tmpdir, ["-debug","-logtimemicros"]))
|
||||
connect_nodes(self.nodes[0], 1)
|
||||
|
||||
def run_test(self):
|
||||
self.nodes[1].generate(100)
|
||||
sync_blocks(self.nodes)
|
||||
balance = self.nodes[0].getbalance()
|
||||
txA = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), Decimal("10"))
|
||||
txB = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), Decimal("10"))
|
||||
txC = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), Decimal("10"))
|
||||
sync_mempools(self.nodes)
|
||||
self.nodes[1].generate(1)
|
||||
|
||||
sync_blocks(self.nodes)
|
||||
newbalance = self.nodes[0].getbalance()
|
||||
assert(balance - newbalance < Decimal("0.001")) #no more than fees lost
|
||||
balance = newbalance
|
||||
|
||||
url = urlparse.urlparse(self.nodes[1].url)
|
||||
self.nodes[0].disconnectnode(url.hostname+":"+str(p2p_port(1)))
|
||||
|
||||
# Identify the 10btc outputs
|
||||
nA = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(txA, 1)["vout"]) if vout["value"] == Decimal("10"))
|
||||
nB = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(txB, 1)["vout"]) if vout["value"] == Decimal("10"))
|
||||
nC = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(txC, 1)["vout"]) if vout["value"] == Decimal("10"))
|
||||
|
||||
inputs =[]
|
||||
# spend 10btc outputs from txA and txB
|
||||
inputs.append({"txid":txA, "vout":nA})
|
||||
inputs.append({"txid":txB, "vout":nB})
|
||||
outputs = {}
|
||||
|
||||
outputs[self.nodes[0].getnewaddress()] = Decimal("14.99998")
|
||||
outputs[self.nodes[1].getnewaddress()] = Decimal("5")
|
||||
signed = self.nodes[0].signrawtransaction(self.nodes[0].createrawtransaction(inputs, outputs))
|
||||
txAB1 = self.nodes[0].sendrawtransaction(signed["hex"])
|
||||
|
||||
# Identify the 14.99998btc output
|
||||
nAB = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(txAB1, 1)["vout"]) if vout["value"] == Decimal("14.99998"))
|
||||
|
||||
#Create a child tx spending AB1 and C
|
||||
inputs = []
|
||||
inputs.append({"txid":txAB1, "vout":nAB})
|
||||
inputs.append({"txid":txC, "vout":nC})
|
||||
outputs = {}
|
||||
outputs[self.nodes[0].getnewaddress()] = Decimal("24.9996")
|
||||
signed2 = self.nodes[0].signrawtransaction(self.nodes[0].createrawtransaction(inputs, outputs))
|
||||
txABC2 = self.nodes[0].sendrawtransaction(signed2["hex"])
|
||||
|
||||
# In mempool txs from self should increase balance from change
|
||||
newbalance = self.nodes[0].getbalance()
|
||||
assert(newbalance == balance - Decimal("30") + Decimal("24.9996"))
|
||||
balance = newbalance
|
||||
|
||||
# Restart the node with a higher min relay fee so the parent tx is no longer in mempool
|
||||
# TODO: redo with eviction
|
||||
# Note had to make sure tx did not have AllowFree priority
|
||||
stop_node(self.nodes[0],0)
|
||||
self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug","-logtimemicros","-minrelaytxfee=0.0001"])
|
||||
|
||||
# Verify txs no longer in mempool
|
||||
assert(len(self.nodes[0].getrawmempool()) == 0)
|
||||
|
||||
# Not in mempool txs from self should only reduce balance
|
||||
# inputs are still spent, but change not received
|
||||
newbalance = self.nodes[0].getbalance()
|
||||
assert(newbalance == balance - Decimal("24.9996"))
|
||||
# Unconfirmed received funds that are not in mempool, also shouldn't show
|
||||
# up in unconfirmed balance
|
||||
unconfbalance = self.nodes[0].getunconfirmedbalance() + self.nodes[0].getbalance()
|
||||
assert(unconfbalance == newbalance)
|
||||
# Also shouldn't show up in listunspent
|
||||
assert(not txABC2 in [utxo["txid"] for utxo in self.nodes[0].listunspent(0)])
|
||||
balance = newbalance
|
||||
|
||||
# Abandon original transaction and verify inputs are available again
|
||||
# including that the child tx was also abandoned
|
||||
self.nodes[0].abandontransaction(txAB1)
|
||||
newbalance = self.nodes[0].getbalance()
|
||||
assert(newbalance == balance + Decimal("30"))
|
||||
balance = newbalance
|
||||
|
||||
# Verify that even with a low min relay fee, the tx is not reaccepted from wallet on startup once abandoned
|
||||
stop_node(self.nodes[0],0)
|
||||
self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug","-logtimemicros","-minrelaytxfee=0.00001"])
|
||||
assert(len(self.nodes[0].getrawmempool()) == 0)
|
||||
assert(self.nodes[0].getbalance() == balance)
|
||||
|
||||
# But if its received again then it is unabandoned
|
||||
# And since now in mempool, the change is available
|
||||
# But its child tx remains abandoned
|
||||
self.nodes[0].sendrawtransaction(signed["hex"])
|
||||
newbalance = self.nodes[0].getbalance()
|
||||
assert(newbalance == balance - Decimal("20") + Decimal("14.99998"))
|
||||
balance = newbalance
|
||||
|
||||
# Send child tx again so its unabandoned
|
||||
self.nodes[0].sendrawtransaction(signed2["hex"])
|
||||
newbalance = self.nodes[0].getbalance()
|
||||
assert(newbalance == balance - Decimal("10") - Decimal("14.99998") + Decimal("24.9996"))
|
||||
balance = newbalance
|
||||
|
||||
# Remove using high relay fee again
|
||||
stop_node(self.nodes[0],0)
|
||||
self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug","-logtimemicros","-minrelaytxfee=0.0001"])
|
||||
assert(len(self.nodes[0].getrawmempool()) == 0)
|
||||
newbalance = self.nodes[0].getbalance()
|
||||
assert(newbalance == balance - Decimal("24.9996"))
|
||||
balance = newbalance
|
||||
|
||||
# Create a double spend of AB1 by spending again from only A's 10 output
|
||||
# Mine double spend from node 1
|
||||
inputs =[]
|
||||
inputs.append({"txid":txA, "vout":nA})
|
||||
outputs = {}
|
||||
outputs[self.nodes[1].getnewaddress()] = Decimal("9.9999")
|
||||
tx = self.nodes[0].createrawtransaction(inputs, outputs)
|
||||
signed = self.nodes[0].signrawtransaction(tx)
|
||||
self.nodes[1].sendrawtransaction(signed["hex"])
|
||||
self.nodes[1].generate(1)
|
||||
|
||||
connect_nodes(self.nodes[0], 1)
|
||||
sync_blocks(self.nodes)
|
||||
|
||||
# Verify that B and C's 10 BTC outputs are available for spending again because AB1 is now conflicted
|
||||
newbalance = self.nodes[0].getbalance()
|
||||
assert(newbalance == balance + Decimal("20"))
|
||||
balance = newbalance
|
||||
|
||||
# There is currently a minor bug around this and so this test doesn't work. See Issue #7315
|
||||
# Invalidate the block with the double spend and B's 10 BTC output should no longer be available
|
||||
# Don't think C's should either
|
||||
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
||||
newbalance = self.nodes[0].getbalance()
|
||||
#assert(newbalance == balance - Decimal("10"))
|
||||
print "If balance has not declined after invalidateblock then out of mempool wallet tx which is no longer"
|
||||
print "conflicted has not resumed causing its inputs to be seen as spent. See Issue #7315"
|
||||
print balance , " -> " , newbalance , " ?"
|
||||
|
||||
if __name__ == '__main__':
|
||||
AbandonConflictTest().main()
|
||||
@@ -9,8 +9,8 @@ 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
|
||||
from test_framework.script import CScript, OP_1NEGATE, OP_CHECKLOCKTIMEVERIFY, OP_DROP
|
||||
from binascii import unhexlify
|
||||
import cStringIO
|
||||
import time
|
||||
|
||||
@@ -19,7 +19,7 @@ def cltv_invalidate(tx):
|
||||
|
||||
Prepends -1 CLTV DROP in the scriptSig itself.
|
||||
'''
|
||||
tx.vin[0].scriptSig = CScript([OP_1NEGATE, OP_NOP2, OP_DROP] +
|
||||
tx.vin[0].scriptSig = CScript([OP_1NEGATE, OP_CHECKLOCKTIMEVERIFY, OP_DROP] +
|
||||
list(CScript(tx.vin[0].scriptSig)))
|
||||
|
||||
'''
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
import os
|
||||
import shutil
|
||||
|
||||
class BIP65Test(BitcoinTestFramework):
|
||||
|
||||
@@ -46,7 +44,7 @@ class BIP65Test(BitcoinTestFramework):
|
||||
self.nodes[2].generate(1)
|
||||
self.sync_all()
|
||||
if (self.nodes[0].getblockcount() != cnt + 851):
|
||||
raise AssertionFailure("Failed to mine a version=4 blocks")
|
||||
raise AssertionError("Failed to mine a version=4 blocks")
|
||||
|
||||
# TODO: check that new CHECKLOCKTIMEVERIFY rules are enforced
|
||||
|
||||
|
||||
540
qa/rpc-tests/bip68-112-113-p2p.py
Executable file
540
qa/rpc-tests/bip68-112-113-p2p.py
Executable file
@@ -0,0 +1,540 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2015 The Bitcoin Core developers
|
||||
# Distributed under the MIT/X11 software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#
|
||||
|
||||
from test_framework.test_framework import ComparisonTestFramework
|
||||
from test_framework.util import *
|
||||
from test_framework.mininode import ToHex, CTransaction, NetworkThread
|
||||
from test_framework.blocktools import create_coinbase, create_block
|
||||
from test_framework.comptool import TestInstance, TestManager
|
||||
from test_framework.script import *
|
||||
from binascii import unhexlify
|
||||
import cStringIO
|
||||
import time
|
||||
|
||||
'''
|
||||
This test is meant to exercise activation of the first version bits soft fork
|
||||
This soft fork will activate the following BIPS:
|
||||
BIP 68 - nSequence relative lock times
|
||||
BIP 112 - CHECKSEQUENCEVERIFY
|
||||
BIP 113 - MedianTimePast semantics for nLockTime
|
||||
|
||||
regtest lock-in with 108/144 block signalling
|
||||
activation after a further 144 blocks
|
||||
|
||||
mine 82 blocks whose coinbases will be used to generate inputs for our tests
|
||||
mine 61 blocks to transition from DEFINED to STARTED
|
||||
mine 144 blocks only 100 of which are signaling readiness in order to fail to change state this period
|
||||
mine 144 blocks with 108 signaling and verify STARTED->LOCKED_IN
|
||||
mine 140 blocks and seed block chain with the 82 inputs will use for our tests at height 572
|
||||
mine 3 blocks and verify still at LOCKED_IN and test that enforcement has not triggered
|
||||
mine 1 block and test that enforcement has triggered (which triggers ACTIVE)
|
||||
Test BIP 113 is enforced
|
||||
Mine 4 blocks so next height is 580 and test BIP 68 is enforced for time and height
|
||||
Mine 1 block so next height is 581 and test BIP 68 now passes time but not height
|
||||
Mine 1 block so next height is 582 and test BIP 68 now passes time and height
|
||||
Test that BIP 112 is enforced
|
||||
|
||||
Various transactions will be used to test that the BIPs rules are not enforced before the soft fork activates
|
||||
And that after the soft fork activates transactions pass and fail as they should according to the rules.
|
||||
For each BIP, transactions of versions 1 and 2 will be tested.
|
||||
----------------
|
||||
BIP 113:
|
||||
bip113tx - modify the nLocktime variable
|
||||
|
||||
BIP 68:
|
||||
bip68txs - 16 txs with nSequence relative locktime of 10 with various bits set as per the relative_locktimes below
|
||||
|
||||
BIP 112:
|
||||
bip112txs_vary_nSequence - 16 txs with nSequence relative_locktimes of 10 evaluated against 10 OP_CSV OP_DROP
|
||||
bip112txs_vary_nSequence_9 - 16 txs with nSequence relative_locktimes of 9 evaluated against 10 OP_CSV OP_DROP
|
||||
bip112txs_vary_OP_CSV - 16 txs with nSequence = 10 evaluated against varying {relative_locktimes of 10} OP_CSV OP_DROP
|
||||
bip112txs_vary_OP_CSV_9 - 16 txs with nSequence = 9 evaluated against varying {relative_locktimes of 10} OP_CSV OP_DROP
|
||||
bip112tx_special - test negative argument to OP_CSV
|
||||
'''
|
||||
|
||||
base_relative_locktime = 10
|
||||
seq_disable_flag = 1<<31
|
||||
seq_random_high_bit = 1<<25
|
||||
seq_type_flag = 1<<22
|
||||
seq_random_low_bit = 1<<18
|
||||
|
||||
# b31,b25,b22,b18 represent the 31st, 25th, 22nd and 18th bits respectively in the nSequence field
|
||||
# relative_locktimes[b31][b25][b22][b18] is a base_relative_locktime with the indicated bits set if their indices are 1
|
||||
relative_locktimes = []
|
||||
for b31 in xrange(2):
|
||||
b25times = []
|
||||
for b25 in xrange(2):
|
||||
b22times = []
|
||||
for b22 in xrange(2):
|
||||
b18times = []
|
||||
for b18 in xrange(2):
|
||||
rlt = base_relative_locktime
|
||||
if (b31):
|
||||
rlt = rlt | seq_disable_flag
|
||||
if (b25):
|
||||
rlt = rlt | seq_random_high_bit
|
||||
if (b22):
|
||||
rlt = rlt | seq_type_flag
|
||||
if (b18):
|
||||
rlt = rlt | seq_random_low_bit
|
||||
b18times.append(rlt)
|
||||
b22times.append(b18times)
|
||||
b25times.append(b22times)
|
||||
relative_locktimes.append(b25times)
|
||||
|
||||
def all_rlt_txs(txarray):
|
||||
txs = []
|
||||
for b31 in xrange(2):
|
||||
for b25 in xrange(2):
|
||||
for b22 in xrange(2):
|
||||
for b18 in xrange(2):
|
||||
txs.append(txarray[b31][b25][b22][b18])
|
||||
return txs
|
||||
|
||||
class BIP68_112_113Test(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=4']],
|
||||
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 send_generic_input_tx(self, node, coinbases):
|
||||
amount = Decimal("49.99")
|
||||
return node.sendrawtransaction(ToHex(self.sign_transaction(node, self.create_transaction(node, node.getblock(coinbases.pop())['tx'][0], self.nodeaddress, amount))))
|
||||
|
||||
def create_transaction(self, node, txid, to_address, amount):
|
||||
inputs = [{ "txid" : txid, "vout" : 0}]
|
||||
outputs = { to_address : amount }
|
||||
rawtx = node.createrawtransaction(inputs, outputs)
|
||||
tx = CTransaction()
|
||||
f = cStringIO.StringIO(unhexlify(rawtx))
|
||||
tx.deserialize(f)
|
||||
return tx
|
||||
|
||||
def sign_transaction(self, node, unsignedtx):
|
||||
rawtx = ToHex(unsignedtx)
|
||||
signresult = node.signrawtransaction(rawtx)
|
||||
tx = CTransaction()
|
||||
f = cStringIO.StringIO(unhexlify(signresult['hex']))
|
||||
tx.deserialize(f)
|
||||
return tx
|
||||
|
||||
def generate_blocks(self, number, version, test_blocks = []):
|
||||
for i in xrange(number):
|
||||
block = self.create_test_block([], version)
|
||||
test_blocks.append([block, True])
|
||||
self.last_block_time += 600
|
||||
self.tip = block.sha256
|
||||
self.tipheight += 1
|
||||
return test_blocks
|
||||
|
||||
def create_test_block(self, txs, version = 536870912):
|
||||
block = create_block(self.tip, create_coinbase(self.tipheight + 1), self.last_block_time + 600)
|
||||
block.nVersion = version
|
||||
block.vtx.extend(txs)
|
||||
block.hashMerkleRoot = block.calc_merkle_root()
|
||||
block.rehash()
|
||||
block.solve()
|
||||
return block
|
||||
|
||||
def create_bip68txs(self, bip68inputs, txversion, locktime_delta = 0):
|
||||
txs = []
|
||||
assert(len(bip68inputs) >= 16)
|
||||
i = 0
|
||||
for b31 in xrange(2):
|
||||
b25txs = []
|
||||
for b25 in xrange(2):
|
||||
b22txs = []
|
||||
for b22 in xrange(2):
|
||||
b18txs = []
|
||||
for b18 in xrange(2):
|
||||
tx = self.create_transaction(self.nodes[0], bip68inputs[i], self.nodeaddress, Decimal("49.98"))
|
||||
i += 1
|
||||
tx.nVersion = txversion
|
||||
tx.vin[0].nSequence = relative_locktimes[b31][b25][b22][b18] + locktime_delta
|
||||
b18txs.append(self.sign_transaction(self.nodes[0], tx))
|
||||
b22txs.append(b18txs)
|
||||
b25txs.append(b22txs)
|
||||
txs.append(b25txs)
|
||||
return txs
|
||||
|
||||
def create_bip112special(self, input, txversion):
|
||||
tx = self.create_transaction(self.nodes[0], input, self.nodeaddress, Decimal("49.98"))
|
||||
tx.nVersion = txversion
|
||||
signtx = self.sign_transaction(self.nodes[0], tx)
|
||||
signtx.vin[0].scriptSig = CScript([-1, OP_NOP3, OP_DROP] + list(CScript(signtx.vin[0].scriptSig)))
|
||||
return signtx
|
||||
|
||||
def create_bip112txs(self, bip112inputs, varyOP_CSV, txversion, locktime_delta = 0):
|
||||
txs = []
|
||||
assert(len(bip112inputs) >= 16)
|
||||
i = 0
|
||||
for b31 in xrange(2):
|
||||
b25txs = []
|
||||
for b25 in xrange(2):
|
||||
b22txs = []
|
||||
for b22 in xrange(2):
|
||||
b18txs = []
|
||||
for b18 in xrange(2):
|
||||
tx = self.create_transaction(self.nodes[0], bip112inputs[i], self.nodeaddress, Decimal("49.98"))
|
||||
i += 1
|
||||
if (varyOP_CSV): # if varying OP_CSV, nSequence is fixed
|
||||
tx.vin[0].nSequence = base_relative_locktime + locktime_delta
|
||||
else: # vary nSequence instead, OP_CSV is fixed
|
||||
tx.vin[0].nSequence = relative_locktimes[b31][b25][b22][b18] + locktime_delta
|
||||
tx.nVersion = txversion
|
||||
signtx = self.sign_transaction(self.nodes[0], tx)
|
||||
if (varyOP_CSV):
|
||||
signtx.vin[0].scriptSig = CScript([relative_locktimes[b31][b25][b22][b18], OP_NOP3, OP_DROP] + list(CScript(signtx.vin[0].scriptSig)))
|
||||
else:
|
||||
signtx.vin[0].scriptSig = CScript([base_relative_locktime, OP_NOP3, OP_DROP] + list(CScript(signtx.vin[0].scriptSig)))
|
||||
b18txs.append(signtx)
|
||||
b22txs.append(b18txs)
|
||||
b25txs.append(b22txs)
|
||||
txs.append(b25txs)
|
||||
return txs
|
||||
|
||||
def get_tests(self):
|
||||
long_past_time = int(time.time()) - 600 * 1000 # enough to build up to 1000 blocks 10 minutes apart without worrying about getting into the future
|
||||
self.nodes[0].setmocktime(long_past_time - 100) # enough so that the generated blocks will still all be before long_past_time
|
||||
self.coinbase_blocks = self.nodes[0].generate(1 + 16 + 2*32 + 1) # 82 blocks generated for inputs
|
||||
self.nodes[0].setmocktime(0) # set time back to present so yielded blocks aren't in the future as we advance last_block_time
|
||||
self.tipheight = 82 # height of the next block to build
|
||||
self.last_block_time = long_past_time
|
||||
self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0)
|
||||
self.nodeaddress = self.nodes[0].getnewaddress()
|
||||
|
||||
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'defined')
|
||||
test_blocks = self.generate_blocks(61, 4)
|
||||
yield TestInstance(test_blocks, sync_every_block=False) # 1
|
||||
# Advanced from DEFINED to STARTED, height = 143
|
||||
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'started')
|
||||
|
||||
# Fail to achieve LOCKED_IN 100 out of 144 signal bit 0
|
||||
# using a variety of bits to simulate multiple parallel softforks
|
||||
test_blocks = self.generate_blocks(50, 536870913) # 0x20000001 (signalling ready)
|
||||
test_blocks = self.generate_blocks(20, 4, test_blocks) # 0x00000004 (signalling not)
|
||||
test_blocks = self.generate_blocks(50, 536871169, test_blocks) # 0x20000101 (signalling ready)
|
||||
test_blocks = self.generate_blocks(24, 536936448, test_blocks) # 0x20010000 (signalling not)
|
||||
yield TestInstance(test_blocks, sync_every_block=False) # 2
|
||||
# Failed to advance past STARTED, height = 287
|
||||
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'started')
|
||||
|
||||
# 108 out of 144 signal bit 0 to achieve lock-in
|
||||
# using a variety of bits to simulate multiple parallel softforks
|
||||
test_blocks = self.generate_blocks(58, 536870913) # 0x20000001 (signalling ready)
|
||||
test_blocks = self.generate_blocks(26, 4, test_blocks) # 0x00000004 (signalling not)
|
||||
test_blocks = self.generate_blocks(50, 536871169, test_blocks) # 0x20000101 (signalling ready)
|
||||
test_blocks = self.generate_blocks(10, 536936448, test_blocks) # 0x20010000 (signalling not)
|
||||
yield TestInstance(test_blocks, sync_every_block=False) # 3
|
||||
# Advanced from STARTED to LOCKED_IN, height = 431
|
||||
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'locked_in')
|
||||
|
||||
# 140 more version 4 blocks
|
||||
test_blocks = self.generate_blocks(140, 4)
|
||||
yield TestInstance(test_blocks, sync_every_block=False) # 4
|
||||
|
||||
### Inputs at height = 572
|
||||
# Put inputs for all tests in the chain at height 572 (tip now = 571) (time increases by 600s per block)
|
||||
# Note we reuse inputs for v1 and v2 txs so must test these separately
|
||||
# 16 normal inputs
|
||||
bip68inputs = []
|
||||
for i in xrange(16):
|
||||
bip68inputs.append(self.send_generic_input_tx(self.nodes[0], self.coinbase_blocks))
|
||||
# 2 sets of 16 inputs with 10 OP_CSV OP_DROP (actually will be prepended to spending scriptSig)
|
||||
bip112basicinputs = []
|
||||
for j in xrange(2):
|
||||
inputs = []
|
||||
for i in xrange(16):
|
||||
inputs.append(self.send_generic_input_tx(self.nodes[0], self.coinbase_blocks))
|
||||
bip112basicinputs.append(inputs)
|
||||
# 2 sets of 16 varied inputs with (relative_lock_time) OP_CSV OP_DROP (actually will be prepended to spending scriptSig)
|
||||
bip112diverseinputs = []
|
||||
for j in xrange(2):
|
||||
inputs = []
|
||||
for i in xrange(16):
|
||||
inputs.append(self.send_generic_input_tx(self.nodes[0], self.coinbase_blocks))
|
||||
bip112diverseinputs.append(inputs)
|
||||
# 1 special input with -1 OP_CSV OP_DROP (actually will be prepended to spending scriptSig)
|
||||
bip112specialinput = self.send_generic_input_tx(self.nodes[0], self.coinbase_blocks)
|
||||
# 1 normal input
|
||||
bip113input = self.send_generic_input_tx(self.nodes[0], self.coinbase_blocks)
|
||||
|
||||
self.nodes[0].setmocktime(self.last_block_time + 600)
|
||||
inputblockhash = self.nodes[0].generate(1)[0] # 1 block generated for inputs to be in chain at height 572
|
||||
self.nodes[0].setmocktime(0)
|
||||
self.tip = int("0x" + inputblockhash + "L", 0)
|
||||
self.tipheight += 1
|
||||
self.last_block_time += 600
|
||||
assert_equal(len(self.nodes[0].getblock(inputblockhash,True)["tx"]), 82+1)
|
||||
|
||||
# 2 more version 4 blocks
|
||||
test_blocks = self.generate_blocks(2, 4)
|
||||
yield TestInstance(test_blocks, sync_every_block=False) # 5
|
||||
# Not yet advanced to ACTIVE, height = 574 (will activate for block 576, not 575)
|
||||
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'locked_in')
|
||||
|
||||
# Test both version 1 and version 2 transactions for all tests
|
||||
# BIP113 test transaction will be modified before each use to put in appropriate block time
|
||||
bip113tx_v1 = self.create_transaction(self.nodes[0], bip113input, self.nodeaddress, Decimal("49.98"))
|
||||
bip113tx_v1.vin[0].nSequence = 0xFFFFFFFE
|
||||
bip113tx_v2 = self.create_transaction(self.nodes[0], bip113input, self.nodeaddress, Decimal("49.98"))
|
||||
bip113tx_v2.vin[0].nSequence = 0xFFFFFFFE
|
||||
bip113tx_v2.nVersion = 2
|
||||
|
||||
# For BIP68 test all 16 relative sequence locktimes
|
||||
bip68txs_v1 = self.create_bip68txs(bip68inputs, 1)
|
||||
bip68txs_v2 = self.create_bip68txs(bip68inputs, 2)
|
||||
|
||||
# For BIP112 test:
|
||||
# 16 relative sequence locktimes of 10 against 10 OP_CSV OP_DROP inputs
|
||||
bip112txs_vary_nSequence_v1 = self.create_bip112txs(bip112basicinputs[0], False, 1)
|
||||
bip112txs_vary_nSequence_v2 = self.create_bip112txs(bip112basicinputs[0], False, 2)
|
||||
# 16 relative sequence locktimes of 9 against 10 OP_CSV OP_DROP inputs
|
||||
bip112txs_vary_nSequence_9_v1 = self.create_bip112txs(bip112basicinputs[1], False, 1, -1)
|
||||
bip112txs_vary_nSequence_9_v2 = self.create_bip112txs(bip112basicinputs[1], False, 2, -1)
|
||||
# sequence lock time of 10 against 16 (relative_lock_time) OP_CSV OP_DROP inputs
|
||||
bip112txs_vary_OP_CSV_v1 = self.create_bip112txs(bip112diverseinputs[0], True, 1)
|
||||
bip112txs_vary_OP_CSV_v2 = self.create_bip112txs(bip112diverseinputs[0], True, 2)
|
||||
# sequence lock time of 9 against 16 (relative_lock_time) OP_CSV OP_DROP inputs
|
||||
bip112txs_vary_OP_CSV_9_v1 = self.create_bip112txs(bip112diverseinputs[1], True, 1, -1)
|
||||
bip112txs_vary_OP_CSV_9_v2 = self.create_bip112txs(bip112diverseinputs[1], True, 2, -1)
|
||||
# -1 OP_CSV OP_DROP input
|
||||
bip112tx_special_v1 = self.create_bip112special(bip112specialinput, 1)
|
||||
bip112tx_special_v2 = self.create_bip112special(bip112specialinput, 2)
|
||||
|
||||
|
||||
### TESTING ###
|
||||
##################################
|
||||
### Before Soft Forks Activate ###
|
||||
##################################
|
||||
# All txs should pass
|
||||
### Version 1 txs ###
|
||||
success_txs = []
|
||||
# add BIP113 tx and -1 CSV tx
|
||||
bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
|
||||
bip113signed1 = self.sign_transaction(self.nodes[0], bip113tx_v1)
|
||||
success_txs.append(bip113signed1)
|
||||
success_txs.append(bip112tx_special_v1)
|
||||
# add BIP 68 txs
|
||||
success_txs.extend(all_rlt_txs(bip68txs_v1))
|
||||
# add BIP 112 with seq=10 txs
|
||||
success_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_v1))
|
||||
success_txs.extend(all_rlt_txs(bip112txs_vary_OP_CSV_v1))
|
||||
# try BIP 112 with seq=9 txs
|
||||
success_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_9_v1))
|
||||
success_txs.extend(all_rlt_txs(bip112txs_vary_OP_CSV_9_v1))
|
||||
yield TestInstance([[self.create_test_block(success_txs), True]]) # 6
|
||||
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
||||
|
||||
### Version 2 txs ###
|
||||
success_txs = []
|
||||
# add BIP113 tx and -1 CSV tx
|
||||
bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
|
||||
bip113signed2 = self.sign_transaction(self.nodes[0], bip113tx_v2)
|
||||
success_txs.append(bip113signed2)
|
||||
success_txs.append(bip112tx_special_v2)
|
||||
# add BIP 68 txs
|
||||
success_txs.extend(all_rlt_txs(bip68txs_v2))
|
||||
# add BIP 112 with seq=10 txs
|
||||
success_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_v2))
|
||||
success_txs.extend(all_rlt_txs(bip112txs_vary_OP_CSV_v2))
|
||||
# try BIP 112 with seq=9 txs
|
||||
success_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_9_v2))
|
||||
success_txs.extend(all_rlt_txs(bip112txs_vary_OP_CSV_9_v2))
|
||||
yield TestInstance([[self.create_test_block(success_txs), True]]) # 7
|
||||
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
||||
|
||||
|
||||
# 1 more version 4 block to get us to height 575 so the fork should now be active for the next block
|
||||
test_blocks = self.generate_blocks(1, 4)
|
||||
yield TestInstance(test_blocks, sync_every_block=False) # 8
|
||||
assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'active')
|
||||
|
||||
|
||||
#################################
|
||||
### After Soft Forks Activate ###
|
||||
#################################
|
||||
### BIP 113 ###
|
||||
# BIP 113 tests should now fail regardless of version number if nLockTime isn't satisfied by new rules
|
||||
bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
|
||||
bip113signed1 = self.sign_transaction(self.nodes[0], bip113tx_v1)
|
||||
bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
|
||||
bip113signed2 = self.sign_transaction(self.nodes[0], bip113tx_v2)
|
||||
for bip113tx in [bip113signed1, bip113signed2]:
|
||||
yield TestInstance([[self.create_test_block([bip113tx]), False]]) # 9,10
|
||||
# BIP 113 tests should now pass if the locktime is < MTP
|
||||
bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 - 1 # < MTP of prior block
|
||||
bip113signed1 = self.sign_transaction(self.nodes[0], bip113tx_v1)
|
||||
bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 - 1 # < MTP of prior block
|
||||
bip113signed2 = self.sign_transaction(self.nodes[0], bip113tx_v2)
|
||||
for bip113tx in [bip113signed1, bip113signed2]:
|
||||
yield TestInstance([[self.create_test_block([bip113tx]), True]]) # 11,12
|
||||
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
||||
|
||||
# Next block height = 580 after 4 blocks of random version
|
||||
test_blocks = self.generate_blocks(4, 1234)
|
||||
yield TestInstance(test_blocks, sync_every_block=False) # 13
|
||||
|
||||
### BIP 68 ###
|
||||
### Version 1 txs ###
|
||||
# All still pass
|
||||
success_txs = []
|
||||
success_txs.extend(all_rlt_txs(bip68txs_v1))
|
||||
yield TestInstance([[self.create_test_block(success_txs), True]]) # 14
|
||||
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
||||
|
||||
### Version 2 txs ###
|
||||
bip68success_txs = []
|
||||
# All txs with SEQUENCE_LOCKTIME_DISABLE_FLAG set pass
|
||||
for b25 in xrange(2):
|
||||
for b22 in xrange(2):
|
||||
for b18 in xrange(2):
|
||||
bip68success_txs.append(bip68txs_v2[1][b25][b22][b18])
|
||||
yield TestInstance([[self.create_test_block(bip68success_txs), True]]) # 15
|
||||
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
||||
# All txs without flag fail as we are at delta height = 8 < 10 and delta time = 8 * 600 < 10 * 512
|
||||
bip68timetxs = []
|
||||
for b25 in xrange(2):
|
||||
for b18 in xrange(2):
|
||||
bip68timetxs.append(bip68txs_v2[0][b25][1][b18])
|
||||
for tx in bip68timetxs:
|
||||
yield TestInstance([[self.create_test_block([tx]), False]]) # 16 - 19
|
||||
bip68heighttxs = []
|
||||
for b25 in xrange(2):
|
||||
for b18 in xrange(2):
|
||||
bip68heighttxs.append(bip68txs_v2[0][b25][0][b18])
|
||||
for tx in bip68heighttxs:
|
||||
yield TestInstance([[self.create_test_block([tx]), False]]) # 20 - 23
|
||||
|
||||
# Advance one block to 581
|
||||
test_blocks = self.generate_blocks(1, 1234)
|
||||
yield TestInstance(test_blocks, sync_every_block=False) # 24
|
||||
|
||||
# Height txs should fail and time txs should now pass 9 * 600 > 10 * 512
|
||||
bip68success_txs.extend(bip68timetxs)
|
||||
yield TestInstance([[self.create_test_block(bip68success_txs), True]]) # 25
|
||||
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
||||
for tx in bip68heighttxs:
|
||||
yield TestInstance([[self.create_test_block([tx]), False]]) # 26 - 29
|
||||
|
||||
# Advance one block to 582
|
||||
test_blocks = self.generate_blocks(1, 1234)
|
||||
yield TestInstance(test_blocks, sync_every_block=False) # 30
|
||||
|
||||
# All BIP 68 txs should pass
|
||||
bip68success_txs.extend(bip68heighttxs)
|
||||
yield TestInstance([[self.create_test_block(bip68success_txs), True]]) # 31
|
||||
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
||||
|
||||
|
||||
### BIP 112 ###
|
||||
### Version 1 txs ###
|
||||
# -1 OP_CSV tx should fail
|
||||
yield TestInstance([[self.create_test_block([bip112tx_special_v1]), False]]) #32
|
||||
# If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in argument to OP_CSV, version 1 txs should still pass
|
||||
success_txs = []
|
||||
for b25 in xrange(2):
|
||||
for b22 in xrange(2):
|
||||
for b18 in xrange(2):
|
||||
success_txs.append(bip112txs_vary_OP_CSV_v1[1][b25][b22][b18])
|
||||
success_txs.append(bip112txs_vary_OP_CSV_9_v1[1][b25][b22][b18])
|
||||
yield TestInstance([[self.create_test_block(success_txs), True]]) # 33
|
||||
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
||||
|
||||
# If SEQUENCE_LOCKTIME_DISABLE_FLAG is unset in argument to OP_CSV, version 1 txs should now fail
|
||||
fail_txs = []
|
||||
fail_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_v1))
|
||||
fail_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_9_v1))
|
||||
for b25 in xrange(2):
|
||||
for b22 in xrange(2):
|
||||
for b18 in xrange(2):
|
||||
fail_txs.append(bip112txs_vary_OP_CSV_v1[0][b25][b22][b18])
|
||||
fail_txs.append(bip112txs_vary_OP_CSV_9_v1[0][b25][b22][b18])
|
||||
|
||||
for tx in fail_txs:
|
||||
yield TestInstance([[self.create_test_block([tx]), False]]) # 34 - 81
|
||||
|
||||
### Version 2 txs ###
|
||||
# -1 OP_CSV tx should fail
|
||||
yield TestInstance([[self.create_test_block([bip112tx_special_v2]), False]]) #82
|
||||
|
||||
# If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in argument to OP_CSV, version 2 txs should pass (all sequence locks are met)
|
||||
success_txs = []
|
||||
for b25 in xrange(2):
|
||||
for b22 in xrange(2):
|
||||
for b18 in xrange(2):
|
||||
success_txs.append(bip112txs_vary_OP_CSV_v2[1][b25][b22][b18]) # 8/16 of vary_OP_CSV
|
||||
success_txs.append(bip112txs_vary_OP_CSV_9_v2[1][b25][b22][b18]) # 8/16 of vary_OP_CSV_9
|
||||
|
||||
yield TestInstance([[self.create_test_block(success_txs), True]]) # 83
|
||||
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
||||
|
||||
## SEQUENCE_LOCKTIME_DISABLE_FLAG is unset in argument to OP_CSV for all remaining txs ##
|
||||
# All txs with nSequence 9 should fail either due to earlier mismatch or failing the CSV check
|
||||
fail_txs = []
|
||||
fail_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_9_v2)) # 16/16 of vary_nSequence_9
|
||||
for b25 in xrange(2):
|
||||
for b22 in xrange(2):
|
||||
for b18 in xrange(2):
|
||||
fail_txs.append(bip112txs_vary_OP_CSV_9_v2[0][b25][b22][b18]) # 16/16 of vary_OP_CSV_9
|
||||
|
||||
for tx in fail_txs:
|
||||
yield TestInstance([[self.create_test_block([tx]), False]]) # 84 - 107
|
||||
|
||||
# If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in nSequence, tx should fail
|
||||
fail_txs = []
|
||||
for b25 in xrange(2):
|
||||
for b22 in xrange(2):
|
||||
for b18 in xrange(2):
|
||||
fail_txs.append(bip112txs_vary_nSequence_v2[1][b25][b22][b18]) # 8/16 of vary_nSequence
|
||||
for tx in fail_txs:
|
||||
yield TestInstance([[self.create_test_block([tx]), False]]) # 108-115
|
||||
|
||||
# If sequencelock types mismatch, tx should fail
|
||||
fail_txs = []
|
||||
for b25 in xrange(2):
|
||||
for b18 in xrange(2):
|
||||
fail_txs.append(bip112txs_vary_nSequence_v2[0][b25][1][b18]) # 12/16 of vary_nSequence
|
||||
fail_txs.append(bip112txs_vary_OP_CSV_v2[0][b25][1][b18]) # 12/16 of vary_OP_CSV
|
||||
for tx in fail_txs:
|
||||
yield TestInstance([[self.create_test_block([tx]), False]]) # 116-123
|
||||
|
||||
# Remaining txs should pass, just test masking works properly
|
||||
success_txs = []
|
||||
for b25 in xrange(2):
|
||||
for b18 in xrange(2):
|
||||
success_txs.append(bip112txs_vary_nSequence_v2[0][b25][0][b18]) # 16/16 of vary_nSequence
|
||||
success_txs.append(bip112txs_vary_OP_CSV_v2[0][b25][0][b18]) # 16/16 of vary_OP_CSV
|
||||
yield TestInstance([[self.create_test_block(success_txs), True]]) # 124
|
||||
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
||||
|
||||
# Additional test, of checking that comparison of two time types works properly
|
||||
time_txs = []
|
||||
for b25 in xrange(2):
|
||||
for b18 in xrange(2):
|
||||
tx = bip112txs_vary_OP_CSV_v2[0][b25][1][b18]
|
||||
tx.vin[0].nSequence = base_relative_locktime | seq_type_flag
|
||||
signtx = self.sign_transaction(self.nodes[0], tx)
|
||||
time_txs.append(signtx)
|
||||
yield TestInstance([[self.create_test_block(time_txs), True]]) # 125
|
||||
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
||||
|
||||
### Missing aspects of test
|
||||
## Testing empty stack fails
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
BIP68_112_113Test().main()
|
||||
425
qa/rpc-tests/bip68-sequence.py
Executable file
425
qa/rpc-tests/bip68-sequence.py
Executable file
@@ -0,0 +1,425 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014-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 BIP68 implementation
|
||||
#
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
from test_framework.script import *
|
||||
from test_framework.mininode import *
|
||||
from test_framework.blocktools import *
|
||||
|
||||
COIN = 100000000
|
||||
SEQUENCE_LOCKTIME_DISABLE_FLAG = (1<<31)
|
||||
SEQUENCE_LOCKTIME_TYPE_FLAG = (1<<22) # this means use time (0 means height)
|
||||
SEQUENCE_LOCKTIME_GRANULARITY = 9 # this is a bit-shift
|
||||
SEQUENCE_LOCKTIME_MASK = 0x0000ffff
|
||||
|
||||
# RPC error for non-BIP68 final transactions
|
||||
NOT_FINAL_ERROR = "64: non-BIP68-final"
|
||||
|
||||
class BIP68Test(BitcoinTestFramework):
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = []
|
||||
self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-blockprioritysize=0"]))
|
||||
self.nodes.append(start_node(1, self.options.tmpdir, ["-debug", "-blockprioritysize=0", "-acceptnonstdtxn=0"]))
|
||||
self.is_network_split = False
|
||||
self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"]
|
||||
connect_nodes(self.nodes[0], 1)
|
||||
|
||||
def run_test(self):
|
||||
# Generate some coins
|
||||
self.nodes[0].generate(110)
|
||||
|
||||
print "Running test disable flag"
|
||||
self.test_disable_flag()
|
||||
|
||||
print "Running test sequence-lock-confirmed-inputs"
|
||||
self.test_sequence_lock_confirmed_inputs()
|
||||
|
||||
print "Running test sequence-lock-unconfirmed-inputs"
|
||||
self.test_sequence_lock_unconfirmed_inputs()
|
||||
|
||||
print "Running test BIP68 not consensus before versionbits activation"
|
||||
self.test_bip68_not_consensus()
|
||||
|
||||
print "Verifying nVersion=2 transactions aren't standard"
|
||||
self.test_version2_relay(before_activation=True)
|
||||
|
||||
print "Activating BIP68 (and 112/113)"
|
||||
self.activateCSV()
|
||||
|
||||
print "Verifying nVersion=2 transactions are now standard"
|
||||
self.test_version2_relay(before_activation=False)
|
||||
|
||||
print "Passed\n"
|
||||
|
||||
# Test that BIP68 is not in effect if tx version is 1, or if
|
||||
# the first sequence bit is set.
|
||||
def test_disable_flag(self):
|
||||
# Create some unconfirmed inputs
|
||||
new_addr = self.nodes[0].getnewaddress()
|
||||
self.nodes[0].sendtoaddress(new_addr, 2) # send 2 BTC
|
||||
|
||||
utxos = self.nodes[0].listunspent(0, 0)
|
||||
assert(len(utxos) > 0)
|
||||
|
||||
utxo = utxos[0]
|
||||
|
||||
tx1 = CTransaction()
|
||||
value = int(satoshi_round(utxo["amount"] - self.relayfee)*COIN)
|
||||
|
||||
# Check that the disable flag disables relative locktime.
|
||||
# If sequence locks were used, this would require 1 block for the
|
||||
# input to mature.
|
||||
sequence_value = SEQUENCE_LOCKTIME_DISABLE_FLAG | 1
|
||||
tx1.vin = [CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"]), nSequence=sequence_value)]
|
||||
tx1.vout = [CTxOut(value, CScript([b'a']))]
|
||||
|
||||
tx1_signed = self.nodes[0].signrawtransaction(ToHex(tx1))["hex"]
|
||||
tx1_id = self.nodes[0].sendrawtransaction(tx1_signed)
|
||||
tx1_id = int(tx1_id, 16)
|
||||
|
||||
# This transaction will enable sequence-locks, so this transaction should
|
||||
# fail
|
||||
tx2 = CTransaction()
|
||||
tx2.nVersion = 2
|
||||
sequence_value = sequence_value & 0x7fffffff
|
||||
tx2.vin = [CTxIn(COutPoint(tx1_id, 0), nSequence=sequence_value)]
|
||||
tx2.vout = [CTxOut(int(value-self.relayfee*COIN), CScript([b'a']))]
|
||||
tx2.rehash()
|
||||
|
||||
try:
|
||||
self.nodes[0].sendrawtransaction(ToHex(tx2))
|
||||
except JSONRPCException as exp:
|
||||
assert_equal(exp.error["message"], NOT_FINAL_ERROR)
|
||||
else:
|
||||
assert(False)
|
||||
|
||||
# Setting the version back down to 1 should disable the sequence lock,
|
||||
# so this should be accepted.
|
||||
tx2.nVersion = 1
|
||||
|
||||
self.nodes[0].sendrawtransaction(ToHex(tx2))
|
||||
|
||||
# Calculate the median time past of a prior block ("confirmations" before
|
||||
# the current tip).
|
||||
def get_median_time_past(self, confirmations):
|
||||
block_hash = self.nodes[0].getblockhash(self.nodes[0].getblockcount()-confirmations)
|
||||
return self.nodes[0].getblockheader(block_hash)["mediantime"]
|
||||
|
||||
# Test that sequence locks are respected for transactions spending confirmed inputs.
|
||||
def test_sequence_lock_confirmed_inputs(self):
|
||||
# Create lots of confirmed utxos, and use them to generate lots of random
|
||||
# transactions.
|
||||
max_outputs = 50
|
||||
addresses = []
|
||||
while len(addresses) < max_outputs:
|
||||
addresses.append(self.nodes[0].getnewaddress())
|
||||
while len(self.nodes[0].listunspent()) < 200:
|
||||
import random
|
||||
random.shuffle(addresses)
|
||||
num_outputs = random.randint(1, max_outputs)
|
||||
outputs = {}
|
||||
for i in xrange(num_outputs):
|
||||
outputs[addresses[i]] = random.randint(1, 20)*0.01
|
||||
self.nodes[0].sendmany("", outputs)
|
||||
self.nodes[0].generate(1)
|
||||
|
||||
utxos = self.nodes[0].listunspent()
|
||||
|
||||
# Try creating a lot of random transactions.
|
||||
# Each time, choose a random number of inputs, and randomly set
|
||||
# some of those inputs to be sequence locked (and randomly choose
|
||||
# between height/time locking). Small random chance of making the locks
|
||||
# all pass.
|
||||
for i in xrange(400):
|
||||
# Randomly choose up to 10 inputs
|
||||
num_inputs = random.randint(1, 10)
|
||||
random.shuffle(utxos)
|
||||
|
||||
# Track whether any sequence locks used should fail
|
||||
should_pass = True
|
||||
|
||||
# Track whether this transaction was built with sequence locks
|
||||
using_sequence_locks = False
|
||||
|
||||
tx = CTransaction()
|
||||
tx.nVersion = 2
|
||||
value = 0
|
||||
for j in xrange(num_inputs):
|
||||
sequence_value = 0xfffffffe # this disables sequence locks
|
||||
|
||||
# 50% chance we enable sequence locks
|
||||
if random.randint(0,1):
|
||||
using_sequence_locks = True
|
||||
|
||||
# 10% of the time, make the input sequence value pass
|
||||
input_will_pass = (random.randint(1,10) == 1)
|
||||
sequence_value = utxos[j]["confirmations"]
|
||||
if not input_will_pass:
|
||||
sequence_value += 1
|
||||
should_pass = False
|
||||
|
||||
# Figure out what the median-time-past was for the confirmed input
|
||||
# Note that if an input has N confirmations, we're going back N blocks
|
||||
# from the tip so that we're looking up MTP of the block
|
||||
# PRIOR to the one the input appears in, as per the BIP68 spec.
|
||||
orig_time = self.get_median_time_past(utxos[j]["confirmations"])
|
||||
cur_time = self.get_median_time_past(0) # MTP of the tip
|
||||
|
||||
# can only timelock this input if it's not too old -- otherwise use height
|
||||
can_time_lock = True
|
||||
if ((cur_time - orig_time) >> SEQUENCE_LOCKTIME_GRANULARITY) >= SEQUENCE_LOCKTIME_MASK:
|
||||
can_time_lock = False
|
||||
|
||||
# if time-lockable, then 50% chance we make this a time lock
|
||||
if random.randint(0,1) and can_time_lock:
|
||||
# Find first time-lock value that fails, or latest one that succeeds
|
||||
time_delta = sequence_value << SEQUENCE_LOCKTIME_GRANULARITY
|
||||
if input_will_pass and time_delta > cur_time - orig_time:
|
||||
sequence_value = ((cur_time - orig_time) >> SEQUENCE_LOCKTIME_GRANULARITY)
|
||||
elif (not input_will_pass and time_delta <= cur_time - orig_time):
|
||||
sequence_value = ((cur_time - orig_time) >> SEQUENCE_LOCKTIME_GRANULARITY)+1
|
||||
sequence_value |= SEQUENCE_LOCKTIME_TYPE_FLAG
|
||||
tx.vin.append(CTxIn(COutPoint(int(utxos[j]["txid"], 16), utxos[j]["vout"]), nSequence=sequence_value))
|
||||
value += utxos[j]["amount"]*COIN
|
||||
# Overestimate the size of the tx - signatures should be less than 120 bytes, and leave 50 for the output
|
||||
tx_size = len(ToHex(tx))//2 + 120*num_inputs + 50
|
||||
tx.vout.append(CTxOut(int(value-self.relayfee*tx_size*COIN/1000), CScript([b'a'])))
|
||||
rawtx = self.nodes[0].signrawtransaction(ToHex(tx))["hex"]
|
||||
|
||||
try:
|
||||
self.nodes[0].sendrawtransaction(rawtx)
|
||||
except JSONRPCException as exp:
|
||||
assert(not should_pass and using_sequence_locks)
|
||||
assert_equal(exp.error["message"], NOT_FINAL_ERROR)
|
||||
else:
|
||||
assert(should_pass or not using_sequence_locks)
|
||||
# Recalculate utxos if we successfully sent the transaction
|
||||
utxos = self.nodes[0].listunspent()
|
||||
|
||||
# Test that sequence locks on unconfirmed inputs must have nSequence
|
||||
# height or time of 0 to be accepted.
|
||||
# Then test that BIP68-invalid transactions are removed from the mempool
|
||||
# after a reorg.
|
||||
def test_sequence_lock_unconfirmed_inputs(self):
|
||||
# Store height so we can easily reset the chain at the end of the test
|
||||
cur_height = self.nodes[0].getblockcount()
|
||||
|
||||
# Create a mempool tx.
|
||||
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 2)
|
||||
tx1 = FromHex(CTransaction(), self.nodes[0].getrawtransaction(txid))
|
||||
tx1.rehash()
|
||||
|
||||
# Anyone-can-spend mempool tx.
|
||||
# Sequence lock of 0 should pass.
|
||||
tx2 = CTransaction()
|
||||
tx2.nVersion = 2
|
||||
tx2.vin = [CTxIn(COutPoint(tx1.sha256, 0), nSequence=0)]
|
||||
tx2.vout = [CTxOut(int(tx1.vout[0].nValue - self.relayfee*COIN), CScript([b'a']))]
|
||||
tx2_raw = self.nodes[0].signrawtransaction(ToHex(tx2))["hex"]
|
||||
tx2 = FromHex(tx2, tx2_raw)
|
||||
tx2.rehash()
|
||||
|
||||
self.nodes[0].sendrawtransaction(tx2_raw)
|
||||
|
||||
# Create a spend of the 0th output of orig_tx with a sequence lock
|
||||
# of 1, and test what happens when submitting.
|
||||
# orig_tx.vout[0] must be an anyone-can-spend output
|
||||
def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock):
|
||||
sequence_value = 1
|
||||
if not use_height_lock:
|
||||
sequence_value |= SEQUENCE_LOCKTIME_TYPE_FLAG
|
||||
|
||||
tx = CTransaction()
|
||||
tx.nVersion = 2
|
||||
tx.vin = [CTxIn(COutPoint(orig_tx.sha256, 0), nSequence=sequence_value)]
|
||||
tx.vout = [CTxOut(int(orig_tx.vout[0].nValue - relayfee*COIN), CScript([b'a']))]
|
||||
tx.rehash()
|
||||
|
||||
try:
|
||||
node.sendrawtransaction(ToHex(tx))
|
||||
except JSONRPCException as exp:
|
||||
assert_equal(exp.error["message"], NOT_FINAL_ERROR)
|
||||
assert(orig_tx.hash in node.getrawmempool())
|
||||
else:
|
||||
# orig_tx must not be in mempool
|
||||
assert(orig_tx.hash not in node.getrawmempool())
|
||||
return tx
|
||||
|
||||
test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=True)
|
||||
test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=False)
|
||||
|
||||
# Now mine some blocks, but make sure tx2 doesn't get mined.
|
||||
# Use prioritisetransaction to lower the effective feerate to 0
|
||||
self.nodes[0].prioritisetransaction(tx2.hash, -1e15, int(-self.relayfee*COIN))
|
||||
cur_time = int(time.time())
|
||||
for i in xrange(10):
|
||||
self.nodes[0].setmocktime(cur_time + 600)
|
||||
self.nodes[0].generate(1)
|
||||
cur_time += 600
|
||||
|
||||
assert(tx2.hash in self.nodes[0].getrawmempool())
|
||||
|
||||
test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=True)
|
||||
test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=False)
|
||||
|
||||
# Mine tx2, and then try again
|
||||
self.nodes[0].prioritisetransaction(tx2.hash, 1e15, int(self.relayfee*COIN))
|
||||
|
||||
# Advance the time on the node so that we can test timelocks
|
||||
self.nodes[0].setmocktime(cur_time+600)
|
||||
self.nodes[0].generate(1)
|
||||
assert(tx2.hash not in self.nodes[0].getrawmempool())
|
||||
|
||||
# Now that tx2 is not in the mempool, a sequence locked spend should
|
||||
# succeed
|
||||
tx3 = test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=False)
|
||||
assert(tx3.hash in self.nodes[0].getrawmempool())
|
||||
|
||||
self.nodes[0].generate(1)
|
||||
assert(tx3.hash not in self.nodes[0].getrawmempool())
|
||||
|
||||
# One more test, this time using height locks
|
||||
tx4 = test_nonzero_locks(tx3, self.nodes[0], self.relayfee, use_height_lock=True)
|
||||
assert(tx4.hash in self.nodes[0].getrawmempool())
|
||||
|
||||
# Now try combining confirmed and unconfirmed inputs
|
||||
tx5 = test_nonzero_locks(tx4, self.nodes[0], self.relayfee, use_height_lock=True)
|
||||
assert(tx5.hash not in self.nodes[0].getrawmempool())
|
||||
|
||||
utxos = self.nodes[0].listunspent()
|
||||
tx5.vin.append(CTxIn(COutPoint(int(utxos[0]["txid"], 16), utxos[0]["vout"]), nSequence=1))
|
||||
tx5.vout[0].nValue += int(utxos[0]["amount"]*COIN)
|
||||
raw_tx5 = self.nodes[0].signrawtransaction(ToHex(tx5))["hex"]
|
||||
|
||||
try:
|
||||
self.nodes[0].sendrawtransaction(raw_tx5)
|
||||
except JSONRPCException as exp:
|
||||
assert_equal(exp.error["message"], NOT_FINAL_ERROR)
|
||||
else:
|
||||
assert(False)
|
||||
|
||||
# Test mempool-BIP68 consistency after reorg
|
||||
#
|
||||
# State of the transactions in the last blocks:
|
||||
# ... -> [ tx2 ] -> [ tx3 ]
|
||||
# tip-1 tip
|
||||
# And currently tx4 is in the mempool.
|
||||
#
|
||||
# If we invalidate the tip, tx3 should get added to the mempool, causing
|
||||
# tx4 to be removed (fails sequence-lock).
|
||||
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
||||
assert(tx4.hash not in self.nodes[0].getrawmempool())
|
||||
assert(tx3.hash in self.nodes[0].getrawmempool())
|
||||
|
||||
# Now mine 2 empty blocks to reorg out the current tip (labeled tip-1 in
|
||||
# diagram above).
|
||||
# This would cause tx2 to be added back to the mempool, which in turn causes
|
||||
# tx3 to be removed.
|
||||
tip = int(self.nodes[0].getblockhash(self.nodes[0].getblockcount()-1), 16)
|
||||
height = self.nodes[0].getblockcount()
|
||||
for i in xrange(2):
|
||||
block = create_block(tip, create_coinbase(height), cur_time)
|
||||
block.nVersion = 3
|
||||
block.rehash()
|
||||
block.solve()
|
||||
tip = block.sha256
|
||||
height += 1
|
||||
self.nodes[0].submitblock(ToHex(block))
|
||||
cur_time += 1
|
||||
|
||||
mempool = self.nodes[0].getrawmempool()
|
||||
assert(tx3.hash not in mempool)
|
||||
assert(tx2.hash in mempool)
|
||||
|
||||
# Reset the chain and get rid of the mocktimed-blocks
|
||||
self.nodes[0].setmocktime(0)
|
||||
self.nodes[0].invalidateblock(self.nodes[0].getblockhash(cur_height+1))
|
||||
self.nodes[0].generate(10)
|
||||
|
||||
# Make sure that BIP68 isn't being used to validate blocks, prior to
|
||||
# versionbits activation. If more blocks are mined prior to this test
|
||||
# being run, then it's possible the test has activated the soft fork, and
|
||||
# this test should be moved to run earlier, or deleted.
|
||||
def test_bip68_not_consensus(self):
|
||||
assert(get_bip9_status(self.nodes[0], 'csv')['status'] != 'active')
|
||||
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 2)
|
||||
|
||||
tx1 = FromHex(CTransaction(), self.nodes[0].getrawtransaction(txid))
|
||||
tx1.rehash()
|
||||
|
||||
# Make an anyone-can-spend transaction
|
||||
tx2 = CTransaction()
|
||||
tx2.nVersion = 1
|
||||
tx2.vin = [CTxIn(COutPoint(tx1.sha256, 0), nSequence=0)]
|
||||
tx2.vout = [CTxOut(int(tx1.vout[0].nValue - self.relayfee*COIN), CScript([b'a']))]
|
||||
|
||||
# sign tx2
|
||||
tx2_raw = self.nodes[0].signrawtransaction(ToHex(tx2))["hex"]
|
||||
tx2 = FromHex(tx2, tx2_raw)
|
||||
tx2.rehash()
|
||||
|
||||
self.nodes[0].sendrawtransaction(ToHex(tx2))
|
||||
|
||||
# Now make an invalid spend of tx2 according to BIP68
|
||||
sequence_value = 100 # 100 block relative locktime
|
||||
|
||||
tx3 = CTransaction()
|
||||
tx3.nVersion = 2
|
||||
tx3.vin = [CTxIn(COutPoint(tx2.sha256, 0), nSequence=sequence_value)]
|
||||
tx3.vout = [CTxOut(int(tx2.vout[0].nValue - self.relayfee*COIN), CScript([b'a']))]
|
||||
tx3.rehash()
|
||||
|
||||
try:
|
||||
self.nodes[0].sendrawtransaction(ToHex(tx3))
|
||||
except JSONRPCException as exp:
|
||||
assert_equal(exp.error["message"], NOT_FINAL_ERROR)
|
||||
else:
|
||||
assert(False)
|
||||
|
||||
# make a block that violates bip68; ensure that the tip updates
|
||||
tip = int(self.nodes[0].getbestblockhash(), 16)
|
||||
block = create_block(tip, create_coinbase(self.nodes[0].getblockcount()+1))
|
||||
block.nVersion = 3
|
||||
block.vtx.extend([tx1, tx2, tx3])
|
||||
block.hashMerkleRoot = block.calc_merkle_root()
|
||||
block.rehash()
|
||||
block.solve()
|
||||
|
||||
self.nodes[0].submitblock(ToHex(block))
|
||||
assert_equal(self.nodes[0].getbestblockhash(), block.hash)
|
||||
|
||||
def activateCSV(self):
|
||||
# activation should happen at block height 432 (3 periods)
|
||||
min_activation_height = 432
|
||||
height = self.nodes[0].getblockcount()
|
||||
assert(height < 432)
|
||||
self.nodes[0].generate(432-height)
|
||||
assert(get_bip9_status(self.nodes[0], 'csv')['status'] == 'active')
|
||||
sync_blocks(self.nodes)
|
||||
|
||||
# Use self.nodes[1] to test standardness relay policy
|
||||
def test_version2_relay(self, before_activation):
|
||||
inputs = [ ]
|
||||
outputs = { self.nodes[1].getnewaddress() : 1.0 }
|
||||
rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
|
||||
rawtxfund = self.nodes[1].fundrawtransaction(rawtx)['hex']
|
||||
tx = FromHex(CTransaction(), rawtxfund)
|
||||
tx.nVersion = 2
|
||||
tx_signed = self.nodes[1].signrawtransaction(ToHex(tx))["hex"]
|
||||
try:
|
||||
tx_id = self.nodes[1].sendrawtransaction(tx_signed)
|
||||
assert(before_activation == False)
|
||||
except:
|
||||
assert(before_activation)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
BIP68Test().main()
|
||||
220
qa/rpc-tests/bip9-softforks.py
Executable file
220
qa/rpc-tests/bip9-softforks.py
Executable file
@@ -0,0 +1,220 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2015 The Bitcoin Core developers
|
||||
# Distributed under the MIT/X11 software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#
|
||||
|
||||
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_NOP3, OP_DROP
|
||||
from binascii import hexlify, unhexlify
|
||||
import cStringIO
|
||||
import time
|
||||
import itertools
|
||||
|
||||
'''
|
||||
This test is meant to exercise BIP forks
|
||||
Connect to a single node.
|
||||
regtest lock-in with 108/144 block signalling
|
||||
activation after a further 144 blocks
|
||||
mine 2 block and save coinbases for later use
|
||||
mine 141 blocks to transition from DEFINED to STARTED
|
||||
mine 100 blocks signalling readiness and 44 not in order to fail to change state this period
|
||||
mine 108 blocks signalling readiness and 36 blocks not signalling readiness (STARTED->LOCKED_IN)
|
||||
mine a further 143 blocks (LOCKED_IN)
|
||||
test that enforcement has not triggered (which triggers ACTIVE)
|
||||
test that enforcement has triggered
|
||||
'''
|
||||
|
||||
|
||||
|
||||
class BIP9SoftForksTest(ComparisonTestFramework):
|
||||
|
||||
def __init__(self):
|
||||
self.num_nodes = 1
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = start_nodes(1, self.options.tmpdir,
|
||||
extra_args=[['-debug', '-whitelist=127.0.0.1']],
|
||||
binary=[self.options.testbinary])
|
||||
|
||||
def run_test(self):
|
||||
self.test = TestManager(self, self.options.tmpdir)
|
||||
self.test.add_all_connections(self.nodes)
|
||||
NetworkThread().start() # Start up network handling in another thread
|
||||
self.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)
|
||||
tx = CTransaction()
|
||||
f = cStringIO.StringIO(unhexlify(rawtx))
|
||||
tx.deserialize(f)
|
||||
tx.nVersion = 2
|
||||
return tx
|
||||
|
||||
def sign_transaction(self, node, tx):
|
||||
signresult = node.signrawtransaction(hexlify(tx.serialize()))
|
||||
tx = CTransaction()
|
||||
f = cStringIO.StringIO(unhexlify(signresult['hex']))
|
||||
tx.deserialize(f)
|
||||
return tx
|
||||
|
||||
def generate_blocks(self, number, version, test_blocks = []):
|
||||
for i in xrange(number):
|
||||
block = create_block(self.tip, create_coinbase(self.height), self.last_block_time + 1)
|
||||
block.nVersion = version
|
||||
block.rehash()
|
||||
block.solve()
|
||||
test_blocks.append([block, True])
|
||||
self.last_block_time += 1
|
||||
self.tip = block.sha256
|
||||
self.height += 1
|
||||
return test_blocks
|
||||
|
||||
def get_bip9_status(self, key):
|
||||
info = self.nodes[0].getblockchaininfo()
|
||||
for row in info['bip9_softforks']:
|
||||
if row['id'] == key:
|
||||
return row
|
||||
raise IndexError ('key:"%s" not found' % key)
|
||||
|
||||
|
||||
def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignature):
|
||||
# generate some coins for later
|
||||
self.coinbase_blocks = self.nodes[0].generate(2)
|
||||
self.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 = int(time.time())
|
||||
|
||||
assert_equal(self.get_bip9_status(bipName)['status'], 'defined')
|
||||
|
||||
# Test 1
|
||||
# Advance from DEFINED to STARTED
|
||||
test_blocks = self.generate_blocks(141, 4)
|
||||
yield TestInstance(test_blocks, sync_every_block=False)
|
||||
|
||||
assert_equal(self.get_bip9_status(bipName)['status'], 'started')
|
||||
|
||||
# Test 2
|
||||
# Fail to achieve LOCKED_IN 100 out of 144 signal bit 1
|
||||
# using a variety of bits to simulate multiple parallel softforks
|
||||
test_blocks = self.generate_blocks(50, activated_version) # 0x20000001 (signalling ready)
|
||||
test_blocks = self.generate_blocks(20, 4, test_blocks) # 0x00000004 (signalling not)
|
||||
test_blocks = self.generate_blocks(50, activated_version, test_blocks) # 0x20000101 (signalling ready)
|
||||
test_blocks = self.generate_blocks(24, 4, test_blocks) # 0x20010000 (signalling not)
|
||||
yield TestInstance(test_blocks, sync_every_block=False)
|
||||
|
||||
assert_equal(self.get_bip9_status(bipName)['status'], 'started')
|
||||
|
||||
# Test 3
|
||||
# 108 out of 144 signal bit 1 to achieve LOCKED_IN
|
||||
# using a variety of bits to simulate multiple parallel softforks
|
||||
test_blocks = self.generate_blocks(58, activated_version) # 0x20000001 (signalling ready)
|
||||
test_blocks = self.generate_blocks(26, 4, test_blocks) # 0x00000004 (signalling not)
|
||||
test_blocks = self.generate_blocks(50, activated_version, test_blocks) # 0x20000101 (signalling ready)
|
||||
test_blocks = self.generate_blocks(10, 4, test_blocks) # 0x20010000 (signalling not)
|
||||
yield TestInstance(test_blocks, sync_every_block=False)
|
||||
|
||||
assert_equal(self.get_bip9_status(bipName)['status'], 'locked_in')
|
||||
|
||||
# Test 4
|
||||
# 143 more version 536870913 blocks (waiting period-1)
|
||||
test_blocks = self.generate_blocks(143, 4)
|
||||
yield TestInstance(test_blocks, sync_every_block=False)
|
||||
|
||||
assert_equal(self.get_bip9_status(bipName)['status'], 'locked_in')
|
||||
|
||||
# Test 5
|
||||
# Check that the new rule is enforced
|
||||
spendtx = self.create_transaction(self.nodes[0],
|
||||
self.coinbase_blocks[0], self.nodeaddress, 1.0)
|
||||
invalidate(spendtx)
|
||||
spendtx = self.sign_transaction(self.nodes[0], spendtx)
|
||||
spendtx.rehash()
|
||||
invalidatePostSignature(spendtx)
|
||||
spendtx.rehash()
|
||||
block = create_block(self.tip, create_coinbase(self.height), self.last_block_time + 1)
|
||||
block.nVersion = activated_version
|
||||
block.vtx.append(spendtx)
|
||||
block.hashMerkleRoot = block.calc_merkle_root()
|
||||
block.rehash()
|
||||
block.solve()
|
||||
|
||||
self.last_block_time += 1
|
||||
self.tip = block.sha256
|
||||
self.height += 1
|
||||
yield TestInstance([[block, True]])
|
||||
|
||||
assert_equal(self.get_bip9_status(bipName)['status'], 'active')
|
||||
|
||||
# Test 6
|
||||
# Check that the new sequence lock rules are enforced
|
||||
spendtx = self.create_transaction(self.nodes[0],
|
||||
self.coinbase_blocks[1], self.nodeaddress, 1.0)
|
||||
invalidate(spendtx)
|
||||
spendtx = self.sign_transaction(self.nodes[0], spendtx)
|
||||
spendtx.rehash()
|
||||
invalidatePostSignature(spendtx)
|
||||
spendtx.rehash()
|
||||
|
||||
block = create_block(self.tip, create_coinbase(self.height), self.last_block_time + 1)
|
||||
block.nVersion = 5
|
||||
block.vtx.append(spendtx)
|
||||
block.hashMerkleRoot = block.calc_merkle_root()
|
||||
block.rehash()
|
||||
block.solve()
|
||||
self.last_block_time += 1
|
||||
yield TestInstance([[block, False]])
|
||||
|
||||
# Restart all
|
||||
stop_nodes(self.nodes)
|
||||
wait_bitcoinds()
|
||||
shutil.rmtree(self.options.tmpdir)
|
||||
self.setup_chain()
|
||||
self.setup_network()
|
||||
self.test.clear_all_connections()
|
||||
self.test.add_all_connections(self.nodes)
|
||||
NetworkThread().start() # Start up network handling in another thread
|
||||
|
||||
|
||||
|
||||
def get_tests(self):
|
||||
for test in itertools.chain(
|
||||
self.test_BIP('csv', 536870913, self.sequence_lock_invalidate, self.donothing),
|
||||
self.test_BIP('csv', 536870913, self.mtp_invalidate, self.donothing),
|
||||
self.test_BIP('csv', 536870913, self.donothing, self.csv_invalidate)
|
||||
):
|
||||
yield test
|
||||
|
||||
def donothing(self, tx):
|
||||
return
|
||||
|
||||
def csv_invalidate(self, tx):
|
||||
'''Modify the signature in vin 0 of the tx to fail CSV
|
||||
Prepends -1 CSV DROP in the scriptSig itself.
|
||||
'''
|
||||
tx.vin[0].scriptSig = CScript([OP_1NEGATE, OP_NOP3, OP_DROP] +
|
||||
list(CScript(tx.vin[0].scriptSig)))
|
||||
|
||||
def sequence_lock_invalidate(self, tx):
|
||||
'''Modify the nSequence to make it fails once sequence lock rule is activated (high timespan)
|
||||
'''
|
||||
tx.vin[0].nSequence = 0x00FFFFFF
|
||||
tx.nLockTime = 0
|
||||
|
||||
def mtp_invalidate(self, tx):
|
||||
'''Modify the nLockTime to make it fails once MTP rule is activated
|
||||
'''
|
||||
# Disable Sequence lock, Activate nLockTime
|
||||
tx.vin[0].nSequence = 0x90FFFFFF
|
||||
tx.nLockTime = self.last_block_time
|
||||
|
||||
if __name__ == '__main__':
|
||||
BIP9SoftForksTest().main()
|
||||
@@ -10,7 +10,7 @@ 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
|
||||
from binascii import hexlify, unhexlify
|
||||
from binascii import unhexlify
|
||||
import cStringIO
|
||||
import time
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
import os
|
||||
import shutil
|
||||
|
||||
class BIP66Test(BitcoinTestFramework):
|
||||
|
||||
@@ -46,7 +44,7 @@ class BIP66Test(BitcoinTestFramework):
|
||||
self.nodes[2].generate(1)
|
||||
self.sync_all()
|
||||
if (self.nodes[0].getblockcount() != cnt + 851):
|
||||
raise AssertionFailure("Failed to mine a version=3 blocks")
|
||||
raise AssertionError("Failed to mine a version=3 blocks")
|
||||
|
||||
# TODO: check that new DERSIG rules are enforced
|
||||
|
||||
|
||||
@@ -1,22 +1,28 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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 RPC calls related to blockchain state.
|
||||
# Test RPC calls related to blockchain state. Tests correspond to code in
|
||||
# rpcblockchain.cpp.
|
||||
#
|
||||
|
||||
import decimal
|
||||
from decimal import Decimal
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.authproxy import JSONRPCException
|
||||
from test_framework.util import (
|
||||
initialize_chain,
|
||||
assert_equal,
|
||||
assert_raises,
|
||||
assert_is_hex_string,
|
||||
assert_is_hash_string,
|
||||
start_nodes,
|
||||
connect_nodes_bi,
|
||||
)
|
||||
|
||||
|
||||
class BlockchainTest(BitcoinTestFramework):
|
||||
"""
|
||||
Test blockchain-related RPC calls:
|
||||
@@ -36,10 +42,14 @@ class BlockchainTest(BitcoinTestFramework):
|
||||
self.sync_all()
|
||||
|
||||
def run_test(self):
|
||||
self._test_gettxoutsetinfo()
|
||||
self._test_getblockheader()
|
||||
|
||||
def _test_gettxoutsetinfo(self):
|
||||
node = self.nodes[0]
|
||||
res = node.gettxoutsetinfo()
|
||||
|
||||
assert_equal(res[u'total_amount'], decimal.Decimal('8725.00000000'))
|
||||
assert_equal(res[u'total_amount'], Decimal('8725.00000000'))
|
||||
assert_equal(res[u'transactions'], 200)
|
||||
assert_equal(res[u'height'], 200)
|
||||
assert_equal(res[u'txouts'], 200)
|
||||
@@ -47,6 +57,30 @@ class BlockchainTest(BitcoinTestFramework):
|
||||
assert_equal(len(res[u'bestblock']), 64)
|
||||
assert_equal(len(res[u'hash_serialized']), 64)
|
||||
|
||||
def _test_getblockheader(self):
|
||||
node = self.nodes[0]
|
||||
|
||||
assert_raises(
|
||||
JSONRPCException, lambda: node.getblockheader('nonsense'))
|
||||
|
||||
besthash = node.getbestblockhash()
|
||||
secondbesthash = node.getblockhash(199)
|
||||
header = node.getblockheader(besthash)
|
||||
|
||||
assert_equal(header['hash'], besthash)
|
||||
assert_equal(header['height'], 200)
|
||||
assert_equal(header['confirmations'], 1)
|
||||
assert_equal(header['previousblockhash'], secondbesthash)
|
||||
assert_is_hex_string(header['chainwork'])
|
||||
assert_is_hash_string(header['hash'])
|
||||
assert_is_hash_string(header['previousblockhash'])
|
||||
assert_is_hash_string(header['merkleroot'])
|
||||
assert_is_hash_string(header['bits'], length=None)
|
||||
assert isinstance(header['time'], int)
|
||||
assert isinstance(header['mediantime'], int)
|
||||
assert isinstance(header['nonce'], int)
|
||||
assert isinstance(header['version'], int)
|
||||
assert isinstance(header['difficulty'], Decimal)
|
||||
|
||||
if __name__ == '__main__':
|
||||
BlockchainTest().main()
|
||||
|
||||
@@ -102,13 +102,13 @@ class DecodeScriptTest(BitcoinTestFramework):
|
||||
# OP_IF
|
||||
# <receiver-pubkey> OP_CHECKSIGVERIFY
|
||||
# OP_ELSE
|
||||
# <lock-until> OP_NOP2 OP_DROP
|
||||
# <lock-until> OP_CHECKLOCKTIMEVERIFY OP_DROP
|
||||
# OP_ENDIF
|
||||
# <sender-pubkey> OP_CHECKSIG
|
||||
#
|
||||
# lock until block 500,000
|
||||
rpc_result = self.nodes[0].decodescript('63' + push_public_key + 'ad670320a107b17568' + push_public_key + 'ac')
|
||||
assert_equal('OP_IF ' + public_key + ' OP_CHECKSIGVERIFY OP_ELSE 500000 OP_NOP2 OP_DROP OP_ENDIF ' + public_key + ' OP_CHECKSIG', rpc_result['asm'])
|
||||
assert_equal('OP_IF ' + public_key + ' OP_CHECKSIGVERIFY OP_ELSE 500000 OP_CHECKLOCKTIMEVERIFY OP_DROP OP_ENDIF ' + public_key + ' OP_CHECKSIG', rpc_result['asm'])
|
||||
|
||||
def decoderawtransaction_asm_sighashtype(self):
|
||||
"""Tests decoding scripts via RPC command "decoderawtransaction".
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
|
||||
|
||||
class DisableWalletTest (BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
import os
|
||||
import shutil
|
||||
|
||||
class ForkNotifyTest(BitcoinTestFramework):
|
||||
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
from pprint import pprint
|
||||
from time import sleep
|
||||
|
||||
# Create one-input, one-output, no-fee transaction:
|
||||
class RawTransactionsTest(BitcoinTestFramework):
|
||||
@@ -30,6 +28,11 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
print "Mining blocks..."
|
||||
|
||||
min_relay_tx_fee = self.nodes[0].getnetworkinfo()['relayfee']
|
||||
# This test is not meant to test fee estimation and we'd like
|
||||
# to be sure all txs are sent at a consistent desired feerate
|
||||
for node in self.nodes:
|
||||
node.settxfee(min_relay_tx_fee)
|
||||
|
||||
# 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
|
||||
@@ -48,11 +51,11 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
watchonly_amount = 200
|
||||
self.nodes[3].importpubkey(watchonly_pubkey, "", True)
|
||||
watchonly_txid = self.nodes[0].sendtoaddress(watchonly_address, watchonly_amount)
|
||||
self.nodes[0].sendtoaddress(self.nodes[3].getnewaddress(), watchonly_amount / 10);
|
||||
self.nodes[0].sendtoaddress(self.nodes[3].getnewaddress(), watchonly_amount / 10)
|
||||
|
||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.5);
|
||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.0);
|
||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),5.0);
|
||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.5)
|
||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.0)
|
||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 5.0)
|
||||
|
||||
self.sync_all()
|
||||
self.nodes[0].generate(1)
|
||||
@@ -125,7 +128,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
for aUtx in listunspent:
|
||||
if aUtx['amount'] == 5.0:
|
||||
utx = aUtx
|
||||
break;
|
||||
break
|
||||
|
||||
assert_equal(utx!=False, True)
|
||||
|
||||
@@ -154,7 +157,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
for aUtx in listunspent:
|
||||
if aUtx['amount'] == 5.0:
|
||||
utx = aUtx
|
||||
break;
|
||||
break
|
||||
|
||||
assert_equal(utx!=False, True)
|
||||
|
||||
@@ -184,7 +187,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
for aUtx in listunspent:
|
||||
if aUtx['amount'] == 1.0:
|
||||
utx = aUtx
|
||||
break;
|
||||
break
|
||||
|
||||
assert_equal(utx!=False, True)
|
||||
|
||||
@@ -309,7 +312,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
except JSONRPCException,e:
|
||||
errorString = e.error['message']
|
||||
|
||||
assert_equal("Insufficient" in errorString, True);
|
||||
assert("Insufficient" in errorString)
|
||||
|
||||
|
||||
|
||||
@@ -321,11 +324,11 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
fundedTx = self.nodes[0].fundrawtransaction(rawTx)
|
||||
|
||||
#create same transaction over sendtoaddress
|
||||
txId = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1.1);
|
||||
txId = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1.1)
|
||||
signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']
|
||||
|
||||
#compare fee
|
||||
feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee);
|
||||
feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
|
||||
assert(feeDelta >= 0 and feeDelta <= feeTolerance)
|
||||
############################################################
|
||||
|
||||
@@ -336,11 +339,11 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
rawTx = self.nodes[0].createrawtransaction(inputs, outputs)
|
||||
fundedTx = self.nodes[0].fundrawtransaction(rawTx)
|
||||
#create same transaction over sendtoaddress
|
||||
txId = self.nodes[0].sendmany("", outputs);
|
||||
txId = self.nodes[0].sendmany("", outputs)
|
||||
signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']
|
||||
|
||||
#compare fee
|
||||
feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee);
|
||||
feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
|
||||
assert(feeDelta >= 0 and feeDelta <= feeTolerance)
|
||||
############################################################
|
||||
|
||||
@@ -363,11 +366,11 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
fundedTx = self.nodes[0].fundrawtransaction(rawTx)
|
||||
|
||||
#create same transaction over sendtoaddress
|
||||
txId = self.nodes[0].sendtoaddress(mSigObj, 1.1);
|
||||
txId = self.nodes[0].sendtoaddress(mSigObj, 1.1)
|
||||
signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']
|
||||
|
||||
#compare fee
|
||||
feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee);
|
||||
feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
|
||||
assert(feeDelta >= 0 and feeDelta <= feeTolerance)
|
||||
############################################################
|
||||
|
||||
@@ -396,11 +399,11 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
fundedTx = self.nodes[0].fundrawtransaction(rawTx)
|
||||
|
||||
#create same transaction over sendtoaddress
|
||||
txId = self.nodes[0].sendtoaddress(mSigObj, 1.1);
|
||||
txId = self.nodes[0].sendtoaddress(mSigObj, 1.1)
|
||||
signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']
|
||||
|
||||
#compare fee
|
||||
feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee);
|
||||
feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
|
||||
assert(feeDelta >= 0 and feeDelta <= feeTolerance)
|
||||
############################################################
|
||||
|
||||
@@ -419,7 +422,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
|
||||
|
||||
# send 1.2 BTC to msig addr
|
||||
txId = self.nodes[0].sendtoaddress(mSigObj, 1.2);
|
||||
txId = self.nodes[0].sendtoaddress(mSigObj, 1.2)
|
||||
self.sync_all()
|
||||
self.nodes[1].generate(1)
|
||||
self.sync_all()
|
||||
@@ -447,6 +450,10 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
wait_bitcoinds()
|
||||
|
||||
self.nodes = start_nodes(4, self.options.tmpdir)
|
||||
# This test is not meant to test fee estimation and we'd like
|
||||
# to be sure all txs are sent at a consistent desired feerate
|
||||
for node in self.nodes:
|
||||
node.settxfee(min_relay_tx_fee)
|
||||
|
||||
connect_nodes_bi(self.nodes,0,1)
|
||||
connect_nodes_bi(self.nodes,1,2)
|
||||
@@ -457,7 +464,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
|
||||
error = False
|
||||
try:
|
||||
self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1.2);
|
||||
self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1.2)
|
||||
except:
|
||||
error = True
|
||||
assert(error)
|
||||
@@ -487,13 +494,13 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
###############################################
|
||||
|
||||
#empty node1, send some small coins from node0 to node1
|
||||
self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), self.nodes[1].getbalance(), "", "", True);
|
||||
self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), self.nodes[1].getbalance(), "", "", True)
|
||||
self.sync_all()
|
||||
self.nodes[0].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
for i in range(0,20):
|
||||
self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01);
|
||||
self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01)
|
||||
self.sync_all()
|
||||
self.nodes[0].generate(1)
|
||||
self.sync_all()
|
||||
@@ -505,11 +512,11 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
fundedTx = self.nodes[1].fundrawtransaction(rawTx)
|
||||
|
||||
#create same transaction over sendtoaddress
|
||||
txId = self.nodes[1].sendmany("", outputs);
|
||||
txId = self.nodes[1].sendmany("", outputs)
|
||||
signedFee = self.nodes[1].getrawmempool(True)[txId]['fee']
|
||||
|
||||
#compare fee
|
||||
feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee);
|
||||
feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
|
||||
assert(feeDelta >= 0 and feeDelta <= feeTolerance*19) #~19 inputs
|
||||
|
||||
|
||||
@@ -518,13 +525,13 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
#############################################
|
||||
|
||||
#again, empty node1, send some small coins from node0 to node1
|
||||
self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), self.nodes[1].getbalance(), "", "", True);
|
||||
self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), self.nodes[1].getbalance(), "", "", True)
|
||||
self.sync_all()
|
||||
self.nodes[0].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
for i in range(0,20):
|
||||
self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01);
|
||||
self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01)
|
||||
self.sync_all()
|
||||
self.nodes[0].generate(1)
|
||||
self.sync_all()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
@@ -23,8 +23,8 @@ class GetChainTipsTest (BitcoinTestFramework):
|
||||
|
||||
# Split the network and build two chains of different lengths.
|
||||
self.split_network ()
|
||||
self.nodes[0].generate(10);
|
||||
self.nodes[2].generate(20);
|
||||
self.nodes[0].generate(10)
|
||||
self.nodes[2].generate(20)
|
||||
self.sync_all ()
|
||||
|
||||
tips = self.nodes[1].getchaintips ()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
@@ -36,13 +36,13 @@ class HTTPBasicsTest (BitcoinTestFramework):
|
||||
conn = httplib.HTTPConnection(url.hostname, url.port)
|
||||
conn.connect()
|
||||
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
|
||||
out1 = conn.getresponse().read();
|
||||
out1 = conn.getresponse().read()
|
||||
assert_equal('"error":null' in out1, True)
|
||||
assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open!
|
||||
|
||||
#send 2nd request without closing connection
|
||||
conn.request('POST', '/', '{"method": "getchaintips"}', headers)
|
||||
out2 = conn.getresponse().read();
|
||||
out2 = conn.getresponse().read()
|
||||
assert_equal('"error":null' in out1, True) #must also response with a correct json-rpc message
|
||||
assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open!
|
||||
conn.close()
|
||||
@@ -53,13 +53,13 @@ class HTTPBasicsTest (BitcoinTestFramework):
|
||||
conn = httplib.HTTPConnection(url.hostname, url.port)
|
||||
conn.connect()
|
||||
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
|
||||
out1 = conn.getresponse().read();
|
||||
out1 = conn.getresponse().read()
|
||||
assert_equal('"error":null' in out1, True)
|
||||
assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open!
|
||||
|
||||
#send 2nd request without closing connection
|
||||
conn.request('POST', '/', '{"method": "getchaintips"}', headers)
|
||||
out2 = conn.getresponse().read();
|
||||
out2 = conn.getresponse().read()
|
||||
assert_equal('"error":null' in out1, True) #must also response with a correct json-rpc message
|
||||
assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open!
|
||||
conn.close()
|
||||
@@ -70,7 +70,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
|
||||
conn = httplib.HTTPConnection(url.hostname, url.port)
|
||||
conn.connect()
|
||||
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
|
||||
out1 = conn.getresponse().read();
|
||||
out1 = conn.getresponse().read()
|
||||
assert_equal('"error":null' in out1, True)
|
||||
assert_equal(conn.sock!=None, False) #now the connection must be closed after the response
|
||||
|
||||
@@ -82,7 +82,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
|
||||
conn = httplib.HTTPConnection(urlNode1.hostname, urlNode1.port)
|
||||
conn.connect()
|
||||
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
|
||||
out1 = conn.getresponse().read();
|
||||
out1 = conn.getresponse().read()
|
||||
assert_equal('"error":null' in out1, True)
|
||||
|
||||
#node2 (third node) is running with standard keep-alive parameters which means keep-alive is on
|
||||
@@ -93,7 +93,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
|
||||
conn = httplib.HTTPConnection(urlNode2.hostname, urlNode2.port)
|
||||
conn.connect()
|
||||
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
|
||||
out1 = conn.getresponse().read();
|
||||
out1 = conn.getresponse().read()
|
||||
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
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
|
||||
@@ -6,10 +6,8 @@
|
||||
|
||||
from test_framework.test_framework import ComparisonTestFramework
|
||||
from test_framework.util import *
|
||||
from test_framework.comptool import TestManager, TestInstance
|
||||
from test_framework.mininode import *
|
||||
from test_framework.comptool import TestManager, TestInstance, RejectResult
|
||||
from test_framework.blocktools import *
|
||||
import logging
|
||||
import copy
|
||||
import time
|
||||
|
||||
@@ -97,7 +95,7 @@ class InvalidBlockRequestTest(ComparisonTestFramework):
|
||||
assert(block2_orig.vtx != block2.vtx)
|
||||
|
||||
self.tip = block2.sha256
|
||||
yield TestInstance([[block2, False], [block2_orig, True]])
|
||||
yield TestInstance([[block2, RejectResult(16,'bad-txns-duplicate')], [block2_orig, True]])
|
||||
height += 1
|
||||
|
||||
'''
|
||||
@@ -112,7 +110,7 @@ class InvalidBlockRequestTest(ComparisonTestFramework):
|
||||
block3.rehash()
|
||||
block3.solve()
|
||||
|
||||
yield TestInstance([[block3, False]])
|
||||
yield TestInstance([[block3, RejectResult(16,'bad-cb-amount')]])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
72
qa/rpc-tests/invalidtxrequest.py
Executable file
72
qa/rpc-tests/invalidtxrequest.py
Executable file
@@ -0,0 +1,72 @@
|
||||
#!/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.comptool import TestManager, TestInstance, RejectResult
|
||||
from test_framework.blocktools import *
|
||||
import time
|
||||
|
||||
|
||||
'''
|
||||
In this test we connect to one node over p2p, and test tx requests.
|
||||
'''
|
||||
|
||||
# Use the ComparisonTestFramework with 1 node: only use --testbinary.
|
||||
class InvalidTxRequestTest(ComparisonTestFramework):
|
||||
|
||||
''' Can either run this test as 1 node with expected answers, or two and compare them.
|
||||
Change the "outcome" variable from each TestInstance object to only do the comparison. '''
|
||||
def __init__(self):
|
||||
self.num_nodes = 1
|
||||
|
||||
def run_test(self):
|
||||
test = TestManager(self, self.options.tmpdir)
|
||||
test.add_all_connections(self.nodes)
|
||||
self.tip = None
|
||||
self.block_time = None
|
||||
NetworkThread().start() # Start up network handling in another thread
|
||||
test.run()
|
||||
|
||||
def get_tests(self):
|
||||
if self.tip is None:
|
||||
self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0)
|
||||
self.block_time = int(time.time())+1
|
||||
|
||||
'''
|
||||
Create a new block with an anyone-can-spend coinbase
|
||||
'''
|
||||
height = 1
|
||||
block = create_block(self.tip, create_coinbase(height), self.block_time)
|
||||
self.block_time += 1
|
||||
block.solve()
|
||||
# Save the coinbase for later
|
||||
self.block1 = block
|
||||
self.tip = block.sha256
|
||||
height += 1
|
||||
yield TestInstance([[block, True]])
|
||||
|
||||
'''
|
||||
Now we need that block to mature so we can spend the coinbase.
|
||||
'''
|
||||
test = TestInstance(sync_every_block=False)
|
||||
for i in xrange(100):
|
||||
block = create_block(self.tip, create_coinbase(height), self.block_time)
|
||||
block.solve()
|
||||
self.tip = block.sha256
|
||||
self.block_time += 1
|
||||
test.blocks_and_transactions.append([block, True])
|
||||
height += 1
|
||||
yield test
|
||||
|
||||
# chr(100) is OP_NOTIF
|
||||
# Transaction will be rejected with code 16 (REJECT_INVALID)
|
||||
tx1 = create_transaction(self.block1.vtx[0], 0, chr(100), 50*100000000)
|
||||
yield TestInstance([[tx1, RejectResult(16, 'mandatory-script-verify-flag-failed')]])
|
||||
|
||||
# TODO: test further transactions...
|
||||
|
||||
if __name__ == '__main__':
|
||||
InvalidTxRequestTest().main()
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
@@ -7,7 +7,15 @@
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
from test_framework.mininode import CTransaction
|
||||
import cStringIO
|
||||
import binascii
|
||||
|
||||
def txFromHex(hexstring):
|
||||
tx = CTransaction()
|
||||
f = cStringIO.StringIO(binascii.unhexlify(hexstring))
|
||||
tx.deserialize(f)
|
||||
return tx
|
||||
|
||||
def check_array_result(object_array, to_match, expected):
|
||||
"""
|
||||
@@ -103,6 +111,107 @@ class ListTransactionsTest(BitcoinTestFramework):
|
||||
{"category":"receive","amount":Decimal("0.1")},
|
||||
{"txid":txid, "account" : "watchonly"} )
|
||||
|
||||
self.run_rbf_opt_in_test()
|
||||
|
||||
# Check that the opt-in-rbf flag works properly, for sent and received
|
||||
# transactions.
|
||||
def run_rbf_opt_in_test(self):
|
||||
# Check whether a transaction signals opt-in RBF itself
|
||||
def is_opt_in(node, txid):
|
||||
rawtx = node.getrawtransaction(txid, 1)
|
||||
for x in rawtx["vin"]:
|
||||
if x["sequence"] < 0xfffffffe:
|
||||
return True
|
||||
return False
|
||||
|
||||
# Find an unconfirmed output matching a certain txid
|
||||
def get_unconfirmed_utxo_entry(node, txid_to_match):
|
||||
utxo = node.listunspent(0, 0)
|
||||
for i in utxo:
|
||||
if i["txid"] == txid_to_match:
|
||||
return i
|
||||
return None
|
||||
|
||||
# 1. Chain a few transactions that don't opt-in.
|
||||
txid_1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1)
|
||||
assert(not is_opt_in(self.nodes[0], txid_1))
|
||||
check_array_result(self.nodes[0].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"})
|
||||
sync_mempools(self.nodes)
|
||||
check_array_result(self.nodes[1].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"})
|
||||
|
||||
# Tx2 will build off txid_1, still not opting in to RBF.
|
||||
utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_1)
|
||||
|
||||
# Create tx2 using createrawtransaction
|
||||
inputs = [{"txid":utxo_to_use["txid"], "vout":utxo_to_use["vout"]}]
|
||||
outputs = {self.nodes[0].getnewaddress(): 0.999}
|
||||
tx2 = self.nodes[1].createrawtransaction(inputs, outputs)
|
||||
tx2_signed = self.nodes[1].signrawtransaction(tx2)["hex"]
|
||||
txid_2 = self.nodes[1].sendrawtransaction(tx2_signed)
|
||||
|
||||
# ...and check the result
|
||||
assert(not is_opt_in(self.nodes[1], txid_2))
|
||||
check_array_result(self.nodes[1].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"})
|
||||
sync_mempools(self.nodes)
|
||||
check_array_result(self.nodes[0].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"})
|
||||
|
||||
# Tx3 will opt-in to RBF
|
||||
utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[0], txid_2)
|
||||
inputs = [{"txid": txid_2, "vout":utxo_to_use["vout"]}]
|
||||
outputs = {self.nodes[1].getnewaddress(): 0.998}
|
||||
tx3 = self.nodes[0].createrawtransaction(inputs, outputs)
|
||||
tx3_modified = txFromHex(tx3)
|
||||
tx3_modified.vin[0].nSequence = 0
|
||||
tx3 = binascii.hexlify(tx3_modified.serialize()).decode('utf-8')
|
||||
tx3_signed = self.nodes[0].signrawtransaction(tx3)['hex']
|
||||
txid_3 = self.nodes[0].sendrawtransaction(tx3_signed)
|
||||
|
||||
assert(is_opt_in(self.nodes[0], txid_3))
|
||||
check_array_result(self.nodes[0].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"})
|
||||
sync_mempools(self.nodes)
|
||||
check_array_result(self.nodes[1].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"})
|
||||
|
||||
# Tx4 will chain off tx3. Doesn't signal itself, but depends on one
|
||||
# that does.
|
||||
utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_3)
|
||||
inputs = [{"txid": txid_3, "vout":utxo_to_use["vout"]}]
|
||||
outputs = {self.nodes[0].getnewaddress(): 0.997}
|
||||
tx4 = self.nodes[1].createrawtransaction(inputs, outputs)
|
||||
tx4_signed = self.nodes[1].signrawtransaction(tx4)["hex"]
|
||||
txid_4 = self.nodes[1].sendrawtransaction(tx4_signed)
|
||||
|
||||
assert(not is_opt_in(self.nodes[1], txid_4))
|
||||
check_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"})
|
||||
sync_mempools(self.nodes)
|
||||
check_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"})
|
||||
|
||||
# Replace tx3, and check that tx4 becomes unknown
|
||||
tx3_b = tx3_modified
|
||||
tx3_b.vout[0].nValue -= 0.004*100000000 # bump the fee
|
||||
tx3_b = binascii.hexlify(tx3_b.serialize()).decode('utf-8')
|
||||
tx3_b_signed = self.nodes[0].signrawtransaction(tx3_b)['hex']
|
||||
txid_3b = self.nodes[0].sendrawtransaction(tx3_b_signed, True)
|
||||
assert(is_opt_in(self.nodes[0], txid_3b))
|
||||
|
||||
check_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"})
|
||||
sync_mempools(self.nodes)
|
||||
check_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"})
|
||||
|
||||
# Check gettransaction as well:
|
||||
for n in self.nodes[0:2]:
|
||||
assert_equal(n.gettransaction(txid_1)["bip125-replaceable"], "no")
|
||||
assert_equal(n.gettransaction(txid_2)["bip125-replaceable"], "no")
|
||||
assert_equal(n.gettransaction(txid_3)["bip125-replaceable"], "yes")
|
||||
assert_equal(n.gettransaction(txid_3b)["bip125-replaceable"], "yes")
|
||||
assert_equal(n.gettransaction(txid_4)["bip125-replaceable"], "unknown")
|
||||
|
||||
# After mining a transaction, it's no longer BIP125-replaceable
|
||||
self.nodes[0].generate(1)
|
||||
assert(txid_3b not in self.nodes[0].getrawmempool())
|
||||
assert_equal(self.nodes[0].gettransaction(txid_3b)["bip125-replaceable"], "no")
|
||||
assert_equal(self.nodes[0].gettransaction(txid_4)["bip125-replaceable"], "unknown")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
ListTransactionsTest().main()
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ class TestManager(NodeConnCB):
|
||||
def __init__(self):
|
||||
NodeConnCB.__init__(self)
|
||||
self.log = logging.getLogger("BlockRelayTest")
|
||||
self.create_callback_map()
|
||||
|
||||
def add_new_connection(self, connection):
|
||||
self.connection = connection
|
||||
|
||||
@@ -25,7 +25,6 @@ if uploadtarget has been reached.
|
||||
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()
|
||||
@@ -85,22 +84,7 @@ class TestNode(NodeConnCB):
|
||||
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
|
||||
self.txouts = gen_return_txouts()
|
||||
|
||||
def add_options(self, parser):
|
||||
parser.add_option("--testbinary", dest="testbinary",
|
||||
|
||||
55
qa/rpc-tests/mempool_limit.py
Executable file
55
qa/rpc-tests/mempool_limit.py
Executable file
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014-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 mempool limiting together/eviction with the wallet
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
|
||||
class MempoolLimitTest(BitcoinTestFramework):
|
||||
|
||||
def __init__(self):
|
||||
self.txouts = gen_return_txouts()
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = []
|
||||
self.nodes.append(start_node(0, self.options.tmpdir, ["-maxmempool=5", "-spendzeroconfchange=0", "-debug"]))
|
||||
self.is_network_split = False
|
||||
self.sync_all()
|
||||
self.relayfee = self.nodes[0].getnetworkinfo()['relayfee']
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 2)
|
||||
|
||||
def run_test(self):
|
||||
txids = []
|
||||
utxos = create_confirmed_utxos(self.relayfee, self.nodes[0], 90)
|
||||
|
||||
#create a mempool tx that will be evicted
|
||||
us0 = utxos.pop()
|
||||
inputs = [{ "txid" : us0["txid"], "vout" : us0["vout"]}]
|
||||
outputs = {self.nodes[0].getnewaddress() : 0.0001}
|
||||
tx = self.nodes[0].createrawtransaction(inputs, outputs)
|
||||
self.nodes[0].settxfee(self.relayfee) # specifically fund this tx with low fee
|
||||
txF = self.nodes[0].fundrawtransaction(tx)
|
||||
self.nodes[0].settxfee(0) # return to automatic fee selection
|
||||
txFS = self.nodes[0].signrawtransaction(txF['hex'])
|
||||
txid = self.nodes[0].sendrawtransaction(txFS['hex'])
|
||||
self.nodes[0].lockunspent(True, [us0])
|
||||
|
||||
relayfee = self.nodes[0].getnetworkinfo()['relayfee']
|
||||
base_fee = relayfee*100
|
||||
for i in xrange (4):
|
||||
txids.append([])
|
||||
txids[i] = create_lots_of_big_transactions(self.nodes[0], self.txouts, utxos[30*i:30*i+30], (i+1)*base_fee)
|
||||
|
||||
# by now, the tx should be evicted, check confirmation state
|
||||
assert(txid not in self.nodes[0].getrawmempool())
|
||||
txdata = self.nodes[0].gettransaction(txid)
|
||||
assert(txdata['confirmations'] == 0) #confirmation should still be 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
MempoolLimitTest().main()
|
||||
@@ -64,17 +64,50 @@ class MempoolPackagesTest(BitcoinTestFramework):
|
||||
for x in reversed(chain):
|
||||
assert_equal(mempool[x]['descendantcount'], descendant_count)
|
||||
descendant_fees += mempool[x]['fee']
|
||||
assert_equal(mempool[x]['modifiedfee'], mempool[x]['fee'])
|
||||
assert_equal(mempool[x]['descendantfees'], SATOSHIS*descendant_fees)
|
||||
descendant_size += mempool[x]['size']
|
||||
assert_equal(mempool[x]['descendantsize'], descendant_size)
|
||||
descendant_count += 1
|
||||
|
||||
# Check that descendant modified fees includes fee deltas from
|
||||
# prioritisetransaction
|
||||
self.nodes[0].prioritisetransaction(chain[-1], 0, 1000)
|
||||
mempool = self.nodes[0].getrawmempool(True)
|
||||
|
||||
descendant_fees = 0
|
||||
for x in reversed(chain):
|
||||
descendant_fees += mempool[x]['fee']
|
||||
assert_equal(mempool[x]['descendantfees'], SATOSHIS*descendant_fees+1000)
|
||||
|
||||
# Adding one more transaction on to the chain should fail.
|
||||
try:
|
||||
self.chain_transaction(self.nodes[0], txid, vout, value, fee, 1)
|
||||
except JSONRPCException as e:
|
||||
print "too-long-ancestor-chain successfully rejected"
|
||||
|
||||
# Check that prioritising a tx before it's added to the mempool works
|
||||
# First clear the mempool by mining a block.
|
||||
self.nodes[0].generate(1)
|
||||
sync_blocks(self.nodes)
|
||||
assert_equal(len(self.nodes[0].getrawmempool()), 0)
|
||||
# Prioritise a transaction that has been mined, then add it back to the
|
||||
# mempool by using invalidateblock.
|
||||
self.nodes[0].prioritisetransaction(chain[-1], 0, 2000)
|
||||
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
||||
# Keep node1's tip synced with node0
|
||||
self.nodes[1].invalidateblock(self.nodes[1].getbestblockhash())
|
||||
|
||||
# Now check that the transaction is in the mempool, with the right modified fee
|
||||
mempool = self.nodes[0].getrawmempool(True)
|
||||
|
||||
descendant_fees = 0
|
||||
for x in reversed(chain):
|
||||
descendant_fees += mempool[x]['fee']
|
||||
if (x == chain[-1]):
|
||||
assert_equal(mempool[x]['modifiedfee'], mempool[x]['fee']+satoshi_round(0.00002))
|
||||
assert_equal(mempool[x]['descendantfees'], SATOSHIS*descendant_fees+2000)
|
||||
|
||||
# TODO: check that node1's mempool is as expected
|
||||
|
||||
# TODO: test ancestor size limits
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
import os
|
||||
import shutil
|
||||
|
||||
# Create one-input, one-output, no-fee transaction:
|
||||
class MempoolCoinbaseTest(BitcoinTestFramework):
|
||||
@@ -25,7 +23,7 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
|
||||
self.nodes.append(start_node(1, self.options.tmpdir, args))
|
||||
connect_nodes(self.nodes[1], 0)
|
||||
self.is_network_split = False
|
||||
self.sync_all
|
||||
self.sync_all()
|
||||
|
||||
def create_tx(self, from_txid, to_address, amount):
|
||||
inputs = [{ "txid" : from_txid, "vout" : 0}]
|
||||
@@ -87,11 +85,11 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
|
||||
|
||||
self.sync_all()
|
||||
|
||||
assert_equal(set(self.nodes[0].getrawmempool()), set([ spend_101_id, spend_102_1_id, timelock_tx_id ]))
|
||||
assert_equal(set(self.nodes[0].getrawmempool()), {spend_101_id, spend_102_1_id, timelock_tx_id})
|
||||
|
||||
for node in self.nodes:
|
||||
node.invalidateblock(last_block[0])
|
||||
assert_equal(set(self.nodes[0].getrawmempool()), set([ spend_101_id, spend_102_1_id, spend_103_1_id ]))
|
||||
assert_equal(set(self.nodes[0].getrawmempool()), {spend_101_id, spend_102_1_id, spend_103_1_id})
|
||||
|
||||
# Use invalidateblock to re-org back and make all those coinbase spends
|
||||
# immature/invalid:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
import os
|
||||
import shutil
|
||||
|
||||
# Create one-input, one-output, no-fee transaction:
|
||||
class MempoolCoinbaseTest(BitcoinTestFramework):
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
import os
|
||||
import shutil
|
||||
|
||||
# Create one-input, one-output, no-fee transaction:
|
||||
class MempoolSpendCoinbaseTest(BitcoinTestFramework):
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
import os
|
||||
import shutil
|
||||
|
||||
class MerkleBlockTest(BitcoinTestFramework):
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
|
||||
#Old authpair
|
||||
authpair = url.username + ':' + url.password
|
||||
|
||||
#New authpair generated via contrib/rpcuser tool
|
||||
#New authpair generated via share/rpcuser tool
|
||||
rpcauth = "rpcauth=rt:93648e835a54c573682c2eb19f882535$7681e9c5b74bdd85e78166031d2058e1069b3ed7ed967c93fc63abba06f31144"
|
||||
password = "cA773lm788buwYe4g4WT+05pKyNruVKjQ25x3n0DQcM="
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
import base64
|
||||
|
||||
try:
|
||||
import http.client as httplib
|
||||
@@ -54,7 +53,7 @@ class NodeHandlingTest (BitcoinTestFramework):
|
||||
self.nodes[2].setban("127.0.0.0/24", "add")
|
||||
self.nodes[2].setban("192.168.0.1", "add", 1) #ban for 1 seconds
|
||||
self.nodes[2].setban("2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/19", "add", 1000) #ban for 1000 seconds
|
||||
listBeforeShutdown = self.nodes[2].listbanned();
|
||||
listBeforeShutdown = self.nodes[2].listbanned()
|
||||
assert_equal("192.168.0.1/32", listBeforeShutdown[2]['address']) #must be here
|
||||
time.sleep(2) #make 100% sure we expired 192.168.0.1 node time
|
||||
|
||||
@@ -62,7 +61,7 @@ class NodeHandlingTest (BitcoinTestFramework):
|
||||
stop_node(self.nodes[2], 2)
|
||||
|
||||
self.nodes[2] = start_node(2, self.options.tmpdir)
|
||||
listAfterShutdown = self.nodes[2].listbanned();
|
||||
listAfterShutdown = self.nodes[2].listbanned()
|
||||
assert_equal("127.0.0.0/24", listAfterShutdown[0]['address'])
|
||||
assert_equal("127.0.0.0/32", listAfterShutdown[1]['address'])
|
||||
assert_equal("/19" in listAfterShutdown[2]['address'], True)
|
||||
|
||||
@@ -62,7 +62,6 @@ The test:
|
||||
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()
|
||||
|
||||
@@ -7,15 +7,11 @@
|
||||
|
||||
from test_framework.test_framework import ComparisonTestFramework
|
||||
from test_framework.util import *
|
||||
from test_framework.comptool import TestManager, TestInstance
|
||||
from test_framework.mininode import *
|
||||
from test_framework.comptool import TestManager, TestInstance, RejectResult
|
||||
from test_framework.blocktools import *
|
||||
import logging
|
||||
import copy
|
||||
import time
|
||||
import numbers
|
||||
from test_framework.key import CECKey
|
||||
from test_framework.script import CScript, CScriptOp, SignatureHash, SIGHASH_ALL, OP_TRUE
|
||||
from test_framework.script import CScript, SignatureHash, SIGHASH_ALL, OP_TRUE, OP_FALSE
|
||||
|
||||
class PreviousSpendableOutput(object):
|
||||
def __init__(self, tx = CTransaction(), n = -1):
|
||||
@@ -122,13 +118,29 @@ class FullBlockTest(ComparisonTestFramework):
|
||||
return TestInstance([[self.tip, True]])
|
||||
|
||||
# returns a test case that asserts that the current tip was rejected
|
||||
def rejected():
|
||||
return TestInstance([[self.tip, False]])
|
||||
def rejected(reject = None):
|
||||
if reject is None:
|
||||
return TestInstance([[self.tip, False]])
|
||||
else:
|
||||
return TestInstance([[self.tip, reject]])
|
||||
|
||||
# move the tip back to a previous block
|
||||
def tip(number):
|
||||
self.tip = self.blocks[number]
|
||||
|
||||
# add transactions to a block produced by next_block
|
||||
def update_block(block_number, new_transactions):
|
||||
block = self.blocks[block_number]
|
||||
old_hash = block.sha256
|
||||
self.add_transactions_to_block(block, new_transactions)
|
||||
block.solve()
|
||||
# Update the internal state just like in next_block
|
||||
self.tip = block
|
||||
self.block_heights[block.sha256] = self.block_heights[old_hash]
|
||||
del self.block_heights[old_hash]
|
||||
self.blocks[block_number] = block
|
||||
return block
|
||||
|
||||
# creates a new block and advances the tip to that block
|
||||
block = self.next_block
|
||||
|
||||
@@ -141,14 +153,15 @@ class FullBlockTest(ComparisonTestFramework):
|
||||
|
||||
# Now we need that block to mature so we can spend the coinbase.
|
||||
test = TestInstance(sync_every_block=False)
|
||||
for i in range(100):
|
||||
for i in range(99):
|
||||
block(1000 + i)
|
||||
test.blocks_and_transactions.append([self.tip, True])
|
||||
save_spendable_output()
|
||||
yield test
|
||||
|
||||
|
||||
# Start by bulding a couple of blocks on top (which output is spent is in parentheses):
|
||||
# Start by building a couple of blocks on top (which output is spent is
|
||||
# in parentheses):
|
||||
# genesis -> b1 (0) -> b2 (1)
|
||||
out0 = get_spendable_output()
|
||||
block(1, spend=out0)
|
||||
@@ -156,8 +169,7 @@ class FullBlockTest(ComparisonTestFramework):
|
||||
yield accepted()
|
||||
|
||||
out1 = get_spendable_output()
|
||||
block(2, spend=out1)
|
||||
# Inv again, then deliver twice (shouldn't break anything).
|
||||
b2 = block(2, spend=out1)
|
||||
yield accepted()
|
||||
|
||||
|
||||
@@ -168,8 +180,8 @@ class FullBlockTest(ComparisonTestFramework):
|
||||
#
|
||||
# Nothing should happen at this point. We saw b2 first so it takes priority.
|
||||
tip(1)
|
||||
block(3, spend=out1)
|
||||
# Deliver twice (should still not break anything)
|
||||
b3 = block(3, spend=out1)
|
||||
txout_b3 = PreviousSpendableOutput(b3.vtx[1], 1)
|
||||
yield rejected()
|
||||
|
||||
|
||||
@@ -214,7 +226,7 @@ class FullBlockTest(ComparisonTestFramework):
|
||||
# \-> b3 (1) -> b4 (2)
|
||||
tip(6)
|
||||
block(9, spend=out4, additional_coinbase_value=1)
|
||||
yield rejected()
|
||||
yield rejected(RejectResult(16, 'bad-cb-amount'))
|
||||
|
||||
|
||||
# Create a fork that ends in a block with too much fee (the one that causes the reorg)
|
||||
@@ -226,7 +238,7 @@ class FullBlockTest(ComparisonTestFramework):
|
||||
yield rejected()
|
||||
|
||||
block(11, spend=out4, additional_coinbase_value=1)
|
||||
yield rejected()
|
||||
yield rejected(RejectResult(16, 'bad-cb-amount'))
|
||||
|
||||
|
||||
# Try again, but with a valid fork first
|
||||
@@ -252,6 +264,10 @@ class FullBlockTest(ComparisonTestFramework):
|
||||
|
||||
yield TestInstance([[b12, True, b13.sha256]]) # New tip should be b13.
|
||||
|
||||
# Add a block with MAX_BLOCK_SIGOPS and one with one more sigop
|
||||
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
|
||||
# \-> b12 (3) -> b13 (4) -> b15 (5) -> b16 (6)
|
||||
# \-> b3 (1) -> b4 (2)
|
||||
|
||||
# Test that a block with a lot of checksigs is okay
|
||||
lots_of_checksigs = CScript([OP_CHECKSIG] * (1000000 / 50 - 1))
|
||||
@@ -264,8 +280,121 @@ class FullBlockTest(ComparisonTestFramework):
|
||||
out6 = get_spendable_output()
|
||||
too_many_checksigs = CScript([OP_CHECKSIG] * (1000000 / 50))
|
||||
block(16, spend=out6, script=too_many_checksigs)
|
||||
yield rejected(RejectResult(16, 'bad-blk-sigops'))
|
||||
|
||||
|
||||
# Attempt to spend a transaction created on a different fork
|
||||
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
|
||||
# \-> b12 (3) -> b13 (4) -> b15 (5) -> b17 (b3.vtx[1])
|
||||
# \-> b3 (1) -> b4 (2)
|
||||
tip(15)
|
||||
block(17, spend=txout_b3)
|
||||
yield rejected(RejectResult(16, 'bad-txns-inputs-missingorspent'))
|
||||
|
||||
# Attempt to spend a transaction created on a different fork (on a fork this time)
|
||||
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
|
||||
# \-> b12 (3) -> b13 (4) -> b15 (5)
|
||||
# \-> b18 (b3.vtx[1]) -> b19 (6)
|
||||
# \-> b3 (1) -> b4 (2)
|
||||
tip(13)
|
||||
block(18, spend=txout_b3)
|
||||
yield rejected()
|
||||
|
||||
block(19, spend=out6)
|
||||
yield rejected()
|
||||
|
||||
# Attempt to spend a coinbase at depth too low
|
||||
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
|
||||
# \-> b12 (3) -> b13 (4) -> b15 (5) -> b20 (7)
|
||||
# \-> b3 (1) -> b4 (2)
|
||||
tip(15)
|
||||
out7 = get_spendable_output()
|
||||
block(20, spend=out7)
|
||||
yield rejected(RejectResult(16, 'bad-txns-premature-spend-of-coinbase'))
|
||||
|
||||
# Attempt to spend a coinbase at depth too low (on a fork this time)
|
||||
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
|
||||
# \-> b12 (3) -> b13 (4) -> b15 (5)
|
||||
# \-> b21 (6) -> b22 (5)
|
||||
# \-> b3 (1) -> b4 (2)
|
||||
tip(13)
|
||||
block(21, spend=out6)
|
||||
yield rejected()
|
||||
|
||||
block(22, spend=out5)
|
||||
yield rejected()
|
||||
|
||||
# Create a block on either side of MAX_BLOCK_SIZE and make sure its accepted/rejected
|
||||
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
|
||||
# \-> b12 (3) -> b13 (4) -> b15 (5) -> b23 (6)
|
||||
# \-> b24 (6) -> b25 (7)
|
||||
# \-> b3 (1) -> b4 (2)
|
||||
tip(15)
|
||||
b23 = block(23, spend=out6)
|
||||
old_hash = b23.sha256
|
||||
tx = CTransaction()
|
||||
script_length = MAX_BLOCK_SIZE - len(b23.serialize()) - 69
|
||||
script_output = CScript([chr(0)*script_length])
|
||||
tx.vout.append(CTxOut(0, script_output))
|
||||
tx.vin.append(CTxIn(COutPoint(b23.vtx[1].sha256, 1)))
|
||||
b23 = update_block(23, [tx])
|
||||
# Make sure the math above worked out to produce a max-sized block
|
||||
assert_equal(len(b23.serialize()), MAX_BLOCK_SIZE)
|
||||
yield accepted()
|
||||
|
||||
# Make the next block one byte bigger and check that it fails
|
||||
tip(15)
|
||||
b24 = block(24, spend=out6)
|
||||
script_length = MAX_BLOCK_SIZE - len(b24.serialize()) - 69
|
||||
script_output = CScript([chr(0)*(script_length+1)])
|
||||
tx.vout = [CTxOut(0, script_output)]
|
||||
b24 = update_block(24, [tx])
|
||||
assert_equal(len(b24.serialize()), MAX_BLOCK_SIZE+1)
|
||||
yield rejected(RejectResult(16, 'bad-blk-length'))
|
||||
|
||||
b25 = block(25, spend=out7)
|
||||
yield rejected()
|
||||
|
||||
# Create blocks with a coinbase input script size out of range
|
||||
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
|
||||
# \-> b12 (3) -> b13 (4) -> b15 (5) -> b23 (6) -> b30 (7)
|
||||
# \-> ... (6) -> ... (7)
|
||||
# \-> b3 (1) -> b4 (2)
|
||||
tip(15)
|
||||
b26 = block(26, spend=out6)
|
||||
b26.vtx[0].vin[0].scriptSig = chr(0)
|
||||
b26.vtx[0].rehash()
|
||||
# update_block causes the merkle root to get updated, even with no new
|
||||
# transactions, and updates the required state.
|
||||
b26 = update_block(26, [])
|
||||
yield rejected(RejectResult(16, 'bad-cb-length'))
|
||||
|
||||
# Extend the b26 chain to make sure bitcoind isn't accepting b26
|
||||
b27 = block(27, spend=out7)
|
||||
yield rejected()
|
||||
|
||||
# Now try a too-large-coinbase script
|
||||
tip(15)
|
||||
b28 = block(28, spend=out6)
|
||||
b28.vtx[0].vin[0].scriptSig = chr(0)*101
|
||||
b28.vtx[0].rehash()
|
||||
b28 = update_block(28, [])
|
||||
yield rejected(RejectResult(16, 'bad-cb-length'))
|
||||
|
||||
# Extend the b28 chain to make sure bitcoind isn't accepted b28
|
||||
b29 = block(29, spend=out7)
|
||||
# TODO: Should get a reject message back with "bad-prevblk", except
|
||||
# there's a bug that prevents this from being detected. Just note
|
||||
# failure for now, and add the reject result later.
|
||||
yield rejected()
|
||||
|
||||
# b30 has a max-sized coinbase scriptSig.
|
||||
tip(23)
|
||||
b30 = block(30)
|
||||
b30.vtx[0].vin[0].scriptSig = chr(0)*100
|
||||
b30.vtx[0].rehash()
|
||||
b30 = update_block(30, [])
|
||||
yield accepted()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
160
qa/rpc-tests/p2p-versionbits-warning.py
Executable file
160
qa/rpc-tests/p2p-versionbits-warning.py
Executable file
@@ -0,0 +1,160 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT/X11 software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#
|
||||
|
||||
from test_framework.mininode import *
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
import time
|
||||
from test_framework.blocktools import create_block, create_coinbase
|
||||
|
||||
'''
|
||||
Test version bits' warning system.
|
||||
|
||||
Generate chains with block versions that appear to be signalling unknown
|
||||
soft-forks, and test that warning alerts are generated.
|
||||
'''
|
||||
|
||||
VB_PERIOD = 144 # versionbits period length for regtest
|
||||
VB_THRESHOLD = 108 # versionbits activation threshold for regtest
|
||||
VB_TOP_BITS = 0x20000000
|
||||
VB_UNKNOWN_BIT = 27 # Choose a bit unassigned to any deployment
|
||||
|
||||
# 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.connection = None
|
||||
self.ping_counter = 1
|
||||
self.last_pong = msg_pong()
|
||||
|
||||
def add_connection(self, conn):
|
||||
self.connection = conn
|
||||
|
||||
def on_inv(self, conn, message):
|
||||
pass
|
||||
|
||||
# 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
|
||||
|
||||
# Sync up with the node after delivery of a block
|
||||
def sync_with_ping(self, timeout=30):
|
||||
self.connection.send_message(msg_ping(nonce=self.ping_counter))
|
||||
received_pong = False
|
||||
sleep_time = 0.05
|
||||
while not received_pong and timeout > 0:
|
||||
time.sleep(sleep_time)
|
||||
timeout -= sleep_time
|
||||
with mininode_lock:
|
||||
if self.last_pong.nonce == self.ping_counter:
|
||||
received_pong = True
|
||||
self.ping_counter += 1
|
||||
return received_pong
|
||||
|
||||
|
||||
class VersionBitsWarningTest(BitcoinTestFramework):
|
||||
def setup_chain(self):
|
||||
initialize_chain_clean(self.options.tmpdir, 1)
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = []
|
||||
self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt")
|
||||
# Open and close to create zero-length file
|
||||
with open(self.alert_filename, 'w') as f:
|
||||
pass
|
||||
self.node_options = ["-debug", "-logtimemicros=1", "-alertnotify=echo %s >> \"" + self.alert_filename + "\""]
|
||||
self.nodes.append(start_node(0, self.options.tmpdir, self.node_options))
|
||||
|
||||
import re
|
||||
self.vb_pattern = re.compile("^Warning.*versionbit")
|
||||
|
||||
# Send numblocks blocks via peer with nVersionToUse set.
|
||||
def send_blocks_with_version(self, peer, numblocks, nVersionToUse):
|
||||
tip = self.nodes[0].getbestblockhash()
|
||||
height = self.nodes[0].getblockcount()
|
||||
block_time = self.nodes[0].getblockheader(tip)["time"]+1
|
||||
tip = int(tip, 16)
|
||||
|
||||
for i in xrange(numblocks):
|
||||
block = create_block(tip, create_coinbase(height+1), block_time)
|
||||
block.nVersion = nVersionToUse
|
||||
block.solve()
|
||||
peer.send_message(msg_block(block))
|
||||
block_time += 1
|
||||
height += 1
|
||||
tip = block.sha256
|
||||
peer.sync_with_ping()
|
||||
|
||||
def test_versionbits_in_alert_file(self):
|
||||
with open(self.alert_filename, 'r') as f:
|
||||
alert_text = f.read()
|
||||
assert(self.vb_pattern.match(alert_text))
|
||||
|
||||
def run_test(self):
|
||||
# Setup the p2p connection and start up the network thread.
|
||||
test_node = TestNode()
|
||||
|
||||
connections = []
|
||||
connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test_node))
|
||||
test_node.add_connection(connections[0])
|
||||
|
||||
NetworkThread().start() # Start up network handling in another thread
|
||||
|
||||
# Test logic begins here
|
||||
test_node.wait_for_verack()
|
||||
|
||||
# 1. Have the node mine one period worth of blocks
|
||||
self.nodes[0].generate(VB_PERIOD)
|
||||
|
||||
# 2. Now build one period of blocks on the tip, with < VB_THRESHOLD
|
||||
# blocks signaling some unknown bit.
|
||||
nVersion = VB_TOP_BITS | (1<<VB_UNKNOWN_BIT)
|
||||
self.send_blocks_with_version(test_node, VB_THRESHOLD-1, nVersion)
|
||||
|
||||
# Fill rest of period with regular version blocks
|
||||
self.nodes[0].generate(VB_PERIOD - VB_THRESHOLD + 1)
|
||||
# Check that we're not getting any versionbit-related errors in
|
||||
# getinfo()
|
||||
assert(not self.vb_pattern.match(self.nodes[0].getinfo()["errors"]))
|
||||
|
||||
# 3. Now build one period of blocks with >= VB_THRESHOLD blocks signaling
|
||||
# some unknown bit
|
||||
self.send_blocks_with_version(test_node, VB_THRESHOLD, nVersion)
|
||||
self.nodes[0].generate(VB_PERIOD - VB_THRESHOLD)
|
||||
# Might not get a versionbits-related alert yet, as we should
|
||||
# have gotten a different alert due to more than 51/100 blocks
|
||||
# being of unexpected version.
|
||||
# Check that getinfo() shows some kind of error.
|
||||
assert(len(self.nodes[0].getinfo()["errors"]) != 0)
|
||||
|
||||
# Mine a period worth of expected blocks so the generic block-version warning
|
||||
# is cleared, and restart the node. This should move the versionbit state
|
||||
# to ACTIVE.
|
||||
self.nodes[0].generate(VB_PERIOD)
|
||||
stop_node(self.nodes[0], 0)
|
||||
wait_bitcoinds()
|
||||
# Empty out the alert file
|
||||
with open(self.alert_filename, 'w') as f:
|
||||
pass
|
||||
self.nodes[0] = start_node(0, self.options.tmpdir, ["-debug", "-logtimemicros=1", "-alertnotify=echo %s >> \"" + self.alert_filename + "\""])
|
||||
|
||||
# Connecting one block should be enough to generate an error.
|
||||
self.nodes[0].generate(1)
|
||||
assert(len(self.nodes[0].getinfo()["errors"]) != 0)
|
||||
stop_node(self.nodes[0], 0)
|
||||
wait_bitcoinds()
|
||||
self.test_versionbits_in_alert_file()
|
||||
|
||||
# Test framework expects the node to still be running...
|
||||
self.nodes[0] = start_node(0, self.options.tmpdir, ["-debug", "-logtimemicros=1", "-alertnotify=echo %s >> \"" + self.alert_filename + "\""])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
VersionBitsWarningTest().main()
|
||||
@@ -15,21 +15,7 @@ COIN = 100000000
|
||||
class PrioritiseTransactionTest(BitcoinTestFramework):
|
||||
|
||||
def __init__(self):
|
||||
# Some pre-processing to create a bunch of OP_RETURN txouts to insert into transactions we create
|
||||
# So we have big transactions (and therefore can't fit very many into each block)
|
||||
# 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
|
||||
self.txouts = gen_return_txouts()
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
@@ -42,62 +28,15 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
|
||||
self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-printpriority=1"]))
|
||||
self.relayfee = self.nodes[0].getnetworkinfo()['relayfee']
|
||||
|
||||
def create_confirmed_utxos(self, count):
|
||||
self.nodes[0].generate(int(0.5*count)+101)
|
||||
utxos = self.nodes[0].listunspent()
|
||||
iterations = count - len(utxos)
|
||||
addr1 = self.nodes[0].getnewaddress()
|
||||
addr2 = self.nodes[0].getnewaddress()
|
||||
if iterations <= 0:
|
||||
return utxos
|
||||
for i in xrange(iterations):
|
||||
t = utxos.pop()
|
||||
fee = self.relayfee
|
||||
inputs = []
|
||||
inputs.append({ "txid" : t["txid"], "vout" : t["vout"]})
|
||||
outputs = {}
|
||||
send_value = t['amount'] - fee
|
||||
outputs[addr1] = satoshi_round(send_value/2)
|
||||
outputs[addr2] = satoshi_round(send_value/2)
|
||||
raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
|
||||
signed_tx = self.nodes[0].signrawtransaction(raw_tx)["hex"]
|
||||
txid = self.nodes[0].sendrawtransaction(signed_tx)
|
||||
|
||||
while (self.nodes[0].getmempoolinfo()['size'] > 0):
|
||||
self.nodes[0].generate(1)
|
||||
|
||||
utxos = self.nodes[0].listunspent()
|
||||
assert(len(utxos) >= count)
|
||||
return utxos
|
||||
|
||||
def create_lots_of_big_transactions(self, utxos, fee):
|
||||
addr = self.nodes[0].getnewaddress()
|
||||
txids = []
|
||||
for i in xrange(len(utxos)):
|
||||
t = utxos.pop()
|
||||
inputs = []
|
||||
inputs.append({ "txid" : t["txid"], "vout" : t["vout"]})
|
||||
outputs = {}
|
||||
send_value = t['amount'] - fee
|
||||
outputs[addr] = satoshi_round(send_value)
|
||||
rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
|
||||
newtx = rawtx[0:92]
|
||||
newtx = newtx + self.txouts
|
||||
newtx = newtx + rawtx[94:]
|
||||
signresult = self.nodes[0].signrawtransaction(newtx, None, None, "NONE")
|
||||
txid = self.nodes[0].sendrawtransaction(signresult["hex"], True)
|
||||
txids.append(txid)
|
||||
return txids
|
||||
|
||||
def run_test(self):
|
||||
utxos = self.create_confirmed_utxos(90)
|
||||
utxos = create_confirmed_utxos(self.relayfee, self.nodes[0], 90)
|
||||
base_fee = self.relayfee*100 # our transactions are smaller than 100kb
|
||||
txids = []
|
||||
|
||||
# Create 3 batches of transactions at 3 different fee rate levels
|
||||
for i in xrange(3):
|
||||
txids.append([])
|
||||
txids[i] = self.create_lots_of_big_transactions(utxos[30*i:30*i+30], (i+1)*base_fee)
|
||||
txids[i] = create_lots_of_big_transactions(self.nodes[0], self.txouts, utxos[30*i:30*i+30], (i+1)*base_fee)
|
||||
|
||||
# add a fee delta to something in the cheapest bucket and make sure it gets mined
|
||||
# also check that a different entry in the cheapest bucket is NOT mined (lower
|
||||
@@ -143,5 +82,45 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
|
||||
if (x != high_fee_tx):
|
||||
assert(x not in mempool)
|
||||
|
||||
# Create a free, low priority transaction. Should be rejected.
|
||||
utxo_list = self.nodes[0].listunspent()
|
||||
assert(len(utxo_list) > 0)
|
||||
utxo = utxo_list[0]
|
||||
|
||||
inputs = []
|
||||
outputs = {}
|
||||
inputs.append({"txid" : utxo["txid"], "vout" : utxo["vout"]})
|
||||
outputs[self.nodes[0].getnewaddress()] = utxo["amount"] - self.relayfee
|
||||
raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
|
||||
tx_hex = self.nodes[0].signrawtransaction(raw_tx)["hex"]
|
||||
txid = self.nodes[0].sendrawtransaction(tx_hex)
|
||||
|
||||
# A tx that spends an in-mempool tx has 0 priority, so we can use it to
|
||||
# test the effect of using prioritise transaction for mempool acceptance
|
||||
inputs = []
|
||||
inputs.append({"txid": txid, "vout": 0})
|
||||
outputs = {}
|
||||
outputs[self.nodes[0].getnewaddress()] = utxo["amount"] - self.relayfee
|
||||
raw_tx2 = self.nodes[0].createrawtransaction(inputs, outputs)
|
||||
tx2_hex = self.nodes[0].signrawtransaction(raw_tx2)["hex"]
|
||||
tx2_id = self.nodes[0].decoderawtransaction(tx2_hex)["txid"]
|
||||
|
||||
try:
|
||||
self.nodes[0].sendrawtransaction(tx2_hex)
|
||||
except JSONRPCException as exp:
|
||||
assert_equal(exp.error['code'], -26) # insufficient fee
|
||||
assert(tx2_id not in self.nodes[0].getrawmempool())
|
||||
else:
|
||||
assert(False)
|
||||
|
||||
# This is a less than 1000-byte transaction, so just set the fee
|
||||
# to be the minimum for a 1000 byte transaction and check that it is
|
||||
# accepted.
|
||||
self.nodes[0].prioritisetransaction(tx2_id, 0, int(self.relayfee*COIN))
|
||||
|
||||
print "Assert that prioritised free transaction is accepted to mempool"
|
||||
assert_equal(self.nodes[0].sendrawtransaction(tx2_hex), tx2_id)
|
||||
assert(tx2_id in self.nodes[0].getrawmempool())
|
||||
|
||||
if __name__ == '__main__':
|
||||
PrioritiseTransactionTest().main()
|
||||
|
||||
@@ -3,9 +3,6 @@
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
import socket
|
||||
import traceback, sys
|
||||
from binascii import hexlify
|
||||
import time, os
|
||||
|
||||
from test_framework.socks5 import Socks5Configuration, Socks5Command, Socks5Server, AddressType
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
@@ -34,7 +31,8 @@ addnode connect to onion
|
||||
addnode connect to generic DNS name
|
||||
'''
|
||||
|
||||
class ProxyTest(BitcoinTestFramework):
|
||||
|
||||
class ProxyTest(BitcoinTestFramework):
|
||||
def __init__(self):
|
||||
# Create two proxies on different ports
|
||||
# ... one unauthenticated
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
import os.path
|
||||
|
||||
def calc_usage(blockdir):
|
||||
return sum(os.path.getsize(blockdir+f) for f in os.listdir(blockdir) if os.path.isfile(blockdir+f))/(1024*1024)
|
||||
@@ -23,24 +22,7 @@ class PruneTest(BitcoinTestFramework):
|
||||
def __init__(self):
|
||||
self.utxo = []
|
||||
self.address = ["",""]
|
||||
|
||||
# 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
|
||||
|
||||
self.txouts = gen_return_txouts()
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
from pprint import pprint
|
||||
from time import sleep
|
||||
|
||||
# Create one-input, one-output, no-fee transaction:
|
||||
class RawTransactionsTest(BitcoinTestFramework):
|
||||
@@ -43,9 +41,9 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
self.sync_all()
|
||||
self.nodes[0].generate(101)
|
||||
self.sync_all()
|
||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.5);
|
||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.0);
|
||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),5.0);
|
||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.5)
|
||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.0)
|
||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),5.0)
|
||||
self.sync_all()
|
||||
self.nodes[0].generate(5)
|
||||
self.sync_all()
|
||||
@@ -64,7 +62,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
except JSONRPCException,e:
|
||||
errorString = e.error['message']
|
||||
|
||||
assert_equal("Missing inputs" in errorString, True);
|
||||
assert("Missing inputs" in errorString)
|
||||
|
||||
#########################
|
||||
# RAW TX MULTISIG TESTS #
|
||||
@@ -83,7 +81,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
bal = self.nodes[2].getbalance()
|
||||
|
||||
# send 1.2 BTC to msig adr
|
||||
txId = self.nodes[0].sendtoaddress(mSigObj, 1.2);
|
||||
txId = self.nodes[0].sendtoaddress(mSigObj, 1.2)
|
||||
self.sync_all()
|
||||
self.nodes[0].generate(1)
|
||||
self.sync_all()
|
||||
@@ -105,7 +103,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey']])
|
||||
mSigObjValid = self.nodes[2].validateaddress(mSigObj)
|
||||
|
||||
txId = self.nodes[0].sendtoaddress(mSigObj, 2.2);
|
||||
txId = self.nodes[0].sendtoaddress(mSigObj, 2.2)
|
||||
decTx = self.nodes[0].gettransaction(txId)
|
||||
rawTx = self.nodes[0].decoderawtransaction(decTx['hex'])
|
||||
sPK = rawTx['vout'][0]['scriptPubKey']['hex']
|
||||
@@ -123,7 +121,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
for outpoint in rawTx['vout']:
|
||||
if outpoint['value'] == Decimal('2.20000000'):
|
||||
vout = outpoint
|
||||
break;
|
||||
break
|
||||
|
||||
bal = self.nodes[0].getbalance()
|
||||
inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex']}]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
import os.path
|
||||
|
||||
class ReindexTest(BitcoinTestFramework):
|
||||
|
||||
|
||||
@@ -54,8 +54,7 @@ def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])):
|
||||
tx2.vout = [CTxOut(amount, scriptPubKey)]
|
||||
tx2.rehash()
|
||||
|
||||
tx2_hex = binascii.hexlify(tx2.serialize()).decode('utf-8')
|
||||
#print tx2_hex
|
||||
binascii.hexlify(tx2.serialize()).decode('utf-8')
|
||||
|
||||
signed_tx = node.signrawtransaction(binascii.hexlify(tx2.serialize()).decode('utf-8'))
|
||||
|
||||
@@ -63,8 +62,14 @@ def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])):
|
||||
|
||||
# If requested, ensure txouts are confirmed.
|
||||
if confirmed:
|
||||
while len(node.getrawmempool()):
|
||||
mempool_size = len(node.getrawmempool())
|
||||
while mempool_size > 0:
|
||||
node.generate(1)
|
||||
new_size = len(node.getrawmempool())
|
||||
# Error out if we have something stuck in the mempool, as this
|
||||
# would likely be a bug.
|
||||
assert(new_size < mempool_size)
|
||||
mempool_size = new_size
|
||||
|
||||
return COutPoint(int(txid, 16), 0)
|
||||
|
||||
@@ -72,7 +77,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = []
|
||||
self.nodes.append(start_node(0, self.options.tmpdir, ["-maxorphantx=1000",
|
||||
self.nodes.append(start_node(0, self.options.tmpdir, ["-maxorphantx=1000", "-debug",
|
||||
"-relaypriority=0", "-whitelist=127.0.0.1",
|
||||
"-limitancestorcount=50",
|
||||
"-limitancestorsize=101",
|
||||
@@ -108,6 +113,9 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
print "Running test opt-in..."
|
||||
self.test_opt_in()
|
||||
|
||||
print "Running test prioritised transactions..."
|
||||
self.test_prioritised_transactions()
|
||||
|
||||
print "Passed\n"
|
||||
|
||||
def test_simple_doublespend(self):
|
||||
@@ -513,5 +521,72 @@ class ReplaceByFeeTest(BitcoinTestFramework):
|
||||
# but make sure it is accepted anyway
|
||||
self.nodes[0].sendrawtransaction(tx3c_hex, True)
|
||||
|
||||
def test_prioritised_transactions(self):
|
||||
# Ensure that fee deltas used via prioritisetransaction are
|
||||
# correctly used by replacement logic
|
||||
|
||||
# 1. Check that feeperkb uses modified fees
|
||||
tx0_outpoint = make_utxo(self.nodes[0], 1.1*COIN)
|
||||
|
||||
tx1a = CTransaction()
|
||||
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
||||
tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
|
||||
tx1a_hex = txToHex(tx1a)
|
||||
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
|
||||
|
||||
# Higher fee, but the actual fee per KB is much lower.
|
||||
tx1b = CTransaction()
|
||||
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
|
||||
tx1b.vout = [CTxOut(0.001*COIN, CScript([b'a'*740000]))]
|
||||
tx1b_hex = txToHex(tx1b)
|
||||
|
||||
# Verify tx1b cannot replace tx1a.
|
||||
try:
|
||||
tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
|
||||
except JSONRPCException as exp:
|
||||
assert_equal(exp.error['code'], -26)
|
||||
else:
|
||||
assert(False)
|
||||
|
||||
# Use prioritisetransaction to set tx1a's fee to 0.
|
||||
self.nodes[0].prioritisetransaction(tx1a_txid, 0, int(-0.1*COIN))
|
||||
|
||||
# Now tx1b should be able to replace tx1a
|
||||
tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
|
||||
|
||||
assert(tx1b_txid in self.nodes[0].getrawmempool())
|
||||
|
||||
# 2. Check that absolute fee checks use modified fee.
|
||||
tx1_outpoint = make_utxo(self.nodes[0], 1.1*COIN)
|
||||
|
||||
tx2a = CTransaction()
|
||||
tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0)]
|
||||
tx2a.vout = [CTxOut(1*COIN, CScript([b'a']))]
|
||||
tx2a_hex = txToHex(tx2a)
|
||||
tx2a_txid = self.nodes[0].sendrawtransaction(tx2a_hex, True)
|
||||
|
||||
# Lower fee, but we'll prioritise it
|
||||
tx2b = CTransaction()
|
||||
tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)]
|
||||
tx2b.vout = [CTxOut(1.01*COIN, CScript([b'a']))]
|
||||
tx2b.rehash()
|
||||
tx2b_hex = txToHex(tx2b)
|
||||
|
||||
# Verify tx2b cannot replace tx2a.
|
||||
try:
|
||||
tx2b_txid = self.nodes[0].sendrawtransaction(tx2b_hex, True)
|
||||
except JSONRPCException as exp:
|
||||
assert_equal(exp.error['code'], -26)
|
||||
else:
|
||||
assert(False)
|
||||
|
||||
# Now prioritise tx2b to have a higher modified fee
|
||||
self.nodes[0].prioritisetransaction(tx2b.hash, 0, int(0.1*COIN))
|
||||
|
||||
# tx2b should now be accepted
|
||||
tx2b_txid = self.nodes[0].sendrawtransaction(tx2b_hex, True)
|
||||
|
||||
assert(tx2b_txid in self.nodes[0].getrawmempool())
|
||||
|
||||
if __name__ == '__main__':
|
||||
ReplaceByFeeTest().main()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
@@ -12,9 +12,7 @@ from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
from struct import *
|
||||
import binascii
|
||||
import json
|
||||
import StringIO
|
||||
import decimal
|
||||
|
||||
try:
|
||||
import http.client as httplib
|
||||
@@ -143,9 +141,9 @@ class RESTTest (BitcoinTestFramework):
|
||||
|
||||
binaryRequest = b'\x01\x02'
|
||||
binaryRequest += binascii.unhexlify(txid)
|
||||
binaryRequest += pack("i", n);
|
||||
binaryRequest += binascii.unhexlify(vintx);
|
||||
binaryRequest += pack("i", 0);
|
||||
binaryRequest += pack("i", n)
|
||||
binaryRequest += binascii.unhexlify(vintx)
|
||||
binaryRequest += pack("i", 0)
|
||||
|
||||
bin_response = http_post_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'bin', binaryRequest)
|
||||
output = StringIO.StringIO()
|
||||
@@ -206,7 +204,7 @@ class RESTTest (BitcoinTestFramework):
|
||||
json_request = '/checkmempool/'
|
||||
for x in range(0, 15):
|
||||
json_request += txid+'-'+str(n)+'/'
|
||||
json_request = json_request.rstrip("/");
|
||||
json_request = json_request.rstrip("/")
|
||||
response = http_post_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json', '', True)
|
||||
assert_equal(response.status, 200) #must be a 500 because we exceeding the limits
|
||||
|
||||
@@ -254,7 +252,7 @@ class RESTTest (BitcoinTestFramework):
|
||||
response_header_json = http_get_call(url.hostname, url.port, '/rest/headers/1/'+bb_hash+self.FORMAT_SEPARATOR+"json", True)
|
||||
assert_equal(response_header_json.status, 200)
|
||||
response_header_json_str = response_header_json.read()
|
||||
json_obj = json.loads(response_header_json_str, parse_float=decimal.Decimal)
|
||||
json_obj = json.loads(response_header_json_str, parse_float=Decimal)
|
||||
assert_equal(len(json_obj), 1) #ensure that there is one header in the json response
|
||||
assert_equal(json_obj[0]['hash'], bb_hash) #request/response hash should be the same
|
||||
|
||||
@@ -282,7 +280,7 @@ class RESTTest (BitcoinTestFramework):
|
||||
assert_equal(len(json_obj), 5) #now we should have 5 header objects
|
||||
|
||||
# do tx test
|
||||
tx_hash = block_json_obj['tx'][0]['txid'];
|
||||
tx_hash = block_json_obj['tx'][0]['txid']
|
||||
json_string = http_get_call(url.hostname, url.port, '/rest/tx/'+tx_hash+self.FORMAT_SEPARATOR+"json")
|
||||
json_obj = json.loads(json_string)
|
||||
assert_equal(json_obj['txid'], tx_hash)
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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 for -rpcbind, as well as -rpcallowip and -rpcconnect
|
||||
|
||||
# Add python-bitcoinrpc to module search path:
|
||||
import os
|
||||
import sys
|
||||
# TODO extend this test from the test framework (like all other tests)
|
||||
|
||||
import json
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import traceback
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
from test_framework.mininode import *
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
import time
|
||||
from test_framework.blocktools import create_block, create_coinbase
|
||||
|
||||
'''
|
||||
@@ -70,7 +69,6 @@ f. Announce 1 more header that builds on that fork.
|
||||
class BaseNode(NodeConnCB):
|
||||
def __init__(self):
|
||||
NodeConnCB.__init__(self)
|
||||
self.create_callback_map()
|
||||
self.connection = None
|
||||
self.last_inv = None
|
||||
self.last_headers = None
|
||||
@@ -221,18 +219,20 @@ class SendHeadersTest(BitcoinTestFramework):
|
||||
|
||||
# mine count blocks and return the new tip
|
||||
def mine_blocks(self, count):
|
||||
# Clear out last block announcement from each p2p listener
|
||||
[ x.clear_last_announcement() for x in self.p2p_connections ]
|
||||
self.nodes[0].generate(count)
|
||||
return int(self.nodes[0].getbestblockhash(), 16)
|
||||
|
||||
# mine a reorg that invalidates length blocks (replacing them with
|
||||
# length+1 blocks).
|
||||
# peers is the p2p nodes we're using; we clear their state after the
|
||||
# Note: we clear the state of our p2p connections after the
|
||||
# to-be-reorged-out blocks are mined, so that we don't break later tests.
|
||||
# return the list of block hashes newly mined
|
||||
def mine_reorg(self, length, peers):
|
||||
def mine_reorg(self, length):
|
||||
self.nodes[0].generate(length) # make sure all invalidated blocks are node0's
|
||||
sync_blocks(self.nodes, wait=0.1)
|
||||
[x.clear_last_announcement() for x in peers]
|
||||
[x.clear_last_announcement() for x in self.p2p_connections]
|
||||
|
||||
tip_height = self.nodes[1].getblockcount()
|
||||
hash_to_invalidate = self.nodes[1].getblockhash(tip_height-(length-1))
|
||||
@@ -246,6 +246,8 @@ class SendHeadersTest(BitcoinTestFramework):
|
||||
inv_node = InvNode()
|
||||
test_node = TestNode()
|
||||
|
||||
self.p2p_connections = [inv_node, test_node]
|
||||
|
||||
connections = []
|
||||
connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], inv_node))
|
||||
# Set nServices to 0 for test_node, so no block download will occur outside of
|
||||
@@ -304,7 +306,6 @@ class SendHeadersTest(BitcoinTestFramework):
|
||||
prev_tip = int(self.nodes[0].getbestblockhash(), 16)
|
||||
test_node.get_headers(locator=[prev_tip], hashstop=0L)
|
||||
test_node.sync_with_ping()
|
||||
test_node.clear_last_announcement() # Clear out empty headers response
|
||||
|
||||
# Now that we've synced headers, headers announcements should work
|
||||
tip = self.mine_blocks(1)
|
||||
@@ -353,8 +354,6 @@ class SendHeadersTest(BitcoinTestFramework):
|
||||
# broadcast it)
|
||||
assert_equal(inv_node.last_inv, None)
|
||||
assert_equal(inv_node.last_headers, None)
|
||||
inv_node.clear_last_announcement()
|
||||
test_node.clear_last_announcement()
|
||||
tip = self.mine_blocks(1)
|
||||
assert_equal(inv_node.check_last_announcement(inv=[tip]), True)
|
||||
assert_equal(test_node.check_last_announcement(headers=[tip]), True)
|
||||
@@ -369,7 +368,7 @@ class SendHeadersTest(BitcoinTestFramework):
|
||||
# getheaders or inv from peer.
|
||||
for j in xrange(2):
|
||||
# First try mining a reorg that can propagate with header announcement
|
||||
new_block_hashes = self.mine_reorg(length=7, peers=[test_node, inv_node])
|
||||
new_block_hashes = self.mine_reorg(length=7)
|
||||
tip = new_block_hashes[-1]
|
||||
assert_equal(inv_node.check_last_announcement(inv=[tip]), True)
|
||||
assert_equal(test_node.check_last_announcement(headers=new_block_hashes), True)
|
||||
@@ -377,7 +376,7 @@ class SendHeadersTest(BitcoinTestFramework):
|
||||
block_time += 8
|
||||
|
||||
# Mine a too-large reorg, which should be announced with a single inv
|
||||
new_block_hashes = self.mine_reorg(length=8, peers=[test_node, inv_node])
|
||||
new_block_hashes = self.mine_reorg(length=8)
|
||||
tip = new_block_hashes[-1]
|
||||
assert_equal(inv_node.check_last_announcement(inv=[tip]), True)
|
||||
assert_equal(test_node.check_last_announcement(inv=[tip]), True)
|
||||
@@ -389,7 +388,7 @@ class SendHeadersTest(BitcoinTestFramework):
|
||||
|
||||
# Use getblocks/getdata
|
||||
test_node.send_getblocks(locator = [fork_point])
|
||||
assert_equal(test_node.check_last_announcement(inv=new_block_hashes[0:-1]), True)
|
||||
assert_equal(test_node.check_last_announcement(inv=new_block_hashes), True)
|
||||
test_node.get_data(new_block_hashes)
|
||||
test_node.wait_for_block(new_block_hashes[-1])
|
||||
|
||||
@@ -408,7 +407,6 @@ class SendHeadersTest(BitcoinTestFramework):
|
||||
test_node.get_headers(locator=[fork_point], hashstop=new_block_hashes[1])
|
||||
test_node.get_data([tip])
|
||||
test_node.wait_for_block(tip)
|
||||
test_node.clear_last_announcement()
|
||||
elif i == 2:
|
||||
test_node.get_data([tip])
|
||||
test_node.wait_for_block(tip)
|
||||
@@ -446,7 +444,7 @@ class SendHeadersTest(BitcoinTestFramework):
|
||||
|
||||
inv_node.sync_with_ping() # Make sure blocks are processed
|
||||
test_node.last_getdata = None
|
||||
test_node.send_header_for_blocks(blocks);
|
||||
test_node.send_header_for_blocks(blocks)
|
||||
test_node.sync_with_ping()
|
||||
# should not have received any getdata messages
|
||||
with mininode_lock:
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#
|
||||
|
||||
from mininode import *
|
||||
from script import CScript, CScriptOp, OP_TRUE, OP_CHECKSIG
|
||||
from script import CScript, OP_TRUE, OP_CHECKSIG
|
||||
|
||||
# Create a block (with regtest difficulty)
|
||||
def create_block(hashprev, coinbase, nTime=None):
|
||||
|
||||
@@ -41,17 +41,32 @@ def wait_until(predicate, attempts=float('inf'), timeout=float('inf')):
|
||||
|
||||
return False
|
||||
|
||||
class RejectResult(object):
|
||||
'''
|
||||
Outcome that expects rejection of a transaction or block.
|
||||
'''
|
||||
def __init__(self, code, reason=''):
|
||||
self.code = code
|
||||
self.reason = reason
|
||||
def match(self, other):
|
||||
if self.code != other.code:
|
||||
return False
|
||||
return other.reason.startswith(self.reason)
|
||||
def __repr__(self):
|
||||
return '%i:%s' % (self.code,self.reason or '*')
|
||||
|
||||
class TestNode(NodeConnCB):
|
||||
|
||||
def __init__(self, block_store, tx_store):
|
||||
NodeConnCB.__init__(self)
|
||||
self.create_callback_map()
|
||||
self.conn = None
|
||||
self.bestblockhash = None
|
||||
self.block_store = block_store
|
||||
self.block_request_map = {}
|
||||
self.tx_store = tx_store
|
||||
self.tx_request_map = {}
|
||||
self.block_reject_map = {}
|
||||
self.tx_reject_map = {}
|
||||
|
||||
# When the pingmap is non-empty we're waiting for
|
||||
# a response
|
||||
@@ -95,6 +110,12 @@ class TestNode(NodeConnCB):
|
||||
except KeyError:
|
||||
raise AssertionError("Got pong for unknown ping [%s]" % repr(message))
|
||||
|
||||
def on_reject(self, conn, message):
|
||||
if message.message == 'tx':
|
||||
self.tx_reject_map[message.data] = RejectResult(message.code, message.reason)
|
||||
if message.message == 'block':
|
||||
self.block_reject_map[message.data] = RejectResult(message.code, message.reason)
|
||||
|
||||
def send_inv(self, obj):
|
||||
mtype = 2 if isinstance(obj, CBlock) else 1
|
||||
self.conn.send_message(msg_inv([CInv(mtype, obj.sha256)]))
|
||||
@@ -172,6 +193,10 @@ class TestManager(object):
|
||||
# associated NodeConn
|
||||
test_node.add_connection(self.connections[-1])
|
||||
|
||||
def clear_all_connections(self):
|
||||
self.connections = []
|
||||
self.test_nodes = []
|
||||
|
||||
def wait_for_disconnections(self):
|
||||
def disconnected():
|
||||
return all(node.closed for node in self.test_nodes)
|
||||
@@ -244,6 +269,15 @@ class TestManager(object):
|
||||
if outcome is None:
|
||||
if c.cb.bestblockhash != self.connections[0].cb.bestblockhash:
|
||||
return False
|
||||
elif isinstance(outcome, RejectResult): # Check that block was rejected w/ code
|
||||
if c.cb.bestblockhash == blockhash:
|
||||
return False
|
||||
if blockhash not in c.cb.block_reject_map:
|
||||
print 'Block not in reject map: %064x' % (blockhash)
|
||||
return False
|
||||
if not outcome.match(c.cb.block_reject_map[blockhash]):
|
||||
print 'Block rejected with %s instead of expected %s: %064x' % (c.cb.block_reject_map[blockhash], outcome, blockhash)
|
||||
return False
|
||||
elif ((c.cb.bestblockhash == blockhash) != outcome):
|
||||
# print c.cb.bestblockhash, blockhash, outcome
|
||||
return False
|
||||
@@ -263,6 +297,15 @@ class TestManager(object):
|
||||
if c.cb.lastInv != self.connections[0].cb.lastInv:
|
||||
# print c.rpc.getrawmempool()
|
||||
return False
|
||||
elif isinstance(outcome, RejectResult): # Check that tx was rejected w/ code
|
||||
if txhash in c.cb.lastInv:
|
||||
return False
|
||||
if txhash not in c.cb.tx_reject_map:
|
||||
print 'Tx not in reject map: %064x' % (txhash)
|
||||
return False
|
||||
if not outcome.match(c.cb.tx_reject_map[txhash]):
|
||||
print 'Tx rejected with %s instead of expected %s: %064x' % (c.cb.tx_reject_map[txhash], outcome, txhash)
|
||||
return False
|
||||
elif ((txhash in c.cb.lastInv) != outcome):
|
||||
# print c.rpc.getrawmempool(), c.cb.lastInv
|
||||
return False
|
||||
|
||||
@@ -36,6 +36,7 @@ MY_VERSION = 60001 # past bip-31 for ping/pong
|
||||
MY_SUBVERSION = "/python-mininode-tester:0.0.1/"
|
||||
|
||||
MAX_INV_SZ = 50000
|
||||
MAX_BLOCK_SIZE = 1000000
|
||||
|
||||
# Keep our own socket map for asyncore, so that we can track disconnects
|
||||
# ourselves (to workaround an issue with closing an asyncore socket when
|
||||
@@ -230,6 +231,14 @@ def ser_int_vector(l):
|
||||
r += struct.pack("<i", i)
|
||||
return r
|
||||
|
||||
# Deserialize from a hex string representation (eg from RPC)
|
||||
def FromHex(obj, hex_string):
|
||||
obj.deserialize(cStringIO.StringIO(binascii.unhexlify(hex_string)))
|
||||
return obj
|
||||
|
||||
# Convert a binary-serializable object to hex (eg for submission via RPC)
|
||||
def ToHex(obj):
|
||||
return binascii.hexlify(obj.serialize()).decode('utf-8')
|
||||
|
||||
# Objects that map to bitcoind objects, which can be serialized/deserialized
|
||||
|
||||
@@ -535,7 +544,7 @@ class CBlock(CBlockHeader):
|
||||
return True
|
||||
|
||||
def solve(self):
|
||||
self.calc_sha256()
|
||||
self.rehash()
|
||||
target = uint256_from_compact(self.nBits)
|
||||
while self.sha256 > target:
|
||||
self.nNonce += 1
|
||||
@@ -1003,6 +1012,18 @@ class msg_reject(object):
|
||||
class NodeConnCB(object):
|
||||
def __init__(self):
|
||||
self.verack_received = False
|
||||
# deliver_sleep_time is helpful for debugging race conditions in p2p
|
||||
# tests; it causes message delivery to sleep for the specified time
|
||||
# before acquiring the global lock and delivering the next message.
|
||||
self.deliver_sleep_time = None
|
||||
|
||||
def set_deliver_sleep_time(self, value):
|
||||
with mininode_lock:
|
||||
self.deliver_sleep_time = value
|
||||
|
||||
def get_deliver_sleep_time(self):
|
||||
with mininode_lock:
|
||||
return self.deliver_sleep_time
|
||||
|
||||
# Spin until verack message is received from the node.
|
||||
# Tests may want to use this as a signal that the test can begin.
|
||||
@@ -1015,32 +1036,13 @@ class NodeConnCB(object):
|
||||
return
|
||||
time.sleep(0.05)
|
||||
|
||||
# Derived classes should call this function once to set the message map
|
||||
# which associates the derived classes' functions to incoming messages
|
||||
def create_callback_map(self):
|
||||
self.cbmap = {
|
||||
"version": self.on_version,
|
||||
"verack": self.on_verack,
|
||||
"addr": self.on_addr,
|
||||
"alert": self.on_alert,
|
||||
"inv": self.on_inv,
|
||||
"getdata": self.on_getdata,
|
||||
"getblocks": self.on_getblocks,
|
||||
"tx": self.on_tx,
|
||||
"block": self.on_block,
|
||||
"getaddr": self.on_getaddr,
|
||||
"ping": self.on_ping,
|
||||
"pong": self.on_pong,
|
||||
"headers": self.on_headers,
|
||||
"getheaders": self.on_getheaders,
|
||||
"reject": self.on_reject,
|
||||
"mempool": self.on_mempool
|
||||
}
|
||||
|
||||
def deliver(self, conn, message):
|
||||
deliver_sleep = self.get_deliver_sleep_time()
|
||||
if deliver_sleep is not None:
|
||||
time.sleep(deliver_sleep)
|
||||
with mininode_lock:
|
||||
try:
|
||||
self.cbmap[message.command](conn, message)
|
||||
getattr(self, 'on_' + message.command)(conn, message)
|
||||
except:
|
||||
print "ERROR delivering %s (%s)" % (repr(message),
|
||||
sys.exc_info()[0])
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
|
||||
@@ -14,7 +14,8 @@ Functionality to build scripts, as well as SignatureHash().
|
||||
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
from test_framework.mininode import CTransaction, CTxOut, hash256
|
||||
from .mininode import CTransaction, CTxOut, hash256
|
||||
from binascii import hexlify
|
||||
|
||||
import sys
|
||||
bchr = chr
|
||||
@@ -24,10 +25,9 @@ if sys.version > '3':
|
||||
bchr = lambda x: bytes([x])
|
||||
bord = lambda x: x
|
||||
|
||||
import copy
|
||||
import struct
|
||||
|
||||
from test_framework.bignum import bn2vch
|
||||
from .bignum import bn2vch
|
||||
|
||||
MAX_SCRIPT_SIZE = 10000
|
||||
MAX_SCRIPT_ELEMENT_SIZE = 520
|
||||
@@ -226,7 +226,7 @@ OP_CHECKMULTISIGVERIFY = CScriptOp(0xaf)
|
||||
|
||||
# expansion
|
||||
OP_NOP1 = CScriptOp(0xb0)
|
||||
OP_NOP2 = CScriptOp(0xb1)
|
||||
OP_CHECKLOCKTIMEVERIFY = CScriptOp(0xb1)
|
||||
OP_NOP3 = CScriptOp(0xb2)
|
||||
OP_NOP4 = CScriptOp(0xb3)
|
||||
OP_NOP5 = CScriptOp(0xb4)
|
||||
@@ -353,7 +353,7 @@ VALID_OPCODES = {
|
||||
OP_CHECKMULTISIGVERIFY,
|
||||
|
||||
OP_NOP1,
|
||||
OP_NOP2,
|
||||
OP_CHECKLOCKTIMEVERIFY,
|
||||
OP_NOP3,
|
||||
OP_NOP4,
|
||||
OP_NOP5,
|
||||
@@ -472,7 +472,7 @@ OPCODE_NAMES.update({
|
||||
OP_CHECKMULTISIG : 'OP_CHECKMULTISIG',
|
||||
OP_CHECKMULTISIGVERIFY : 'OP_CHECKMULTISIGVERIFY',
|
||||
OP_NOP1 : 'OP_NOP1',
|
||||
OP_NOP2 : 'OP_NOP2',
|
||||
OP_CHECKLOCKTIMEVERIFY : 'OP_CHECKLOCKTIMEVERIFY',
|
||||
OP_NOP3 : 'OP_NOP3',
|
||||
OP_NOP4 : 'OP_NOP4',
|
||||
OP_NOP5 : 'OP_NOP5',
|
||||
@@ -591,7 +591,7 @@ OPCODES_BY_NAME = {
|
||||
'OP_CHECKMULTISIG' : OP_CHECKMULTISIG,
|
||||
'OP_CHECKMULTISIGVERIFY' : OP_CHECKMULTISIGVERIFY,
|
||||
'OP_NOP1' : OP_NOP1,
|
||||
'OP_NOP2' : OP_NOP2,
|
||||
'OP_CHECKLOCKTIMEVERIFY' : OP_CHECKLOCKTIMEVERIFY,
|
||||
'OP_NOP3' : OP_NOP3,
|
||||
'OP_NOP4' : OP_NOP4,
|
||||
'OP_NOP5' : OP_NOP5,
|
||||
@@ -777,7 +777,7 @@ class CScript(bytes):
|
||||
# need to change
|
||||
def _repr(o):
|
||||
if isinstance(o, bytes):
|
||||
return "x('%s')" % binascii.hexlify(o).decode('utf8')
|
||||
return "x('%s')" % hexlify(o).decode('utf8')
|
||||
else:
|
||||
return repr(o)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
@@ -120,7 +120,7 @@ class BitcoinTestFramework(object):
|
||||
if self.options.coveragedir:
|
||||
enable_coverage(self.options.coveragedir)
|
||||
|
||||
os.environ['PATH'] = self.options.srcdir+":"+os.environ['PATH']
|
||||
os.environ['PATH'] = self.options.srcdir+":"+self.options.srcdir+"/qt:"+os.environ['PATH']
|
||||
|
||||
check_json_precision()
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
#
|
||||
@@ -102,11 +102,12 @@ def initialize_datadir(dirname, n):
|
||||
if not os.path.isdir(datadir):
|
||||
os.makedirs(datadir)
|
||||
with open(os.path.join(datadir, "bitcoin.conf"), 'w') as f:
|
||||
f.write("regtest=1\n");
|
||||
f.write("rpcuser=rt\n");
|
||||
f.write("rpcpassword=rt\n");
|
||||
f.write("port="+str(p2p_port(n))+"\n");
|
||||
f.write("rpcport="+str(rpc_port(n))+"\n");
|
||||
f.write("regtest=1\n")
|
||||
f.write("rpcuser=rt\n")
|
||||
f.write("rpcpassword=rt\n")
|
||||
f.write("port="+str(p2p_port(n))+"\n")
|
||||
f.write("rpcport="+str(rpc_port(n))+"\n")
|
||||
f.write("listenonion=0\n")
|
||||
return datadir
|
||||
|
||||
def initialize_chain(test_dir):
|
||||
@@ -130,7 +131,7 @@ def initialize_chain(test_dir):
|
||||
# Create cache directories, run bitcoinds:
|
||||
for i in range(4):
|
||||
datadir=initialize_datadir("cache", i)
|
||||
args = [ os.getenv("BITCOIND", "bitcoind"), "-keypool=1", "-datadir="+datadir, "-discover=0" ]
|
||||
args = [ os.getenv("BITCOIND", "bitcoind"), "-server", "-keypool=1", "-datadir="+datadir, "-discover=0" ]
|
||||
if i > 0:
|
||||
args.append("-connect=127.0.0.1:"+str(p2p_port(0)))
|
||||
bitcoind_processes[i] = subprocess.Popen(args)
|
||||
@@ -218,7 +219,7 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=
|
||||
if binary is None:
|
||||
binary = os.getenv("BITCOIND", "bitcoind")
|
||||
# RPC tests still depend on free transactions
|
||||
args = [ binary, "-datadir="+datadir, "-keypool=1", "-discover=0", "-rest", "-blockprioritysize=50000" ]
|
||||
args = [ binary, "-datadir="+datadir, "-server", "-keypool=1", "-discover=0", "-rest", "-blockprioritysize=50000" ]
|
||||
if extra_args is not None: args.extend(extra_args)
|
||||
bitcoind_processes[i] = subprocess.Popen(args)
|
||||
devnull = open(os.devnull, "w")
|
||||
@@ -406,5 +407,93 @@ def assert_raises(exc, fun, *args, **kwds):
|
||||
else:
|
||||
raise AssertionError("No exception raised")
|
||||
|
||||
def assert_is_hex_string(string):
|
||||
try:
|
||||
int(string, 16)
|
||||
except Exception as e:
|
||||
raise AssertionError(
|
||||
"Couldn't interpret %r as hexadecimal; raised: %s" % (string, e))
|
||||
|
||||
def assert_is_hash_string(string, length=64):
|
||||
if not isinstance(string, basestring):
|
||||
raise AssertionError("Expected a string, got type %r" % type(string))
|
||||
elif length and len(string) != length:
|
||||
raise AssertionError(
|
||||
"String of length %d expected; got %d" % (length, len(string)))
|
||||
elif not re.match('[abcdef0-9]+$', string):
|
||||
raise AssertionError(
|
||||
"String %r contains invalid characters for a hash." % string)
|
||||
|
||||
def satoshi_round(amount):
|
||||
return Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN)
|
||||
|
||||
def create_confirmed_utxos(fee, node, count):
|
||||
node.generate(int(0.5*count)+101)
|
||||
utxos = node.listunspent()
|
||||
iterations = count - len(utxos)
|
||||
addr1 = node.getnewaddress()
|
||||
addr2 = node.getnewaddress()
|
||||
if iterations <= 0:
|
||||
return utxos
|
||||
for i in xrange(iterations):
|
||||
t = utxos.pop()
|
||||
inputs = []
|
||||
inputs.append({ "txid" : t["txid"], "vout" : t["vout"]})
|
||||
outputs = {}
|
||||
send_value = t['amount'] - fee
|
||||
outputs[addr1] = satoshi_round(send_value/2)
|
||||
outputs[addr2] = satoshi_round(send_value/2)
|
||||
raw_tx = node.createrawtransaction(inputs, outputs)
|
||||
signed_tx = node.signrawtransaction(raw_tx)["hex"]
|
||||
txid = node.sendrawtransaction(signed_tx)
|
||||
|
||||
while (node.getmempoolinfo()['size'] > 0):
|
||||
node.generate(1)
|
||||
|
||||
utxos = node.listunspent()
|
||||
assert(len(utxos) >= count)
|
||||
return utxos
|
||||
|
||||
def gen_return_txouts():
|
||||
# Some pre-processing to create a bunch of OP_RETURN txouts to insert into transactions we create
|
||||
# So we have big transactions (and therefore can't fit very many into each block)
|
||||
# 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
|
||||
txouts = "81"
|
||||
for k in xrange(128):
|
||||
# add txout value
|
||||
txouts = txouts + "0000000000000000"
|
||||
# add length of script_pubkey
|
||||
txouts = txouts + "fd0402"
|
||||
# add script_pubkey
|
||||
txouts = txouts + script_pubkey
|
||||
return txouts
|
||||
|
||||
def create_lots_of_big_transactions(node, txouts, utxos, fee):
|
||||
addr = node.getnewaddress()
|
||||
txids = []
|
||||
for i in xrange(len(utxos)):
|
||||
t = utxos.pop()
|
||||
inputs = []
|
||||
inputs.append({ "txid" : t["txid"], "vout" : t["vout"]})
|
||||
outputs = {}
|
||||
send_value = t['amount'] - fee
|
||||
outputs[addr] = satoshi_round(send_value)
|
||||
rawtx = node.createrawtransaction(inputs, outputs)
|
||||
newtx = rawtx[0:92]
|
||||
newtx = newtx + txouts
|
||||
newtx = newtx + rawtx[94:]
|
||||
signresult = node.signrawtransaction(newtx, None, None, "NONE")
|
||||
txid = node.sendrawtransaction(signresult["hex"], True)
|
||||
txids.append(txid)
|
||||
return txids
|
||||
|
||||
def get_bip9_status(node, key):
|
||||
info = node.getblockchaininfo()
|
||||
for row in info['bip9_softforks']:
|
||||
if row['id'] == key:
|
||||
return row
|
||||
raise IndexError ('key:"%s" not found' % key)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
@@ -8,11 +8,7 @@
|
||||
#
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.authproxy import AuthServiceProxy, JSONRPCException
|
||||
from decimal import Decimal
|
||||
from test_framework.util import *
|
||||
import os
|
||||
import shutil
|
||||
|
||||
class TxnMallTest(BitcoinTestFramework):
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
@@ -9,9 +9,6 @@
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
from decimal import Decimal
|
||||
import os
|
||||
import shutil
|
||||
|
||||
class TxnMallTest(BitcoinTestFramework):
|
||||
|
||||
|
||||
@@ -1,23 +1,8 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
#
|
||||
# Exercise the wallet. Ported from wallet.sh.
|
||||
# Does the following:
|
||||
# a) creates 3 nodes, with an empty chain (no blocks).
|
||||
# b) node0 mines a block
|
||||
# c) node1 mines 101 blocks, so now nodes 0 and 1 have 50btc, node2 has none.
|
||||
# d) node0 sends 21 btc to node2, in two transactions (11 btc, then 10 btc).
|
||||
# e) node0 mines a block, collects the fee on the second transaction
|
||||
# f) node1 mines 100 blocks, to mature node0's just-mined block
|
||||
# g) check that node0 has 100-21, node2 has 21
|
||||
# h) node0 should now have 2 unspent outputs; send these to node2 via raw tx broadcast by node1
|
||||
# i) have node1 mine a block
|
||||
# j) check balances - node0 should have 0, node2 should have 100
|
||||
# k) test ResendWalletTransactions - create transactions, startup fourth node, make sure it syncs
|
||||
#
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
@@ -160,7 +145,7 @@ class WalletTest (BitcoinTestFramework):
|
||||
sync_blocks(self.nodes)
|
||||
|
||||
relayed = self.nodes[0].resendwallettransactions()
|
||||
assert_equal(set(relayed), set([txid1, txid2]))
|
||||
assert_equal(set(relayed), {txid1, txid2})
|
||||
sync_mempools(self.nodes)
|
||||
|
||||
assert(txid1 in self.nodes[3].getrawmempool())
|
||||
@@ -190,7 +175,7 @@ class WalletTest (BitcoinTestFramework):
|
||||
for uTx in unspentTxs:
|
||||
if uTx['txid'] == zeroValueTxid:
|
||||
found = True
|
||||
assert_equal(uTx['amount'], Decimal('0.00000000'));
|
||||
assert_equal(uTx['amount'], Decimal('0'))
|
||||
assert(found)
|
||||
|
||||
#do some -walletbroadcast tests
|
||||
@@ -202,21 +187,22 @@ class WalletTest (BitcoinTestFramework):
|
||||
connect_nodes_bi(self.nodes,0,2)
|
||||
self.sync_all()
|
||||
|
||||
txIdNotBroadcasted = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2);
|
||||
txIdNotBroadcasted = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2)
|
||||
txObjNotBroadcasted = self.nodes[0].gettransaction(txIdNotBroadcasted)
|
||||
self.nodes[1].generate(1) #mine a block, tx should not be in there
|
||||
self.sync_all()
|
||||
assert_equal(self.nodes[2].getbalance(), node_2_bal); #should not be changed because tx was not broadcasted
|
||||
assert_equal(self.nodes[2].getbalance(), node_2_bal) #should not be changed because tx was not broadcasted
|
||||
|
||||
#now broadcast from another node, mine a block, sync, and check the balance
|
||||
self.nodes[1].sendrawtransaction(txObjNotBroadcasted['hex'])
|
||||
self.nodes[1].generate(1)
|
||||
self.sync_all()
|
||||
node_2_bal += 2
|
||||
txObjNotBroadcasted = self.nodes[0].gettransaction(txIdNotBroadcasted)
|
||||
assert_equal(self.nodes[2].getbalance(), node_2_bal + Decimal('2')); #should not be
|
||||
assert_equal(self.nodes[2].getbalance(), node_2_bal)
|
||||
|
||||
#create another tx
|
||||
txIdNotBroadcasted = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2);
|
||||
txIdNotBroadcasted = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2)
|
||||
|
||||
#restart the nodes with -walletbroadcast=1
|
||||
stop_nodes(self.nodes)
|
||||
@@ -229,23 +215,24 @@ class WalletTest (BitcoinTestFramework):
|
||||
|
||||
self.nodes[0].generate(1)
|
||||
sync_blocks(self.nodes)
|
||||
node_2_bal += 2
|
||||
|
||||
#tx should be added to balance because after restarting the nodes tx should be broadcastet
|
||||
assert_equal(self.nodes[2].getbalance(), node_2_bal + Decimal('4')); #should not be
|
||||
assert_equal(self.nodes[2].getbalance(), node_2_bal)
|
||||
|
||||
#send a tx with value in a string (PR#6380 +)
|
||||
txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "2")
|
||||
txObj = self.nodes[0].gettransaction(txId)
|
||||
assert_equal(txObj['amount'], Decimal('-2.00000000'))
|
||||
assert_equal(txObj['amount'], Decimal('-2'))
|
||||
|
||||
txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "0.0001")
|
||||
txObj = self.nodes[0].gettransaction(txId)
|
||||
assert_equal(txObj['amount'], Decimal('-0.00010000'))
|
||||
assert_equal(txObj['amount'], Decimal('-0.0001'))
|
||||
|
||||
#check if JSON parser can handle scientific notation in strings
|
||||
txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "1e-4")
|
||||
txObj = self.nodes[0].gettransaction(txId)
|
||||
assert_equal(txObj['amount'], Decimal('-0.00010000'))
|
||||
assert_equal(txObj['amount'], Decimal('-0.0001'))
|
||||
|
||||
#this should fail
|
||||
errorString = ""
|
||||
@@ -254,7 +241,7 @@ class WalletTest (BitcoinTestFramework):
|
||||
except JSONRPCException,e:
|
||||
errorString = e.error['message']
|
||||
|
||||
assert_equal("Invalid amount" in errorString, True);
|
||||
assert_equal("Invalid amount" in errorString, True)
|
||||
|
||||
errorString = ""
|
||||
try:
|
||||
@@ -262,7 +249,30 @@ class WalletTest (BitcoinTestFramework):
|
||||
except JSONRPCException,e:
|
||||
errorString = e.error['message']
|
||||
|
||||
assert_equal("not an integer" in errorString, True);
|
||||
assert_equal("not an integer" in errorString, True)
|
||||
|
||||
#check if wallet or blochchain maintenance changes the balance
|
||||
self.sync_all()
|
||||
self.nodes[0].generate(1)
|
||||
self.sync_all()
|
||||
balance_nodes = [self.nodes[i].getbalance() for i in range(3)]
|
||||
|
||||
maintenance = [
|
||||
'-rescan',
|
||||
'-reindex',
|
||||
'-zapwallettxes=1',
|
||||
'-zapwallettxes=2',
|
||||
'-salvagewallet',
|
||||
]
|
||||
for m in maintenance:
|
||||
stop_nodes(self.nodes)
|
||||
wait_bitcoinds()
|
||||
self.nodes = start_nodes(3, self.options.tmpdir, [[m]] * 3)
|
||||
connect_nodes_bi(self.nodes,0,1)
|
||||
connect_nodes_bi(self.nodes,1,2)
|
||||
connect_nodes_bi(self.nodes,0,2)
|
||||
self.sync_all()
|
||||
assert_equal(balance_nodes, [self.nodes[i].getbalance() for i in range(3)])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-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.
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user