aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml13
-rw-r--r--Makefile.am6
-rw-r--r--README.md6
-rwxr-xr-xautogen.sh2
-rw-r--r--build-aux/m4/bitcoin_qt.m42
-rw-r--r--configure.ac2
-rw-r--r--contrib/README.md7
-rwxr-xr-xcontrib/devtools/github-merge.py20
-rwxr-xr-xcontrib/devtools/security-check.py34
-rwxr-xr-xcontrib/devtools/symbol-check.py63
-rw-r--r--contrib/gitian-descriptors/gitian-linux.yml1
-rw-r--r--contrib/gitian-descriptors/gitian-osx.yml1
-rw-r--r--contrib/gitian-descriptors/gitian-win.yml1
-rwxr-xr-xcontrib/macdeploy/custom_dsstore.py6
-rwxr-xr-xcontrib/macdeploy/macdeployqtplus136
-rw-r--r--contrib/rpm/README.md185
-rw-r--r--contrib/rpm/bitcoin-0.12.0-libressl.patch24
-rw-r--r--contrib/rpm/bitcoin.fc8
-rw-r--r--contrib/rpm/bitcoin.if157
-rw-r--r--contrib/rpm/bitcoin.spec444
-rw-r--r--contrib/rpm/bitcoin.te81
-rw-r--r--contrib/verifysfbinaries/README.md4
-rw-r--r--depends/builders/darwin.mk2
-rw-r--r--depends/builders/linux.mk2
-rwxr-xr-xdepends/config.guess90
-rwxr-xr-xdepends/config.sub12
-rw-r--r--depends/packages/miniupnpc.mk4
-rw-r--r--depends/patches/boost/darwin_boost_atomic-1.patch35
-rw-r--r--depends/patches/boost/darwin_boost_atomic-2.patch55
-rw-r--r--depends/patches/boost/gcc_5_no_cxx11.patch37
-rw-r--r--doc/README.md2
-rw-r--r--doc/bips.md3
-rw-r--r--doc/build-unix.md37
-rw-r--r--doc/gitian-building.md3
-rw-r--r--doc/release-notes.md24
-rw-r--r--doc/release-notes/release-notes-0.10.4.md172
-rw-r--r--doc/release-notes/release-notes-0.11.2.md217
-rw-r--r--doc/release-notes/release-notes-0.12.0.md890
-rw-r--r--doc/release-process.md22
-rw-r--r--doc/shared-libraries.md2
-rw-r--r--doc/tor.md2
-rw-r--r--doc/travis-ci.txt2
-rw-r--r--qa/README.md11
-rwxr-xr-xqa/pull-tester/rpc-tests.py17
-rwxr-xr-xqa/rpc-tests/abandonconflict.py6
-rwxr-xr-xqa/rpc-tests/bip68-112-113-p2p.py547
-rwxr-xr-xqa/rpc-tests/bip68-sequence.py386
-rwxr-xr-xqa/rpc-tests/bip9-softforks.py220
-rwxr-xr-xqa/rpc-tests/blockchain.py2
-rwxr-xr-xqa/rpc-tests/disablewallet.py14
-rwxr-xr-xqa/rpc-tests/fundrawtransaction.py34
-rwxr-xr-xqa/rpc-tests/getblocktemplate_proposals.py10
-rwxr-xr-xqa/rpc-tests/httpbasics.py26
-rwxr-xr-xqa/rpc-tests/importprunedfunds.py140
-rwxr-xr-xqa/rpc-tests/invalidblockrequest.py6
-rwxr-xr-xqa/rpc-tests/invalidtxrequest.py2
-rwxr-xr-xqa/rpc-tests/listtransactions.py4
-rwxr-xr-xqa/rpc-tests/maxuploadtarget.py3
-rwxr-xr-xqa/rpc-tests/mempool_limit.py1
-rwxr-xr-xqa/rpc-tests/mempool_packages.py8
-rwxr-xr-xqa/rpc-tests/mempool_reorg.py18
-rwxr-xr-xqa/rpc-tests/mempool_resurrect_test.py12
-rwxr-xr-xqa/rpc-tests/mempool_spendcoinbase.py10
-rwxr-xr-xqa/rpc-tests/multi_rpc.py2
-rwxr-xr-xqa/rpc-tests/p2p-feefilter.py99
-rwxr-xr-xqa/rpc-tests/p2p-versionbits-warning.py160
-rwxr-xr-xqa/rpc-tests/prioritise_transaction.py33
-rwxr-xr-xqa/rpc-tests/replace-by-fee.py1
-rw-r--r--qa/rpc-tests/test_framework/authproxy.py7
-rw-r--r--qa/rpc-tests/test_framework/blocktools.py2
-rwxr-xr-xqa/rpc-tests/test_framework/comptool.py18
-rwxr-xr-xqa/rpc-tests/test_framework/mininode.py75
-rw-r--r--qa/rpc-tests/test_framework/util.py74
-rwxr-xr-xqa/rpc-tests/wallet.py45
-rwxr-xr-xqa/rpc-tests/zapwallettxes.py10
-rwxr-xr-xshare/qt/extract_strings_qt.py9
-rw-r--r--share/rpcuser/README.md3
-rw-r--r--src/Makefile.am6
-rw-r--r--src/Makefile.qt.include2
-rw-r--r--src/Makefile.test.include9
-rw-r--r--src/alert.cpp266
-rw-r--r--src/alert.h113
-rw-r--r--src/amount.cpp6
-rw-r--r--src/amount.h12
-rw-r--r--src/base58.cpp11
-rw-r--r--src/bitcoin-cli.cpp21
-rw-r--r--src/chain.h2
-rw-r--r--src/chainparams.cpp34
-rw-r--r--src/chainparams.h3
-rw-r--r--src/coincontrol.h5
-rw-r--r--src/consensus/consensus.h5
-rw-r--r--src/consensus/params.h30
-rw-r--r--src/httprpc.cpp7
-rw-r--r--src/init.cpp222
-rw-r--r--src/main.cpp577
-rw-r--r--src/main.h49
-rw-r--r--src/merkleblock.cpp14
-rw-r--r--src/merkleblock.h9
-rw-r--r--src/miner.cpp218
-rw-r--r--src/miner.h5
-rw-r--r--src/net.cpp36
-rw-r--r--src/net.h13
-rw-r--r--src/policy/fees.cpp19
-rw-r--r--src/policy/fees.h13
-rw-r--r--src/policy/policy.cpp2
-rw-r--r--src/policy/policy.h6
-rw-r--r--src/primitives/block.cpp2
-rw-r--r--src/primitives/block.h3
-rw-r--r--src/primitives/transaction.cpp2
-rw-r--r--src/primitives/transaction.h48
-rw-r--r--src/protocol.cpp6
-rw-r--r--src/protocol.h14
-rw-r--r--src/qt/clientmodel.cpp37
-rw-r--r--src/qt/clientmodel.h4
-rw-r--r--src/qt/coincontroldialog.cpp2
-rw-r--r--src/qt/forms/debugwindow.ui103
-rw-r--r--src/qt/forms/sendcoinsdialog.ui55
-rw-r--r--src/qt/res/icons/about.pngbin4726 -> 3717 bytes
-rw-r--r--src/qt/res/icons/chevron.pngbin1923 -> 803 bytes
-rw-r--r--src/qt/rpcconsole.cpp35
-rw-r--r--src/qt/rpcconsole.h4
-rw-r--r--src/qt/sendcoinsdialog.cpp8
-rw-r--r--src/qt/transactiondesc.cpp3
-rw-r--r--src/qt/transactionrecord.cpp7
-rw-r--r--src/qt/transactionrecord.h4
-rw-r--r--src/qt/transactiontablemodel.cpp28
-rw-r--r--src/qt/transactiontablemodel.h2
-rw-r--r--src/qt/transactionview.cpp16
-rw-r--r--src/qt/transactionview.h1
-rw-r--r--src/rest.cpp3
-rw-r--r--src/rpc/blockchain.cpp53
-rw-r--r--src/rpc/client.cpp7
-rw-r--r--src/rpc/mining.cpp185
-rw-r--r--src/rpc/misc.cpp18
-rw-r--r--src/rpc/net.cpp22
-rw-r--r--src/rpc/rawtransaction.cpp28
-rw-r--r--src/rpc/register.h32
-rw-r--r--src/rpc/server.cpp76
-rw-r--r--src/rpc/server.h66
-rw-r--r--src/script/interpreter.cpp91
-rw-r--r--src/script/interpreter.h11
-rw-r--r--src/script/script.h12
-rw-r--r--src/script/script_error.h2
-rw-r--r--src/test/alert_tests.cpp183
-rw-r--r--src/test/amount_tests.cpp42
-rw-r--r--src/test/bctest.py2
-rwxr-xr-xsrc/test/bitcoin-util-test.py2
-rw-r--r--src/test/bloom_tests.cpp23
-rw-r--r--src/test/checkblock_tests.cpp66
-rw-r--r--src/test/data/alertTests.rawbin1279 -> 0 bytes
-rw-r--r--src/test/data/script_invalid.json1055
-rw-r--r--src/test/data/tx_invalid.json54
-rw-r--r--src/test/data/tx_valid.json84
-rw-r--r--src/test/mempool_tests.cpp146
-rw-r--r--src/test/miner_tests.cpp159
-rw-r--r--src/test/pmt_tests.cpp8
-rw-r--r--src/test/rpc_tests.cpp2
-rw-r--r--src/test/script_tests.cpp187
-rw-r--r--src/test/test_bitcoin.cpp12
-rw-r--r--src/test/test_bitcoin.h4
-rw-r--r--src/test/testutil.cpp33
-rw-r--r--src/test/testutil.h15
-rw-r--r--src/test/transaction_tests.cpp3
-rw-r--r--src/test/txvalidationcache_tests.cpp2
-rw-r--r--src/test/util_tests.cpp9
-rw-r--r--src/test/versionbits_tests.cpp316
-rw-r--r--src/timedata.cpp2
-rw-r--r--src/timedata.h2
-rw-r--r--src/torcontrol.cpp23
-rw-r--r--src/txmempool.cpp222
-rw-r--r--src/txmempool.h137
-rw-r--r--src/ui_interface.h5
-rw-r--r--src/uint256.h8
-rw-r--r--src/util.cpp22
-rw-r--r--src/util.h1
-rw-r--r--src/version.h9
-rw-r--r--src/versionbits.cpp133
-rw-r--r--src/versionbits.h59
-rw-r--r--src/wallet/db.cpp28
-rw-r--r--src/wallet/rpcdump.cpp107
-rw-r--r--src/wallet/rpcwallet.cpp39
-rw-r--r--src/wallet/rpcwallet.h4
-rw-r--r--src/wallet/wallet.cpp296
-rw-r--r--src/wallet/wallet.h11
-rw-r--r--src/wallet/walletdb.cpp57
-rw-r--r--src/wallet/walletdb.h3
-rw-r--r--src/zmq/zmqnotificationinterface.cpp1
-rw-r--r--src/zmq/zmqpublishnotifier.cpp1
188 files changed, 8064 insertions, 3049 deletions
diff --git a/.travis.yml b/.travis.yml
index 54ae74fd3c..31b3d6d96e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -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
@@ -11,6 +17,7 @@ env:
global:
- MAKEJOBS=-j3
- RUN_TESTS=false
+ - CHECK_DOC=0
- BOOST_TEST_RANDOM=1$TRAVIS_BUILD_ID
- CCACHE_SIZE=100M
- CCACHE_TEMPDIR=/tmp/.ccache-temp
@@ -29,7 +36,7 @@ matrix:
fast_finish: true
include:
- compiler: ": ARM"
- env: HOST=arm-linux-gnueabihf PACKAGES="g++-arm-linux-gnueabihf" DEP_OPTS="NO_QT=1" GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports"
+ env: HOST=arm-linux-gnueabihf PACKAGES="g++-arm-linux-gnueabihf" DEP_OPTS="NO_QT=1" CHECK_DOC=1 GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports"
- compiler: ": Win32"
env: HOST=i686-w64-mingw32 PPA="ppa:ubuntu-wine/ppa" PACKAGES="nsis gcc-mingw-w64-i686 g++-mingw-w64-i686 binutils-mingw-w64-i686 mingw-w64-dev wine1.7 bc" RUN_TESTS=true GOAL="deploy" BITCOIN_CONFIG="--enable-gui --enable-reduce-exports" MAKEJOBS="-j2"
- compiler: ": 32-bit + dash"
@@ -51,8 +58,9 @@ install:
- if [ -n "$PACKAGES" ]; then travis_retry sudo apt-get install --no-install-recommends --no-upgrade -qq $PACKAGES; fi
before_script:
- unset CC; unset CXX
+ - if [ "$CHECK_DOC" = 1 ]; then contrib/devtools/check-doc.py; fi
- 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:
@@ -64,7 +72,6 @@ script:
- test -n "$USE_SHELL" && eval '"$USE_SHELL" -c "./autogen.sh"' || ./autogen.sh
- ./configure --cache-file=config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false)
- make distdir PACKAGE=bitcoin VERSION=$HOST
- - if [ "$RUN_TESTS" = "true" ]; then contrib/devtools/check-doc.py; fi
- cd bitcoin-$HOST
- ./configure --cache-file=../config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false)
- make $MAKEJOBS $GOAL || ( echo "Build failure. Verbose build follows." && make $GOAL V=1 ; false )
diff --git a/Makefile.am b/Makefile.am
index d6cbd7cb12..0929a59ed2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -110,7 +110,7 @@ osx_volname:
if BUILD_DARWIN
$(OSX_DMG): $(OSX_APP_BUILT) $(OSX_PACKAGING)
- $(OSX_DEPLOY_SCRIPT) $(OSX_APP) -add-qt-tr $(OSX_QT_TRANSLATIONS) -translations-dir=$(QT_TRANSLATION_DIR) -dmg -fancy $(OSX_FANCY_PLIST) -verbose 2 -volname $(OSX_VOLNAME)
+ $(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) -add-qt-tr $(OSX_QT_TRANSLATIONS) -translations-dir=$(QT_TRANSLATION_DIR) -dmg -fancy $(OSX_FANCY_PLIST) -verbose 2 -volname $(OSX_VOLNAME)
deploydir: $(OSX_DMG)
else
@@ -134,10 +134,10 @@ $(APP_DIST_DIR)/.background/$(OSX_BACKGROUND_IMAGE): $(OSX_BACKGROUND_IMAGE_DPIF
$(TIFFCP) -c none $(OSX_BACKGROUND_IMAGE_DPIFILES) $@
$(APP_DIST_DIR)/.DS_Store: $(OSX_DSSTORE_GEN)
- $< "$@" "$(OSX_VOLNAME)"
+ $(PYTHON) $< "$@" "$(OSX_VOLNAME)"
$(APP_DIST_DIR)/$(OSX_APP)/Contents/MacOS/Bitcoin-Qt: $(OSX_APP_BUILT) $(OSX_PACKAGING)
- INSTALLNAMETOOL=$(INSTALLNAMETOOL) OTOOL=$(OTOOL) STRIP=$(STRIP) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) -translations-dir=$(QT_TRANSLATION_DIR) -add-qt-tr $(OSX_QT_TRANSLATIONS) -verbose 2
+ INSTALLNAMETOOL=$(INSTALLNAMETOOL) OTOOL=$(OTOOL) STRIP=$(STRIP) $(PYTHON) $(OSX_DEPLOY_SCRIPT) $(OSX_APP) -translations-dir=$(QT_TRANSLATION_DIR) -add-qt-tr $(OSX_QT_TRANSLATIONS) -verbose 2
deploydir: $(APP_DIST_EXTRAS)
endif
diff --git a/README.md b/README.md
index b568978f05..85b1985560 100644
--- a/README.md
+++ b/README.md
@@ -15,7 +15,7 @@ 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, or read the
+the Bitcoin Core software, see https://bitcoin.org/en/download, or read the
[original whitepaper](https://bitcoincore.org/bitcoin.pdf).
License
@@ -55,10 +55,10 @@ submit new unit tests for old code. Unit tests can be compiled and run
There are also [regression and integration tests](/qa) of the RPC interface, written
in Python, that are run automatically on the build server.
-These tests can be run with: `qa/pull-tester/rpc-tests.py`
+These tests can be run (if the [test dependencies](/qa) are installed) with: `qa/pull-tester/rpc-tests.py`
The Travis CI system makes sure that every pull request is built for Windows
-and Linux, OSX, and that unit and sanity tests are automatically run.
+and Linux, OS X, and that unit and sanity tests are automatically run.
### Manual Quality Assurance (QA) Testing
diff --git a/autogen.sh b/autogen.sh
index 3e26a18305..46e36ff5b2 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -6,4 +6,6 @@ if [ -z ${LIBTOOLIZE} ] && GLIBTOOLIZE="`which glibtoolize 2>/dev/null`"; then
LIBTOOLIZE="${GLIBTOOLIZE}"
export LIBTOOLIZE
fi
+which autoreconf >/dev/null || \
+ (echo "configuration failed, please install autoconf first" && exit 1)
autoreconf --install --force --warnings=all
diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4
index 5fe12fda9b..efffa4887d 100644
--- a/build-aux/m4/bitcoin_qt.m4
+++ b/build-aux/m4/bitcoin_qt.m4
@@ -384,7 +384,7 @@ AC_DEFUN([_BITCOIN_QT_FIND_LIBS_WITH_PKGCONFIG],[
dnl qt version is set to 'auto' and the preferred version wasn't found. Now try the other.
if test x$have_qt = xno && test x$bitcoin_qt_want_version = xauto; then
- if test x$auto_priority_version = x$qt5; then
+ if test x$auto_priority_version = xqt5; then
PKG_CHECK_MODULES([QT], [$qt4_modules], [QT_INCLUDES="$QT_CFLAGS"; have_qt=yes; QT_LIB_PREFIX=Qt; bitcoin_qt_got_major_vers=4], [have_qt=no])
else
PKG_CHECK_MODULES([QT], [$qt5_modules], [QT_INCLUDES="$QT_CFLAGS"; have_qt=yes; QT_LIB_PREFIX=Qt5; bitcoin_qt_got_major_vers=5], [have_qt=no])
diff --git a/configure.ac b/configure.ac
index bd30b6ab87..1e894f5767 100644
--- a/configure.ac
+++ b/configure.ac
@@ -60,7 +60,7 @@ AC_PATH_TOOL(STRIP, strip)
AC_PATH_TOOL(GCOV, gcov)
AC_PATH_PROG(LCOV, lcov)
AC_PATH_PROG(JAVA, java)
-AC_PATH_PROG(PYTHON, python)
+AC_PATH_PROGS([PYTHON], [python3 python2.7 python2 python])
AC_PATH_PROG(GENHTML, genhtml)
AC_PATH_PROG([GIT], [git])
AC_PATH_PROG(CCACHE,ccache)
diff --git a/contrib/README.md b/contrib/README.md
index b6e572102a..9461539166 100644
--- a/contrib/README.md
+++ b/contrib/README.md
@@ -42,15 +42,14 @@ Various PGP files of core developers.
### [MacDeploy](/contrib/macdeploy) ###
Scripts and notes for Mac builds.
+### [RPM](/contrib/rpm) ###
+RPM spec file for building bitcoin-core on RPM based distributions
+
Test and Verify Tools
---------------------
### [TestGen](/contrib/testgen) ###
Utilities to generate test vectors for the data-driven Bitcoin tests.
-### [Test Patches](/contrib/test-patches) ###
-These patches are applied when the automated pull-tester
-tests each pull and when master is tested using jenkins.
-
### [Verify SF Binaries](/contrib/verifysfbinaries) ###
This script attempts to download and verify the signature file SHA256SUMS.asc from SourceForge.
diff --git a/contrib/devtools/github-merge.py b/contrib/devtools/github-merge.py
index c8dcaae268..9a62fccbbb 100755
--- a/contrib/devtools/github-merge.py
+++ b/contrib/devtools/github-merge.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
# Copyright (c) 2016 Bitcoin Core Developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -19,6 +19,11 @@ import os,sys
from sys import stdin,stdout,stderr
import argparse
import subprocess
+import json,codecs
+try:
+ from urllib.request import Request,urlopen
+except:
+ from urllib2 import Request,urlopen
# External tools (can be overridden using environment)
GIT = os.getenv('GIT','git')
@@ -38,7 +43,7 @@ def git_config_get(option, default=None):
Get named configuration option from git repository.
'''
try:
- return subprocess.check_output([GIT,'config','--get',option]).rstrip()
+ return subprocess.check_output([GIT,'config','--get',option]).rstrip().decode('utf-8')
except subprocess.CalledProcessError as e:
return default
@@ -47,18 +52,19 @@ def retrieve_pr_title(repo,pull):
Retrieve pull request title from github.
Return None if no title can be found, or an error happens.
'''
- import urllib2,json
try:
- req = urllib2.Request("https://api.github.com/repos/"+repo+"/pulls/"+pull)
- result = urllib2.urlopen(req)
- result = json.load(result)
- return result['title']
+ req = Request("https://api.github.com/repos/"+repo+"/pulls/"+pull)
+ result = urlopen(req)
+ reader = codecs.getreader('utf-8')
+ obj = json.load(reader(result))
+ return obj['title']
except Exception as e:
print('Warning: unable to retrieve pull title from github: %s' % e)
return None
def ask_prompt(text):
print(text,end=" ",file=stderr)
+ stderr.flush()
reply = stdin.readline().rstrip()
print("",file=stderr)
return reply
diff --git a/contrib/devtools/security-check.py b/contrib/devtools/security-check.py
index 0319f739c4..301fea85c1 100755
--- a/contrib/devtools/security-check.py
+++ b/contrib/devtools/security-check.py
@@ -5,7 +5,7 @@ Exit status will be 0 if successful, and the program will be silent.
Otherwise the exit status will be 1 and it will log which executables failed which checks.
Needs `readelf` (for ELF) and `objdump` (for PE).
'''
-from __future__ import division,print_function
+from __future__ import division,print_function,unicode_literals
import subprocess
import sys
import os
@@ -23,9 +23,9 @@ def check_ELF_PIE(executable):
raise IOError('Error opening file')
ok = False
- for line in stdout.split('\n'):
+ for line in stdout.split(b'\n'):
line = line.split()
- if len(line)>=2 and line[0] == 'Type:' and line[1] == 'DYN':
+ if len(line)>=2 and line[0] == b'Type:' and line[1] == b'DYN':
ok = True
return ok
@@ -38,17 +38,17 @@ def get_ELF_program_headers(executable):
in_headers = False
count = 0
headers = []
- for line in stdout.split('\n'):
- if line.startswith('Program Headers:'):
+ for line in stdout.split(b'\n'):
+ if line.startswith(b'Program Headers:'):
in_headers = True
- if line == '':
+ if line == b'':
in_headers = False
if in_headers:
if count == 1: # header line
- ofs_typ = line.find('Type')
- ofs_offset = line.find('Offset')
- ofs_flags = line.find('Flg')
- ofs_align = line.find('Align')
+ ofs_typ = line.find(b'Type')
+ ofs_offset = line.find(b'Offset')
+ ofs_flags = line.find(b'Flg')
+ ofs_align = line.find(b'Align')
if ofs_typ == -1 or ofs_offset == -1 or ofs_flags == -1 or ofs_align == -1:
raise ValueError('Cannot parse elfread -lW output')
elif count > 1:
@@ -65,9 +65,9 @@ def check_ELF_NX(executable):
have_wx = False
have_gnu_stack = False
for (typ, flags) in get_ELF_program_headers(executable):
- if typ == 'GNU_STACK':
+ if typ == b'GNU_STACK':
have_gnu_stack = True
- if 'W' in flags and 'E' in flags: # section is both writable and executable
+ if b'W' in flags and b'E' in flags: # section is both writable and executable
have_wx = True
return have_gnu_stack and not have_wx
@@ -84,7 +84,7 @@ def check_ELF_RELRO(executable):
# However, the dynamic linker need to write to this area so these are RW.
# Glibc itself takes care of mprotecting this area R after relocations are finished.
# See also http://permalink.gmane.org/gmane.comp.gnu.binutils/71347
- if typ == 'GNU_RELRO':
+ if typ == b'GNU_RELRO':
have_gnu_relro = True
have_bindnow = False
@@ -92,9 +92,9 @@ def check_ELF_RELRO(executable):
(stdout, stderr) = p.communicate()
if p.returncode:
raise IOError('Error opening file')
- for line in stdout.split('\n'):
+ for line in stdout.split(b'\n'):
tokens = line.split()
- if len(tokens)>1 and tokens[1] == '(BIND_NOW)' or (len(tokens)>2 and tokens[1] == '(FLAGS)' and 'BIND_NOW' in tokens[2]):
+ if len(tokens)>1 and tokens[1] == b'(BIND_NOW)' or (len(tokens)>2 and tokens[1] == b'(FLAGS)' and b'BIND_NOW' in tokens[2]):
have_bindnow = True
return have_gnu_relro and have_bindnow
@@ -107,8 +107,8 @@ def check_ELF_Canary(executable):
if p.returncode:
raise IOError('Error opening file')
ok = False
- for line in stdout.split('\n'):
- if '__stack_chk_fail' in line:
+ for line in stdout.split(b'\n'):
+ if b'__stack_chk_fail' in line:
ok = True
return ok
diff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py
index 4ad5136f79..e26c0fbb94 100755
--- a/contrib/devtools/symbol-check.py
+++ b/contrib/devtools/symbol-check.py
@@ -11,7 +11,7 @@ Example usage:
find ../gitian-builder/build -type f -executable | xargs python contrib/devtools/symbol-check.py
'''
-from __future__ import division, print_function
+from __future__ import division, print_function, unicode_literals
import subprocess
import re
import sys
@@ -47,28 +47,28 @@ MAX_VERSIONS = {
# Ignore symbols that are exported as part of every executable
IGNORE_EXPORTS = {
-'_edata', '_end', '_init', '__bss_start', '_fini', '_IO_stdin_used'
+b'_edata', b'_end', b'_init', b'__bss_start', b'_fini', b'_IO_stdin_used'
}
READELF_CMD = os.getenv('READELF', '/usr/bin/readelf')
CPPFILT_CMD = os.getenv('CPPFILT', '/usr/bin/c++filt')
# Allowed NEEDED libraries
ALLOWED_LIBRARIES = {
# bitcoind and bitcoin-qt
-'libgcc_s.so.1', # GCC base support
-'libc.so.6', # C library
-'libpthread.so.0', # threading
-'libanl.so.1', # DNS resolve
-'libm.so.6', # math library
-'librt.so.1', # real-time (clock)
-'ld-linux-x86-64.so.2', # 64-bit dynamic linker
-'ld-linux.so.2', # 32-bit dynamic linker
+b'libgcc_s.so.1', # GCC base support
+b'libc.so.6', # C library
+b'libpthread.so.0', # threading
+b'libanl.so.1', # DNS resolve
+b'libm.so.6', # math library
+b'librt.so.1', # real-time (clock)
+b'ld-linux-x86-64.so.2', # 64-bit dynamic linker
+b'ld-linux.so.2', # 32-bit dynamic linker
# bitcoin-qt only
-'libX11-xcb.so.1', # part of X11
-'libX11.so.6', # part of X11
-'libxcb.so.1', # part of X11
-'libfontconfig.so.1', # font support
-'libfreetype.so.6', # font parsing
-'libdl.so.2' # programming interface to dynamic linker
+b'libX11-xcb.so.1', # part of X11
+b'libX11.so.6', # part of X11
+b'libxcb.so.1', # part of X11
+b'libfontconfig.so.1', # font support
+b'libfreetype.so.6', # font parsing
+b'libdl.so.2' # programming interface to dynamic linker
}
class CPPFilt(object):
@@ -81,7 +81,8 @@ class CPPFilt(object):
self.proc = subprocess.Popen(CPPFILT_CMD, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
def __call__(self, mangled):
- self.proc.stdin.write(mangled + '\n')
+ self.proc.stdin.write(mangled + b'\n')
+ self.proc.stdin.flush()
return self.proc.stdout.readline().rstrip()
def close(self):
@@ -99,24 +100,24 @@ def read_symbols(executable, imports=True):
if p.returncode:
raise IOError('Could not read symbols for %s: %s' % (executable, stderr.strip()))
syms = []
- for line in stdout.split('\n'):
+ for line in stdout.split(b'\n'):
line = line.split()
- if len(line)>7 and re.match('[0-9]+:$', line[0]):
- (sym, _, version) = line[7].partition('@')
- is_import = line[6] == 'UND'
- if version.startswith('@'):
+ if len(line)>7 and re.match(b'[0-9]+:$', line[0]):
+ (sym, _, version) = line[7].partition(b'@')
+ is_import = line[6] == b'UND'
+ if version.startswith(b'@'):
version = version[1:]
if is_import == imports:
syms.append((sym, version))
return syms
def check_version(max_versions, version):
- if '_' in version:
- (lib, _, ver) = version.rpartition('_')
+ if b'_' in version:
+ (lib, _, ver) = version.rpartition(b'_')
else:
lib = version
ver = '0'
- ver = tuple([int(x) for x in ver.split('.')])
+ ver = tuple([int(x) for x in ver.split(b'.')])
if not lib in max_versions:
return False
return ver <= max_versions[lib]
@@ -127,10 +128,10 @@ def read_libraries(filename):
if p.returncode:
raise IOError('Error opening file')
libraries = []
- for line in stdout.split('\n'):
+ for line in stdout.split(b'\n'):
tokens = line.split()
- if len(tokens)>2 and tokens[1] == '(NEEDED)':
- match = re.match('^Shared library: \[(.*)\]$', ' '.join(tokens[2:]))
+ if len(tokens)>2 and tokens[1] == b'(NEEDED)':
+ match = re.match(b'^Shared library: \[(.*)\]$', b' '.join(tokens[2:]))
if match:
libraries.append(match.group(1))
else:
@@ -144,18 +145,18 @@ if __name__ == '__main__':
# Check imported symbols
for sym,version in read_symbols(filename, True):
if version and not check_version(MAX_VERSIONS, version):
- print('%s: symbol %s from unsupported version %s' % (filename, cppfilt(sym), version))
+ print('%s: symbol %s from unsupported version %s' % (filename, cppfilt(sym).decode('utf-8'), version.decode('utf-8')))
retval = 1
# Check exported symbols
for sym,version in read_symbols(filename, False):
if sym in IGNORE_EXPORTS:
continue
- print('%s: export of symbol %s not allowed' % (filename, cppfilt(sym)))
+ print('%s: export of symbol %s not allowed' % (filename, cppfilt(sym).decode('utf-8')))
retval = 1
# Check dependency libraries
for library_name in read_libraries(filename):
if library_name not in ALLOWED_LIBRARIES:
- print('%s: NEEDED library %s is not allowed' % (filename, library_name))
+ print('%s: NEEDED library %s is not allowed' % (filename, library_name.decode('utf-8')))
retval = 1
exit(retval)
diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml
index b4b6ed2909..1f2c4f9999 100644
--- a/contrib/gitian-descriptors/gitian-linux.yml
+++ b/contrib/gitian-descriptors/gitian-linux.yml
@@ -6,6 +6,7 @@ suites:
architectures:
- "amd64"
packages:
+- "curl"
- "g++-multilib"
- "git-core"
- "pkg-config"
diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml
index 4a4592398b..6f68ae08ce 100644
--- a/contrib/gitian-descriptors/gitian-osx.yml
+++ b/contrib/gitian-descriptors/gitian-osx.yml
@@ -7,6 +7,7 @@ architectures:
- "amd64"
packages:
- "ca-certificates"
+- "curl"
- "g++"
- "git-core"
- "pkg-config"
diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml
index 233f5c5498..f0fbff3e10 100644
--- a/contrib/gitian-descriptors/gitian-win.yml
+++ b/contrib/gitian-descriptors/gitian-win.yml
@@ -6,6 +6,7 @@ suites:
architectures:
- "amd64"
packages:
+- "curl"
- "g++"
- "git-core"
- "pkg-config"
diff --git a/contrib/macdeploy/custom_dsstore.py b/contrib/macdeploy/custom_dsstore.py
index 8481e903a0..03e2325fc0 100755
--- a/contrib/macdeploy/custom_dsstore.py
+++ b/contrib/macdeploy/custom_dsstore.py
@@ -2,7 +2,7 @@
# Copyright (c) 2013-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 __future__ import division,print_function,unicode_literals
import biplist
from ds_store import DSStore
from mac_alias import Alias
@@ -14,7 +14,7 @@ package_name_ns = sys.argv[2]
ds = DSStore.open(output_file, 'w+')
ds['.']['bwsp'] = {
'ShowStatusBar': False,
- 'WindowBounds': '{{300, 280}, {500, 343}}',
+ 'WindowBounds': b'{{300, 280}, {500, 343}}',
'ContainerShowSidebar': False,
'SidebarWidth': 0,
'ShowTabView': False,
@@ -28,7 +28,7 @@ icvp = {
'gridOffsetX': 0.0,
'textSize': 12.0,
'viewOptionsVersion': 1,
- 'backgroundImageAlias': '\x00\x00\x00\x00\x02\x1e\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd1\x94\\\xb0H+\x00\x05\x00\x00\x00\x98\x0fbackground.tiff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x99\xd19\xb0\xf8\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\r\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b.background\x00\x00\x10\x00\x08\x00\x00\xd1\x94\\\xb0\x00\x00\x00\x11\x00\x08\x00\x00\xd19\xb0\xf8\x00\x00\x00\x01\x00\x04\x00\x00\x00\x98\x00\x0e\x00 \x00\x0f\x00b\x00a\x00c\x00k\x00g\x00r\x00o\x00u\x00n\x00d\x00.\x00t\x00i\x00f\x00f\x00\x0f\x00\x02\x00\x00\x00\x12\x00\x1c/.background/background.tiff\x00\x14\x01\x06\x00\x00\x00\x00\x01\x06\x00\x02\x00\x00\x0cMacintosh HD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xce\x97\xab\xc3H+\x00\x00\x01\x88[\x88\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02u\xab\x8d\xd1\x94\\\xb0devrddsk\xff\xff\xff\xff\x00\x00\t \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07bitcoin\x00\x00\x10\x00\x08\x00\x00\xce\x97\xab\xc3\x00\x00\x00\x11\x00\x08\x00\x00\xd1\x94\\\xb0\x00\x00\x00\x01\x00\x14\x01\x88[\x88\x00\x16\xa9\t\x00\x08\xfaR\x00\x08\xfaQ\x00\x02d\x8e\x00\x0e\x00\x02\x00\x00\x00\x0f\x00\x1a\x00\x0c\x00M\x00a\x00c\x00i\x00n\x00t\x00o\x00s\x00h\x00 \x00H\x00D\x00\x13\x00\x01/\x00\x00\x15\x00\x02\x00\x14\xff\xff\x00\x00\xff\xff\x00\x00',
+ 'backgroundImageAlias': b'\x00\x00\x00\x00\x02\x1e\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd1\x94\\\xb0H+\x00\x05\x00\x00\x00\x98\x0fbackground.tiff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x99\xd19\xb0\xf8\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\r\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b.background\x00\x00\x10\x00\x08\x00\x00\xd1\x94\\\xb0\x00\x00\x00\x11\x00\x08\x00\x00\xd19\xb0\xf8\x00\x00\x00\x01\x00\x04\x00\x00\x00\x98\x00\x0e\x00 \x00\x0f\x00b\x00a\x00c\x00k\x00g\x00r\x00o\x00u\x00n\x00d\x00.\x00t\x00i\x00f\x00f\x00\x0f\x00\x02\x00\x00\x00\x12\x00\x1c/.background/background.tiff\x00\x14\x01\x06\x00\x00\x00\x00\x01\x06\x00\x02\x00\x00\x0cMacintosh HD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xce\x97\xab\xc3H+\x00\x00\x01\x88[\x88\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02u\xab\x8d\xd1\x94\\\xb0devrddsk\xff\xff\xff\xff\x00\x00\t \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07bitcoin\x00\x00\x10\x00\x08\x00\x00\xce\x97\xab\xc3\x00\x00\x00\x11\x00\x08\x00\x00\xd1\x94\\\xb0\x00\x00\x00\x01\x00\x14\x01\x88[\x88\x00\x16\xa9\t\x00\x08\xfaR\x00\x08\xfaQ\x00\x02d\x8e\x00\x0e\x00\x02\x00\x00\x00\x0f\x00\x1a\x00\x0c\x00M\x00a\x00c\x00i\x00n\x00t\x00o\x00s\x00h\x00 \x00H\x00D\x00\x13\x00\x01/\x00\x00\x15\x00\x02\x00\x14\xff\xff\x00\x00\xff\xff\x00\x00',
'backgroundColorBlue': 1.0,
'iconSize': 96.0,
'backgroundColorGreen': 1.0,
diff --git a/contrib/macdeploy/macdeployqtplus b/contrib/macdeploy/macdeployqtplus
index 7e6270c743..685ed8e5b8 100755
--- a/contrib/macdeploy/macdeployqtplus
+++ b/contrib/macdeploy/macdeployqtplus
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-
+from __future__ import division, print_function, unicode_literals
#
# Copyright (C) 2011 Patrick "p2k" Schneider <me@p2k-network.org>
#
@@ -201,7 +201,7 @@ class DeploymentInfo(object):
def getFrameworks(binaryPath, verbose):
if verbose >= 3:
- print "Inspecting with otool: " + binaryPath
+ print("Inspecting with otool: " + binaryPath)
otoolbin=os.getenv("OTOOL", "otool")
otool = subprocess.Popen([otoolbin, "-L", binaryPath], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
o_stdout, o_stderr = otool.communicate()
@@ -222,8 +222,8 @@ def getFrameworks(binaryPath, verbose):
info = FrameworkInfo.fromOtoolLibraryLine(line.strip())
if info is not None:
if verbose >= 3:
- print "Found framework:"
- print info
+ print("Found framework:")
+ print(info)
libraries.append(info)
return libraries
@@ -234,24 +234,24 @@ def runInstallNameTool(action, *args):
def changeInstallName(oldName, newName, binaryPath, verbose):
if verbose >= 3:
- print "Using install_name_tool:"
- print " in", binaryPath
- print " change reference", oldName
- print " to", newName
+ print("Using install_name_tool:")
+ print(" in", binaryPath)
+ print(" change reference", oldName)
+ print(" to", newName)
runInstallNameTool("change", oldName, newName, binaryPath)
def changeIdentification(id, binaryPath, verbose):
if verbose >= 3:
- print "Using install_name_tool:"
- print " change identification in", binaryPath
- print " to", id
+ print("Using install_name_tool:")
+ print(" change identification in", binaryPath)
+ print(" to", id)
runInstallNameTool("id", id, binaryPath)
def runStrip(binaryPath, verbose):
stripbin=os.getenv("STRIP", "strip")
if verbose >= 3:
- print "Using strip:"
- print " stripped", binaryPath
+ print("Using strip:")
+ print(" stripped", binaryPath)
subprocess.check_call([stripbin, "-x", binaryPath])
def copyFramework(framework, path, verbose):
@@ -274,8 +274,8 @@ def copyFramework(framework, path, verbose):
shutil.copy2(fromPath, toPath)
if verbose >= 3:
- print "Copied:", fromPath
- print " to:", toPath
+ print("Copied:", fromPath)
+ print(" to:", toPath)
permissions = os.stat(toPath)
if not permissions.st_mode & stat.S_IWRITE:
@@ -288,14 +288,14 @@ def copyFramework(framework, path, verbose):
if not os.path.exists(linkfrom):
os.symlink(linkto, linkfrom)
if verbose >= 2:
- print "Linked:", linkfrom, "->", linkto
+ print("Linked:", linkfrom, "->", linkto)
fromResourcesDir = framework.sourceResourcesDirectory
if os.path.exists(fromResourcesDir):
toResourcesDir = os.path.join(path, framework.destinationResourcesDirectory)
shutil.copytree(fromResourcesDir, toResourcesDir, symlinks=True)
if verbose >= 3:
- print "Copied resources:", fromResourcesDir
- print " to:", toResourcesDir
+ print("Copied resources:", fromResourcesDir)
+ print(" to:", toResourcesDir)
fromContentsDir = framework.sourceVersionContentsDirectory
if not os.path.exists(fromContentsDir):
fromContentsDir = framework.sourceContentsDirectory
@@ -304,16 +304,16 @@ def copyFramework(framework, path, verbose):
shutil.copytree(fromContentsDir, toContentsDir, symlinks=True)
contentslinkfrom = os.path.join(path, framework.destinationContentsDirectory)
if verbose >= 3:
- print "Copied Contents:", fromContentsDir
- print " to:", toContentsDir
+ print("Copied Contents:", fromContentsDir)
+ print(" to:", toContentsDir)
elif framework.frameworkName.startswith("libQtGui"): # Copy qt_menu.nib (applies to non-framework layout)
qtMenuNibSourcePath = os.path.join(framework.frameworkDirectory, "Resources", "qt_menu.nib")
qtMenuNibDestinationPath = os.path.join(path, "Contents", "Resources", "qt_menu.nib")
if os.path.exists(qtMenuNibSourcePath) and not os.path.exists(qtMenuNibDestinationPath):
shutil.copytree(qtMenuNibSourcePath, qtMenuNibDestinationPath, symlinks=True)
if verbose >= 3:
- print "Copied for libQtGui:", qtMenuNibSourcePath
- print " to:", qtMenuNibDestinationPath
+ print("Copied for libQtGui:", qtMenuNibSourcePath)
+ print(" to:", qtMenuNibDestinationPath)
return toPath
@@ -326,7 +326,7 @@ def deployFrameworks(frameworks, bundlePath, binaryPath, strip, verbose, deploym
deploymentInfo.deployedFrameworks.append(framework.frameworkName)
if verbose >= 2:
- print "Processing", framework.frameworkName, "..."
+ print("Processing", framework.frameworkName, "...")
# Get the Qt path from one of the Qt frameworks
if deploymentInfo.qtPath is None and framework.isQtFramework():
@@ -334,7 +334,7 @@ def deployFrameworks(frameworks, bundlePath, binaryPath, strip, verbose, deploym
if framework.installName.startswith("@executable_path") or framework.installName.startswith(bundlePath):
if verbose >= 2:
- print framework.frameworkName, "already deployed, skipping."
+ print(framework.frameworkName, "already deployed, skipping.")
continue
# install_name_tool the new id into the binary
@@ -366,7 +366,7 @@ def deployFrameworks(frameworks, bundlePath, binaryPath, strip, verbose, deploym
def deployFrameworksForAppBundle(applicationBundle, strip, verbose):
frameworks = getFrameworks(applicationBundle.binaryPath, verbose)
if len(frameworks) == 0 and verbose >= 1:
- print "Warning: Could not find any external frameworks to deploy in %s." % (applicationBundle.path)
+ print("Warning: Could not find any external frameworks to deploy in %s." % (applicationBundle.path))
return DeploymentInfo()
else:
return deployFrameworks(frameworks, applicationBundle.path, applicationBundle.binaryPath, strip, verbose)
@@ -444,7 +444,7 @@ def deployPlugins(appBundleInfo, deploymentInfo, strip, verbose):
for pluginDirectory, pluginName in plugins:
if verbose >= 2:
- print "Processing plugin", os.path.join(pluginDirectory, pluginName), "..."
+ print("Processing plugin", os.path.join(pluginDirectory, pluginName), "...")
sourcePath = os.path.join(deploymentInfo.pluginPath, pluginDirectory, pluginName)
destinationDirectory = os.path.join(appBundleInfo.pluginPath, pluginDirectory)
@@ -454,8 +454,8 @@ def deployPlugins(appBundleInfo, deploymentInfo, strip, verbose):
destinationPath = os.path.join(destinationDirectory, pluginName)
shutil.copy2(sourcePath, destinationPath)
if verbose >= 3:
- print "Copied:", sourcePath
- print " to:", destinationPath
+ print("Copied:", sourcePath)
+ print(" to:", destinationPath)
if strip:
runStrip(destinationPath, verbose)
@@ -525,7 +525,7 @@ if config.translations_dir and config.translations_dir[0]:
for p in config.add_resources:
if verbose >= 3:
- print "Checking for \"%s\"..." % p
+ print("Checking for \"%s\"..." % p)
if not os.path.exists(p):
if verbose >= 1:
sys.stderr.write("Error: Could not find additional resource file \"%s\"\n" % (p))
@@ -535,7 +535,7 @@ for p in config.add_resources:
if len(config.fancy) == 1:
if verbose >= 3:
- print "Fancy: Importing plistlib..."
+ print("Fancy: Importing plistlib...")
try:
import plistlib
except ImportError:
@@ -545,7 +545,7 @@ if len(config.fancy) == 1:
p = config.fancy[0]
if verbose >= 3:
- print "Fancy: Loading \"%s\"..." % p
+ print("Fancy: Loading \"%s\"..." % p)
if not os.path.exists(p):
if verbose >= 1:
sys.stderr.write("Error: Could not find fancy disk image plist at \"%s\"\n" % (p))
@@ -559,23 +559,23 @@ if len(config.fancy) == 1:
sys.exit(1)
try:
- assert not fancy.has_key("window_bounds") or (isinstance(fancy["window_bounds"], list) and len(fancy["window_bounds"]) == 4)
- assert not fancy.has_key("background_picture") or isinstance(fancy["background_picture"], str)
- assert not fancy.has_key("icon_size") or isinstance(fancy["icon_size"], int)
- assert not fancy.has_key("applications_symlink") or isinstance(fancy["applications_symlink"], bool)
- if fancy.has_key("items_position"):
+ assert "window_bounds" not in fancy or (isinstance(fancy["window_bounds"], list) and len(fancy["window_bounds"]) == 4)
+ assert "background_picture" not in fancy or isinstance(fancy["background_picture"], str)
+ assert "icon_size" not in fancy or isinstance(fancy["icon_size"], int)
+ assert "applications_symlink" not in fancy or isinstance(fancy["applications_symlink"], bool)
+ if "items_position" in fancy:
assert isinstance(fancy["items_position"], dict)
- for key, value in fancy["items_position"].iteritems():
+ for key, value in fancy["items_position"].items():
assert isinstance(value, list) and len(value) == 2 and isinstance(value[0], int) and isinstance(value[1], int)
except:
if verbose >= 1:
sys.stderr.write("Error: Bad format of fancy disk image plist at \"%s\"\n" % (p))
sys.exit(1)
- if fancy.has_key("background_picture"):
+ if "background_picture" in fancy:
bp = fancy["background_picture"]
if verbose >= 3:
- print "Fancy: Resolving background picture \"%s\"..." % bp
+ print("Fancy: Resolving background picture \"%s\"..." % bp)
if not os.path.exists(bp):
bp = os.path.join(os.path.dirname(p), bp)
if not os.path.exists(bp):
@@ -591,7 +591,7 @@ else:
if os.path.exists("dist"):
if verbose >= 2:
- print "+ Removing old dist folder +"
+ print("+ Removing old dist folder +")
shutil.rmtree("dist")
@@ -607,9 +607,9 @@ else:
target = os.path.join("dist", "Bitcoin-Qt.app")
if verbose >= 2:
- print "+ Copying source bundle +"
+ print("+ Copying source bundle +")
if verbose >= 3:
- print app_bundle, "->", target
+ print(app_bundle, "->", target)
os.mkdir("dist")
shutil.copytree(app_bundle, target, symlinks=True)
@@ -619,7 +619,7 @@ applicationBundle = ApplicationBundleInfo(target)
# ------------------------------------------------
if verbose >= 2:
- print "+ Deploying frameworks +"
+ print("+ Deploying frameworks +")
try:
deploymentInfo = deployFrameworksForAppBundle(applicationBundle, config.strip, verbose)
@@ -638,7 +638,7 @@ except RuntimeError as e:
if config.plugins:
if verbose >= 2:
- print "+ Deploying plugins +"
+ print("+ Deploying plugins +")
try:
deployPlugins(applicationBundle, deploymentInfo, config.strip, verbose)
@@ -664,7 +664,7 @@ else:
for lng_file in add_qt_tr:
p = os.path.join(qt_tr_dir, lng_file)
if verbose >= 3:
- print "Checking for \"%s\"..." % p
+ print("Checking for \"%s\"..." % p)
if not os.path.exists(p):
if verbose >= 1:
sys.stderr.write("Error: Could not find Qt translation file \"%s\"\n" % (lng_file))
@@ -673,7 +673,7 @@ else:
# ------------------------------------------------
if verbose >= 2:
- print "+ Installing qt.conf +"
+ print("+ Installing qt.conf +")
f = open(os.path.join(applicationBundle.resourcesPath, "qt.conf"), "wb")
f.write(qt_conf)
@@ -682,22 +682,22 @@ f.close()
# ------------------------------------------------
if len(add_qt_tr) > 0 and verbose >= 2:
- print "+ Adding Qt translations +"
+ print("+ Adding Qt translations +")
for lng_file in add_qt_tr:
if verbose >= 3:
- print os.path.join(qt_tr_dir, lng_file), "->", os.path.join(applicationBundle.resourcesPath, lng_file)
+ print(os.path.join(qt_tr_dir, lng_file), "->", os.path.join(applicationBundle.resourcesPath, lng_file))
shutil.copy2(os.path.join(qt_tr_dir, lng_file), os.path.join(applicationBundle.resourcesPath, lng_file))
# ------------------------------------------------
if len(config.add_resources) > 0 and verbose >= 2:
- print "+ Adding additional resources +"
+ print("+ Adding additional resources +")
for p in config.add_resources:
t = os.path.join(applicationBundle.resourcesPath, os.path.basename(p))
if verbose >= 3:
- print p, "->", t
+ print(p, "->", t)
if os.path.isdir(p):
shutil.copytree(p, t, symlinks=True)
else:
@@ -706,10 +706,10 @@ for p in config.add_resources:
# ------------------------------------------------
if config.sign and 'CODESIGNARGS' not in os.environ:
- print "You must set the CODESIGNARGS environment variable. Skipping signing."
+ print("You must set the CODESIGNARGS environment variable. Skipping signing.")
elif config.sign:
if verbose >= 1:
- print "Code-signing app bundle %s"%(target,)
+ print("Code-signing app bundle %s"%(target,))
subprocess.check_call("codesign --force %s %s"%(os.environ['CODESIGNARGS'], target), shell=True)
# ------------------------------------------------
@@ -734,7 +734,7 @@ if config.dmg is not None:
def runHDIUtil(verb, image_basename, **kwargs):
hdiutil_args = ["hdiutil", verb, image_basename + ".dmg"]
- if kwargs.has_key("capture_stdout"):
+ if "capture_stdout" in kwargs:
del kwargs["capture_stdout"]
run = subprocess.check_output
else:
@@ -744,7 +744,7 @@ if config.dmg is not None:
hdiutil_args.append("-verbose")
run = subprocess.check_call
- for key, value in kwargs.iteritems():
+ for key, value in kwargs.items():
hdiutil_args.append("-" + key)
if not value is True:
hdiutil_args.append(str(value))
@@ -753,9 +753,9 @@ if config.dmg is not None:
if verbose >= 2:
if fancy is None:
- print "+ Creating .dmg disk image +"
+ print("+ Creating .dmg disk image +")
else:
- print "+ Preparing .dmg disk image +"
+ print("+ Preparing .dmg disk image +")
if config.dmg != "":
dmg_name = config.dmg
@@ -770,7 +770,7 @@ if config.dmg is not None:
sys.exit(e.returncode)
else:
if verbose >= 3:
- print "Determining size of \"dist\"..."
+ print("Determining size of \"dist\"...")
size = 0
for path, dirs, files in os.walk("dist"):
for file in files:
@@ -778,14 +778,14 @@ if config.dmg is not None:
size += int(size * 0.15)
if verbose >= 3:
- print "Creating temp image for modification..."
+ print("Creating temp image for modification...")
try:
runHDIUtil("create", dmg_name + ".temp", srcfolder="dist", format="UDRW", size=size, volname=volname, ov=True)
except subprocess.CalledProcessError as e:
sys.exit(e.returncode)
if verbose >= 3:
- print "Attaching temp image..."
+ print("Attaching temp image...")
try:
output = runHDIUtil("attach", dmg_name + ".temp", readwrite=True, noverify=True, noautoopen=True, capture_stdout=True)
except subprocess.CalledProcessError as e:
@@ -796,13 +796,13 @@ if config.dmg is not None:
disk_name = m.group(1)
if verbose >= 2:
- print "+ Applying fancy settings +"
+ print("+ Applying fancy settings +")
- if fancy.has_key("background_picture"):
+ if "background_picture" in fancy:
bg_path = os.path.join(disk_root, ".background", os.path.basename(fancy["background_picture"]))
os.mkdir(os.path.dirname(bg_path))
if verbose >= 3:
- print fancy["background_picture"], "->", bg_path
+ print(fancy["background_picture"], "->", bg_path)
shutil.copy2(fancy["background_picture"], bg_path)
else:
bg_path = None
@@ -839,8 +839,8 @@ if config.dmg is not None:
itemscript = Template('set position of item "${item}" of container window to {${position}}')
items_positions = []
- if fancy.has_key("items_position"):
- for name, position in fancy["items_position"].iteritems():
+ if "items_position" in fancy:
+ for name, position in fancy["items_position"].items():
params = { "item" : name, "position" : ",".join([str(p) for p in position]) }
items_positions.append(itemscript.substitute(params))
@@ -851,9 +851,9 @@ if config.dmg is not None:
"background_commands" : "",
"items_positions" : "\n ".join(items_positions)
}
- if fancy.has_key("window_bounds"):
+ if "window_bounds" in fancy:
params["window.bounds"] = ",".join([str(p) for p in fancy["window_bounds"]])
- if fancy.has_key("icon_size"):
+ if "icon_size" in fancy:
params["icon_size"] = str(fancy["icon_size"])
if bg_path is not None:
# Set background file, then call SetFile to make it invisible.
@@ -873,7 +873,7 @@ if config.dmg is not None:
print("Error running osascript.")
if verbose >= 2:
- print "+ Finalizing .dmg disk image +"
+ print("+ Finalizing .dmg disk image +")
time.sleep(5)
try:
@@ -886,6 +886,6 @@ if config.dmg is not None:
# ------------------------------------------------
if verbose >= 2:
- print "+ Done +"
+ print("+ Done +")
sys.exit(0)
diff --git a/contrib/rpm/README.md b/contrib/rpm/README.md
new file mode 100644
index 0000000000..aecb3ba84f
--- /dev/null
+++ b/contrib/rpm/README.md
@@ -0,0 +1,185 @@
+RPM Spec File Notes
+-------------------
+
+The RPM spec file provided here is for Bitcoin-Core 0.12.0 and builds on CentOS
+7 with either the CentOS provided OpenSSL library or with LibreSSL as packaged
+at [LibreLAMP.com](https://librelamp.com/). It should hopefully not be too
+difficult to port the RPM spec file to most RPM based Linux distributions.
+
+When porting the spec file to build for a particular distribution, there are
+some important notes.
+
+## Sources
+
+It is considered good form for all sources to reference a URL where the source
+can be downloaded.
+
+Sources 0-9 should be reserved for source code tarballs. `Source0` should
+reference the release tarball available from https://bitcoin.org/bin/ and
+`Source1` should reference the BerkeleyDB source.
+
+Sources 10-99 are for source files that are maintained in the
+[Bitcoin git repository](https://github.com/bitcoin/bitcoin) but are not part of
+the release tarball. Most of these will reside in the `contrib` sub-directory.
+
+Sources 10-19 should be reserved for miscellaneous configuration files.
+Currently only `Source10` is used, for the example `bitcoin.conf` file.
+
+Sources 20-29 should be reserved for man pages. Currently only `Source20`
+through `Source23` are used.
+
+Sources 30-39 should be reserved for SELinux related files. Currently only
+`Source30` through `Source32` are used. Until those files are in a tagged
+release, the full URL specified in the RPM spec file will not work. You can get
+them from the git ropository where you retrieved this file.
+
+Sources 100+ are for files that are not source tarballs and are not maintained
+in the bitcoin git repository. At present only an SVG version of the Bitcoin
+icon is used.
+
+## Patches
+
+In general, patches should be avoided. When a packager feels a patch is
+necessary, the packager should bring the problem to the attention of the bitcoin
+developers so that an official fix to the issue can make it into the next
+release.
+
+### Patch0 bitcoin-0.12.0-libressl.patch
+
+This patch is only needed if building against LibreSSL. LibreSSL is not the
+standard TLS library on most Linux distributions. The patch will likely not be
+needed when 0.12.1 is released, a proper fix is already in the Bitcoin git
+master branch.
+
+## BuildRequires
+
+The packages specified in the `BuildRequires` are specified according to the
+package naming convention currently used in CentOS 7 and EPEL for CentOS 7. You
+may need to change some of the package names for other distributions. This is
+most likely to be the case with the Qt packages.
+
+## BerkeleyDB
+
+The `build-unix.md` file recommends building against BerkeleyDB 4.8.30. Even if
+that is the version your Linux distribution ships with, it probably is a good
+idea to build Bitcoin Core against a static version of that library compiled
+according to the instructions in the `build-unix.md` file so that any changes
+the distribution may make in the future will not result in a problem for users.
+
+The problem that can exist, clients built against different versions of
+BerkeleyDB may not be able read each other's `wallet.dat` file which can make it
+difficult for a user to recover from backup in the event of a system failure.
+
+## Graphical User Interface and Qt Version
+
+The RPM spec file will by default build the GUI client linked against the Qt5
+libraries. If you wish instead to link against the Qt4 libraries you need to
+pass the switch `-D '_use_qt4 1'` at build time to the `rpmbuild` or `mock`
+command used to build the packages.
+
+If you would prefer not to build the GUI at all, you can pass the switch
+`-D '_no_gui 1'` to the `rpmbuild` or `mock` build command.
+
+## Desktop and KDE Files
+
+The desktop and KDE meta files are created in the spec file itself with the
+`cat` command. This is done to allow easy distribution specific changes without
+needing to use any patches. A specific time stamp is given to the files so that
+it does not they do not appear to have been updated every time the package is
+built. If you do make changes to them, you probably should update time stamp
+assigned to them in the `touch` command that specifies the time stamp.
+
+## SVG, PNG, and XPM Icons
+
+The `bitcoin.svg` file is from the source listed as `Source100`. It is used as
+the source for the PNG and XPM files. The generated PNG and XPM files are given
+the same time stamp as the source SVG file as a means of indicating they are
+derived from it.
+
+## Systemd
+
+This spec file assumes the target distribution uses systemd. That really only
+matters for the `bitcoin-server` package. At this point, most RPM based
+distributions that still receive vendor updates do in fact use systemd.
+
+The files to control the service are created in the RPM spec file itself using
+the `cat` command. This is done to make it easy to modify for other
+distributions that may implement things differently without needing to patch
+source. A specific time stamp is given to the files so that they do not appear
+to have been updated every time the package is built. If you do make changes to
+them, you probably should update the time stamp assigned to them in the `touch`
+command that specifies the time stamp.
+
+## SELinux
+
+The `bitcoin-server` package should have SELinux support. How to properly do
+that *may* vary by distribution and version of distribution.
+
+The SELinux stuff in this RPM spec file *should* be correct for CentOS, RHEL,
+and Fedora but it would be a good idea to review it before building the package
+on other distributions.
+
+## Tests
+
+The `%check` section takes a very long time to run. If your build system has a
+time limit for package build, you may need to make an exception for this
+package. On CentOS 7 the `%check` section completes successfully with both
+OpenSSL and LibreSSL, a failure really does mean something is wrong.
+
+## LibreSSL Build Notes
+
+To build against LibreSSL you will need to pass the switch
+`-D '_use_libressl 1'` to the `rpmbuild` or `mock` command or the spec file will
+want the OpenSSL development files.
+
+### LibreSSL and Boost
+
+LibreSSL (and some newer builds of OpenSSL) do not have support for SSLv3. This
+can cause issues with the Boost package if the Boost package has not been
+patched accordingly. On those distributions, you will either need to build
+Bitcoin-Core against OpenSSL or use a patched version of Boost in the build
+system.
+
+As SSLv3 is no longer safe, distributions that have not patched Boost to work
+with TLS libraries that do not support SSLv3 should have bug reports filed
+against the Boost package. This bug report has already been filed for RHEL 7 but
+it may need to be filed for other distributions.
+
+A patch for Boost: https://github.com/boostorg/asio/pull/23/files
+
+## ZeroMQ
+
+At this time, this RPM spec file does not support the ZeroMQ build options. A
+suitable version of ZeroMQ is not available for the platform this spec file was
+developed on (CentOS 7).
+
+## Legacy Credit
+
+This RPM spec file is largely based upon the work of Michael Hampton at
+[Ringing Liberty](https://www.ringingliberty.com/bitcoin/). He has been
+packaging Bitcoin for Fedora at least since 2012.
+
+Most of the differences between his packaging and this package are stylistic in
+nature. The major differences:
+
+1. He builds from a github tagged release rather than a release tarball. This
+should not result in different source code.
+
+2. He does not build BerkeleyDB but instead uses the BerkeleyDB provided by the
+Linux distribution. For the distributions he packages for, they currently all
+use the same version of BerkeleyDB so that difference is *probably* just
+academic.
+
+3. As of his 10.11.2 package he did not allow for building against LibreSSL,
+specifying a build without the Qt GUI, or specifying which version of the Qt
+libraries to use.
+
+4. I renamed the `bitcoin` package that contains the Qt GUI to `bitcoin-core` as
+that appears to be how the general population refers to it, in contrast to
+`bitcoin-xt` or `bitcoin-classic`. I wanted to make sure the general population
+knows what they are getting when installing the GUI package.
+
+As far as minor differences, I generally prefer to assign the file permissions
+in the `%files` portion of an RPM spec file rather than specifying the
+permissions of a file during `%install` and other minor things like that that
+are largely just cosmetic.
diff --git a/contrib/rpm/bitcoin-0.12.0-libressl.patch b/contrib/rpm/bitcoin-0.12.0-libressl.patch
new file mode 100644
index 0000000000..555614a06d
--- /dev/null
+++ b/contrib/rpm/bitcoin-0.12.0-libressl.patch
@@ -0,0 +1,24 @@
+diff -ur bitcoin-0.12.0.orig/src/init.cpp bitcoin-0.12.0/src/init.cpp
+--- bitcoin-0.12.0.orig/src/init.cpp 2015-12-31 16:00:00.000000000 -0800
++++ bitcoin-0.12.0/src/init.cpp 2016-02-23 06:03:47.133227757 -0800
+@@ -1075,7 +1075,7 @@
+ if (fPrintToDebugLog)
+ OpenDebugLog();
+
+-#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
++#if defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x10100000L)
+ LogPrintf("Using OpenSSL version %s\n", SSLeay_version(SSLEAY_VERSION));
+ #else
+ LogPrintf("Using OpenSSL version %s\n", OpenSSL_version(OPENSSL_VERSION));
+diff -ur bitcoin-0.12.0.orig/src/qt/rpcconsole.cpp bitcoin-0.12.0/src/qt/rpcconsole.cpp
+--- bitcoin-0.12.0.orig/src/qt/rpcconsole.cpp 2015-12-31 16:00:00.000000000 -0800
++++ bitcoin-0.12.0/src/qt/rpcconsole.cpp 2016-02-23 15:09:42.881126841 -0800
+@@ -264,7 +264,7 @@
+
+ // set library version labels
+
+-#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
++#if defined(LIBRESSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x10100000L)
+ ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION));
+ #else
+ ui->openSSLVersion->setText(OpenSSL_version(OPENSSL_VERSION));
diff --git a/contrib/rpm/bitcoin.fc b/contrib/rpm/bitcoin.fc
new file mode 100644
index 0000000000..6f5eef6375
--- /dev/null
+++ b/contrib/rpm/bitcoin.fc
@@ -0,0 +1,8 @@
+/usr/bin/bitcoin-cli -- gen_context(system_u:object_r:bitcoin_exec_t,s0)
+/usr/sbin/bitcoind -- gen_context(system_u:object_r:bitcoin_exec_t,s0)
+/usr/lib(64)?/bitcoin/bitcoind -- gen_context(system_u:object_r:bitcoin_exec_t,s0)
+
+/etc/bitcoin(/.*)? gen_context(system_u:object_r:bitcoin_conf_t,s0)
+/var/lib/bitcoin(/.*)? gen_context(system_u:object_r:bitcoin_var_lib_t,s0)
+
+(/var)?/run/bitcoind(/.*)? gen_context(system_u:object_r:bitcoin_var_run_t,s0)
diff --git a/contrib/rpm/bitcoin.if b/contrib/rpm/bitcoin.if
new file mode 100644
index 0000000000..2b096c24dc
--- /dev/null
+++ b/contrib/rpm/bitcoin.if
@@ -0,0 +1,157 @@
+
+## <summary>policy for bitcoin</summary>
+
+
+########################################
+## <summary>
+## Transition to bitcoin.
+## </summary>
+## <param name="domain">
+## <summary>
+## Domain allowed to transition.
+## </summary>
+## </param>
+#
+interface(`bitcoin_domtrans',`
+ gen_require(`
+ type bitcoin_t, bitcoin_exec_t;
+ ')
+
+ corecmd_search_bin($1)
+ domtrans_pattern($1, bitcoin_exec_t, bitcoin_t)
+')
+
+
+########################################
+## <summary>
+## Execute bitcoin server in the bitcoin domain.
+## </summary>
+## <param name="domain">
+## <summary>
+## Domain allowed access.
+## </summary>
+## </param>
+#
+interface(`bitcoin_initrc_domtrans',`
+ gen_require(`
+ type bitcoin_initrc_exec_t;
+ ')
+
+ init_labeled_script_domtrans($1, bitcoin_initrc_exec_t)
+')
+
+
+########################################
+## <summary>
+## Search bitcoin lib directories.
+## </summary>
+## <param name="domain">
+## <summary>
+## Domain allowed access.
+## </summary>
+## </param>
+#
+interface(`bitcoin_search_lib',`
+ gen_require(`
+ type bitcoin_var_lib_t;
+ ')
+
+ allow $1 bitcoin_var_lib_t:dir search_dir_perms;
+ files_search_var_lib($1)
+')
+
+########################################
+## <summary>
+## Read bitcoin lib files.
+## </summary>
+## <param name="domain">
+## <summary>
+## Domain allowed access.
+## </summary>
+## </param>
+#
+interface(`bitcoin_read_lib_files',`
+ gen_require(`
+ type bitcoin_var_lib_t;
+ ')
+
+ files_search_var_lib($1)
+ read_files_pattern($1, bitcoin_var_lib_t, bitcoin_var_lib_t)
+')
+
+########################################
+## <summary>
+## Manage bitcoin lib files.
+## </summary>
+## <param name="domain">
+## <summary>
+## Domain allowed access.
+## </summary>
+## </param>
+#
+interface(`bitcoin_manage_lib_files',`
+ gen_require(`
+ type bitcoin_var_lib_t;
+ ')
+
+ files_search_var_lib($1)
+ manage_files_pattern($1, bitcoin_var_lib_t, bitcoin_var_lib_t)
+')
+
+########################################
+## <summary>
+## Manage bitcoin lib directories.
+## </summary>
+## <param name="domain">
+## <summary>
+## Domain allowed access.
+## </summary>
+## </param>
+#
+interface(`bitcoin_manage_lib_dirs',`
+ gen_require(`
+ type bitcoin_var_lib_t;
+ ')
+
+ files_search_var_lib($1)
+ manage_dirs_pattern($1, bitcoin_var_lib_t, bitcoin_var_lib_t)
+')
+
+
+########################################
+## <summary>
+## All of the rules required to administrate
+## an bitcoin environment
+## </summary>
+## <param name="domain">
+## <summary>
+## Domain allowed access.
+## </summary>
+## </param>
+## <param name="role">
+## <summary>
+## Role allowed access.
+## </summary>
+## </param>
+## <rolecap/>
+#
+interface(`bitcoin_admin',`
+ gen_require(`
+ type bitcoin_t;
+ type bitcoin_initrc_exec_t;
+ type bitcoin_var_lib_t;
+ ')
+
+ allow $1 bitcoin_t:process { ptrace signal_perms };
+ ps_process_pattern($1, bitcoin_t)
+
+ bitcoin_initrc_domtrans($1)
+ domain_system_change_exemption($1)
+ role_transition $2 bitcoin_initrc_exec_t system_r;
+ allow $2 system_r;
+
+ files_search_var_lib($1)
+ admin_pattern($1, bitcoin_var_lib_t)
+
+')
+
diff --git a/contrib/rpm/bitcoin.spec b/contrib/rpm/bitcoin.spec
new file mode 100644
index 0000000000..38ae038180
--- /dev/null
+++ b/contrib/rpm/bitcoin.spec
@@ -0,0 +1,444 @@
+%define bdbv 4.8.30
+%global selinux_variants mls strict targeted
+
+%if 0%{?_no_gui:1}
+%define _buildqt 0
+%define buildargs --with-gui=no
+%else
+%define _buildqt 1
+%if 0%{?_use_qt4}
+%define buildargs --with-qrencode --with-gui=qt4
+%else
+%define buildargs --with-qrencode --with-gui=qt5
+%endif
+%endif
+
+Name: bitcoin
+Version: 0.12.0
+Release: 2%{?dist}
+Summary: Peer to Peer Cryptographic Currency
+
+Group: Applications/System
+License: MIT
+URL: https://bitcoin.org/
+Source0: https://bitcoin.org/bin/bitcoin-core-%{version}/bitcoin-%{version}.tar.gz
+Source1: http://download.oracle.com/berkeley-db/db-%{bdbv}.NC.tar.gz
+
+Source10: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/debian/examples/bitcoin.conf
+
+#man pages
+Source20: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/debian/manpages/bitcoind.1
+Source21: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/debian/manpages/bitcoin-cli.1
+Source22: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/debian/manpages/bitcoin-qt.1
+Source23: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/debian/manpages/bitcoin.conf.5
+
+#selinux
+Source30: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/rpm/bitcoin.te
+# Source31 - what about bitcoin-tx and bench_bitcoin ???
+Source31: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/rpm/bitcoin.fc
+Source32: https://raw.githubusercontent.com/bitcoin/bitcoin/v%{version}/contrib/rpm/bitcoin.if
+
+Source100: https://upload.wikimedia.org/wikipedia/commons/4/46/Bitcoin.svg
+
+%if 0%{?_use_libressl:1}
+BuildRequires: libressl-devel
+%else
+BuildRequires: openssl-devel
+%endif
+BuildRequires: boost-devel
+BuildRequires: miniupnpc-devel
+BuildRequires: autoconf automake libtool
+BuildRequires: libevent-devel
+
+
+Patch0: bitcoin-0.12.0-libressl.patch
+
+
+%description
+Bitcoin is a digital cryptographic currency that uses peer-to-peer technology to
+operate with no central authority or banks; managing transactions and the
+issuing of bitcoins is carried out collectively by the network.
+
+%if %{_buildqt}
+%package core
+Summary: Peer to Peer Cryptographic Currency
+Group: Applications/System
+Obsoletes: %{name} < %{version}-%{release}
+Provides: %{name} = %{version}-%{release}
+%if 0%{?_use_qt4}
+BuildRequires: qt-devel
+%else
+BuildRequires: qt5-qtbase-devel
+# for /usr/bin/lrelease-qt5
+BuildRequires: qt5-linguist
+%endif
+BuildRequires: protobuf-devel
+BuildRequires: qrencode-devel
+BuildRequires: %{_bindir}/desktop-file-validate
+# for icon generation from SVG
+BuildRequires: %{_bindir}/inkscape
+BuildRequires: %{_bindir}/convert
+
+%description core
+Bitcoin is a digital cryptographic currency that uses peer-to-peer technology to
+operate with no central authority or banks; managing transactions and the
+issuing of bitcoins is carried out collectively by the network.
+
+This package contains the Qt based graphical client and node. If you are looking
+to run a Bitcoin wallet, this is probably the package you want.
+%endif
+
+
+%package libs
+Summary: Bitcoin shared libraries
+Group: System Environment/Libraries
+
+%description libs
+This package provides the bitcoinconsensus shared libraries. These libraries
+may be used by third party software to provide consensus verification
+functionality.
+
+Unless you know need this package, you probably do not.
+
+%package devel
+Summary: Development files for bitcoin
+Group: Development/Libraries
+Requires: %{name}-libs = %{version}-%{release}
+
+%description devel
+This package contains the header files and static library for the
+bitcoinconsensus shared library. If you are developing or compiling software
+that wants to link against that library, then you need this package installed.
+
+Most people do not need this package installed.
+
+%package server
+Summary: The bitcoin daemon
+Group: System Environment/Daemons
+Requires: bitcoin-utils = %{version}-%{release}
+Requires: selinux-policy policycoreutils-python
+Requires(pre): shadow-utils
+Requires(post): %{_sbindir}/semodule %{_sbindir}/restorecon %{_sbindir}/fixfiles %{_sbindir}/sestatus
+Requires(postun): %{_sbindir}/semodule %{_sbindir}/restorecon %{_sbindir}/fixfiles %{_sbindir}/sestatus
+BuildRequires: systemd
+BuildRequires: checkpolicy
+BuildRequires: %{_datadir}/selinux/devel/Makefile
+
+%description server
+This package provides a stand-alone bitcoin-core daemon. For most users, this
+package is only needed if they need a full-node without the graphical client.
+
+Some third party wallet software will want this package to provide the actual
+bitcoin-core node they use to connect to the network.
+
+If you use the graphical bitcoin-core client then you almost certainly do not
+need this package.
+
+%package utils
+Summary: Bitcoin utilities
+Group: Applications/System
+
+%description utils
+This package provides several command line utilities for interacting with a
+bitcoin-core daemon.
+
+The bitcoin-cli utility allows you to communicate and control a bitcoin daemon
+over RPC, the bitcoin-tx utility allows you to create a custom transaction, and
+the bench_bitcoin utility can be used to perform some benchmarks.
+
+This package contains utilities needed by the bitcoin-server package.
+
+
+%prep
+%setup -q
+%patch0 -p1 -b .libressl
+cp -p %{SOURCE10} ./bitcoin.conf.example
+tar -zxf %{SOURCE1}
+cp -p db-%{bdbv}.NC/LICENSE ./db-%{bdbv}.NC-LICENSE
+mkdir db4 SELinux
+cp -p %{SOURCE30} %{SOURCE31} %{SOURCE32} SELinux/
+
+
+%build
+CWD=`pwd`
+cd db-%{bdbv}.NC/build_unix/
+../dist/configure --enable-cxx --disable-shared --with-pic --prefix=${CWD}/db4
+make install
+cd ../..
+
+./autogen.sh
+%configure LDFLAGS="-L${CWD}/db4/lib/" CPPFLAGS="-I${CWD}/db4/include/" --with-miniupnpc --enable-glibc-back-compat %{buildargs}
+make %{?_smp_mflags}
+
+pushd SELinux
+for selinuxvariant in %{selinux_variants}; do
+ make NAME=${selinuxvariant} -f %{_datadir}/selinux/devel/Makefile
+ mv bitcoin.pp bitcoin.pp.${selinuxvariant}
+ make NAME=${selinuxvariant} -f %{_datadir}/selinux/devel/Makefile clean
+done
+popd
+
+
+%install
+make install DESTDIR=%{buildroot}
+
+mkdir -p -m755 %{buildroot}%{_sbindir}
+mv %{buildroot}%{_bindir}/bitcoind %{buildroot}%{_sbindir}/bitcoind
+
+# systemd stuff
+mkdir -p %{buildroot}%{_tmpfilesdir}
+cat <<EOF > %{buildroot}%{_tmpfilesdir}/bitcoin.conf
+d /run/bitcoind 0750 bitcoin bitcoin -
+EOF
+touch -a -m -t 201504280000 %{buildroot}%{_tmpfilesdir}/bitcoin.conf
+
+mkdir -p %{buildroot}%{_sysconfdir}/sysconfig
+cat <<EOF > %{buildroot}%{_sysconfdir}/sysconfig/bitcoin
+# Provide options to the bitcoin daemon here, for example
+# OPTIONS="-testnet -disable-wallet"
+
+OPTIONS=""
+
+# System service defaults.
+# Don't change these unless you know what you're doing.
+CONFIG_FILE="%{_sysconfdir}/bitcoin/bitcoin.conf"
+DATA_DIR="%{_localstatedir}/lib/bitcoin"
+PID_FILE="/run/bitcoind/bitcoind.pid"
+EOF
+touch -a -m -t 201504280000 %{buildroot}%{_sysconfdir}/sysconfig/bitcoin
+
+mkdir -p %{buildroot}%{_unitdir}
+cat <<EOF > %{buildroot}%{_unitdir}/bitcoin.service
+[Unit]
+Description=Bitcoin daemon
+After=syslog.target network.target
+
+[Service]
+Type=forking
+ExecStart=%{_sbindir}/bitcoind -daemon -conf=\${CONFIG_FILE} -datadir=\${DATA_DIR} -pid=\${PID_FILE} \$OPTIONS
+EnvironmentFile=%{_sysconfdir}/sysconfig/bitcoin
+User=bitcoin
+Group=bitcoin
+
+Restart=on-failure
+PrivateTmp=true
+TimeoutStopSec=120
+TimeoutStartSec=60
+StartLimitInterval=240
+StartLimitBurst=5
+
+[Install]
+WantedBy=multi-user.target
+EOF
+touch -a -m -t 201504280000 %{buildroot}%{_unitdir}/bitcoin.service
+#end systemd stuff
+
+mkdir %{buildroot}%{_sysconfdir}/bitcoin
+mkdir -p %{buildroot}%{_localstatedir}/lib/bitcoin
+
+#SELinux
+for selinuxvariant in %{selinux_variants}; do
+ install -d %{buildroot}%{_datadir}/selinux/${selinuxvariant}
+ install -p -m 644 SELinux/bitcoin.pp.${selinuxvariant} %{buildroot}%{_datadir}/selinux/${selinuxvariant}/bitcoin.pp
+done
+
+%if %{_buildqt}
+# qt icons
+install -D -p share/pixmaps/bitcoin.ico %{buildroot}%{_datadir}/pixmaps/bitcoin.ico
+install -p share/pixmaps/nsis-header.bmp %{buildroot}%{_datadir}/pixmaps/
+install -p share/pixmaps/nsis-wizard.bmp %{buildroot}%{_datadir}/pixmaps/
+install -p %{SOURCE100} %{buildroot}%{_datadir}/pixmaps/bitcoin.svg
+%{_bindir}/inkscape %{SOURCE100} --export-png=%{buildroot}%{_datadir}/pixmaps/bitcoin16.png -w16 -h16
+%{_bindir}/inkscape %{SOURCE100} --export-png=%{buildroot}%{_datadir}/pixmaps/bitcoin32.png -w32 -h32
+%{_bindir}/inkscape %{SOURCE100} --export-png=%{buildroot}%{_datadir}/pixmaps/bitcoin64.png -w64 -h64
+%{_bindir}/inkscape %{SOURCE100} --export-png=%{buildroot}%{_datadir}/pixmaps/bitcoin128.png -w128 -h128
+%{_bindir}/inkscape %{SOURCE100} --export-png=%{buildroot}%{_datadir}/pixmaps/bitcoin256.png -w256 -h256
+%{_bindir}/convert -resize 16x16 %{buildroot}%{_datadir}/pixmaps/bitcoin256.png %{buildroot}%{_datadir}/pixmaps/bitcoin16.xpm
+%{_bindir}/convert -resize 32x32 %{buildroot}%{_datadir}/pixmaps/bitcoin256.png %{buildroot}%{_datadir}/pixmaps/bitcoin32.xpm
+%{_bindir}/convert -resize 64x64 %{buildroot}%{_datadir}/pixmaps/bitcoin256.png %{buildroot}%{_datadir}/pixmaps/bitcoin64.xpm
+%{_bindir}/convert -resize 128x128 %{buildroot}%{_datadir}/pixmaps/bitcoin256.png %{buildroot}%{_datadir}/pixmaps/bitcoin128.xpm
+%{_bindir}/convert %{buildroot}%{_datadir}/pixmaps/bitcoin256.png %{buildroot}%{_datadir}/pixmaps/bitcoin256.xpm
+touch %{buildroot}%{_datadir}/pixmaps/*.png -r %{SOURCE100}
+touch %{buildroot}%{_datadir}/pixmaps/*.xpm -r %{SOURCE100}
+
+# Desktop File - change the touch timestamp if modifying
+mkdir -p %{buildroot}%{_datadir}/applications
+cat <<EOF > %{buildroot}%{_datadir}/applications/bitcoin-core.desktop
+[Desktop Entry]
+Encoding=UTF-8
+Name=Bitcoin
+Comment=Bitcoin P2P Cryptocurrency
+Comment[fr]=Bitcoin, monnaie virtuelle cryptographique pair à pair
+Comment[tr]=Bitcoin, eÅŸten eÅŸe kriptografik sanal para birimi
+Exec=bitcoin-qt %u
+Terminal=false
+Type=Application
+Icon=bitcoin128
+MimeType=x-scheme-handler/bitcoin;
+Categories=Office;Finance;
+EOF
+# change touch date when modifying desktop
+touch -a -m -t 201511100546 %{buildroot}%{_datadir}/applications/bitcoin-core.desktop
+%{_bindir}/desktop-file-validate %{buildroot}%{_datadir}/applications/bitcoin-core.desktop
+
+# KDE protocol - change the touch timestamp if modifying
+mkdir -p %{buildroot}%{_datadir}/kde4/services
+cat <<EOF > %{buildroot}%{_datadir}/kde4/services/bitcoin-core.protocol
+[Protocol]
+exec=bitcoin-qt '%u'
+protocol=bitcoin
+input=none
+output=none
+helper=true
+listing=
+reading=false
+writing=false
+makedir=false
+deleting=false
+EOF
+# change touch date when modifying protocol
+touch -a -m -t 201511100546 %{buildroot}%{_datadir}/kde4/services/bitcoin-core.protocol
+%endif
+
+# man pages
+install -D -p %{SOURCE20} %{buildroot}%{_mandir}/man1/bitcoind.1
+install -p %{SOURCE21} %{buildroot}%{_mandir}/man1/bitcoin-cli.1
+%if %{_buildqt}
+install -p %{SOURCE22} %{buildroot}%{_mandir}/man1/bitcoin-qt.1
+%endif
+install -D -p %{SOURCE23} %{buildroot}%{_mandir}/man5/bitcoin.conf.5
+
+# nuke these, we do extensive testing of binaries in %%check before packaging
+rm -f %{buildroot}%{_bindir}/test_*
+
+%check
+make check
+pushd src
+srcdir=. test/bitcoin-util-test.py
+popd
+qa/pull-tester/rpc-tests.py -extended
+
+%post libs -p /sbin/ldconfig
+
+%postun libs -p /sbin/ldconfig
+
+%pre server
+getent group bitcoin >/dev/null || groupadd -r bitcoin
+getent passwd bitcoin >/dev/null ||
+ useradd -r -g bitcoin -d /var/lib/bitcoin -s /sbin/nologin \
+ -c "Bitcoin wallet server" bitcoin
+exit 0
+
+%post server
+%systemd_post bitcoin.service
+# SELinux
+if [ `%{_sbindir}/sestatus |grep -c "disabled"` -eq 0 ]; then
+for selinuxvariant in %{selinux_variants}; do
+ %{_sbindir}/semodule -s ${selinuxvariant} -i %{_datadir}/selinux/${selinuxvariant}/bitcoin.pp &> /dev/null || :
+done
+%{_sbindir}/semanage port -a -t bitcoin_port_t -p tcp 8332
+%{_sbindir}/semanage port -a -t bitcoin_port_t -p tcp 8333
+%{_sbindir}/semanage port -a -t bitcoin_port_t -p tcp 18332
+%{_sbindir}/semanage port -a -t bitcoin_port_t -p tcp 18333
+%{_sbindir}/fixfiles -R bitcoin-server restore &> /dev/null || :
+%{_sbindir}/restorecon -R %{_localstatedir}/lib/bitcoin || :
+fi
+
+%posttrans server
+%{_bindir}/systemd-tmpfiles --create
+
+%preun server
+%systemd_preun bitcoin.service
+
+%postun server
+%systemd_postun bitcoin.service
+# SELinux
+if [ $1 -eq 0 ]; then
+ if [ `%{_sbindir}/sestatus |grep -c "disabled"` -eq 0 ]; then
+ %{_sbindir}/semanage port -d -p tcp 8332
+ %{_sbindir}/semanage port -d -p tcp 8333
+ %{_sbindir}/semanage port -d -p tcp 18332
+ %{_sbindir}/semanage port -d -p tcp 18333
+ for selinuxvariant in %{selinux_variants}; do
+ %{_sbindir}/semodule -s ${selinuxvariant} -r bitcoin &> /dev/null || :
+ done
+ %{_sbindir}/fixfiles -R bitcoin-server restore &> /dev/null || :
+ [ -d %{_localstatedir}/lib/bitcoin ] && \
+ %{_sbindir}/restorecon -R %{_localstatedir}/lib/bitcoin &> /dev/null || :
+ fi
+fi
+
+%clean
+rm -rf %{buildroot}
+
+%if %{_buildqt}
+%files core
+%defattr(-,root,root,-)
+%license COPYING db-%{bdbv}.NC-LICENSE
+%doc COPYING bitcoin.conf.example doc/README.md doc/bips.md doc/files.md doc/multiwallet-qt.md doc/reduce-traffic.md doc/release-notes.md doc/tor.md
+%attr(0755,root,root) %{_bindir}/bitcoin-qt
+%attr(0644,root,root) %{_datadir}/applications/bitcoin-core.desktop
+%attr(0644,root,root) %{_datadir}/kde4/services/bitcoin-core.protocol
+%attr(0644,root,root) %{_datadir}/pixmaps/*.ico
+%attr(0644,root,root) %{_datadir}/pixmaps/*.bmp
+%attr(0644,root,root) %{_datadir}/pixmaps/*.svg
+%attr(0644,root,root) %{_datadir}/pixmaps/*.png
+%attr(0644,root,root) %{_datadir}/pixmaps/*.xpm
+%attr(0644,root,root) %{_mandir}/man1/bitcoin-qt.1*
+%endif
+
+%files libs
+%defattr(-,root,root,-)
+%license COPYING
+%doc COPYING doc/README.md doc/shared-libraries.md
+%{_libdir}/lib*.so.*
+
+%files devel
+%defattr(-,root,root,-)
+%license COPYING
+%doc COPYING doc/README.md doc/developer-notes.md doc/shared-libraries.md
+%attr(0644,root,root) %{_includedir}/*.h
+%{_libdir}/*.so
+%{_libdir}/*.a
+%{_libdir}/*.la
+%attr(0644,root,root) %{_libdir}/pkgconfig/*.pc
+
+%files server
+%defattr(-,root,root,-)
+%license COPYING db-%{bdbv}.NC-LICENSE
+%doc COPYING bitcoin.conf.example doc/README.md doc/REST-interface.md doc/bips.md doc/dnsseed-policy.md doc/files.md doc/reduce-traffic.md doc/release-notes.md doc/tor.md
+%attr(0755,root,root) %{_sbindir}/bitcoind
+%attr(0644,root,root) %{_tmpfilesdir}/bitcoin.conf
+%attr(0644,root,root) %{_unitdir}/bitcoin.service
+%dir %attr(0750,bitcoin,bitcoin) %{_sysconfdir}/bitcoin
+%dir %attr(0750,bitcoin,bitcoin) %{_localstatedir}/lib/bitcoin
+%config(noreplace) %attr(0600,root,root) %{_sysconfdir}/sysconfig/bitcoin
+%attr(0644,root,root) %{_datadir}/selinux/*/*.pp
+%attr(0644,root,root) %{_mandir}/man1/bitcoind.1*
+%attr(0644,root,root) %{_mandir}/man5/bitcoin.conf.5*
+
+%files utils
+%defattr(-,root,root,-)
+%license COPYING
+%doc COPYING bitcoin.conf.example doc/README.md
+%attr(0755,root,root) %{_bindir}/bitcoin-cli
+%attr(0755,root,root) %{_bindir}/bitcoin-tx
+%attr(0755,root,root) %{_bindir}/bench_bitcoin
+%attr(0644,root,root) %{_mandir}/man1/bitcoin-cli.1*
+%attr(0644,root,root) %{_mandir}/man5/bitcoin.conf.5*
+
+
+
+%changelog
+* Fri Feb 26 2016 Alice Wonder <buildmaster@librelamp.com> - 0.12.0-2
+- Rename Qt package from bitcoin to bitcoin-core
+- Make building of the Qt package optional
+- When building the Qt package, default to Qt5 but allow building
+- against Qt4
+- Only run SELinux stuff in post scripts if it is not set to disabled
+
+* Wed Feb 24 2016 Alice Wonder <buildmaster@librelamp.com> - 0.12.0-1
+- Initial spec file for 0.12.0 release
+
+# This spec file is written from scratch but a lot of the packaging decisions are directly
+# based upon the 0.11.2 package spec file from https://www.ringingliberty.com/bitcoin/
diff --git a/contrib/rpm/bitcoin.te b/contrib/rpm/bitcoin.te
new file mode 100644
index 0000000000..d6231c591a
--- /dev/null
+++ b/contrib/rpm/bitcoin.te
@@ -0,0 +1,81 @@
+policy_module(bitcoin, 1.100.1)
+
+########################################
+#
+# Declarations
+#
+
+type bitcoin_t;
+type bitcoin_exec_t;
+init_daemon_domain(bitcoin_t, bitcoin_exec_t)
+
+permissive bitcoin_t;
+
+type bitcoin_initrc_exec_t;
+init_script_file(bitcoin_initrc_exec_t)
+
+type bitcoin_conf_t;
+files_type(bitcoin_conf_t)
+
+type bitcoin_var_lib_t;
+files_type(bitcoin_var_lib_t)
+
+type bitcoin_var_run_t;
+files_type(bitcoin_var_run_t)
+
+type bitcoin_port_t;
+corenet_port(bitcoin_port_t)
+
+########################################
+#
+# bitcoin local policy
+#
+allow bitcoin_t self:process { fork };
+
+allow bitcoin_t self:fifo_file rw_fifo_file_perms;
+allow bitcoin_t self:unix_stream_socket create_stream_socket_perms;
+
+manage_dirs_pattern(bitcoin_t, bitcoin_conf_t, bitcoin_conf_t)
+manage_files_pattern(bitcoin_t, bitcoin_conf_t, bitcoin_conf_t)
+
+manage_dirs_pattern(bitcoin_t, bitcoin_var_lib_t, bitcoin_var_lib_t)
+manage_files_pattern(bitcoin_t, bitcoin_var_lib_t, bitcoin_var_lib_t)
+files_var_lib_filetrans(bitcoin_t, bitcoin_var_lib_t, { dir file })
+
+manage_dirs_pattern(bitcoin_t, bitcoin_var_run_t, bitcoin_var_run_t)
+manage_files_pattern(bitcoin_t, bitcoin_var_run_t, bitcoin_var_run_t)
+
+sysnet_dns_name_resolve(bitcoin_t)
+corenet_all_recvfrom_unlabeled(bitcoin_t)
+
+allow bitcoin_t self:tcp_socket create_stream_socket_perms;
+corenet_tcp_sendrecv_generic_if(bitcoin_t)
+corenet_tcp_sendrecv_generic_node(bitcoin_t)
+corenet_tcp_sendrecv_all_ports(bitcoin_t)
+corenet_tcp_bind_generic_node(bitcoin_t)
+
+gen_require(`
+ type bitcoin_port_t;
+')
+allow bitcoin_t bitcoin_port_t:tcp_socket name_bind;
+
+gen_require(`
+ type bitcoin_port_t;
+')
+allow bitcoin_t bitcoin_port_t:tcp_socket name_connect;
+
+domain_use_interactive_fds(bitcoin_t)
+
+files_read_etc_files(bitcoin_t)
+
+miscfiles_read_localization(bitcoin_t)
+
+sysnet_dns_name_resolve(bitcoin_t)
+
+allow bitcoin_t bitcoin_exec_t:file execute_no_trans;
+allow bitcoin_t self:process setsched;
+corecmd_exec_ls(bitcoin_t)
+corenet_tcp_connect_http_port(bitcoin_t)
+dev_read_urand(bitcoin_t)
+fs_getattr_xattr_fs(bitcoin_t)
+kernel_read_system_state(bitcoin_t)
diff --git a/contrib/verifysfbinaries/README.md b/contrib/verifysfbinaries/README.md
index 8c038865bd..1db3fe52fc 100644
--- a/contrib/verifysfbinaries/README.md
+++ b/contrib/verifysfbinaries/README.md
@@ -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. \ No newline at end of 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.
diff --git a/depends/builders/darwin.mk b/depends/builders/darwin.mk
index b366460e64..200d6ed22a 100644
--- a/depends/builders/darwin.mk
+++ b/depends/builders/darwin.mk
@@ -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)
diff --git a/depends/builders/linux.mk b/depends/builders/linux.mk
index 98d0e9de34..b03f424010 100644
--- a/depends/builders/linux.mk
+++ b/depends/builders/linux.mk
@@ -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
diff --git a/depends/config.guess b/depends/config.guess
index fba6e87a0f..373a659a06 100755
--- a/depends/config.guess
+++ b/depends/config.guess
@@ -1,8 +1,8 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright 1992-2015 Free Software Foundation, Inc.
+# Copyright 1992-2016 Free Software Foundation, Inc.
-timestamp='2015-11-19'
+timestamp='2016-02-11'
# 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
@@ -27,7 +27,7 @@ timestamp='2015-11-19'
# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
#
# You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
#
# Please send patches to <config-patches@gnu.org>.
@@ -50,7 +50,7 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright 1992-2015 Free Software Foundation, Inc.
+Copyright 1992-2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -237,6 +237,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
exit ;;
+ *:LibertyBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE}
+ exit ;;
*:ekkoBSD:*:*)
echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
exit ;;
@@ -268,42 +272,42 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
case "$ALPHA_CPU_TYPE" in
"EV4 (21064)")
- UNAME_MACHINE="alpha" ;;
+ UNAME_MACHINE=alpha ;;
"EV4.5 (21064)")
- UNAME_MACHINE="alpha" ;;
+ UNAME_MACHINE=alpha ;;
"LCA4 (21066/21068)")
- UNAME_MACHINE="alpha" ;;
+ UNAME_MACHINE=alpha ;;
"EV5 (21164)")
- UNAME_MACHINE="alphaev5" ;;
+ UNAME_MACHINE=alphaev5 ;;
"EV5.6 (21164A)")
- UNAME_MACHINE="alphaev56" ;;
+ UNAME_MACHINE=alphaev56 ;;
"EV5.6 (21164PC)")
- UNAME_MACHINE="alphapca56" ;;
+ UNAME_MACHINE=alphapca56 ;;
"EV5.7 (21164PC)")
- UNAME_MACHINE="alphapca57" ;;
+ UNAME_MACHINE=alphapca57 ;;
"EV6 (21264)")
- UNAME_MACHINE="alphaev6" ;;
+ UNAME_MACHINE=alphaev6 ;;
"EV6.7 (21264A)")
- UNAME_MACHINE="alphaev67" ;;
+ UNAME_MACHINE=alphaev67 ;;
"EV6.8CB (21264C)")
- UNAME_MACHINE="alphaev68" ;;
+ UNAME_MACHINE=alphaev68 ;;
"EV6.8AL (21264B)")
- UNAME_MACHINE="alphaev68" ;;
+ UNAME_MACHINE=alphaev68 ;;
"EV6.8CX (21264D)")
- UNAME_MACHINE="alphaev68" ;;
+ UNAME_MACHINE=alphaev68 ;;
"EV6.9A (21264/EV69A)")
- UNAME_MACHINE="alphaev69" ;;
+ UNAME_MACHINE=alphaev69 ;;
"EV7 (21364)")
- UNAME_MACHINE="alphaev7" ;;
+ UNAME_MACHINE=alphaev7 ;;
"EV7.9 (21364A)")
- UNAME_MACHINE="alphaev79" ;;
+ UNAME_MACHINE=alphaev79 ;;
esac
# A Pn.n version is a patched version.
# A Vn.n version is a released version.
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
- echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
exitcode=$?
trap '' 0
@@ -376,16 +380,16 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
exit ;;
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
eval $set_cc_for_build
- SUN_ARCH="i386"
+ SUN_ARCH=i386
# If there is a compiler, see if it is configured for 64-bit objects.
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
# This test works for both compilers.
- if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
- SUN_ARCH="x86_64"
+ SUN_ARCH=x86_64
fi
fi
echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
@@ -410,7 +414,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
exit ;;
sun*:*:4.2BSD:*)
UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
- test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3
case "`/bin/arch`" in
sun3)
echo m68k-sun-sunos${UNAME_RELEASE}
@@ -635,13 +639,13 @@ EOF
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
case "${sc_cpu_version}" in
- 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
- 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
532) # CPU_PA_RISC2_0
case "${sc_kernel_bits}" in
- 32) HP_ARCH="hppa2.0n" ;;
- 64) HP_ARCH="hppa2.0w" ;;
- '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ 32) HP_ARCH=hppa2.0n ;;
+ 64) HP_ARCH=hppa2.0w ;;
+ '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20
esac ;;
esac
fi
@@ -684,7 +688,7 @@ EOF
test -z "$HP_ARCH" && HP_ARCH=hppa
fi ;;
esac
- if [ ${HP_ARCH} = "hppa2.0w" ]
+ if [ ${HP_ARCH} = hppa2.0w ]
then
eval $set_cc_for_build
@@ -700,9 +704,9 @@ EOF
if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
grep -q __LP64__
then
- HP_ARCH="hppa2.0w"
+ HP_ARCH=hppa2.0w
else
- HP_ARCH="hppa64"
+ HP_ARCH=hppa64
fi
fi
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
@@ -807,14 +811,14 @@ EOF
echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
- FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
5000:UNIX_System_V:4.*:*)
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
@@ -919,7 +923,7 @@ EOF
EV68*) UNAME_MACHINE=alphaev68 ;;
esac
objdump --private-headers /bin/sh | grep -q ld.so.1
- if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
+ if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
arc:Linux:*:* | arceb:Linux:*:*)
@@ -1285,7 +1289,7 @@ EOF
UNAME_PROCESSOR=powerpc
fi
if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
- if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
@@ -1309,7 +1313,7 @@ EOF
exit ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
UNAME_PROCESSOR=`uname -p`
- if test "$UNAME_PROCESSOR" = "x86"; then
+ if test "$UNAME_PROCESSOR" = x86; then
UNAME_PROCESSOR=i386
UNAME_MACHINE=pc
fi
@@ -1340,7 +1344,7 @@ EOF
# "uname -m" is not consistent, so use $cputype instead. 386
# is converted to i386 for consistency with other x86
# operating systems.
- if test "$cputype" = "386"; then
+ if test "$cputype" = 386; then
UNAME_MACHINE=i386
else
UNAME_MACHINE="$cputype"
@@ -1394,7 +1398,7 @@ EOF
echo ${UNAME_MACHINE}-unknown-esx
exit ;;
amd64:Isilon\ OneFS:*:*)
- echo x86_64-unknown-onefs
+ echo x86_64-unknown-onefs
exit ;;
esac
@@ -1405,9 +1409,9 @@ This script, last modified $timestamp, has failed to recognize
the operating system you are using. It is advised that you
download the most up to date version of the config scripts from
- http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
and
- http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
If the version you run ($0) is already up to date, please
send the following data and any information you think might be
diff --git a/depends/config.sub b/depends/config.sub
index ea8747d30f..6223dde931 100755
--- a/depends/config.sub
+++ b/depends/config.sub
@@ -1,8 +1,8 @@
#! /bin/sh
# Configuration validation subroutine script.
-# Copyright 1992-2015 Free Software Foundation, Inc.
+# Copyright 1992-2016 Free Software Foundation, Inc.
-timestamp='2015-11-22'
+timestamp='2016-01-01'
# 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
@@ -33,7 +33,7 @@ timestamp='2015-11-22'
# Otherwise, we print the canonical config type on stdout and succeed.
# You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
@@ -67,7 +67,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
-Copyright 1992-2015 Free Software Foundation, Inc.
+Copyright 1992-2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -520,7 +520,7 @@ case $basic_machine in
basic_machine=i386-pc
os=-aros
;;
- asmjs)
+ asmjs)
basic_machine=asmjs-unknown
;;
aux)
@@ -1382,7 +1382,7 @@ case $os in
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
- | -bitrig* | -openbsd* | -solidbsd* \
+ | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
diff --git a/depends/packages/miniupnpc.mk b/depends/packages/miniupnpc.mk
index 3d5a6df974..45fa03631f 100644
--- a/depends/packages/miniupnpc.mk
+++ b/depends/packages/miniupnpc.mk
@@ -1,8 +1,8 @@
package=miniupnpc
-$(package)_version=1.9.20151026
+$(package)_version=1.9.20160209
$(package)_download_path=http://miniupnp.free.fr/files
$(package)_file_name=$(package)-$($(package)_version).tar.gz
-$(package)_sha256_hash=f3cf9a5a31588a917d4d9237e5bc50f84d00c5aa48e27ed50d9b88dfa6a25d47
+$(package)_sha256_hash=572171eacc1d72537ce47b6f4571260757ab7bcfdaf54c3a55c7f88594d94b6f
define $(package)_set_vars
$(package)_build_opts=CC="$($(package)_cc)"
diff --git a/depends/patches/boost/darwin_boost_atomic-1.patch b/depends/patches/boost/darwin_boost_atomic-1.patch
deleted file mode 100644
index 97f59cb7e4..0000000000
--- a/depends/patches/boost/darwin_boost_atomic-1.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-diff --git a/include/boost/atomic/detail/cas128strong.hpp b/include/boost/atomic/detail/cas128strong.hpp
-index 906c13e..dcb4d7d 100644
---- a/include/boost/atomic/detail/cas128strong.hpp
-+++ b/include/boost/atomic/detail/cas128strong.hpp
-@@ -196,15 +196,17 @@ class base_atomic<T, void, 16, Sign>
-
- public:
- BOOST_DEFAULTED_FUNCTION(base_atomic(void), {})
-- explicit base_atomic(value_type const& v) BOOST_NOEXCEPT : v_(0)
-+ explicit base_atomic(value_type const& v) BOOST_NOEXCEPT
- {
-+ memset(&v_, 0, sizeof(v_));
- memcpy(&v_, &v, sizeof(value_type));
- }
-
- void
- store(value_type const& value, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
- {
-- storage_type value_s = 0;
-+ storage_type value_s;
-+ memset(&value_s, 0, sizeof(value_s));
- memcpy(&value_s, &value, sizeof(value_type));
- platform_fence_before_store(order);
- platform_store128(value_s, &v_);
-@@ -247,7 +249,9 @@ class base_atomic<T, void, 16, Sign>
- memory_order success_order,
- memory_order failure_order) volatile BOOST_NOEXCEPT
- {
-- storage_type expected_s = 0, desired_s = 0;
-+ storage_type expected_s, desired_s;
-+ memset(&expected_s, 0, sizeof(expected_s));
-+ memset(&desired_s, 0, sizeof(desired_s));
- memcpy(&expected_s, &expected, sizeof(value_type));
- memcpy(&desired_s, &desired, sizeof(value_type));
-
diff --git a/depends/patches/boost/darwin_boost_atomic-2.patch b/depends/patches/boost/darwin_boost_atomic-2.patch
deleted file mode 100644
index ca50765200..0000000000
--- a/depends/patches/boost/darwin_boost_atomic-2.patch
+++ /dev/null
@@ -1,55 +0,0 @@
-diff --git a/include/boost/atomic/detail/gcc-atomic.hpp b/include/boost/atomic/detail/gcc-atomic.hpp
-index a130590..4af99a1 100644
---- a/include/boost/atomic/detail/gcc-atomic.hpp
-+++ b/include/boost/atomic/detail/gcc-atomic.hpp
-@@ -958,14 +958,16 @@ class base_atomic<T, void, 16, Sign>
-
- public:
- BOOST_DEFAULTED_FUNCTION(base_atomic(void), {})
-- explicit base_atomic(value_type const& v) BOOST_NOEXCEPT : v_(0)
-+ explicit base_atomic(value_type const& v) BOOST_NOEXCEPT
- {
-+ memset(&v_, 0, sizeof(v_));
- memcpy(&v_, &v, sizeof(value_type));
- }
-
- void store(value_type const& v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
- {
-- storage_type tmp = 0;
-+ storage_type tmp;
-+ memset(&tmp, 0, sizeof(tmp));
- memcpy(&tmp, &v, sizeof(value_type));
- __atomic_store_n(&v_, tmp, atomics::detail::convert_memory_order_to_gcc(order));
- }
-@@ -980,7 +982,8 @@ class base_atomic<T, void, 16, Sign>
-
- value_type exchange(value_type const& v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
- {
-- storage_type tmp = 0;
-+ storage_type tmp;
-+ memset(&tmp, 0, sizeof(tmp));
- memcpy(&tmp, &v, sizeof(value_type));
- tmp = __atomic_exchange_n(&v_, tmp, atomics::detail::convert_memory_order_to_gcc(order));
- value_type res;
-@@ -994,7 +997,9 @@ class base_atomic<T, void, 16, Sign>
- memory_order success_order,
- memory_order failure_order) volatile BOOST_NOEXCEPT
- {
-- storage_type expected_s = 0, desired_s = 0;
-+ storage_type expected_s, desired_s;
-+ memset(&expected_s, 0, sizeof(expected_s));
-+ memset(&desired_s, 0, sizeof(desired_s));
- memcpy(&expected_s, &expected, sizeof(value_type));
- memcpy(&desired_s, &desired, sizeof(value_type));
- const bool success = __atomic_compare_exchange_n(&v_, &expected_s, desired_s, false,
-@@ -1010,7 +1015,9 @@ class base_atomic<T, void, 16, Sign>
- memory_order success_order,
- memory_order failure_order) volatile BOOST_NOEXCEPT
- {
-- storage_type expected_s = 0, desired_s = 0;
-+ storage_type expected_s, desired_s;
-+ memset(&expected_s, 0, sizeof(expected_s));
-+ memset(&desired_s, 0, sizeof(desired_s));
- memcpy(&expected_s, &expected, sizeof(value_type));
- memcpy(&desired_s, &desired, sizeof(value_type));
- const bool success = __atomic_compare_exchange_n(&v_, &expected_s, desired_s, true,
diff --git a/depends/patches/boost/gcc_5_no_cxx11.patch b/depends/patches/boost/gcc_5_no_cxx11.patch
deleted file mode 100644
index 04514c593a..0000000000
--- a/depends/patches/boost/gcc_5_no_cxx11.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From eec808554936ae068b23df07ab54d4dc6302a695 Mon Sep 17 00:00:00 2001
-From: jzmaddock <jzmaddock@gmail.com>
-Date: Sat, 23 Aug 2014 09:38:02 +0100
-Subject: [PATCH] Fix BOOST_NO_CXX11_VARIADIC_TEMPLATES definition - the
- feature was introduced in GCC 4.4.
-
----
- include/boost/config/compiler/gcc.hpp | 9 +--------
- 1 file changed, 1 insertion(+), 8 deletions(-)
-
-diff --git a/include/boost/config/compiler/gcc.hpp b/include/boost/config/compiler/gcc.hpp
-index f37159d..97d8a18 100644
---- a/include/boost/config/compiler/gcc.hpp
-+++ b/include/boost/config/compiler/gcc.hpp
-@@ -154,14 +154,6 @@
- # define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS
- # define BOOST_NO_CXX11_RVALUE_REFERENCES
- # define BOOST_NO_CXX11_STATIC_ASSERT
--
--// Variadic templates compiler:
--// http://www.generic-programming.org/~dgregor/cpp/variadic-templates.html
--# if defined(__VARIADIC_TEMPLATES) || (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4) && defined(__GXX_EXPERIMENTAL_CXX0X__))
--# define BOOST_HAS_VARIADIC_TMPL
--# else
--# define BOOST_NO_CXX11_VARIADIC_TEMPLATES
--# endif
- #endif
-
- // C++0x features in 4.4.n and later
-@@ -176,6 +168,7 @@
- # define BOOST_NO_CXX11_DELETED_FUNCTIONS
- # define BOOST_NO_CXX11_TRAILING_RESULT_TYPES
- # define BOOST_NO_CXX11_INLINE_NAMESPACES
-+# define BOOST_NO_CXX11_VARIADIC_TEMPLATES
- #endif
-
- #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5)
diff --git a/doc/README.md b/doc/README.md
index c0f9ee5220..cf475ef18e 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -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)
diff --git a/doc/bips.md b/doc/bips.md
index e73add0130..b8efabbcf2 100644
--- a/doc/bips.md
+++ b/doc/bips.md
@@ -17,6 +17,7 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.12.0**):
* [`BIP 65`](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki): The CHECKLOCKTIMEVERIFY softfork was merged in **v0.12.0** ([PR #6351](https://github.com/bitcoin/bitcoin/pull/6351)), and backported to **v0.11.2** and **v0.10.4**. Mempool-only CLTV was added in [PR #6124](https://github.com/bitcoin/bitcoin/pull/6124).
* [`BIP 66`](https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki): The strict DER rules and associated version 3 blocks have been implemented since **v0.10.0** ([PR #5713](https://github.com/bitcoin/bitcoin/pull/5713)).
* [`BIP 70`](https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki) [`71`](https://github.com/bitcoin/bips/blob/master/bip-0071.mediawiki) [`72`](https://github.com/bitcoin/bips/blob/master/bip-0072.mediawiki): Payment Protocol support has been available in Bitcoin Core GUI since **v0.9.0** ([PR #5216](https://github.com/bitcoin/bitcoin/pull/5216)).
-* [`BIP 111`](https://github.com/bitcoin/bips/blob/master/bip-0111.mediawiki): `NODE_BLOOM` service bit added, but only enforced for peer versions `>=70011` as of **v0.12.0** ([PR #6579](https://github.com/bitcoin/bitcoin/pull/6579)).
+* [`BIP 111`](https://github.com/bitcoin/bips/blob/master/bip-0111.mediawiki): `NODE_BLOOM` service bit added, and enforced for all peer versions as of **v0.13.0** ([PR #6579](https://github.com/bitcoin/bitcoin/pull/6579) and [PR #6641](https://github.com/bitcoin/bitcoin/pull/6641)).
* [`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)).
+* [`BIP 133`](https://github.com/bitcoin/bips/blob/master/bip-0133.mediawiki): feefilter messages are respected and sent for peer versions `>=70013` as of **v0.13.0** ([PR 7542](https://github.com/bitcoin/bitcoin/pull/7542)).
diff --git a/doc/build-unix.md b/doc/build-unix.md
index 96de098c38..c1e92d8d15 100644
--- a/doc/build-unix.md
+++ b/doc/build-unix.md
@@ -7,11 +7,11 @@ Some notes on how to build Bitcoin Core in Unix.
Note
---------------------
Always use absolute paths to configure and compile bitcoin and the dependencies,
-for example, when specifying the the path of the dependency:
+for example, when specifying the path of the dependency:
../dist/configure --enable-cxx --disable-shared --with-pic --prefix=$BDB_PREFIX
-Here BDB_PREFIX must absolute path - it is defined using $(pwd) which ensures
+Here BDB_PREFIX must be an absolute path - it is defined using $(pwd) which ensures
the usage of the absolute path.
To Build
@@ -67,15 +67,17 @@ Build requirements:
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
+Options when installing required Boost library files:
+
+1. 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
install necessary parts of boost:
- sudo apt-get install libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-program-options-dev libboost-test-dev libboost-thread-dev
+ sudo apt-get install libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-program-options-dev libboost-test-dev libboost-thread-dev
-If that doesn't work, you can install all boost development packages with:
+2. If that doesn't work, you can install all boost development packages with:
- sudo apt-get install libboost-all-dev
+ sudo apt-get install libboost-all-dev
BerkeleyDB is required for the wallet. db4.8 packages are available [here](https://launchpad.net/~bitcoin/+archive/bitcoin).
You can add the repository and install using the following commands:
@@ -246,3 +248,26 @@ 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. \ No newline at end of file
diff --git a/doc/gitian-building.md b/doc/gitian-building.md
index 5ca91505e7..54993d13a9 100644
--- a/doc/gitian-building.md
+++ b/doc/gitian-building.md
@@ -252,7 +252,7 @@ First we need to log in as `root` to set up dependencies and make sure that our
user can use the sudo command. Type/paste the following in the terminal:
```bash
-apt-get install git ruby sudo apt-cacher-ng qemu-utils debootstrap lxc python-cheetah parted kpartx bridge-utils make ubuntu-archive-keyring
+apt-get install git ruby sudo apt-cacher-ng qemu-utils debootstrap lxc python-cheetah parted kpartx bridge-utils make ubuntu-archive-keyring curl
adduser debian sudo
```
@@ -262,6 +262,7 @@ Then set up LXC and the rest with the following, which is a complex jumble of se
# 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
+echo "%sudo ALL=NOPASSWD: /usr/bin/lxc-execute" >> /etc/sudoers.d/gitian-lxc
# 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
diff --git a/doc/release-notes.md b/doc/release-notes.md
index 801b684e6b..806d174ebf 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -8,6 +8,19 @@ Example item
----------------
+bitcoin-cli: arguments privacy
+--------------------------------
+
+The RPC command line client gained a new argument, `-stdin`
+to read extra arguments from standard input, one per line until EOF/Ctrl-D.
+For example:
+
+ $ echo -e "mysecretcode\n120" | src/bitcoin-cli -stdin walletpassphrase
+
+It is recommended to use this for sensitive information such as wallet
+passphrases, as command-line arguments can usually be read from the process
+table by any user on the system.
+
0.13.0 Change log
=================
@@ -38,6 +51,17 @@ The following outputs are affected by this change:
### P2P protocol and network code
+The p2p alert system has been removed in #7692 and the 'alert' message is no longer supported.
+
+
+Fee filtering of invs (BIP 133)
+------------------------------------
+
+The optional new p2p message "feefilter" is implemented and the protocol
+version is bumped to 70013. Upon receiving a feefilter message from a peer,
+a node will not send invs for any transactions which do not meet the filter
+feerate. [BIP 133](https://github.com/bitcoin/bips/blob/master/bip-0133.mediawiki)
+
### Validation
### Build system
diff --git a/doc/release-notes/release-notes-0.10.4.md b/doc/release-notes/release-notes-0.10.4.md
new file mode 100644
index 0000000000..38a2c1347d
--- /dev/null
+++ b/doc/release-notes/release-notes-0.10.4.md
@@ -0,0 +1,172 @@
+Bitcoin Core version 0.10.4 is now available from:
+
+ <https://bitcoin.org/bin/bitcoin-core-0.10.4/>
+
+This is a new minor version release, bringing bug fixes, the BIP65
+(CLTV) consensus change, and relay policy preparation for BIP113. It is
+recommended to upgrade to this version as soon as possible.
+
+Please report bugs using the issue tracker at github:
+
+ <https://github.com/bitcoin/bitcoin/issues>
+
+Upgrading and downgrading
+=========================
+
+How to Upgrade
+--------------
+
+If you are running an older version, shut it down. Wait until it has completely
+shut down (which might take a few minutes for older versions), then run the
+installer (on Windows) or just copy over /Applications/Bitcoin-Qt (on Mac) or
+bitcoind/bitcoin-qt (on Linux).
+
+Downgrade warning
+------------------
+
+Because release 0.10.0 and later makes use of headers-first synchronization and
+parallel block download (see further), the block files and databases are not
+backwards-compatible with pre-0.10 versions of Bitcoin Core or other software:
+
+* Blocks will be stored on disk out of order (in the order they are
+received, really), which makes it incompatible with some tools or
+other programs. Reindexing using earlier versions will also not work
+anymore as a result of this.
+
+* The block index database will now hold headers for which no block is
+stored on disk, which earlier versions won't support.
+
+If you want to be able to downgrade smoothly, make a backup of your entire data
+directory. Without this your node will need start syncing (or importing from
+bootstrap.dat) anew afterwards. It is possible that the data from a completely
+synchronised 0.10 node may be usable in older versions as-is, but this is not
+supported and may break as soon as the older version attempts to reindex.
+
+This does not affect wallet forward or backward compatibility. There are no
+known problems when downgrading from 0.11.x to 0.10.x.
+
+Notable changes since 0.10.3
+============================
+
+BIP65 soft fork to enforce OP_CHECKLOCKTIMEVERIFY opcode
+--------------------------------------------------------
+
+This release includes several changes related to the [BIP65][] soft fork
+which redefines the existing OP_NOP2 opcode as OP_CHECKLOCKTIMEVERIFY
+(CLTV) so that a transaction output can be made unspendable until a
+specified point in the future.
+
+1. This release will only relay and mine transactions spending a CLTV
+ output if they comply with the BIP65 rules as provided in code.
+
+2. This release will produce version 4 blocks by default. Please see the
+ *notice to miners* below.
+
+3. Once 951 out of a sequence of 1,001 blocks on the local node's best block
+ chain contain version 4 (or higher) blocks, this release will no
+ longer accept new version 3 blocks and it will only accept version 4
+ blocks if they comply with the BIP65 rules for CLTV.
+
+For more information about the soft-forking change, please see
+<https://github.com/bitcoin/bitcoin/pull/6351>
+
+Graphs showing the progress towards block version 4 adoption may be
+found at the URLs below:
+
+- Block versions over the last 50,000 blocks as progress towards BIP65
+ consensus enforcement: <http://bitcoin.sipa.be/ver-50k.png>
+
+- Block versions over the last 2,000 blocks showing the days to the
+ earliest possible BIP65 consensus-enforced block: <http://bitcoin.sipa.be/ver-2k.png>
+
+**Notice to miners:** 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 libblkmaker either
+version FIXME or any version from FIXME 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.
+
+[BIP65]: https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki
+
+Windows bug fix for corrupted UTXO database on unclean shutdowns
+----------------------------------------------------------------
+
+Several Windows users reported that they often need to reindex the
+entire blockchain after an unclean shutdown of Bitcoin Core on Windows
+(or an unclean shutdown of Windows itself). Although unclean shutdowns
+remain unsafe, this release no longer relies on memory-mapped files for
+the UTXO database, which significantly reduced the frequency of unclean
+shutdowns leading to required reindexes during testing.
+
+For more information, see: <https://github.com/bitcoin/bitcoin/pull/6917>
+
+Other fixes for database corruption on Windows are expected in the
+next major release.
+
+0.10.4 Change log
+=================
+
+Detailed release notes follow. This overview includes changes that affect
+behavior, not code moves, refactors and string updates. For convenience in locating
+the code changes and accompanying discussion, both the pull request and
+git merge commit are mentioned.
+
+- #6953 `8b3311f` alias -h for --help
+- #6953 `97546fc` Change URLs to https in debian/control
+- #6953 `38671bf` Update debian/changelog and slight tweak to debian/control
+- #6953 `256321e` Correct spelling mistakes in doc folder
+- #6953 `eae0350` Clarification of unit test build instructions
+- #6953 `90897ab` Update bluematt-key, the old one is long-since revoked
+- #6953 `a2f2fb6` build: disable -Wself-assign
+- #6953 `cf67d8b` Bugfix: Allow mining on top of old tip blocks for testnet (fixes testnet-in-a-box use case)
+- #6953 `b3964e3` Drop "with minimal dependencies" from description
+- #6953 `43c2789` Split bitcoin-tx into its own package
+- #6953 `dfe0d4d` Include bitcoin-tx binary on Debian/Ubuntu
+- #6953 `612efe8` [Qt] Raise debug window when requested
+- #6953 `3ad96bd` Fix locking in GetTransaction
+- #6953 `9c81005` Fix spelling of Qt
+- #6946 `94b67e5` Update LevelDB
+- #6706 `5dc72f8` CLTV: Add more tests to improve coverage
+- #6706 `6a1343b` Add RPC tests for the CHECKLOCKTIMEVERIFY (BIP65) soft-fork
+- #6706 `4137248` Add CHECKLOCKTIMEVERIFY (BIP65) soft-fork logic
+- #6706 `0e01d0f` Enable CHECKLOCKTIMEVERIFY as a standard script verify flag
+- #6706 `6d01325` Replace NOP2 with CHECKLOCKTIMEVERIFY (BIP65)
+- #6706 `750d54f` Move LOCKTIME_THRESHOLD to src/script/script.h
+- #6706 `6897468` Make CScriptNum() take nMaxNumSize as an argument
+- #6867 `5297194` Set TCP_NODELAY on P2P sockets
+- #6836 `fb818b6` Bring historical release notes up to date
+- #6852 `0b3fd07` build: make sure OpenSSL heeds noexecstack
+
+Credits
+=======
+
+Thanks to everyone who directly contributed to this release:
+
+- Alex Morcos
+- Daniel Cousens
+- Diego Viola
+- Eric Lombrozo
+- Esteban Ordano
+- Gregory Maxwell
+- Luke Dashjr
+- MarcoFalke
+- Matt Corallo
+- Micha
+- Mitchell Cash
+- Peter Todd
+- Pieter Wuille
+- Wladimir J. van der Laan
+- Zak Wilcox
+
+And those who contributed additional code review and/or security research.
+
+As well as everyone that helped translating on [Transifex](https://www.transifex.com/projects/p/bitcoin/).
diff --git a/doc/release-notes/release-notes-0.11.2.md b/doc/release-notes/release-notes-0.11.2.md
new file mode 100644
index 0000000000..2351b80656
--- /dev/null
+++ b/doc/release-notes/release-notes-0.11.2.md
@@ -0,0 +1,217 @@
+Bitcoin Core version 0.11.2 is now available from:
+
+ <https://bitcoin.org/bin/bitcoin-core-0.11.2/>
+
+This is a new minor version release, bringing bug fixes, the BIP65
+(CLTV) consensus change, and relay policy preparation for BIP113. It is
+recommended to upgrade to this version as soon as possible.
+
+Please report bugs using the issue tracker at github:
+
+ <https://github.com/bitcoin/bitcoin/issues>
+
+Upgrading and downgrading
+=========================
+
+How to Upgrade
+--------------
+
+If you are running an older version, shut it down. Wait until it has completely
+shut down (which might take a few minutes for older versions), then run the
+installer (on Windows) or just copy over /Applications/Bitcoin-Qt (on Mac) or
+bitcoind/bitcoin-qt (on Linux).
+
+Downgrade warning
+------------------
+
+Because release 0.10.0 and later makes use of headers-first synchronization and
+parallel block download (see further), the block files and databases are not
+backwards-compatible with pre-0.10 versions of Bitcoin Core or other software:
+
+* Blocks will be stored on disk out of order (in the order they are
+received, really), which makes it incompatible with some tools or
+other programs. Reindexing using earlier versions will also not work
+anymore as a result of this.
+
+* The block index database will now hold headers for which no block is
+stored on disk, which earlier versions won't support.
+
+If you want to be able to downgrade smoothly, make a backup of your entire data
+directory. Without this your node will need start syncing (or importing from
+bootstrap.dat) anew afterwards. It is possible that the data from a completely
+synchronised 0.10 node may be usable in older versions as-is, but this is not
+supported and may break as soon as the older version attempts to reindex.
+
+This does not affect wallet forward or backward compatibility. There are no
+known problems when downgrading from 0.11.x to 0.10.x.
+
+Notable changes since 0.11.1
+============================
+
+BIP65 soft fork to enforce OP_CHECKLOCKTIMEVERIFY opcode
+--------------------------------------------------------
+
+This release includes several changes related to the [BIP65][] soft fork
+which redefines the existing OP_NOP2 opcode as OP_CHECKLOCKTIMEVERIFY
+(CLTV) so that a transaction output can be made unspendable until a
+specified point in the future.
+
+1. This release will only relay and mine transactions spending a CLTV
+ output if they comply with the BIP65 rules as provided in code.
+
+2. This release will produce version 4 blocks by default. Please see the
+ *notice to miners* below.
+
+3. Once 951 out of a sequence of 1,001 blocks on the local node's best block
+ chain contain version 4 (or higher) blocks, this release will no
+ longer accept new version 3 blocks and it will only accept version 4
+ blocks if they comply with the BIP65 rules for CLTV.
+
+For more information about the soft-forking change, please see
+<https://github.com/bitcoin/bitcoin/pull/6351>
+
+Graphs showing the progress towards block version 4 adoption may be
+found at the URLs below:
+
+- Block versions over the last 50,000 blocks as progress towards BIP65
+ consensus enforcement: <http://bitcoin.sipa.be/ver-50k.png>
+
+- Block versions over the last 2,000 blocks showing the days to the
+ earliest possible BIP65 consensus-enforced block: <http://bitcoin.sipa.be/ver-2k.png>
+
+**Notice to miners:** 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 libblkmaker either
+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.
+
+[BIP65]: https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki
+
+BIP113 mempool-only locktime enforcement using GetMedianTimePast()
+----------------------------------------------------------------
+
+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.
+
+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.
+
+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.
+
+[BIP113][] specifies a soft fork (**not 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.
+
+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.
+
+**Implication for miners:** you will begin rejecting transactions that
+would not be valid under BIP113, which will prevent you from producing
+invalid blocks if/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.
+
+**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.
+
+[BIP113]: https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki
+
+Windows bug fix for corrupted UTXO database on unclean shutdowns
+----------------------------------------------------------------
+
+Several Windows users reported that they often need to reindex the
+entire blockchain after an unclean shutdown of Bitcoin Core on Windows
+(or an unclean shutdown of Windows itself). Although unclean shutdowns
+remain unsafe, this release no longer relies on memory-mapped files for
+the UTXO database, which significantly reduced the frequency of unclean
+shutdowns leading to required reindexes during testing.
+
+For more information, see: <https://github.com/bitcoin/bitcoin/pull/6917>
+
+Other fixes for database corruption on Windows are expected in the
+next major release.
+
+0.11.2 Change log
+=================
+
+Detailed release notes follow. This overview includes changes that affect
+behavior, not code moves, refactors and string updates. For convenience in locating
+the code changes and accompanying discussion, both the pull request and
+git merge commit are mentioned.
+
+- #6124 `684636b` Make CScriptNum() take nMaxNumSize as an argument
+- #6124 `4fa7a04` Replace NOP2 with CHECKLOCKTIMEVERIFY (BIP65)
+- #6124 `6ea5ca4` Enable CHECKLOCKTIMEVERIFY as a standard script verify flag
+- #6351 `5e82e1c` Add CHECKLOCKTIMEVERIFY (BIP65) soft-fork logic
+- #6353 `ba1da90` Show softfork status in getblockchaininfo
+- #6351 `6af25b0` Add BIP65 to getblockchaininfo softforks list
+- #6688 `01878c9` Fix locking in GetTransaction
+- #6653 `b3eaa30` [Qt] Raise debug window when requested
+- #6600 `1e672ae` Debian/Ubuntu: Include bitcoin-tx binary
+- #6600 `2394f4d` Debian/Ubuntu: Split bitcoin-tx into its own package
+- #5987 `33d6825` Bugfix: Allow mining on top of old tip blocks for testnet
+- #6852 `21e58b8` build: make sure OpenSSL heeds noexecstack
+- #6846 `af6edac` alias `-h` for `--help`
+- #6867 `95a5039` Set TCP_NODELAY on P2P sockets.
+- #6856 `dfe55bd` Do not allow blockfile pruning during reindex.
+- #6566 `a1d3c6f` Add rules--presently disabled--for using GetMedianTimePast as end point for lock-time calculations
+- #6566 `f720c5f` Enable policy enforcing GetMedianTimePast as the end point of lock-time constraints
+- #6917 `0af5b8e` leveldb: Win32WritableFile without memory mapping
+- #6948 `4e895b0` Always flush block and undo when switching to new file
+
+Credits
+=======
+
+Thanks to everyone who directly contributed to this release:
+
+- Alex Morcos
+- ฿tcDrak
+- Chris Kleeschulte
+- Daniel Cousens
+- Diego Viola
+- Eric Lombrozo
+- Esteban Ordano
+- Gregory Maxwell
+- Luke Dashjr
+- Marco Falke
+- Mark Friedenbach
+- Matt Corallo
+- Micha
+- Mitchell Cash
+- Peter Todd
+- Pieter Wuille
+- Wladimir J. van der Laan
+- Zak Wilcox
+
+And those who contributed additional code review and/or security research.
+
+As well as everyone that helped translating on [Transifex](https://www.transifex.com/projects/p/bitcoin/).
diff --git a/doc/release-notes/release-notes-0.12.0.md b/doc/release-notes/release-notes-0.12.0.md
new file mode 100644
index 0000000000..135cd68a7c
--- /dev/null
+++ b/doc/release-notes/release-notes-0.12.0.md
@@ -0,0 +1,890 @@
+Bitcoin Core version 0.12.0 is now available from:
+
+ <https://bitcoin.org/bin/bitcoin-core-0.12.0/>
+
+This is a new major version release, bringing new features and other improvements.
+
+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.10.0
+
+Because release 0.10.0 and later makes use of headers-first synchronization and
+parallel block download (see further), the block files and databases are not
+backwards-compatible with pre-0.10 versions of Bitcoin Core or other software:
+
+* Blocks will be stored on disk out of order (in the order they are
+received, really), which makes it incompatible with some tools or
+other programs. Reindexing using earlier versions will also not work
+anymore as a result of this.
+
+* The block index database will now hold headers for which no block is
+stored on disk, which earlier versions won't support.
+
+If you want to be able to downgrade smoothly, make a backup of your entire data
+directory. Without this your node will need start syncing (or importing from
+bootstrap.dat) anew afterwards. It is possible that the data from a completely
+synchronised 0.10 node may be usable in older versions as-is, but this is not
+supported and may break as soon as the older version attempts to reindex.
+
+This does not affect wallet forward or backward compatibility.
+
+### 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
+===============
+
+Signature validation using libsecp256k1
+---------------------------------------
+
+ECDSA signatures inside Bitcoin transactions now use validation using
+[libsecp256k1](https://github.com/bitcoin/secp256k1) instead of OpenSSL.
+
+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.
+
+Reduce upload traffic
+---------------------
+
+A major part of the outbound traffic is caused by serving historic blocks to
+other nodes in initial block download state.
+
+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.
+
+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.
+
+Whitelisted peers will never be disconnected, although their traffic counts for
+calculating the target.
+
+A more detailed documentation about keeping traffic low can be found in
+[/doc/reduce-traffic.md](/doc/reduce-traffic.md).
+
+Direct headers announcement (BIP 130)
+-------------------------------------
+
+Between compatible peers, [BIP 130]
+(https://github.com/bitcoin/bips/blob/master/bip-0130.mediawiki)
+direct headers announcement is used. This means that blocks are advertised 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.
+
+With this change, pruning nodes are now able to relay new blocks to compatible
+peers.
+
+Memory pool limiting
+--------------------
+
+Previous versions of Bitcoin Core had their mempool limited by checking
+a transaction's fees against the node's minimum relay fee. There was no
+upper bound on the size of the mempool and attackers could send a large
+number of transactions paying just slighly more than the default minimum
+relay fee to crash nodes with relatively low RAM. A temporary workaround
+for previous versions of Bitcoin Core was to raise the default minimum
+relay fee.
+
+Bitcoin Core 0.12 will have a strict maximum size on the mempool. The
+default value is 300 MB and can be configured with the `-maxmempool`
+parameter. Whenever a transaction would cause the mempool to exceed
+its maximum size, the transaction that (along with in-mempool descendants) has
+the lowest total feerate (as a package) will be evicted and the node's effective
+minimum relay feerate will be increased to match this feerate plus the initial
+minimum relay feerate. The initial minimum relay feerate is set to
+1000 satoshis per kB.
+
+Bitcoin Core 0.12 also introduces new default policy limits on the length and
+size of unconfirmed transaction chains that are allowed in the mempool
+(generally limiting the length of unconfirmed chains to 25 transactions, with a
+total size of 101 KB). These limits can be overriden using command line
+arguments; see the extended help (`--help -help-debug`) for more information.
+
+Opt-in Replace-by-fee transactions
+----------------------------------
+
+It is now possible to replace transactions in the transaction memory pool of
+Bitcoin Core 0.12 nodes. Bitcoin Core will only allow replacement of
+transactions which have any of their inputs' `nSequence` number set to less
+than `0xffffffff - 1`. Moreover, a replacement transaction may only be
+accepted when it pays sufficient fee, as described in [BIP 125]
+(https://github.com/bitcoin/bips/blob/master/bip-0125.mediawiki).
+
+Transaction replacement can be disabled with a new command line option,
+`-mempoolreplacement=0`. Transactions signaling replacement under BIP125 will
+still be allowed into the mempool in this configuration, but replacements will
+be rejected. This option is intended for miners who want to continue the
+transaction selection behavior of previous releases.
+
+The `-mempoolreplacement` option is *not recommended* for wallet users seeking
+to avoid receipt of unconfirmed opt-in transactions, because this option does
+not prevent transactions which are replaceable under BIP 125 from being accepted
+(only subsequent replacements, which other nodes on the network that implement
+BIP 125 are likely to relay and mine). Wallet users wishing to detect whether
+a transaction is subject to replacement under BIP 125 should instead use the
+updated RPC calls `gettransaction` and `listtransactions`, which now have an
+additional field in the output indicating if a transaction is replaceable under
+BIP125 ("bip125-replaceable").
+
+Note that the wallet in Bitcoin Core 0.12 does not yet have support for
+creating transactions that would be replaceable under BIP 125.
+
+
+RPC: 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.
+
+Relay: 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) after
+the OP_RETURN. 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)
+
+Relay and Mining: Priority transactions
+---------------------------------------
+
+Bitcoin Core has a heuristic 'priority' based on coin value and age. This
+calculation is used for relaying of transactions which do not pay the
+minimum relay fee, and can be used as an alternative way of sorting
+transactions for mined blocks. Bitcoin Core will relay transactions with
+insufficient fees depending on the setting of `-limitfreerelay=<r>` (default:
+`r=15` kB per minute) and `-blockprioritysize=<s>`.
+
+In Bitcoin Core 0.12, when mempool limit has been reached a higher minimum
+relay fee takes effect to limit memory usage. Transactions which do not meet
+this higher effective minimum relay fee will not be relayed or mined even if
+they rank highly according to the priority heuristic.
+
+The mining of transactions based on their priority is also now disabled by
+default. To re-enable it, simply set `-blockprioritysize=<n>` where is the size
+in bytes of your blocks to reserve for these transactions. The old default was
+50k, so to retain approximately the same policy, you would set
+`-blockprioritysize=50000`.
+
+Additionally, as a result of computational simplifications, the priority value
+used for transactions received with unconfirmed inputs is lower than in prior
+versions due to avoiding recomputing the amounts as input transactions confirm.
+
+External miner policy set via the `prioritisetransaction` RPC to rank
+transactions already in the mempool continues to work as it has previously.
+Note, however, that if mining priority transactions is left disabled, the
+priority delta will be ignored and only the fee metric will be effective.
+
+This internal automatic prioritization handling is being considered for removal
+entirely in Bitcoin Core 0.13, and it is at this time undecided whether the
+more accurate priority calculation for chained unconfirmed transactions will be
+restored. Community direction on this topic is particularly requested to help
+set project priorities.
+
+Automatically use Tor hidden services
+-------------------------------------
+
+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.
+
+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.
+
+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`.
+
+Notifications through ZMQ
+-------------------------
+
+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](/doc/zmq.md) for details of operation.
+
+Wallet: Transaction fees
+------------------------
+
+Various improvements have been made to how the wallet calculates
+transaction fees.
+
+Users can decide to pay a predefined fee rate by setting `-paytxfee=<n>`
+(or `settxfee <n>` rpc during runtime). A value of `n=0` signals Bitcoin
+Core to use floating fees. By default, Bitcoin Core will use floating
+fees.
+
+Based on past transaction data, floating fees approximate the fees
+required to get into the `m`th block from now. This is configurable
+with `-txconfirmtarget=<m>` (default: `2`).
+
+Sometimes, it is not possible to give good estimates, or an estimate
+at all. Therefore, a fallback value can be set with `-fallbackfee=<f>`
+(default: `0.0002` BTC/kB).
+
+At all times, Bitcoin Core will cap fees at `-maxtxfee=<x>` (default:
+0.10) BTC.
+Furthermore, Bitcoin Core will never create transactions paying less than
+the current minimum relay fee.
+Finally, a user can set the minimum fee rate for all transactions with
+`-mintxfee=<i>`, which defaults to 1000 satoshis per kB.
+
+Wallet: 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.
+
+Wallet: Merkle branches removed
+-------------------------------
+
+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.
+
+Wallet: Pruning
+---------------
+
+With 0.12 it is possible to use wallet functionality in pruned mode.
+This can reduce the disk usage from currently around 60 GB to
+around 2 GB.
+
+However, rescans as well as the RPCs `importwallet`, `importaddress`,
+`importprivkey` are disabled.
+
+To enable block pruning set `prune=<N>` on the command line or in
+`bitcoin.conf`, where `N` is the number of MiB to allot for
+raw block & undo data.
+
+A value of 0 disables pruning. The minimal value above 0 is 550. Your
+wallet is as secure with high values as it is with low ones. Higher
+values merely ensure that your node will not shut down upon blockchain
+reorganizations of more than 2 days - which are unlikely to happen in
+practice. In future releases, a higher value may also help the network
+as a whole: stored blocks could be served to other nodes.
+
+For further information about pruning, you may also consult the [release
+notes of v0.11.0](https://github.com/bitcoin/bitcoin/blob/v0.11.0/doc/release-notes.md#block-file-pruning).
+
+`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.
+
+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.
+
+RPC: Low-level 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.
+
+* The `asm` property of each scriptSig now contains the decoded signature hash
+ type for each signature that provides a valid defined hash type.
+
+* OP_NOP2 has been renamed to OP_CHECKLOCKTIMEVERIFY by [BIP 65](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki)
+
+The following items contain assembly representations of scriptSig signatures
+and are affected by this change:
+
+- RPC `getrawtransaction`
+- RPC `decoderawtransaction`
+- RPC `decodescript`
+- 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 400000 OP_NOP2
+
+now shows as:
+
+ 304502207fa7a6d1e0ee81132a269ad84e68d695483745cde8b541e3bf630749894e342a022100c1f7ab20e13e22fb95281a870f3dcf38d782e53023ee313d741ad0cfbc0c5090[ALL] 400000 OP_CHECKLOCKTIMEVERIFY
+
+Note that the output of the RPC `decodescript` did not change because it is
+configured specifically to process scriptPubKey and not scriptSig scripts.
+
+RPC: SSL support dropped
+------------------------
+
+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.
+
+Trying to use `rpcssl` will result in an error:
+
+ Error: SSL mode for RPC (-rpcssl) is no longer supported.
+
+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:
+
+ sudo apt-get install stunnel4
+
+Then, to tunnel a SSL connection on 28332 to a RPC server bound on localhost on port 18332 do:
+
+ stunnel -d 28332 -r 127.0.0.1:18332 -p stunnel.pem -P ''
+
+It can also be set up system-wide in inetd style.
+
+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:
+
+ Listen 443
+
+ NameVirtualHost *:443
+ <VirtualHost *:443>
+
+ 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>
+
+Mining Code Changes
+-------------------
+
+The mining code in 0.12 has been optimized to be significantly faster and use less
+memory. As part of these changes, consensus critical calculations are cached on a
+transaction's acceptance into the mempool and the mining code now relies on the
+consistency of the mempool to assemble blocks. However all blocks are still tested
+for validity after assembly.
+
+Other P2P Changes
+-----------------
+
+The list of banned peers is now stored on disk rather than in memory.
+Restarting bitcoind will no longer clear out the list of banned peers; instead
+a new RPC call (`clearbanned`) can be used to manually clear the list. The new
+`setban` RPC call can also be used to manually ban or unban a peer.
+
+0.12.0 Change log
+=================
+
+Detailed release notes follow. This overview includes changes that affect
+behavior, not code moves, refactors and string updates. For convenience in locating
+the code changes and accompanying discussion, both the pull request and
+git merge commit are mentioned.
+
+### RPC and REST
+
+- #6121 `466f0ea` Convert entire source tree from json_spirit to UniValue (Jonas Schnelli)
+- #6234 `d38cd47` fix rpcmining/getblocktemplate univalue transition logic error (Jonas Schnelli)
+- #6239 `643114f` Don't go through double in AmountFromValue and ValueFromAmount (Wladimir J. van der Laan)
+- #6266 `ebab5d3` Fix univalue handling of \u0000 characters. (Daniel Kraft)
+- #6276 `f3d4dbb` Fix getbalance * 0 (Tom Harding)
+- #6257 `5ebe7db` Add `paytxfee` and `errors` JSON fields where appropriate (Stephen)
+- #6271 `754aae5` New RPC command disconnectnode (Alex van der Peet)
+- #6158 `0abfa8a` Add setban/listbanned RPC commands (Jonas Schnelli)
+- #6307 `7ecdcd9` rpcban fixes (Jonas Schnelli)
+- #6290 `5753988` rpc: make `gettxoutsettinfo` run lock-free (Wladimir J. van der Laan)
+- #6262 `247b914` Return all available information via RPC call "validateaddress" (dexX7)
+- #6339 `c3f0490` UniValue: don't escape solidus, keep espacing of reverse solidus (Jonas Schnelli)
+- #6353 `6bcb0a2` Show softfork status in getblockchaininfo (Wladimir J. van der Laan)
+- #6247 `726e286` Add getblockheader RPC call (Peter Todd)
+- #6362 `d6db115` Fix null id in RPC response during startup (Forrest Voight)
+- #5486 `943b322` [REST] JSON support for /rest/headers (Jonas Schnelli)
+- #6379 `c52e8b3` rpc: Accept scientific notation for monetary amounts in JSON (Wladimir J. van der Laan)
+- #6388 `fd5dfda` rpc: Implement random-cookie based authentication (Wladimir J. van der Laan)
+- #6457 `3c923e8` Include pruned state in chaininfo.json (Simon Males)
+- #6456 `bfd807f` rpc: Avoid unnecessary parsing roundtrip in number formatting, fix locale issue (Wladimir J. van der Laan)
+- #6380 `240b30e` rpc: Accept strings in AmountFromValue (Wladimir J. van der Laan)
+- #6346 `6bb2805` Add OP_RETURN support in createrawtransaction RPC call, add tests. (paveljanik)
+- #6013 `6feeec1` [REST] Add memory pool API (paveljanik)
+- #6576 `da9beb2` Stop parsing JSON after first finished construct. (Daniel Kraft)
+- #5677 `9aa9099` libevent-based http server (Wladimir J. van der Laan)
+- #6633 `bbc2b39` Report minimum ping time in getpeerinfo (Matt Corallo)
+- #6648 `cd381d7` Simplify logic of REST request suffix parsing. (Daniel Kraft)
+- #6695 `5e21388` libevent http fixes (Wladimir J. van der Laan)
+- #5264 `48efbdb` show scriptSig signature hash types in transaction decodes. fixes #3166 (mruddy)
+- #6719 `1a9f19a` Make HTTP server shutdown more graceful (Wladimir J. van der Laan)
+- #6859 `0fbfc51` http: Restrict maximum size of http + headers (Wladimir J. van der Laan)
+- #5936 `bf7c195` [RPC] Add optional locktime to createrawtransaction (Tom Harding)
+- #6877 `26f5b34` rpc: Add maxmempool and effective min fee to getmempoolinfo (Wladimir J. van der Laan)
+- #6970 `92701b3` Fix crash in validateaddress with -disablewallet (Wladimir J. van der Laan)
+- #5574 `755b4ba` Expose GUI labels in RPC as comments (Luke-Jr)
+- #6990 `dbd2c13` http: speed up shutdown (Wladimir J. van der Laan)
+- #7013 `36baa9f` Remove LOCK(cs_main) from decodescript (Peter Todd)
+- #6999 `972bf9c` add (max)uploadtarget infos to getnettotals RPC help (Jonas Schnelli)
+- #7011 `31de241` Add mediantime to getblockchaininfo (Peter Todd)
+- #7065 `f91e29f` http: add Boost 1.49 compatibility (Wladimir J. van der Laan)
+- #7087 `be281d8` [Net]Add -enforcenodebloom option (Patrick Strateman)
+- #7044 `438ee59` RPC: Added additional config option for multiple RPC users. (Gregory Sanders)
+- #7072 `c143c49` [RPC] Add transaction size to JSON output (Nikita Zhavoronkov)
+- #7022 `9afbd96` Change default block priority size to 0 (Alex Morcos)
+- #7141 `c0c08c7` rpc: Don't translate warning messages (Wladimir J. van der Laan)
+- #7312 `fd4bd50` Add RPC call abandontransaction (Alex Morcos)
+- #7222 `e25b158` RPC: indicate which transactions are replaceable (Suhas Daftuar)
+- #7472 `b2f2b85` rpc: Add WWW-Authenticate header to 401 response (Wladimir J. van der Laan)
+- #7469 `9cb31e6` net.h fix spelling: misbeha{b,v}ing (Matt)
+
+### Configuration and command-line options
+
+- #6164 `8d05ec7` Allow user to use -debug=1 to enable all debugging (lpescher)
+- #5288 `4452205` Added `-whiteconnections=<n>` option (Josh Lehan)
+- #6284 `10ac38e` Fix argument parsing oddity with -noX (Wladimir J. van der Laan)
+- #6489 `c9c017a` Give a better error message if system clock is bad (Casey Rodarmor)
+- #6462 `c384800` implement uacomment config parameter which can add comments to user agent as per BIP-0014 (Pavol Rusnak)
+- #6647 `a3babc8` Sanitize uacomment (MarcoFalke)
+- #6742 `3b2d37c` Changed logging to make -logtimestamps to work also for -printtoconsole (arnuschky)
+- #6846 `2cd020d` alias -h for -help (Daniel Cousens)
+- #6622 `7939164` Introduce -maxuploadtarget (Jonas Schnelli)
+- #6881 `2b62551` Debug: Add option for microsecond precision in debug.log (Suhas Daftuar)
+- #6776 `e06c14f` Support -checkmempool=N, which runs checks once every N transactions (Pieter Wuille)
+- #6896 `d482c0a` Make -checkmempool=1 not fail through int32 overflow (Pieter Wuille)
+- #6993 `b632145` Add -blocksonly option (Patrick Strateman)
+- #7323 `a344880` 0.12: Backport -bytespersigop option (Luke-Jr)
+- #7386 `da83ecd` Add option `-permitrbf` to set transaction replacement policy (Wladimir J. van der Laan)
+- #7290 `b16b5bc` Add missing options help (MarcoFalke)
+- #7440 `c76bfff` Rename permitrbf to mempoolreplacement and provide minimal string-list forward compatibility (Luke-Jr)
+
+### Block and transaction handling
+
+- #6203 `f00b623` Remove P2SH coinbase flag, no longer interesting (Luke-Jr)
+- #6222 `9c93ee5` Explicitly set tx.nVersion for the genesis block and mining tests (Mark Friedenbach)
+- #5985 `3a1d3e8` Fix removing of orphan transactions (Alex Morcos)
+- #6221 `dd8fe82` Prune: Support noncontiguous block files (Adam Weiss)
+- #6124 `41076aa` Mempool only CHECKLOCKTIMEVERIFY (BIP65) verification, unparameterized version (Peter Todd)
+- #6329 `d0a10c1` acceptnonstdtxn option to skip (most) "non-standard transaction" checks, for testnet/regtest only (Luke-Jr)
+- #6410 `7cdefb9` Implement accurate memory accounting for mempool (Pieter Wuille)
+- #6444 `24ce77d` Exempt unspendable transaction outputs from dust checks (dexX7)
+- #5913 `a0625b8` Add absurdly high fee message to validation state (Shaul Kfir)
+- #6177 `2f746c6` Prevent block.nTime from decreasing (Mark Friedenbach)
+- #6377 `e545371` Handle no chain tip available in InvalidChainFound() (Ross Nicoll)
+- #6551 `39ddaeb` Handle leveldb::DestroyDB() errors on wipe failure (Adam Weiss)
+- #6654 `b0ce450` Mempool package tracking (Suhas Daftuar)
+- #6715 `82d2aef` Fix mempool packages (Suhas Daftuar)
+- #6680 `4f44530` use CBlockIndex instead of uint256 for UpdatedBlockTip signal (Jonas Schnelli)
+- #6650 `4fac576` Obfuscate chainstate (James O'Beirne)
+- #6777 `9caaf6e` Unobfuscate chainstate data in CCoinsViewDB::GetStats (James O'Beirne)
+- #6722 `3b20e23` Limit mempool by throwing away the cheapest txn and setting min relay fee to it (Matt Corallo)
+- #6889 `38369dd` fix locking issue with new mempool limiting (Jonas Schnelli)
+- #6464 `8f3b3cd` Always clean up manual transaction prioritization (Casey Rodarmor)
+- #6865 `d0badb9` Fix chainstate serialized_size computation (Pieter Wuille)
+- #6566 `ff057f4` BIP-113: Mempool-only median time-past as endpoint for lock-time calculations (Mark Friedenbach)
+- #6934 `3038eb6` Restores mempool only BIP113 enforcement (Gregory Maxwell)
+- #6965 `de7d459` Benchmark sanity checks and fork checks in ConnectBlock (Matt Corallo)
+- #6918 `eb6172a` Make sigcache faster, more efficient, larger (Pieter Wuille)
+- #6771 `38ed190` Policy: Lower default limits for tx chains (Alex Morcos)
+- #6932 `73fa5e6` ModifyNewCoins saves database lookups (Alex Morcos)
+- #5967 `05d5918` Alter assumptions in CCoinsViewCache::BatchWrite (Alex Morcos)
+- #6871 `0e93586` nSequence-based Full-RBF opt-in (Peter Todd)
+- #7008 `eb77416` Lower bound priority (Alex Morcos)
+- #6915 `2ef5ffa` [Mempool] Improve removal of invalid transactions after reorgs (Suhas Daftuar)
+- #6898 `4077ad2` Rewrite CreateNewBlock (Alex Morcos)
+- #6872 `bdda4d5` Remove UTXO cache entries when the tx they were added for is removed/does not enter mempool (Matt Corallo)
+- #7062 `12c469b` [Mempool] Fix mempool limiting and replace-by-fee for PrioritiseTransaction (Suhas Daftuar)
+- #7276 `76de36f` Report non-mandatory script failures correctly (Pieter Wuille)
+- #7217 `e08b7cb` Mark blocks with too many sigops as failed (Suhas Daftuar)
+- #7387 `f4b2ce8` Get rid of inaccurate ScriptSigArgsExpected (Pieter Wuille)
+
+### P2P protocol and network code
+
+- #6172 `88a7ead` Ignore getheaders requests when not synced (Suhas Daftuar)
+- #5875 `9d60602` Be stricter in processing unrequested blocks (Suhas Daftuar)
+- #6256 `8ccc07c` Use best header chain timestamps to detect partitioning (Gavin Andresen)
+- #6283 `a903ad7` make CAddrMan::size() return the correct type of size_t (Diapolo)
+- #6272 `40400d5` Improve proxy initialization (continues #4871) (Wladimir J. van der Laan, Diapolo)
+- #6310 `66e5465` banlist.dat: store banlist on disk (Jonas Schnelli)
+- #6412 `1a2de32` Test whether created sockets are select()able (Pieter Wuille)
+- #6498 `219b916` Keep track of recently rejected transactions with a rolling bloom filter (cont'd) (Peter Todd)
+- #6556 `70ec975` Fix masking of irrelevant bits in address groups. (Alex Morcos)
+- #6530 `ea19c2b` Improve addrman Select() performance when buckets are nearly empty (Pieter Wuille)
+- #6583 `af9305a` add support for miniupnpc api version 14 (Pavel Vasin)
+- #6374 `69dc5b5` Connection slot exhaustion DoS mitigation (Patrick Strateman)
+- #6636 `536207f` net: correctly initialize nMinPingUsecTime (Wladimir J. van der Laan)
+- #6579 `0c27795` Add NODE_BLOOM service bit and bump protocol version (Matt Corallo)
+- #6148 `999c8be` Relay blocks when pruning (Suhas Daftuar)
+- #6588 `cf9bb11` In (strCommand == "tx"), return if AlreadyHave() (Tom Harding)
+- #6974 `2f71b07` Always allow getheaders from whitelisted peers (Wladimir J. van der Laan)
+- #6639 `bd629d7` net: Automatically create hidden service, listen on Tor (Wladimir J. van der Laan)
+- #6984 `9ffc687` don't enforce maxuploadtarget's disconnect for whitelisted peers (Jonas Schnelli)
+- #7046 `c322652` Net: Improve blocks only mode. (Patrick Strateman)
+- #7090 `d6454f6` Connect to Tor hidden services by default (when listening on Tor) (Peter Todd)
+- #7106 `c894fbb` Fix and improve relay from whitelisted peers (Pieter Wuille)
+- #7129 `5d5ef3a` Direct headers announcement (rebase of #6494) (Pieter Wuille)
+- #7079 `1b5118b` Prevent peer flooding inv request queue (redux) (redux) (Gregory Maxwell)
+- #7166 `6ba25d2` Disconnect on mempool requests from peers when over the upload limit. (Gregory Maxwell)
+- #7133 `f31955d` Replace setInventoryKnown with a rolling bloom filter (rebase of #7100) (Pieter Wuille)
+- #7174 `82aff88` Don't do mempool lookups for "mempool" command without a filter (Matt Corallo)
+- #7179 `44fef99` net: Fix sent reject messages for blocks and transactions (Wladimir J. van der Laan)
+- #7181 `8fc174a` net: Add and document network messages in protocol.h (Wladimir J. van der Laan)
+- #7125 `10b88be` Replace global trickle node with random delays (Pieter Wuille)
+- #7415 `cb83beb` net: Hardcoded seeds update January 2016 (Wladimir J. van der Laan)
+- #7438 `e2d9a58` Do not absolutely protect local peers; decide group ties based on time (Gregory Maxwell)
+- #7439 `86755bc` Add whitelistforcerelay to control forced relaying. [#7099 redux] (Gregory Maxwell)
+- #7482 `e16f5b4` Ensure headers count is correct (Suhas Daftuar)
+
+### Validation
+
+- #5927 `8d9f0a6` Reduce checkpoints' effect on consensus. (Pieter Wuille)
+- #6299 `24f2489` Bugfix: Don't check the genesis block header before accepting it (Jorge Timón)
+- #6361 `d7ada03` Use real number of cores for default -par, ignore virtual cores (Wladimir J. van der Laan)
+- #6519 `87f37e2` Make logging for validation optional (Wladimir J. van der Laan)
+- #6351 `2a1090d` CHECKLOCKTIMEVERIFY (BIP65) IsSuperMajority() soft-fork (Peter Todd)
+- #6931 `54e8bfe` Skip BIP 30 verification where not necessary (Alex Morcos)
+- #6954 `e54ebbf` Switch to libsecp256k1-based ECDSA validation (Pieter Wuille)
+- #6508 `61457c2` Switch to a constant-space Merkle root/branch algorithm. (Pieter Wuille)
+- #6914 `327291a` Add pre-allocated vector type and use it for CScript (Pieter Wuille)
+- #7500 `889e5b3` Correctly report high-S violations (Pieter Wuille)
+
+
+### Build system
+
+- #6210 `0e4f2a0` build: disable optional use of gmp in internal secp256k1 build (Wladimir J. van der Laan)
+- #6214 `87406aa` [OSX] revert renaming of Bitcoin-Qt.app and use CFBundleDisplayName (partial revert of #6116) (Jonas Schnelli)
+- #6218 `9d67b10` build/gitian misc updates (Cory Fields)
+- #6269 `d4565b6` gitian: Use the new bitcoin-detached-sigs git repo for OSX signatures (Cory Fields)
+- #6418 `d4a910c` Add autogen.sh to source tarball. (randy-waterhouse)
+- #6373 `1ae3196` depends: non-qt bumps for 0.12 (Cory Fields)
+- #6434 `059b352` Preserve user-passed CXXFLAGS with --enable-debug (Gavin Andresen)
+- #6501 `fee6554` Misc build fixes (Cory Fields)
+- #6600 `ef4945f` Include bitcoin-tx binary on Debian/Ubuntu (Zak Wilcox)
+- #6619 `4862708` depends: bump miniupnpc and ccache (Michael Ford)
+- #6801 `ae69a75` [depends] Latest config.guess and config.sub (Michael Ford)
+- #6938 `193f7b5` build: If both Qt4 and Qt5 are installed, use Qt5 (Wladimir J. van der Laan)
+- #7092 `348b281` build: Set osx permissions in the dmg to make Gatekeeper happy (Cory Fields)
+- #6980 `eccd671` [Depends] Bump Boost, miniupnpc, ccache & zeromq (Michael Ford)
+- #7424 `aa26ee0` Add security/export checks to gitian and fix current failures (Cory Fields)
+
+### Wallet
+
+- #6183 `87550ee` Fix off-by-one error w/ nLockTime in the wallet (Peter Todd)
+- #6057 `ac5476e` re-enable wallet in autoprune (Jonas Schnelli)
+- #6356 `9e6c33b` Delay initial pruning until after wallet init (Adam Weiss)
+- #6088 `91389e5` fundrawtransaction (Matt Corallo)
+- #6415 `ddd8d80` Implement watchonly support in fundrawtransaction (Matt Corallo)
+- #6567 `0f0f323` Fix crash when mining with empty keypool. (Daniel Kraft)
+- #6688 `4939eab` Fix locking in GetTransaction. (Alex Morcos)
+- #6645 `4dbd43e` Enable wallet key imports without rescan in pruned mode. (Gregory Maxwell)
+- #6550 `5b77244` Do not store Merkle branches in the wallet. (Pieter Wuille)
+- #5924 `12a7712` Clean up change computation in CreateTransaction. (Daniel Kraft)
+- #6906 `48b5b84` Reject invalid pubkeys when reading ckey items from the wallet. (Gregory Maxwell)
+- #7010 `e0a5ef8` Fix fundrawtransaction handling of includeWatching (Peter Todd)
+- #6851 `616d61b` Optimisation: Store transaction list order in memory rather than compute it every need (Luke-Jr)
+- #6134 `e92377f` Improve usage of fee estimation code (Alex Morcos)
+- #7103 `a775182` [wallet, rpc tests] Fix settxfee, paytxfee (MarcoFalke)
+- #7105 `30c2d8c` Keep track of explicit wallet conflicts instead of using mempool (Pieter Wuille)
+- #7096 `9490bd7` [Wallet] Improve minimum absolute fee GUI options (Jonas Schnelli)
+- #6216 `83f06ca` Take the training wheels off anti-fee-sniping (Peter Todd)
+- #4906 `96e8d12` Issue#1643: Coinselection prunes extraneous inputs from ApproximateBestSubset (Murch)
+- #7200 `06c6a58` Checks for null data transaction before issuing error to debug.log (Andy Craze)
+- #7296 `a36d79b` Add sane fallback for fee estimation (Alex Morcos)
+- #7293 `ff9b610` Add regression test for vValue sort order (MarcoFalke)
+- #7306 `4707797` Make sure conflicted wallet tx's update balances (Alex Morcos)
+- #7381 `621bbd8` [walletdb] Fix syntax error in key parser (MarcoFalke)
+- #7491 `00ec73e` wallet: Ignore MarkConflict if block hash is not known (Wladimir J. van der Laan)
+- #7502 `1329963` Update the wallet best block marker before pruning (Pieter Wuille)
+
+### GUI
+
+- #6217 `c57e12a` disconnect peers from peers tab via context menu (Diapolo)
+- #6209 `ab0ec67` extend rpc console peers tab (Diapolo)
+- #6484 `1369d69` use CHashWriter also in SignVerifyMessageDialog (Pavel Vasin)
+- #6487 `9848d42` Introduce PlatformStyle (Wladimir J. van der Laan)
+- #6505 `100c9d3` cleanup icons (MarcoFalke)
+- #4587 `0c465f5` allow users to set -onion via GUI (Diapolo)
+- #6529 `c0f66ce` show client user agent in debug window (Diapolo)
+- #6594 `878ea69` Disallow duplicate windows. (Casey Rodarmor)
+- #5665 `6f55cdd` add verifySize() function to PaymentServer (Diapolo)
+- #6317 `ca5e2a1` minor optimisations in peertablemodel (Diapolo)
+- #6315 `e59d2a8` allow banning and unbanning over UI->peers table (Jonas Schnelli)
+- #6653 `e04b2fa` Pop debug window in foreground when opened twice (MarcoFalke)
+- #6864 `c702521` Use monospace font (MarcoFalke)
+- #6887 `3694b74` Update coin control and smartfee labels (MarcoFalke)
+- #7000 `814697c` add shortcurts for debug-/console-window (Jonas Schnelli)
+- #6951 `03403d8` Use maxTxFee instead of 10000000 (MarcoFalke)
+- #7051 `a190777` ui: Add "Copy raw transaction data" to transaction list context menu (Wladimir J. van der Laan)
+- #6979 `776848a` simple mempool info in debug window (Jonas Schnelli)
+- #7006 `26af1ac` add startup option to reset Qt settings (Jonas Schnelli)
+- #6780 `2a94cd6` Call init's parameter interaction before we create the UI options model (Jonas Schnelli)
+- #7112 `96b8025` reduce cs_main locks during tip update, more fluently update UI (Jonas Schnelli)
+- #7206 `f43c2f9` Add "NODE_BLOOM" to guiutil so that peers don't get UNKNOWN[4] (Matt Corallo)
+- #7282 `5cadf3e` fix coincontrol update issue when deleting a send coins entry (Jonas Schnelli)
+- #7319 `1320300` Intro: Display required space (MarcoFalke)
+- #7318 `9265e89` quickfix for RPC timer interface problem (Jonas Schnelli)
+- #7327 `b16b5bc` [Wallet] Transaction View: LastMonth calculation fixed (crowning-)
+- #7364 `7726c48` [qt] Windows: Make rpcconsole monospace font larger (MarcoFalke)
+- #7384 `294f432` [qt] Peertable: Increase SUBVERSION_COLUMN_WIDTH (MarcoFalke)
+
+### Tests and QA
+
+- #6305 `9005c91` build: comparison tool swap (Cory Fields)
+- #6318 `e307e13` build: comparison tool NPE fix (Cory Fields)
+- #6337 `0564c5b` Testing infrastructure: mocktime fixes (Gavin Andresen)
+- #6350 `60abba1` add unit tests for the decodescript rpc (mruddy)
+- #5881 `3203a08` Fix and improve txn_doublespend.py test (Tom Harding)
+- #6390 `6a73d66` tests: Fix bitcoin-tx signing test case (Wladimir J. van der Laan)
+- #6368 `7fc25c2` CLTV: Add more tests to improve coverage (Esteban Ordano)
+- #6414 `5121c68` Fix intermittent test failure, reduce test time (Tom Harding)
+- #6417 `44fa82d` [QA] fix possible reorg issue in (fund)rawtransaction(s).py RPC test (Jonas Schnelli)
+- #6398 `3d9362d` rpc: Remove chain-specific RequireRPCPassword (Wladimir J. van der Laan)
+- #6428 `bb59e78` tests: Remove old sh-based test framework (Wladimir J. van der Laan)
+- #5515 `d946e9a` RFC: Assert on probable deadlocks if the second lock isnt try_lock (Matt Corallo)
+- #6287 `d2464df` Clang lock debug (Cory Fields)
+- #6465 `410fd74` Don't share objects between TestInstances (Casey Rodarmor)
+- #6534 `6c1c7fd` Fix test locking issues and un-revert the probable-deadlines assertions commit (Cory Fields)
+- #6509 `bb4faee` Fix race condition on test node shutdown (Casey Rodarmor)
+- #6523 `561f8af` Add p2p-fullblocktest.py (Casey Rodarmor)
+- #6590 `981fd92` Fix stale socket rebinding and re-enable python tests for Windows (Cory Fields)
+- #6730 `cb4d6d0` build: Remove dependency of bitcoin-cli on secp256k1 (Wladimir J. van der Laan)
+- #6616 `5ab5dca` Regression Tests: Migrated rpc-tests.sh to all Python rpc-tests.py (Peter Tschipper)
+- #6720 `d479311` Creates unittests for addrman, makes addrman more testable. (Ethan Heilman)
+- #6853 `c834f56` Added fPowNoRetargeting field to Consensus::Params (Eric Lombrozo)
+- #6827 `87e5539` [rpc-tests] Check return code (MarcoFalke)
+- #6848 `f2c869a` Add DERSIG transaction test cases (Ross Nicoll)
+- #6813 `5242bb3` Support gathering code coverage data for RPC tests with lcov (dexX7)
+- #6888 `c8322ff` Clear strMiscWarning before running PartitionAlert (Eric Lombrozo)
+- #6894 `2675276` [Tests] Fix BIP65 p2p test (Suhas Daftuar)
+- #6863 `725539e` [Test Suite] Fix test for null tx input (Daniel Kraft)
+- #6926 `a6d0d62` tests: Initialize networking on windows (Wladimir J. van der Laan)
+- #6822 `9fa54a1` [tests] Be more strict checking dust (MarcoFalke)
+- #6804 `5fcc14e` [tests] Add basic coverage reporting for RPC tests (James O'Beirne)
+- #7045 `72dccfc` Bugfix: Use unique autostart filenames on Linux for testnet/regtest (Luke-Jr)
+- #7095 `d8368a0` Replace scriptnum_test's normative ScriptNum implementation (Wladimir J. van der Laan)
+- #7063 `6abf6eb` [Tests] Add prioritisetransaction RPC test (Suhas Daftuar)
+- #7137 `16f4a6e` Tests: Explicitly set chain limits in replace-by-fee test (Suhas Daftuar)
+- #7216 `9572e49` Removed offline testnet DNSSeed 'alexykot.me'. (tnull)
+- #7209 `f3ad812` test: don't override BITCOIND and BITCOINCLI if they're set (Wladimir J. van der Laan)
+- #7226 `301f16a` Tests: Add more tests to p2p-fullblocktest (Suhas Daftuar)
+- #7153 `9ef7c54` [Tests] Add mempool_limit.py test (Jonas Schnelli)
+- #7170 `453c567` tests: Disable Tor interaction (Wladimir J. van der Laan)
+- #7229 `1ed938b` [qa] wallet: Check if maintenance changes the balance (MarcoFalke)
+- #7308 `d513405` [Tests] Eliminate intermittent failures in sendheaders.py (Suhas Daftuar)
+- #7468 `947c4ff` [rpc-tests] Change solve() to use rehash (Brad Andrews)
+
+### Miscellaneous
+
+- #6213 `e54ff2f` [init] add -blockversion help and extend -upnp help (Diapolo)
+- #5975 `1fea667` Consensus: Decouple ContextualCheckBlockHeader from checkpoints (Jorge Timón)
+- #6061 `eba2f06` Separate Consensus::CheckTxInputs and GetSpendHeight in CheckInputs (Jorge Timón)
+- #5994 `786ed11` detach wallet from miner (Jonas Schnelli)
+- #6387 `11576a5` [bitcoin-cli] improve error output (Jonas Schnelli)
+- #6401 `6db53b4` Add BITCOIND_SIGTERM_TIMEOUT to OpenRC init scripts (Florian Schmaus)
+- #6430 `b01981e` doc: add documentation for shared library libbitcoinconsensus (Braydon Fuller)
+- #6372 `dcc495e` Update Linearize tool to support Windows paths; fix variable scope; update README and example configuration (Paul Georgiou)
+- #6453 `8fe5cce` Separate core memory usage computation in core_memusage.h (Pieter Wuille)
+- #6149 `633fe10` Buffer log messages and explicitly open logs (Adam Weiss)
+- #6488 `7cbed7f` Avoid leaking file descriptors in RegisterLoad (Casey Rodarmor)
+- #6497 `a2bf40d` Make sure LogPrintf strings are line-terminated (Wladimir J. van der Laan)
+- #6504 `b6fee6b` Rationalize currency unit to "BTC" (Ross Nicoll)
+- #6507 `9bb4dd8` Removed contrib/bitrpc (Casey Rodarmor)
+- #6527 `41d650f` Use unique name for AlertNotify tempfile (Casey Rodarmor)
+- #6561 `e08a7d9` limitedmap fixes and tests (Casey Rodarmor)
+- #6565 `a6f2aff` Make sure we re-acquire lock if a task throws (Casey Rodarmor)
+- #6599 `f4d88c4` Make sure LogPrint strings are line-terminated (Ross Nicoll)
+- #6630 `195942d` Replace boost::reverse_lock with our own (Casey Rodarmor)
+- #6103 `13b8282` Add ZeroMQ notifications (João Barbosa)
+- #6692 `d5d1d2e` devtools: don't push if signing fails in github-merge (Wladimir J. van der Laan)
+- #6728 `2b0567b` timedata: Prevent warning overkill (Wladimir J. van der Laan)
+- #6713 `f6ce59c` SanitizeString: Allow hypen char (MarcoFalke)
+- #5987 `4899a04` Bugfix: Fix testnet-in-a-box use case (Luke-Jr)
+- #6733 `b7d78fd` Simple benchmarking framework (Gavin Andresen)
+- #6854 `a092970` devtools: Add security-check.py (Wladimir J. van der Laan)
+- #6790 `fa1d252` devtools: add clang-format.py (MarcoFalke)
+- #7114 `f3d0fdd` util: Don't set strMiscWarning on every exception (Wladimir J. van der Laan)
+- #7078 `93e0514` uint256::GetCheapHash bigendian compatibility (arowser)
+- #7094 `34e02e0` Assert now > 0 in GetTime GetTimeMillis GetTimeMicros (Patrick Strateman)
+
+Credits
+=======
+
+Thanks to everyone who directly contributed to this release:
+
+- accraze
+- Adam Weiss
+- Alex Morcos
+- Alex van der Peet
+- AlSzacrel
+- Altoidnerd
+- Andriy Voskoboinyk
+- antonio-fr
+- Arne Brutschy
+- Ashley Holman
+- Bob McElrath
+- Braydon Fuller
+- BtcDrak
+- Casey Rodarmor
+- centaur1
+- Chris Kleeschulte
+- Christian Decker
+- Cory Fields
+- crowning-
+- daniel
+- Daniel Cousens
+- Daniel Kraft
+- David Hill
+- dexX7
+- Diego Viola
+- Elias Rohrer
+- Eric Lombrozo
+- Erik Mossberg
+- Esteban Ordano
+- EthanHeilman
+- Florian Schmaus
+- Forrest Voight
+- Gavin Andresen
+- Gregory Maxwell
+- Gregory Sanders / instagibbs
+- Ian T
+- Irving Ruan
+- Jacob Welsh
+- James O'Beirne
+- Jeff Garzik
+- Johnathan Corgan
+- Jonas Schnelli
+- Jonathan Cross
+- João Barbosa
+- Jorge Timón
+- Josh Lehan
+- J Ross Nicoll
+- kazcw
+- Kevin Cooper
+- lpescher
+- Luke Dashjr
+- MarcoFalke
+- Mark Friedenbach
+- Matt
+- Matt Bogosian
+- Matt Corallo
+- Matt Quinn
+- Micha
+- Michael
+- Michael Ford / fanquake
+- Midnight Magic
+- Mitchell Cash
+- mrbandrews
+- mruddy
+- Nick
+- Patrick Strateman
+- Paul Georgiou
+- Paul Rabahy
+- Pavel Janík / paveljanik
+- Pavel Vasin
+- Pavol Rusnak
+- Peter Josling
+- Peter Todd
+- Philip Kaufmann
+- Pieter Wuille
+- ptschip
+- randy-waterhouse
+- rion
+- Ross Nicoll
+- Ryan Havar
+- Shaul Kfir
+- Simon Males
+- Stephen
+- Suhas Daftuar
+- tailsjoin
+- Thomas Kerin
+- Tom Harding
+- tulip
+- unsystemizer
+- Veres Lajos
+- Wladimir J. van der Laan
+- xor-freenet
+- Zak Wilcox
+- zathras-crypto
+
+As well as everyone that helped translating on [Transifex](https://www.transifex.com/projects/p/bitcoin/).
+
diff --git a/doc/release-process.md b/doc/release-process.md
index 39e3032a67..2c83896c22 100644
--- a/doc/release-process.md
+++ b/doc/release-process.md
@@ -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
@@ -84,16 +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 Sign 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
+ 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
+ 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
+ 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:
@@ -115,13 +123,6 @@ The gbuild invocations below <b>DO NOT DO THIS</b> by default.
./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
-###Move the outputs to the correct directory
-
- mv build/out/bitcoin-*.tar.gz build/out/src/bitcoin-*.tar.gz ../
- 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-*-osx-unsigned.tar.gz inputs/bitcoin-osx-unsigned.tar.gz
- mv build/out/bitcoin-*.tar.gz build/out/bitcoin-*.dmg ../
popd
###Next steps:
@@ -137,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.
@@ -210,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
diff --git a/doc/shared-libraries.md b/doc/shared-libraries.md
index f4ff53d6e9..ec6f16c8aa 100644
--- a/doc/shared-libraries.md
+++ b/doc/shared-libraries.md
@@ -11,7 +11,7 @@ The interface is defined in the C header `bitcoinconsensus.h` located in `src/s
#### Version
-`bitcoinconsensus_version` returns an `unsigned int` with the the API version *(currently at an experimental `0`)*.
+`bitcoinconsensus_version` returns an `unsigned int` with the API version *(currently at an experimental `0`)*.
#### Script Validation
diff --git a/doc/tor.md b/doc/tor.md
index 1d35a658bc..be41255449 100644
--- a/doc/tor.md
+++ b/doc/tor.md
@@ -52,7 +52,7 @@ your bitcoind's P2P listen port (8333 by default).
this option, and this can be a .onion address. Given the above
configuration, you can find your onion address in
/var/lib/tor/bitcoin-service/hostname. Onion addresses are given
- preference for your node to advertize itself with, for connections
+ preference for your node to advertise itself with, for connections
coming from unroutable addresses (such as 127.0.0.1, where the
Tor proxy typically runs).
diff --git a/doc/travis-ci.txt b/doc/travis-ci.txt
index 01f7d02a86..06410405d6 100644
--- a/doc/travis-ci.txt
+++ b/doc/travis-ci.txt
@@ -27,7 +27,7 @@ In order to avoid rebuilding all dependencies for each build, the binaries are
cached and re-used when possible. Changes in the dependency-generator will
trigger cache-invalidation and rebuilds as necessary.
-These caches can be manually removed if necessary. This is one of the the very few
+These caches can be manually removed if necessary. This is one of the very few
manual operations that is possible with Travis, and it can be done by the
Bitcoin Core committer via the Travis web interface.
diff --git a/qa/README.md b/qa/README.md
index 758d1f47e5..2b476c4d8d 100644
--- a/qa/README.md
+++ b/qa/README.md
@@ -5,6 +5,17 @@ Every pull request to the bitcoin repository is built and run through
the regression test suite. You can also run all or only individual
tests locally.
+Test dependencies
+=================
+Before running the tests, the following must be installed.
+
+Unix
+----
+The python-zmq library is required. On Ubuntu or Debian it can be installed via:
+```
+sudo apt-get install python-zmq
+```
+
Running tests
=============
diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py
index e7173fda08..d794dbe806 100755
--- a/qa/pull-tester/rpc-tests.py
+++ b/qa/pull-tester/rpc-tests.py
@@ -40,6 +40,15 @@ if not vars().has_key('ENABLE_UTILS'):
ENABLE_UTILS=0
if not vars().has_key('ENABLE_ZMQ'):
ENABLE_ZMQ=0
+
+# python-zmq may not be installed. Handle this gracefully and with some helpful info
+if ENABLE_ZMQ:
+ try:
+ import zmq
+ except ImportError:
+ print("WARNING: \"import zmq\" failed. Setting ENABLE_ZMQ=0. " \
+ "To run zmq tests, see dependency info in /qa/README.md.")
+ ENABLE_ZMQ=0
ENABLE_COVERAGE=0
@@ -74,6 +83,7 @@ if EXEEXT == ".exe" and "-win" not in opts:
#Tests
testScripts = [
+ 'bip68-112-113-p2p.py',
'wallet.py',
'listtransactions.py',
'receivedby.py',
@@ -106,17 +116,20 @@ testScripts = [
'invalidblockrequest.py',
'invalidtxrequest.py',
'abandonconflict.py',
+ 'p2p-versionbits-warning.py',
+ 'importprunedfunds.py',
]
testScriptsExt = [
+ 'bip9-softforks.py',
'bip65-cltv.py',
'bip65-cltv-p2p.py',
+ 'bip68-sequence.py',
'bipdersig-p2p.py',
'bipdersig.py',
'getblocktemplate_longpoll.py',
'getblocktemplate_proposals.py',
'txn_doublespend.py',
'txn_clone.py --mineblock',
- 'pruning.py',
'forknotify.py',
'invalidateblock.py',
# 'rpcbind_test.py', #temporary, bug in libevent, see #6655
@@ -126,6 +139,8 @@ testScriptsExt = [
'mempool_packages.py',
'maxuploadtarget.py',
'replace-by-fee.py',
+ 'p2p-feefilter.py',
+ 'pruning.py', # leave pruning last as it takes a REALLY long time
]
#Enable ZMQ tests
diff --git a/qa/rpc-tests/abandonconflict.py b/qa/rpc-tests/abandonconflict.py
index 38028df079..a83aa97fcd 100755
--- a/qa/rpc-tests/abandonconflict.py
+++ b/qa/rpc-tests/abandonconflict.py
@@ -83,6 +83,12 @@ class AbandonConflictTest(BitcoinTestFramework):
# 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
diff --git a/qa/rpc-tests/bip68-112-113-p2p.py b/qa/rpc-tests/bip68-112-113-p2p.py
new file mode 100755
index 0000000000..7d3c59be3e
--- /dev/null
+++ b/qa/rpc-tests/bip68-112-113-p2p.py
@@ -0,0 +1,547 @@
+#!/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 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 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(self.get_bip9_status('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(self.get_bip9_status('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(self.get_bip9_status('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(self.get_bip9_status('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(self.get_bip9_status('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(self.get_bip9_status('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()
diff --git a/qa/rpc-tests/bip68-sequence.py b/qa/rpc-tests/bip68-sequence.py
new file mode 100755
index 0000000000..84f941da33
--- /dev/null
+++ b/qa/rpc-tests/bip68-sequence.py
@@ -0,0 +1,386 @@
+#!/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 (mempool only)
+#
+
+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 *
+
+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.is_network_split = False
+ self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"]
+
+ 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()
+
+ # This test needs to change when BIP68 becomes consensus
+ print "Running test BIP68 not consensus"
+ self.test_bip68_not_consensus()
+
+ 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 = 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(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.
+ def test_bip68_not_consensus(self):
+ 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)
+
+
+if __name__ == '__main__':
+ BIP68Test().main()
diff --git a/qa/rpc-tests/bip9-softforks.py b/qa/rpc-tests/bip9-softforks.py
new file mode 100755
index 0000000000..cbb1b7d4ce
--- /dev/null
+++ b/qa/rpc-tests/bip9-softforks.py
@@ -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 = 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() \ No newline at end of file
diff --git a/qa/rpc-tests/blockchain.py b/qa/rpc-tests/blockchain.py
index 7045ae435c..272a5dc154 100755
--- a/qa/rpc-tests/blockchain.py
+++ b/qa/rpc-tests/blockchain.py
@@ -28,6 +28,7 @@ class BlockchainTest(BitcoinTestFramework):
Test blockchain-related RPC calls:
- gettxoutsetinfo
+ - verifychain
"""
@@ -44,6 +45,7 @@ class BlockchainTest(BitcoinTestFramework):
def run_test(self):
self._test_gettxoutsetinfo()
self._test_getblockheader()
+ self.nodes[0].verifychain(4, 0)
def _test_gettxoutsetinfo(self):
node = self.nodes[0]
diff --git a/qa/rpc-tests/disablewallet.py b/qa/rpc-tests/disablewallet.py
index 6964348d55..5af8158467 100755
--- a/qa/rpc-tests/disablewallet.py
+++ b/qa/rpc-tests/disablewallet.py
@@ -29,5 +29,19 @@ class DisableWalletTest (BitcoinTestFramework):
x = self.nodes[0].validateaddress('mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ')
assert(x['isvalid'] == True)
+ # Checking mining to an address without a wallet
+ try:
+ self.nodes[0].generatetoaddress(1, 'mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ')
+ except JSONRPCException,e:
+ assert("Invalid address" not in e.error['message'])
+ assert("ProcessNewBlock, block not accepted" not in e.error['message'])
+ assert("Couldn't create new block" not in e.error['message'])
+
+ try:
+ self.nodes[0].generatetoaddress(1, '3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy')
+ raise AssertionError("Must not mine to invalid address!")
+ except JSONRPCException,e:
+ assert("Invalid address" in e.error['message'])
+
if __name__ == '__main__':
DisableWalletTest ().main ()
diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py
index 0287965b97..4458712815 100755
--- a/qa/rpc-tests/fundrawtransaction.py
+++ b/qa/rpc-tests/fundrawtransaction.py
@@ -71,7 +71,7 @@ class RawTransactionsTest(BitcoinTestFramework):
rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
fee = rawtxfund['fee']
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
- assert_equal(len(dec_tx['vin']) > 0, True) #test if we have enought inputs
+ assert(len(dec_tx['vin']) > 0) #test if we have enought inputs
##############################
# simple test with two coins #
@@ -84,7 +84,7 @@ class RawTransactionsTest(BitcoinTestFramework):
rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
fee = rawtxfund['fee']
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
- assert_equal(len(dec_tx['vin']) > 0, True) #test if we have enough inputs
+ assert(len(dec_tx['vin']) > 0) #test if we have enough inputs
##############################
# simple test with two coins #
@@ -97,7 +97,7 @@ class RawTransactionsTest(BitcoinTestFramework):
rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
fee = rawtxfund['fee']
dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
- assert_equal(len(dec_tx['vin']) > 0, True)
+ assert(len(dec_tx['vin']) > 0)
assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '')
@@ -116,7 +116,7 @@ class RawTransactionsTest(BitcoinTestFramework):
for out in dec_tx['vout']:
totalOut += out['value']
- assert_equal(len(dec_tx['vin']) > 0, True)
+ assert(len(dec_tx['vin']) > 0)
assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '')
@@ -130,7 +130,7 @@ class RawTransactionsTest(BitcoinTestFramework):
utx = aUtx
break
- assert_equal(utx!=False, True)
+ assert(utx!=False)
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}]
outputs = { self.nodes[0].getnewaddress() : 1.0 }
@@ -159,7 +159,7 @@ class RawTransactionsTest(BitcoinTestFramework):
utx = aUtx
break
- assert_equal(utx!=False, True)
+ assert(utx!=False)
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}]
outputs = { self.nodes[0].getnewaddress() : Decimal(5.0) - fee - feeTolerance }
@@ -189,7 +189,7 @@ class RawTransactionsTest(BitcoinTestFramework):
utx = aUtx
break
- assert_equal(utx!=False, True)
+ assert(utx!=False)
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}]
outputs = { self.nodes[0].getnewaddress() : 1.0 }
@@ -234,7 +234,7 @@ class RawTransactionsTest(BitcoinTestFramework):
utx2 = aUtx
- assert_equal(utx!=False, True)
+ assert(utx!=False)
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']},{'txid' : utx2['txid'], 'vout' : utx2['vout']} ]
outputs = { self.nodes[0].getnewaddress() : 6.0 }
@@ -276,7 +276,7 @@ class RawTransactionsTest(BitcoinTestFramework):
utx2 = aUtx
- assert_equal(utx!=False, True)
+ assert(utx!=False)
inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']},{'txid' : utx2['txid'], 'vout' : utx2['vout']} ]
outputs = { self.nodes[0].getnewaddress() : 6.0, self.nodes[0].getnewaddress() : 1.0 }
@@ -306,14 +306,11 @@ class RawTransactionsTest(BitcoinTestFramework):
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
dec_tx = self.nodes[2].decoderawtransaction(rawtx)
- errorString = ""
try:
rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
+ raise AssertionError("Spent more than available")
except JSONRPCException,e:
- errorString = e.error['message']
-
- assert("Insufficient" in errorString)
-
+ assert("Insufficient" in e.error['message'])
############################################################
@@ -462,12 +459,11 @@ class RawTransactionsTest(BitcoinTestFramework):
self.is_network_split=False
self.sync_all()
- error = False
try:
self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1.2)
- except:
- error = True
- assert(error)
+ raise AssertionError("Wallet unlocked without passphrase")
+ except JSONRPCException as e:
+ assert('walletpassphrase' in e.error['message'])
oldBalance = self.nodes[0].getbalance()
@@ -580,7 +576,7 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(len(res_dec["vin"]), 1)
assert_equal(res_dec["vin"][0]["txid"], watchonly_txid)
- assert_equal("fee" in result.keys(), True)
+ assert("fee" in result.keys())
assert_greater_than(result["changepos"], -1)
###############################################################
diff --git a/qa/rpc-tests/getblocktemplate_proposals.py b/qa/rpc-tests/getblocktemplate_proposals.py
index f83b5f140d..d2cb4ab8d6 100755
--- a/qa/rpc-tests/getblocktemplate_proposals.py
+++ b/qa/rpc-tests/getblocktemplate_proposals.py
@@ -120,10 +120,7 @@ class GetBlockTemplateProposalTest(BitcoinTestFramework):
# Test 3: Truncated final tx
lastbyte = txlist[-1].pop()
- try:
- assert_template(node, tmpl, txlist, 'n/a')
- except JSONRPCException:
- pass # Expected
+ assert_raises(JSONRPCException, assert_template, node, tmpl, txlist, 'n/a')
txlist[-1].append(lastbyte)
# Test 4: Add an invalid tx to the end (duplicate of gen tx)
@@ -144,10 +141,7 @@ class GetBlockTemplateProposalTest(BitcoinTestFramework):
# Test 7: Bad tx count
txlist.append(b'')
- try:
- assert_template(node, tmpl, txlist, 'n/a')
- except JSONRPCException:
- pass # Expected
+ assert_raises(JSONRPCException, assert_template, node, tmpl, txlist, 'n/a')
txlist.pop()
# Test 8: Bad bits
diff --git a/qa/rpc-tests/httpbasics.py b/qa/rpc-tests/httpbasics.py
index eb548aee9d..c231676ec8 100755
--- a/qa/rpc-tests/httpbasics.py
+++ b/qa/rpc-tests/httpbasics.py
@@ -37,14 +37,14 @@ class HTTPBasicsTest (BitcoinTestFramework):
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
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!
+ assert('"error":null' in out1)
+ assert(conn.sock!=None) #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()
- 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!
+ assert('"error":null' in out1) #must also response with a correct json-rpc message
+ assert(conn.sock!=None) #according to http/1.1 connection must still be open!
conn.close()
#same should be if we add keep-alive because this should be the std. behaviour
@@ -54,14 +54,14 @@ class HTTPBasicsTest (BitcoinTestFramework):
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
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!
+ assert('"error":null' in out1)
+ assert(conn.sock!=None) #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()
- 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!
+ assert('"error":null' in out1) #must also response with a correct json-rpc message
+ assert(conn.sock!=None) #according to http/1.1 connection must still be open!
conn.close()
#now do the same with "Connection: close"
@@ -71,8 +71,8 @@ class HTTPBasicsTest (BitcoinTestFramework):
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
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
+ assert('"error":null' in out1)
+ assert(conn.sock==None) #now the connection must be closed after the response
#node1 (2nd node) is running with disabled keep-alive option
urlNode1 = urlparse.urlparse(self.nodes[1].url)
@@ -83,7 +83,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
out1 = conn.getresponse().read()
- assert_equal('"error":null' in out1, True)
+ assert('"error":null' in out1)
#node2 (third node) is running with standard keep-alive parameters which means keep-alive is on
urlNode2 = urlparse.urlparse(self.nodes[2].url)
@@ -94,8 +94,8 @@ class HTTPBasicsTest (BitcoinTestFramework):
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
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
+ assert('"error":null' in out1)
+ assert(conn.sock!=None) #connection must be closed because bitcoind should use keep-alive by default
# Check excessive request size
conn = httplib.HTTPConnection(urlNode2.hostname, urlNode2.port)
diff --git a/qa/rpc-tests/importprunedfunds.py b/qa/rpc-tests/importprunedfunds.py
new file mode 100755
index 0000000000..5cbdcde9aa
--- /dev/null
+++ b/qa/rpc-tests/importprunedfunds.py
@@ -0,0 +1,140 @@
+#!/usr/bin/env python2
+# Copyright (c) 2014-2016 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 *
+import decimal
+
+class ImportPrunedFundsTest(BitcoinTestFramework):
+
+ def setup_chain(self):
+ print("Initializing test directory "+self.options.tmpdir)
+ initialize_chain_clean(self.options.tmpdir, 4)
+
+ def setup_network(self, split=False):
+ self.nodes = start_nodes(2, self.options.tmpdir)
+ connect_nodes_bi(self.nodes,0,1)
+ self.is_network_split=False
+ self.sync_all()
+
+ def run_test (self):
+ import time
+ begintime = int(time.time())
+
+ print "Mining blocks..."
+ self.nodes[0].generate(101)
+
+ # sync
+ self.sync_all()
+
+ # address
+ address1 = self.nodes[0].getnewaddress()
+ # pubkey
+ address2 = self.nodes[0].getnewaddress()
+ address2_pubkey = self.nodes[0].validateaddress(address2)['pubkey'] # Using pubkey
+ # privkey
+ address3 = self.nodes[0].getnewaddress()
+ address3_privkey = self.nodes[0].dumpprivkey(address3) # Using privkey
+
+ #Check only one address
+ address_info = self.nodes[0].validateaddress(address1)
+ assert_equal(address_info['ismine'], True)
+
+ self.sync_all()
+
+ #Node 1 sync test
+ assert_equal(self.nodes[1].getblockcount(),101)
+
+ #Address Test - before import
+ address_info = self.nodes[1].validateaddress(address1)
+ assert_equal(address_info['iswatchonly'], False)
+ assert_equal(address_info['ismine'], False)
+
+ address_info = self.nodes[1].validateaddress(address2)
+ assert_equal(address_info['iswatchonly'], False)
+ assert_equal(address_info['ismine'], False)
+
+ address_info = self.nodes[1].validateaddress(address3)
+ assert_equal(address_info['iswatchonly'], False)
+ assert_equal(address_info['ismine'], False)
+
+ #Send funds to self
+ txnid1 = self.nodes[0].sendtoaddress(address1, 0.1)
+ self.nodes[0].generate(1)
+ rawtxn1 = self.nodes[0].gettransaction(txnid1)['hex']
+ proof1 = self.nodes[0].gettxoutproof([txnid1])
+
+ txnid2 = self.nodes[0].sendtoaddress(address2, 0.05)
+ self.nodes[0].generate(1)
+ rawtxn2 = self.nodes[0].gettransaction(txnid2)['hex']
+ proof2 = self.nodes[0].gettxoutproof([txnid2])
+
+
+ txnid3 = self.nodes[0].sendtoaddress(address3, 0.025)
+ self.nodes[0].generate(1)
+ rawtxn3 = self.nodes[0].gettransaction(txnid3)['hex']
+ proof3 = self.nodes[0].gettxoutproof([txnid3])
+
+ self.sync_all()
+
+ #Import with no affiliated address
+ try:
+ result1 = self.nodes[1].importprunedfunds(rawtxn1, proof1, "")
+ except JSONRPCException,e:
+ errorString = e.error['message']
+
+ assert('No addresses' in errorString)
+
+ balance1 = self.nodes[1].getbalance("", 0, True)
+ assert_equal(balance1, Decimal(0))
+
+ #Import with affiliated address with no rescan
+ self.nodes[1].importaddress(address2, "", False)
+ result2 = self.nodes[1].importprunedfunds(rawtxn2, proof2, "")
+ balance2 = Decimal(self.nodes[1].getbalance("", 0, True))
+ assert_equal(balance2, Decimal('0.05'))
+
+ #Import with private key with no rescan
+ self.nodes[1].importprivkey(address3_privkey, "", False)
+ result3 = self.nodes[1].importprunedfunds(rawtxn3, proof3, "")
+ balance3 = Decimal(self.nodes[1].getbalance("", 0, False))
+ assert_equal(balance3, Decimal('0.025'))
+ balance3 = Decimal(self.nodes[1].getbalance("", 0, True))
+ assert_equal(balance3, Decimal('0.075'))
+
+ #Addresses Test - after import
+ address_info = self.nodes[1].validateaddress(address1)
+ assert_equal(address_info['iswatchonly'], False)
+ assert_equal(address_info['ismine'], False)
+ address_info = self.nodes[1].validateaddress(address2)
+ assert_equal(address_info['iswatchonly'], True)
+ assert_equal(address_info['ismine'], False)
+ address_info = self.nodes[1].validateaddress(address3)
+ assert_equal(address_info['iswatchonly'], False)
+ assert_equal(address_info['ismine'], True)
+
+ #Remove transactions
+
+ try:
+ self.nodes[1].removeprunedfunds(txnid1)
+ except JSONRPCException,e:
+ errorString = e.error['message']
+
+ assert('does not exist' in errorString)
+
+ balance1 = Decimal(self.nodes[1].getbalance("", 0, True))
+ assert_equal(balance1, Decimal('0.075'))
+
+
+ self.nodes[1].removeprunedfunds(txnid2)
+ balance2 = Decimal(self.nodes[1].getbalance("", 0, True))
+ assert_equal(balance2, Decimal('0.025'))
+
+ self.nodes[1].removeprunedfunds(txnid3)
+ balance3 = Decimal(self.nodes[1].getbalance("", 0, True))
+ assert_equal(balance3, Decimal('0.0'))
+
+if __name__ == '__main__':
+ ImportPrunedFundsTest ().main ()
diff --git a/qa/rpc-tests/invalidblockrequest.py b/qa/rpc-tests/invalidblockrequest.py
index f91a8da015..daad312d36 100755
--- a/qa/rpc-tests/invalidblockrequest.py
+++ b/qa/rpc-tests/invalidblockrequest.py
@@ -78,8 +78,8 @@ class InvalidBlockRequestTest(ComparisonTestFramework):
self.block_time += 1
# chr(81) is OP_TRUE
- tx1 = create_transaction(self.block1.vtx[0], 0, chr(81), 50*100000000)
- tx2 = create_transaction(tx1, 0, chr(81), 50*100000000)
+ tx1 = create_transaction(self.block1.vtx[0], 0, chr(81), 50 * COIN)
+ tx2 = create_transaction(tx1, 0, chr(81), 50 * COIN)
block2.vtx.extend([tx1, tx2])
block2.hashMerkleRoot = block2.calc_merkle_root()
@@ -103,7 +103,7 @@ class InvalidBlockRequestTest(ComparisonTestFramework):
'''
block3 = create_block(self.tip, create_coinbase(height), self.block_time)
self.block_time += 1
- block3.vtx[0].vout[0].nValue = 100*100000000 # Too high!
+ block3.vtx[0].vout[0].nValue = 100 * COIN # Too high!
block3.vtx[0].sha256=None
block3.vtx[0].calc_sha256()
block3.hashMerkleRoot = block3.calc_merkle_root()
diff --git a/qa/rpc-tests/invalidtxrequest.py b/qa/rpc-tests/invalidtxrequest.py
index c2fe4f1dff..8fe471ccd3 100755
--- a/qa/rpc-tests/invalidtxrequest.py
+++ b/qa/rpc-tests/invalidtxrequest.py
@@ -63,7 +63,7 @@ class InvalidTxRequestTest(ComparisonTestFramework):
# 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 - 12000)
+ tx1 = create_transaction(self.block1.vtx[0], 0, chr(100), 50 * COIN - 12000)
yield TestInstance([[tx1, RejectResult(16, 'mandatory-script-verify-flag-failed')]])
# TODO: test further transactions...
diff --git a/qa/rpc-tests/listtransactions.py b/qa/rpc-tests/listtransactions.py
index 45ede8f040..da1e98dc33 100755
--- a/qa/rpc-tests/listtransactions.py
+++ b/qa/rpc-tests/listtransactions.py
@@ -7,7 +7,7 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-from test_framework.mininode import CTransaction
+from test_framework.mininode import CTransaction, COIN
import cStringIO
import binascii
@@ -192,7 +192,7 @@ class ListTransactionsTest(BitcoinTestFramework):
# 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.vout[0].nValue -= 0.004 * COIN # 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)
diff --git a/qa/rpc-tests/maxuploadtarget.py b/qa/rpc-tests/maxuploadtarget.py
index 4d6b343f77..e4127500cd 100755
--- a/qa/rpc-tests/maxuploadtarget.py
+++ b/qa/rpc-tests/maxuploadtarget.py
@@ -7,7 +7,6 @@
from test_framework.mininode import *
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-from test_framework.comptool import wait_until
import time
'''
@@ -176,7 +175,7 @@ class MaxUploadTest(BitcoinTestFramework):
getdata_request.inv.append(CInv(2, big_old_block))
max_bytes_per_day = 200*1024*1024
- daily_buffer = 144 * 1000000
+ daily_buffer = 144 * MAX_BLOCK_SIZE
max_bytes_available = max_bytes_per_day - daily_buffer
success_count = max_bytes_available / old_block_size
diff --git a/qa/rpc-tests/mempool_limit.py b/qa/rpc-tests/mempool_limit.py
index 7914ceea22..c19a63c699 100755
--- a/qa/rpc-tests/mempool_limit.py
+++ b/qa/rpc-tests/mempool_limit.py
@@ -38,7 +38,6 @@ class MempoolLimitTest(BitcoinTestFramework):
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
diff --git a/qa/rpc-tests/mempool_packages.py b/qa/rpc-tests/mempool_packages.py
index 47c1028b9f..bc3f9e051c 100755
--- a/qa/rpc-tests/mempool_packages.py
+++ b/qa/rpc-tests/mempool_packages.py
@@ -7,6 +7,7 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
+from test_framework.mininode import COIN
MAX_ANCESTORS = 25
MAX_DESCENDANTS = 25
@@ -59,13 +60,12 @@ class MempoolPackagesTest(BitcoinTestFramework):
descendant_count = 1
descendant_fees = 0
descendant_size = 0
- SATOSHIS = 100000000
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)
+ assert_equal(mempool[x]['descendantfees'], descendant_fees * COIN)
descendant_size += mempool[x]['size']
assert_equal(mempool[x]['descendantsize'], descendant_size)
descendant_count += 1
@@ -78,7 +78,7 @@ class MempoolPackagesTest(BitcoinTestFramework):
descendant_fees = 0
for x in reversed(chain):
descendant_fees += mempool[x]['fee']
- assert_equal(mempool[x]['descendantfees'], SATOSHIS*descendant_fees+1000)
+ assert_equal(mempool[x]['descendantfees'], descendant_fees * COIN + 1000)
# Adding one more transaction on to the chain should fail.
try:
@@ -106,7 +106,7 @@ class MempoolPackagesTest(BitcoinTestFramework):
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)
+ assert_equal(mempool[x]['descendantfees'], descendant_fees * COIN + 2000)
# TODO: check that node1's mempool is as expected
diff --git a/qa/rpc-tests/mempool_reorg.py b/qa/rpc-tests/mempool_reorg.py
index 40684e7fbb..5e9856e5d4 100755
--- a/qa/rpc-tests/mempool_reorg.py
+++ b/qa/rpc-tests/mempool_reorg.py
@@ -25,14 +25,6 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
self.is_network_split = False
self.sync_all()
- def create_tx(self, from_txid, to_address, amount):
- inputs = [{ "txid" : from_txid, "vout" : 0}]
- outputs = { to_address : amount }
- rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
- signresult = self.nodes[0].signrawtransaction(rawtx)
- assert_equal(signresult["complete"], True)
- return signresult["hex"]
-
def run_test(self):
start_count = self.nodes[0].getblockcount()
@@ -52,9 +44,9 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
# and make sure the mempool code behaves correctly.
b = [ self.nodes[0].getblockhash(n) for n in range(101, 105) ]
coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ]
- spend_101_raw = self.create_tx(coinbase_txids[1], node1_address, 49.99)
- spend_102_raw = self.create_tx(coinbase_txids[2], node0_address, 49.99)
- spend_103_raw = self.create_tx(coinbase_txids[3], node0_address, 49.99)
+ spend_101_raw = create_tx(self.nodes[0], coinbase_txids[1], node1_address, 49.99)
+ spend_102_raw = create_tx(self.nodes[0], coinbase_txids[2], node0_address, 49.99)
+ spend_103_raw = create_tx(self.nodes[0], coinbase_txids[3], node0_address, 49.99)
# Create a block-height-locked transaction which will be invalid after reorg
timelock_tx = self.nodes[0].createrawtransaction([{"txid": coinbase_txids[0], "vout": 0}], {node0_address: 49.99})
@@ -71,8 +63,8 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
assert_raises(JSONRPCException, self.nodes[0].sendrawtransaction, timelock_tx)
# Create 102_1 and 103_1:
- spend_102_1_raw = self.create_tx(spend_102_id, node1_address, 49.98)
- spend_103_1_raw = self.create_tx(spend_103_id, node1_address, 49.98)
+ spend_102_1_raw = create_tx(self.nodes[0], spend_102_id, node1_address, 49.98)
+ spend_103_1_raw = create_tx(self.nodes[0], spend_103_id, node1_address, 49.98)
# Broadcast and mine 103_1:
spend_103_1_id = self.nodes[0].sendrawtransaction(spend_103_1_raw)
diff --git a/qa/rpc-tests/mempool_resurrect_test.py b/qa/rpc-tests/mempool_resurrect_test.py
index 9fcc88a2a3..0ba46e6f51 100755
--- a/qa/rpc-tests/mempool_resurrect_test.py
+++ b/qa/rpc-tests/mempool_resurrect_test.py
@@ -21,14 +21,6 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
self.nodes.append(start_node(0, self.options.tmpdir, args))
self.is_network_split = False
- def create_tx(self, from_txid, to_address, amount):
- inputs = [{ "txid" : from_txid, "vout" : 0}]
- outputs = { to_address : amount }
- rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
- signresult = self.nodes[0].signrawtransaction(rawtx)
- assert_equal(signresult["complete"], True)
- return signresult["hex"]
-
def run_test(self):
node0_address = self.nodes[0].getnewaddress()
# Spend block 1/2/3's coinbase transactions
@@ -43,13 +35,13 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
b = [ self.nodes[0].getblockhash(n) for n in range(1, 4) ]
coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ]
- spends1_raw = [ self.create_tx(txid, node0_address, 49.99) for txid in coinbase_txids ]
+ spends1_raw = [ create_tx(self.nodes[0], txid, node0_address, 49.99) for txid in coinbase_txids ]
spends1_id = [ self.nodes[0].sendrawtransaction(tx) for tx in spends1_raw ]
blocks = []
blocks.extend(self.nodes[0].generate(1))
- spends2_raw = [ self.create_tx(txid, node0_address, 49.98) for txid in spends1_id ]
+ spends2_raw = [ create_tx(self.nodes[0], txid, node0_address, 49.98) for txid in spends1_id ]
spends2_id = [ self.nodes[0].sendrawtransaction(tx) for tx in spends2_raw ]
blocks.extend(self.nodes[0].generate(1))
diff --git a/qa/rpc-tests/mempool_spendcoinbase.py b/qa/rpc-tests/mempool_spendcoinbase.py
index 16f512db38..507b5ff416 100755
--- a/qa/rpc-tests/mempool_spendcoinbase.py
+++ b/qa/rpc-tests/mempool_spendcoinbase.py
@@ -26,14 +26,6 @@ class MempoolSpendCoinbaseTest(BitcoinTestFramework):
self.nodes.append(start_node(0, self.options.tmpdir, args))
self.is_network_split = False
- def create_tx(self, from_txid, to_address, amount):
- inputs = [{ "txid" : from_txid, "vout" : 0}]
- outputs = { to_address : amount }
- rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
- signresult = self.nodes[0].signrawtransaction(rawtx)
- assert_equal(signresult["complete"], True)
- return signresult["hex"]
-
def run_test(self):
chain_height = self.nodes[0].getblockcount()
assert_equal(chain_height, 200)
@@ -44,7 +36,7 @@ class MempoolSpendCoinbaseTest(BitcoinTestFramework):
# is too immature to spend.
b = [ self.nodes[0].getblockhash(n) for n in range(101, 103) ]
coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ]
- spends_raw = [ self.create_tx(txid, node0_address, 49.99) for txid in coinbase_txids ]
+ spends_raw = [ create_tx(self.nodes[0], txid, node0_address, 49.99) for txid in coinbase_txids ]
spend_101_id = self.nodes[0].sendrawtransaction(spends_raw[0])
diff --git a/qa/rpc-tests/multi_rpc.py b/qa/rpc-tests/multi_rpc.py
index 62071d426e..2452b77319 100755
--- a/qa/rpc-tests/multi_rpc.py
+++ b/qa/rpc-tests/multi_rpc.py
@@ -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="
diff --git a/qa/rpc-tests/p2p-feefilter.py b/qa/rpc-tests/p2p-feefilter.py
new file mode 100755
index 0000000000..f85c18dcd5
--- /dev/null
+++ b/qa/rpc-tests/p2p-feefilter.py
@@ -0,0 +1,99 @@
+#!/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
+
+'''
+FeeFilterTest -- test processing of feefilter messages
+'''
+
+def hashToHex(hash):
+ return format(hash, '064x').decode('utf-8')
+
+# Wait up to 60 secs to see if the testnode has received all the expected invs
+def allInvsMatch(invsExpected, testnode):
+ for x in xrange(60):
+ with mininode_lock:
+ if (sorted(invsExpected) == sorted(testnode.txinvs)):
+ return True;
+ time.sleep(1)
+ return False;
+
+# TestNode: bare-bones "peer". Used to track which invs are received from a node
+# and to send the node feefilter messages.
+class TestNode(SingleNodeConnCB):
+ def __init__(self):
+ SingleNodeConnCB.__init__(self)
+ self.txinvs = []
+
+ def on_inv(self, conn, message):
+ for i in message.inv:
+ if (i.type == 1):
+ self.txinvs.append(hashToHex(i.hash))
+
+ def clear_invs(self):
+ with mininode_lock:
+ self.txinvs = []
+
+ def send_filter(self, feerate):
+ self.send_message(msg_feefilter(feerate))
+ self.sync_with_ping()
+
+class FeeFilterTest(BitcoinTestFramework):
+ def setup_network(self):
+ # Node1 will be used to generate txs which should be relayed from Node0
+ # to our test node
+ self.nodes = []
+ self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-logtimemicros"]))
+ self.nodes.append(start_node(1, self.options.tmpdir, ["-debug", "-logtimemicros"]))
+ connect_nodes(self.nodes[0], 1)
+
+ def run_test(self):
+ node1 = self.nodes[1]
+ # Get out of IBD
+ node1.generate(1)
+ sync_blocks(self.nodes)
+
+ # Setup the p2p connections and start up the network thread.
+ test_node = TestNode()
+ connection = NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test_node)
+ test_node.add_connection(connection)
+ NetworkThread().start()
+ test_node.wait_for_verack()
+
+ # Test that invs are received for all txs at feerate of 20 sat/byte
+ node1.settxfee(Decimal("0.00020000"))
+ txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in xrange(3)]
+ assert(allInvsMatch(txids, test_node))
+ test_node.clear_invs()
+
+ # Set a filter of 15 sat/byte
+ test_node.send_filter(15000)
+
+ # Test that txs are still being received (paying 20 sat/byte)
+ txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in xrange(3)]
+ assert(allInvsMatch(txids, test_node))
+ test_node.clear_invs()
+
+ # Change tx fee rate to 10 sat/byte and test they are no longer received
+ node1.settxfee(Decimal("0.00010000"))
+ [node1.sendtoaddress(node1.getnewaddress(), 1) for x in xrange(3)]
+ sync_mempools(self.nodes) # must be sure node 0 has received all txs
+ time.sleep(10) # wait 10 secs to be sure its doesn't relay any
+ assert(allInvsMatch([], test_node))
+ test_node.clear_invs()
+
+ # Remove fee filter and check that txs are received again
+ test_node.send_filter(0)
+ txids = [node1.sendtoaddress(node1.getnewaddress(), 1) for x in xrange(3)]
+ assert(allInvsMatch(txids, test_node))
+ test_node.clear_invs()
+
+if __name__ == '__main__':
+ FeeFilterTest().main()
diff --git a/qa/rpc-tests/p2p-versionbits-warning.py b/qa/rpc-tests/p2p-versionbits-warning.py
new file mode 100755
index 0000000000..061dcbf0e1
--- /dev/null
+++ b/qa/rpc-tests/p2p-versionbits-warning.py
@@ -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()
diff --git a/qa/rpc-tests/prioritise_transaction.py b/qa/rpc-tests/prioritise_transaction.py
index 4a79d38da0..f8d9063b4e 100755
--- a/qa/rpc-tests/prioritise_transaction.py
+++ b/qa/rpc-tests/prioritise_transaction.py
@@ -9,8 +9,7 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-
-COIN = 100000000
+from test_framework.mininode import COIN, MAX_BLOCK_SIZE
class PrioritiseTransactionTest(BitcoinTestFramework):
@@ -29,14 +28,29 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
self.relayfee = self.nodes[0].getnetworkinfo()['relayfee']
def run_test(self):
- utxos = create_confirmed_utxos(self.relayfee, self.nodes[0], 90)
+ utxo_count = 90
+ utxos = create_confirmed_utxos(self.relayfee, self.nodes[0], utxo_count)
base_fee = self.relayfee*100 # our transactions are smaller than 100kb
txids = []
# Create 3 batches of transactions at 3 different fee rate levels
+ range_size = utxo_count // 3
for i in xrange(3):
txids.append([])
- txids[i] = create_lots_of_big_transactions(self.nodes[0], self.txouts, utxos[30*i:30*i+30], (i+1)*base_fee)
+ start_range = i * range_size
+ end_range = start_range + range_size
+ txids[i] = create_lots_of_big_transactions(self.nodes[0], self.txouts, utxos[start_range:end_range], (i+1)*base_fee)
+
+ # Make sure that the size of each group of transactions exceeds
+ # MAX_BLOCK_SIZE -- otherwise the test needs to be revised to create
+ # more transactions.
+ mempool = self.nodes[0].getrawmempool(True)
+ sizes = [0, 0, 0]
+ for i in xrange(3):
+ for j in txids[i]:
+ assert(j in mempool)
+ sizes[i] += mempool[j]['size']
+ assert(sizes[i] > MAX_BLOCK_SIZE) # Fail => raise utxo_count
# 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
@@ -47,7 +61,7 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
self.nodes[0].generate(1)
mempool = self.nodes[0].getrawmempool()
- print "Assert that prioritised transasction was mined"
+ print "Assert that prioritised transaction was mined"
assert(txids[0][0] not in mempool)
assert(txids[0][1] in mempool)
@@ -60,7 +74,7 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
assert(high_fee_tx != None)
# Add a prioritisation before a tx is in the mempool (de-prioritising a
- # high-fee transaction).
+ # high-fee transaction so that it's now low fee).
self.nodes[0].prioritisetransaction(high_fee_tx, -1e15, -int(2*base_fee*COIN))
# Add everything back to mempool
@@ -70,8 +84,11 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
mempool = self.nodes[0].getrawmempool()
assert(high_fee_tx in mempool)
- # Now verify the high feerate transaction isn't mined.
- self.nodes[0].generate(5)
+ # Now verify the modified-high feerate transaction isn't mined before
+ # the other high fee transactions. Keep mining until our mempool has
+ # decreased by all the high fee size that we calculated above.
+ while (self.nodes[0].getmempoolinfo()['bytes'] > sizes[0] + sizes[1]):
+ self.nodes[0].generate(1)
# High fee transaction should not have been mined, but other high fee rate
# transactions should have been.
diff --git a/qa/rpc-tests/replace-by-fee.py b/qa/rpc-tests/replace-by-fee.py
index ba1956853a..eded24f405 100755
--- a/qa/rpc-tests/replace-by-fee.py
+++ b/qa/rpc-tests/replace-by-fee.py
@@ -13,7 +13,6 @@ from test_framework.script import *
from test_framework.mininode import *
import binascii
-COIN = 100000000
MAX_REPLACEMENT_LIMIT = 100
def satoshi_round(amount):
diff --git a/qa/rpc-tests/test_framework/authproxy.py b/qa/rpc-tests/test_framework/authproxy.py
index fba469a0dd..1eb2772592 100644
--- a/qa/rpc-tests/test_framework/authproxy.py
+++ b/qa/rpc-tests/test_framework/authproxy.py
@@ -61,7 +61,7 @@ class JSONRPCException(Exception):
def EncodeDecimal(o):
if isinstance(o, decimal.Decimal):
- return round(o, 8)
+ return str(o)
raise TypeError(repr(o) + " is not JSON serializable")
class AuthServiceProxy(object):
@@ -92,11 +92,10 @@ class AuthServiceProxy(object):
self.__conn = connection
elif self.__url.scheme == 'https':
self.__conn = httplib.HTTPSConnection(self.__url.hostname, port,
- None, None, False,
- timeout)
+ timeout=timeout)
else:
self.__conn = httplib.HTTPConnection(self.__url.hostname, port,
- False, timeout)
+ timeout=timeout)
def __getattr__(self, name):
if name.startswith('__') and name.endswith('__'):
diff --git a/qa/rpc-tests/test_framework/blocktools.py b/qa/rpc-tests/test_framework/blocktools.py
index 7eea41b75c..b075f69c47 100644
--- a/qa/rpc-tests/test_framework/blocktools.py
+++ b/qa/rpc-tests/test_framework/blocktools.py
@@ -45,7 +45,7 @@ def create_coinbase(height, pubkey = None):
coinbase.vin.append(CTxIn(COutPoint(0, 0xffffffff),
ser_string(serialize_script_num(height)), 0xffffffff))
coinbaseoutput = CTxOut()
- coinbaseoutput.nValue = 50*100000000
+ coinbaseoutput.nValue = 50 * COIN
halvings = int(height/150) # regtest
coinbaseoutput.nValue >>= halvings
if (pubkey != None):
diff --git a/qa/rpc-tests/test_framework/comptool.py b/qa/rpc-tests/test_framework/comptool.py
index a4cd4d0a89..f19edbf069 100755
--- a/qa/rpc-tests/test_framework/comptool.py
+++ b/qa/rpc-tests/test_framework/comptool.py
@@ -27,20 +27,6 @@ generator that returns TestInstance objects. See below for definition.
global mininode_lock
-def wait_until(predicate, attempts=float('inf'), timeout=float('inf')):
- attempt = 0
- elapsed = 0
-
- while attempt < attempts and elapsed < timeout:
- with mininode_lock:
- if predicate():
- return True
- attempt += 1
- elapsed += 0.05
- time.sleep(0.05)
-
- return False
-
class RejectResult(object):
'''
Outcome that expects rejection of a transaction or block.
@@ -193,6 +179,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)
diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py
index 2135570b8c..20386c642c 100755
--- a/qa/rpc-tests/test_framework/mininode.py
+++ b/qa/rpc-tests/test_framework/mininode.py
@@ -38,6 +38,8 @@ MY_SUBVERSION = "/python-mininode-tester:0.0.1/"
MAX_INV_SZ = 50000
MAX_BLOCK_SIZE = 1000000
+COIN = 100000000L # 1 btc in satoshis
+
# Keep our own socket map for asyncore, so that we can track disconnects
# ourselves (to workaround an issue with closing an asyncore socket when
# using select)
@@ -231,6 +233,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
@@ -369,7 +379,7 @@ class CTxOut(object):
def __repr__(self):
return "CTxOut(nValue=%i.%08i scriptPubKey=%s)" \
- % (self.nValue // 100000000, self.nValue % 100000000,
+ % (self.nValue // COIN, self.nValue % COIN,
binascii.hexlify(self.scriptPubKey))
@@ -418,7 +428,7 @@ class CTransaction(object):
def is_valid(self):
self.calc_sha256()
for tout in self.vout:
- if tout.nValue < 0 or tout.nValue > 21000000L * 100000000L:
+ if tout.nValue < 0 or tout.nValue > 21000000 * COIN:
return False
return True
@@ -998,6 +1008,37 @@ class msg_reject(object):
return "msg_reject: %s %d %s [%064x]" \
% (self.message, self.code, self.reason, self.data)
+# Helper function
+def wait_until(predicate, attempts=float('inf'), timeout=float('inf')):
+ attempt = 0
+ elapsed = 0
+
+ while attempt < attempts and elapsed < timeout:
+ with mininode_lock:
+ if predicate():
+ return True
+ attempt += 1
+ elapsed += 0.05
+ time.sleep(0.05)
+
+ return False
+
+class msg_feefilter(object):
+ command = "feefilter"
+
+ def __init__(self, feerate=0L):
+ self.feerate = feerate
+
+ def deserialize(self, f):
+ self.feerate = struct.unpack("<Q", f.read(8))[0]
+
+ def serialize(self):
+ r = ""
+ r += struct.pack("<Q", self.feerate)
+ return r
+
+ def __repr__(self):
+ return "msg_feefilter(feerate=%08x)" % self.feerate
# This is what a callback should look like for NodeConn
# Reimplement the on_* functions to provide handling for events
@@ -1074,7 +1115,34 @@ class NodeConnCB(object):
def on_close(self, conn): pass
def on_mempool(self, conn): pass
def on_pong(self, conn, message): pass
+ def on_feefilter(self, conn, message): pass
+# More useful callbacks and functions for NodeConnCB's which have a single NodeConn
+class SingleNodeConnCB(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
+
+ # 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
+ def sync_with_ping(self, timeout=30):
+ def received_pong():
+ return (self.last_pong.nonce == self.ping_counter)
+ self.send_message(msg_ping(nonce=self.ping_counter))
+ success = wait_until(received_pong, timeout)
+ self.ping_counter += 1
+ return success
# The actual NodeConn class
# This class provides an interface for a p2p connection to a specified node
@@ -1095,7 +1163,8 @@ class NodeConn(asyncore.dispatcher):
"headers": msg_headers,
"getheaders": msg_getheaders,
"reject": msg_reject,
- "mempool": msg_mempool
+ "mempool": msg_mempool,
+ "feefilter": msg_feefilter
}
MAGIC_BYTES = {
"mainnet": "\xf9\xbe\xb4\xd9", # mainnet
diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py
index 8c472a518d..f069c32a60 100644
--- a/qa/rpc-tests/test_framework/util.py
+++ b/qa/rpc-tests/test_framework/util.py
@@ -16,6 +16,7 @@ import shutil
import subprocess
import time
import re
+import errno
from . import coverage
from .authproxy import AuthServiceProxy, JSONRPCException
@@ -130,11 +131,33 @@ def initialize_datadir(dirname, n):
f.write("listenonion=0\n")
return datadir
+def rpc_url(i, rpchost=None):
+ return "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1', rpc_port(i))
+
+def wait_for_bitcoind_start(process, url, i):
+ '''
+ Wait for bitcoind to start. This means that RPC is accessible and fully initialized.
+ Raise an exception if bitcoind exits during initialization.
+ '''
+ while True:
+ if process.poll() is not None:
+ raise Exception('bitcoind exited with status %i during initialization' % process.returncode)
+ try:
+ rpc = get_rpc_proxy(url, i)
+ blocks = rpc.getblockcount()
+ break # break out of loop on success
+ except IOError as e:
+ if e.errno != errno.ECONNREFUSED: # Port not yet open?
+ raise # unknown IO error
+ except JSONRPCException as e: # Initialization phase
+ if e.error['code'] != -28: # RPC in warmup?
+ raise # unkown JSON RPC exception
+ time.sleep(0.25)
+
def initialize_chain(test_dir):
"""
Create (or copy from cache) a 200-block-long chain and
4 wallets.
- bitcoind and bitcoin-cli must be in search path.
"""
if (not os.path.isdir(os.path.join("cache","node0"))
@@ -147,7 +170,6 @@ def initialize_chain(test_dir):
if os.path.isdir(os.path.join("cache","node"+str(i))):
shutil.rmtree(os.path.join("cache","node"+str(i)))
- devnull = open(os.devnull, "w")
# Create cache directories, run bitcoinds:
for i in range(4):
datadir=initialize_datadir("cache", i)
@@ -156,19 +178,15 @@ def initialize_chain(test_dir):
args.append("-connect=127.0.0.1:"+str(p2p_port(0)))
bitcoind_processes[i] = subprocess.Popen(args)
if os.getenv("PYTHON_DEBUG", ""):
- print "initialize_chain: bitcoind started, calling bitcoin-cli -rpcwait getblockcount"
- subprocess.check_call([ os.getenv("BITCOINCLI", "bitcoin-cli"), "-datadir="+datadir,
- "-rpcwait", "getblockcount"], stdout=devnull)
+ print "initialize_chain: bitcoind started, waiting for RPC to come up"
+ wait_for_bitcoind_start(bitcoind_processes[i], rpc_url(i), i)
if os.getenv("PYTHON_DEBUG", ""):
- print "initialize_chain: bitcoin-cli -rpcwait getblockcount completed"
- devnull.close()
+ print "initialize_chain: RPC succesfully started"
rpcs = []
-
for i in range(4):
try:
- url = "http://rt:rt@127.0.0.1:%d" % (rpc_port(i),)
- rpcs.append(get_rpc_proxy(url, i))
+ rpcs.append(get_rpc_proxy(rpc_url(i), i))
except:
sys.stderr.write("Error connecting to "+url+"\n")
sys.exit(1)
@@ -243,17 +261,12 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=
args = [ binary, "-datadir="+datadir, "-server", "-keypool=1", "-discover=0", "-rest", "-mocktime="+str(get_mocktime()) ]
if extra_args is not None: args.extend(extra_args)
bitcoind_processes[i] = subprocess.Popen(args)
- devnull = open(os.devnull, "w")
if os.getenv("PYTHON_DEBUG", ""):
- print "start_node: bitcoind started, calling bitcoin-cli -rpcwait getblockcount"
- subprocess.check_call([ os.getenv("BITCOINCLI", "bitcoin-cli"), "-datadir="+datadir] +
- _rpchost_to_args(rpchost) +
- ["-rpcwait", "getblockcount"], stdout=devnull)
+ print "start_node: bitcoind started, waiting for RPC to come up"
+ url = rpc_url(i, rpchost)
+ wait_for_bitcoind_start(bitcoind_processes[i], url, i)
if os.getenv("PYTHON_DEBUG", ""):
- print "start_node: calling bitcoin-cli -rpcwait getblockcount returned"
- devnull.close()
- url = "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1', rpc_port(i))
-
+ print "start_node: RPC succesfully started"
proxy = get_rpc_proxy(url, i, timeout=timewait)
if COVERAGE_DIR:
@@ -267,7 +280,14 @@ def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, binary=None):
"""
if extra_args is None: extra_args = [ None for i in range(num_nodes) ]
if binary is None: binary = [ None for i in range(num_nodes) ]
- return [ start_node(i, dirname, extra_args[i], rpchost, binary=binary[i]) for i in range(num_nodes) ]
+ rpcs = []
+ try:
+ for i in range(num_nodes):
+ rpcs.append(start_node(i, dirname, extra_args[i], rpchost, binary=binary[i]))
+ except: # If one node failed to start, stop the others
+ stop_nodes(rpcs)
+ raise
+ return rpcs
def log_filename(dirname, n_node, logname):
return os.path.join(dirname, "node"+str(n_node), "regtest", logname)
@@ -448,6 +468,8 @@ def assert_is_hash_string(string, length=64):
def satoshi_round(amount):
return Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN)
+# Helper to create at least "count" utxos
+# Pass in a fee that is sufficient for relay and mining new transactions.
def create_confirmed_utxos(fee, node, count):
node.generate(int(0.5*count)+101)
utxos = node.listunspent()
@@ -475,6 +497,8 @@ def create_confirmed_utxos(fee, node, count):
assert(len(utxos) >= count)
return utxos
+# Create large OP_RETURN txouts that can be appended to a transaction
+# to make it large (helper for constructing large transactions).
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)
@@ -493,6 +517,16 @@ def gen_return_txouts():
txouts = txouts + script_pubkey
return txouts
+def create_tx(node, coinbase, to_address, amount):
+ inputs = [{ "txid" : coinbase, "vout" : 0}]
+ outputs = { to_address : amount }
+ rawtx = node.createrawtransaction(inputs, outputs)
+ signresult = node.signrawtransaction(rawtx)
+ assert_equal(signresult["complete"], True)
+ return signresult["hex"]
+
+# Create a spend of each passed-in utxo, splicing in "txouts" to each raw
+# transaction to make it large. See gen_return_txouts() above.
def create_lots_of_big_transactions(node, txouts, utxos, fee):
addr = node.getnewaddress()
txids = []
diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py
index 6cd879e4a0..e6ce397119 100755
--- a/qa/rpc-tests/wallet.py
+++ b/qa/rpc-tests/wallet.py
@@ -59,6 +59,15 @@ class WalletTest (BitcoinTestFramework):
self.nodes[0].generate(1)
self.sync_all()
+ # Exercise locking of unspent outputs
+ unspent_0 = self.nodes[2].listunspent()[0]
+ unspent_0 = {"txid": unspent_0["txid"], "vout": unspent_0["vout"]}
+ self.nodes[2].lockunspent(False, [unspent_0])
+ assert_raises(JSONRPCException, self.nodes[2].sendtoaddress, self.nodes[2].getnewaddress(), 20)
+ assert_equal([unspent_0], self.nodes[2].listlockunspent())
+ self.nodes[2].lockunspent(True, [unspent_0])
+ assert_equal(len(self.nodes[2].listlockunspent()), 0)
+
# Have node1 generate 100 blocks (so node0 can recover the fee)
self.nodes[1].generate(100)
self.sync_all()
@@ -148,6 +157,10 @@ class WalletTest (BitcoinTestFramework):
assert(txid1 in self.nodes[3].getrawmempool())
+ # Exercise balance rpcs
+ assert_equal(self.nodes[0].getwalletinfo()["unconfirmed_balance"], 1)
+ assert_equal(self.nodes[0].getunconfirmedbalance(), 1)
+
#check if we can list zero value tx as available coins
#1. create rawtx
#2. hex-changed one output to 0.0
@@ -239,7 +252,7 @@ class WalletTest (BitcoinTestFramework):
except JSONRPCException,e:
errorString = e.error['message']
- assert_equal("Invalid amount" in errorString, True)
+ assert("Invalid amount" in errorString)
errorString = ""
try:
@@ -247,13 +260,26 @@ class WalletTest (BitcoinTestFramework):
except JSONRPCException,e:
errorString = e.error['message']
- assert_equal("not an integer" in errorString, True)
+ assert("not an integer" in errorString)
+
+ # Mine a block from node0 to an address from node1
+ cbAddr = self.nodes[1].getnewaddress()
+ blkHash = self.nodes[0].generatetoaddress(1, cbAddr)[0]
+ cbTxId = self.nodes[0].getblock(blkHash)['tx'][0]
+ self.sync_all()
+
+ # Check that the txid and balance is found by node1
+ try:
+ self.nodes[1].gettransaction(cbTxId)
+ except JSONRPCException,e:
+ assert("Invalid or non-wallet transaction id" not in e.error['message'])
#check if wallet or blochchain maintenance changes the balance
self.sync_all()
- self.nodes[0].generate(1)
+ blocks = self.nodes[0].generate(2)
self.sync_all()
balance_nodes = [self.nodes[i].getbalance() for i in range(3)]
+ block_count = self.nodes[0].getblockcount()
maintenance = [
'-rescan',
@@ -267,12 +293,17 @@ class WalletTest (BitcoinTestFramework):
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()
+ while m == '-reindex' and [block_count] * 3 != [self.nodes[i].getblockcount() for i in range(3)]:
+ # reindex will leave rpc warm up "early"; Wait for it to finish
+ time.sleep(0.1)
assert_equal(balance_nodes, [self.nodes[i].getbalance() for i in range(3)])
+ # Exercise listsinceblock with the last two blocks
+ coinbase_tx_1 = self.nodes[0].listsinceblock(blocks[0])
+ assert_equal(coinbase_tx_1["lastblock"], blocks[1])
+ assert_equal(len(coinbase_tx_1["transactions"]), 1)
+ assert_equal(coinbase_tx_1["transactions"][0]["blockhash"], blocks[1])
+ assert_equal(len(self.nodes[0].listsinceblock(blocks[1])["transactions"]), 0)
if __name__ == '__main__':
WalletTest ().main ()
diff --git a/qa/rpc-tests/zapwallettxes.py b/qa/rpc-tests/zapwallettxes.py
index 1ee0f79ac0..1ba4ded249 100755
--- a/qa/rpc-tests/zapwallettxes.py
+++ b/qa/rpc-tests/zapwallettxes.py
@@ -65,14 +65,8 @@ class ZapWalletTXesTest (BitcoinTestFramework):
#restart bitcoind with zapwallettxes
self.nodes[0] = start_node(0,self.options.tmpdir, ["-zapwallettxes=1"])
- aException = False
- try:
- tx3 = self.nodes[0].gettransaction(txid3)
- except JSONRPCException,e:
- print e
- aException = True
-
- assert_equal(aException, True) #there must be a expection because the unconfirmed wallettx0 must be gone by now
+ assert_raises(JSONRPCException, self.nodes[0].gettransaction, [txid3])
+ #there must be a expection because the unconfirmed wallettx0 must be gone by now
tx0 = self.nodes[0].gettransaction(txid0)
assert_equal(tx0['txid'], txid0) #tx0 (confirmed) must still be available because it was confirmed
diff --git a/share/qt/extract_strings_qt.py b/share/qt/extract_strings_qt.py
index 2a6e4b930c..7728a43775 100755
--- a/share/qt/extract_strings_qt.py
+++ b/share/qt/extract_strings_qt.py
@@ -1,8 +1,9 @@
#!/usr/bin/python
'''
-Extract _("...") strings for translation and convert to Qt4 stringdefs so that
+Extract _("...") strings for translation and convert to Qt stringdefs so that
they can be picked up by Qt linguist.
'''
+from __future__ import division,print_function,unicode_literals
from subprocess import Popen, PIPE
import glob
import operator
@@ -52,10 +53,14 @@ files = sys.argv[1:]
# xgettext -n --keyword=_ $FILES
XGETTEXT=os.getenv('XGETTEXT', 'xgettext')
+if not XGETTEXT:
+ print('Cannot extract strings: xgettext utility is not installed or not configured.',file=sys.stderr)
+ print('Please install package "gettext" and re-run \'./configure\'.',file=sys.stderr)
+ exit(1)
child = Popen([XGETTEXT,'--output=-','-n','--keyword=_'] + files, stdout=PIPE)
(out, err) = child.communicate()
-messages = parse_po(out)
+messages = parse_po(out.decode('utf-8'))
f = open(OUT_CPP, 'w')
f.write("""
diff --git a/share/rpcuser/README.md b/share/rpcuser/README.md
index 7c2c909a42..12a8e6fb0c 100644
--- a/share/rpcuser/README.md
+++ b/share/rpcuser/README.md
@@ -7,5 +7,4 @@ Create an RPC user login credential.
Usage:
-./rpcuser.py <username>
-
+ ./rpcuser.py <username>
diff --git a/src/Makefile.am b/src/Makefile.am
index c4f7188971..1e54512cbd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -87,7 +87,6 @@ endif
# bitcoin core #
BITCOIN_CORE_H = \
addrman.h \
- alert.h \
base58.h \
bloom.h \
chain.h \
@@ -131,6 +130,7 @@ BITCOIN_CORE_H = \
rpc/client.h \
rpc/protocol.h \
rpc/server.h \
+ rpc/register.h \
scheduler.h \
script/sigcache.h \
script/sign.h \
@@ -152,6 +152,7 @@ BITCOIN_CORE_H = \
utilmoneystr.h \
utiltime.h \
validationinterface.h \
+ versionbits.h \
wallet/crypter.h \
wallet/db.h \
wallet/rpcwallet.h \
@@ -175,7 +176,6 @@ libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CP
libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libbitcoin_server_a_SOURCES = \
addrman.cpp \
- alert.cpp \
bloom.cpp \
chain.cpp \
checkpoints.cpp \
@@ -204,6 +204,7 @@ libbitcoin_server_a_SOURCES = \
txdb.cpp \
txmempool.cpp \
validationinterface.cpp \
+ versionbits.cpp \
$(BITCOIN_CORE_H)
if ENABLE_ZMQ
@@ -430,6 +431,7 @@ endif
#
CLEANFILES = leveldb/libleveldb.a leveldb/libmemenv.a
+CLEANFILES += $(EXTRA_LIBRARIES)
CLEANFILES += *.gcda *.gcno
CLEANFILES += compat/*.gcda compat/*.gcno
CLEANFILES += consensus/*.gcda consensus/*.gcno
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index ca4e1e70d0..357e4c47ff 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -391,7 +391,7 @@ SECONDARY: $(QT_QM)
qt/bitcoinstrings.cpp: $(libbitcoin_server_a_SOURCES) $(libbitcoin_wallet_a_SOURCES)
@test -n $(XGETTEXT) || echo "xgettext is required for updating translations"
- $(AM_V_GEN) cd $(srcdir); XGETTEXT=$(XGETTEXT) PACKAGE_NAME="$(PACKAGE_NAME)" COPYRIGHT_HOLDERS="$(COPYRIGHT_HOLDERS)" COPYRIGHT_HOLDERS_SUBSTITUTION="$(COPYRIGHT_HOLDERS_SUBSTITUTION)" ../share/qt/extract_strings_qt.py $^
+ $(AM_V_GEN) cd $(srcdir); XGETTEXT=$(XGETTEXT) PACKAGE_NAME="$(PACKAGE_NAME)" COPYRIGHT_HOLDERS="$(COPYRIGHT_HOLDERS)" COPYRIGHT_HOLDERS_SUBSTITUTION="$(COPYRIGHT_HOLDERS_SUBSTITUTION)" $(PYTHON) ../share/qt/extract_strings_qt.py $^
translate: qt/bitcoinstrings.cpp $(QT_FORMS_UI) $(QT_FORMS_UI) $(BITCOIN_QT_CPP) $(BITCOIN_QT_H) $(BITCOIN_MM)
@test -n $(LUPDATE) || echo "lupdate is required for updating translations"
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 468d3043a7..d806fb219e 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -29,7 +29,7 @@ JSON_TEST_FILES = \
test/data/tx_valid.json \
test/data/sighash.json
-RAW_TEST_FILES = test/data/alertTests.raw
+RAW_TEST_FILES =
GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h)
@@ -38,13 +38,13 @@ BITCOIN_TESTS =\
test/scriptnum10.h \
test/addrman_tests.cpp \
test/alert_tests.cpp \
+ test/amount_tests.cpp \
test/allocator_tests.cpp \
test/base32_tests.cpp \
test/base58_tests.cpp \
test/base64_tests.cpp \
test/bip32_tests.cpp \
test/bloom_tests.cpp \
- test/checkblock_tests.cpp \
test/Checkpoints_tests.cpp \
test/coins_tests.cpp \
test/compress_tests.cpp \
@@ -79,9 +79,12 @@ BITCOIN_TESTS =\
test/streams_tests.cpp \
test/test_bitcoin.cpp \
test/test_bitcoin.h \
+ test/testutil.cpp \
+ test/testutil.h \
test/timedata_tests.cpp \
test/transaction_tests.cpp \
test/txvalidationcache_tests.cpp \
+ test/versionbits_tests.cpp \
test/uint256_tests.cpp \
test/univalue_tests.cpp \
test/util_tests.cpp
@@ -127,7 +130,7 @@ bitcoin_test_clean : FORCE
check-local:
@echo "Running test/bitcoin-util-test.py..."
- $(AM_V_at)srcdir=$(srcdir) PYTHONPATH=$(builddir)/test $(srcdir)/test/bitcoin-util-test.py
+ $(AM_V_at)srcdir=$(srcdir) PYTHONPATH=$(builddir)/test $(PYTHON) $(srcdir)/test/bitcoin-util-test.py
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C secp256k1 check
if EMBEDDED_UNIVALUE
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C univalue check
diff --git a/src/alert.cpp b/src/alert.cpp
deleted file mode 100644
index eb1cd5e7f6..0000000000
--- a/src/alert.cpp
+++ /dev/null
@@ -1,266 +0,0 @@
-// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2015 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#include "alert.h"
-
-#include "clientversion.h"
-#include "net.h"
-#include "pubkey.h"
-#include "timedata.h"
-#include "ui_interface.h"
-#include "util.h"
-#include "utilstrencodings.h"
-
-#include <stdint.h>
-#include <algorithm>
-#include <map>
-
-#include <boost/algorithm/string/classification.hpp>
-#include <boost/algorithm/string/replace.hpp>
-#include <boost/foreach.hpp>
-#include <boost/thread.hpp>
-
-using namespace std;
-
-map<uint256, CAlert> mapAlerts;
-CCriticalSection cs_mapAlerts;
-
-void CUnsignedAlert::SetNull()
-{
- nVersion = 1;
- nRelayUntil = 0;
- nExpiration = 0;
- nID = 0;
- nCancel = 0;
- setCancel.clear();
- nMinVer = 0;
- nMaxVer = 0;
- setSubVer.clear();
- nPriority = 0;
-
- strComment.clear();
- strStatusBar.clear();
- strReserved.clear();
-}
-
-std::string CUnsignedAlert::ToString() const
-{
- std::string strSetCancel;
- BOOST_FOREACH(int n, setCancel)
- strSetCancel += strprintf("%d ", n);
- std::string strSetSubVer;
- BOOST_FOREACH(const std::string& str, setSubVer)
- strSetSubVer += "\"" + str + "\" ";
- return strprintf(
- "CAlert(\n"
- " nVersion = %d\n"
- " nRelayUntil = %d\n"
- " nExpiration = %d\n"
- " nID = %d\n"
- " nCancel = %d\n"
- " setCancel = %s\n"
- " nMinVer = %d\n"
- " nMaxVer = %d\n"
- " setSubVer = %s\n"
- " nPriority = %d\n"
- " strComment = \"%s\"\n"
- " strStatusBar = \"%s\"\n"
- ")\n",
- nVersion,
- nRelayUntil,
- nExpiration,
- nID,
- nCancel,
- strSetCancel,
- nMinVer,
- nMaxVer,
- strSetSubVer,
- nPriority,
- strComment,
- strStatusBar);
-}
-
-void CAlert::SetNull()
-{
- CUnsignedAlert::SetNull();
- vchMsg.clear();
- vchSig.clear();
-}
-
-bool CAlert::IsNull() const
-{
- return (nExpiration == 0);
-}
-
-uint256 CAlert::GetHash() const
-{
- return Hash(this->vchMsg.begin(), this->vchMsg.end());
-}
-
-bool CAlert::IsInEffect() const
-{
- return (GetAdjustedTime() < nExpiration);
-}
-
-bool CAlert::Cancels(const CAlert& alert) const
-{
- if (!IsInEffect())
- return false; // this was a no-op before 31403
- return (alert.nID <= nCancel || setCancel.count(alert.nID));
-}
-
-bool CAlert::AppliesTo(int nVersion, const std::string& strSubVerIn) const
-{
- // TODO: rework for client-version-embedded-in-strSubVer ?
- return (IsInEffect() &&
- nMinVer <= nVersion && nVersion <= nMaxVer &&
- (setSubVer.empty() || setSubVer.count(strSubVerIn)));
-}
-
-bool CAlert::AppliesToMe() const
-{
- return AppliesTo(PROTOCOL_VERSION, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<std::string>()));
-}
-
-bool CAlert::RelayTo(CNode* pnode) const
-{
- if (!IsInEffect())
- return false;
- // don't relay to nodes which haven't sent their version message
- if (pnode->nVersion == 0)
- return false;
- // returns true if wasn't already contained in the set
- if (pnode->setKnown.insert(GetHash()).second)
- {
- if (AppliesTo(pnode->nVersion, pnode->strSubVer) ||
- AppliesToMe() ||
- GetAdjustedTime() < nRelayUntil)
- {
- pnode->PushMessage(NetMsgType::ALERT, *this);
- return true;
- }
- }
- return false;
-}
-
-bool CAlert::CheckSignature(const std::vector<unsigned char>& alertKey) const
-{
- CPubKey key(alertKey);
- if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
- return error("CAlert::CheckSignature(): verify signature failed");
-
- // Now unserialize the data
- CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION);
- sMsg >> *(CUnsignedAlert*)this;
- return true;
-}
-
-CAlert CAlert::getAlertByHash(const uint256 &hash)
-{
- CAlert retval;
- {
- LOCK(cs_mapAlerts);
- map<uint256, CAlert>::iterator mi = mapAlerts.find(hash);
- if(mi != mapAlerts.end())
- retval = mi->second;
- }
- return retval;
-}
-
-bool CAlert::ProcessAlert(const std::vector<unsigned char>& alertKey, bool fThread)
-{
- if (!CheckSignature(alertKey))
- return false;
- if (!IsInEffect())
- return false;
-
- // alert.nID=max is reserved for if the alert key is
- // compromised. It must have a pre-defined message,
- // must never expire, must apply to all versions,
- // and must cancel all previous
- // alerts or it will be ignored (so an attacker can't
- // send an "everything is OK, don't panic" version that
- // cannot be overridden):
- int maxInt = std::numeric_limits<int>::max();
- if (nID == maxInt)
- {
- if (!(
- nExpiration == maxInt &&
- nCancel == (maxInt-1) &&
- nMinVer == 0 &&
- nMaxVer == maxInt &&
- setSubVer.empty() &&
- nPriority == maxInt &&
- strStatusBar == "URGENT: Alert key compromised, upgrade required"
- ))
- return false;
- }
-
- {
- LOCK(cs_mapAlerts);
- // Cancel previous alerts
- for (map<uint256, CAlert>::iterator mi = mapAlerts.begin(); mi != mapAlerts.end();)
- {
- const CAlert& alert = (*mi).second;
- if (Cancels(alert))
- {
- LogPrint("alert", "cancelling alert %d\n", alert.nID);
- uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
- mapAlerts.erase(mi++);
- }
- else if (!alert.IsInEffect())
- {
- LogPrint("alert", "expiring alert %d\n", alert.nID);
- uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
- mapAlerts.erase(mi++);
- }
- else
- mi++;
- }
-
- // Check if this alert has been cancelled
- BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
- {
- const CAlert& alert = item.second;
- if (alert.Cancels(*this))
- {
- LogPrint("alert", "alert already cancelled by %d\n", alert.nID);
- return false;
- }
- }
-
- // Add to mapAlerts
- mapAlerts.insert(make_pair(GetHash(), *this));
- // Notify UI and -alertnotify if it applies to me
- if(AppliesToMe())
- {
- uiInterface.NotifyAlertChanged(GetHash(), CT_NEW);
- Notify(strStatusBar, fThread);
- }
- }
-
- LogPrint("alert", "accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe());
- return true;
-}
-
-void
-CAlert::Notify(const std::string& strMessage, bool fThread)
-{
- std::string strCmd = GetArg("-alertnotify", "");
- if (strCmd.empty()) return;
-
- // Alert text should be plain ascii coming from a trusted source, but to
- // be safe we first strip anything not in safeChars, then add single quotes around
- // the whole string before passing it to the shell:
- std::string singleQuote("'");
- std::string safeStatus = SanitizeString(strMessage);
- safeStatus = singleQuote+safeStatus+singleQuote;
- boost::replace_all(strCmd, "%s", safeStatus);
-
- if (fThread)
- boost::thread t(runCommand, strCmd); // thread runs free
- else
- runCommand(strCmd);
-}
diff --git a/src/alert.h b/src/alert.h
deleted file mode 100644
index 8cb86e338c..0000000000
--- a/src/alert.h
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2015 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#ifndef BITCOIN_ALERT_H
-#define BITCOIN_ALERT_H
-
-#include "serialize.h"
-#include "sync.h"
-
-#include <map>
-#include <set>
-#include <stdint.h>
-#include <string>
-
-class CAlert;
-class CNode;
-class uint256;
-
-extern std::map<uint256, CAlert> mapAlerts;
-extern CCriticalSection cs_mapAlerts;
-
-/** Alerts are for notifying old versions if they become too obsolete and
- * need to upgrade. The message is displayed in the status bar.
- * Alert messages are broadcast as a vector of signed data. Unserializing may
- * not read the entire buffer if the alert is for a newer version, but older
- * versions can still relay the original data.
- */
-class CUnsignedAlert
-{
-public:
- int nVersion;
- int64_t nRelayUntil; // when newer nodes stop relaying to newer nodes
- int64_t nExpiration;
- int nID;
- int nCancel;
- std::set<int> setCancel;
- int nMinVer; // lowest version inclusive
- int nMaxVer; // highest version inclusive
- std::set<std::string> setSubVer; // empty matches all
- int nPriority;
-
- // Actions
- std::string strComment;
- std::string strStatusBar;
- std::string strReserved;
-
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- READWRITE(this->nVersion);
- nVersion = this->nVersion;
- READWRITE(nRelayUntil);
- READWRITE(nExpiration);
- READWRITE(nID);
- READWRITE(nCancel);
- READWRITE(setCancel);
- READWRITE(nMinVer);
- READWRITE(nMaxVer);
- READWRITE(setSubVer);
- READWRITE(nPriority);
-
- READWRITE(LIMITED_STRING(strComment, 65536));
- READWRITE(LIMITED_STRING(strStatusBar, 256));
- READWRITE(LIMITED_STRING(strReserved, 256));
- }
-
- void SetNull();
-
- std::string ToString() const;
-};
-
-/** An alert is a combination of a serialized CUnsignedAlert and a signature. */
-class CAlert : public CUnsignedAlert
-{
-public:
- std::vector<unsigned char> vchMsg;
- std::vector<unsigned char> vchSig;
-
- CAlert()
- {
- SetNull();
- }
-
- ADD_SERIALIZE_METHODS;
-
- template <typename Stream, typename Operation>
- inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- READWRITE(vchMsg);
- READWRITE(vchSig);
- }
-
- void SetNull();
- bool IsNull() const;
- uint256 GetHash() const;
- bool IsInEffect() const;
- bool Cancels(const CAlert& alert) const;
- bool AppliesTo(int nVersion, const std::string& strSubVerIn) const;
- bool AppliesToMe() const;
- bool RelayTo(CNode* pnode) const;
- bool CheckSignature(const std::vector<unsigned char>& alertKey) const;
- bool ProcessAlert(const std::vector<unsigned char>& alertKey, bool fThread = true); // fThread means run -alertnotify in a free-running thread
- static void Notify(const std::string& strMessage, bool fThread);
-
- /*
- * Get copy of (active) alert object by hash. Returns a null alert if it is not found.
- */
- static CAlert getAlertByHash(const uint256 &hash);
-};
-
-#endif // BITCOIN_ALERT_H
diff --git a/src/amount.cpp b/src/amount.cpp
index a3abd8cd83..68806ff062 100644
--- a/src/amount.cpp
+++ b/src/amount.cpp
@@ -19,10 +19,10 @@ CFeeRate::CFeeRate(const CAmount& nFeePaid, size_t nSize)
CAmount CFeeRate::GetFee(size_t nSize) const
{
- CAmount nFee = nSatoshisPerK*nSize / 1000;
+ CAmount nFee = nSatoshisPerK * nSize / 1000;
- if (nFee == 0 && nSatoshisPerK > 0)
- nFee = nSatoshisPerK;
+ if (nFee == 0 && nSize != 0 && nSatoshisPerK > 0)
+ nFee = CAmount(1);
return nFee;
}
diff --git a/src/amount.h b/src/amount.h
index a48b17d514..9aba6525c7 100644
--- a/src/amount.h
+++ b/src/amount.h
@@ -42,10 +42,14 @@ public:
explicit CFeeRate(const CAmount& _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) { }
CFeeRate(const CAmount& nFeePaid, size_t nSize);
CFeeRate(const CFeeRate& other) { nSatoshisPerK = other.nSatoshisPerK; }
-
- CAmount GetFee(size_t size) const; // unit returned is satoshis
- CAmount GetFeePerK() const { return GetFee(1000); } // satoshis-per-1000-bytes
-
+ /**
+ * Return the fee in satoshis for the given size in bytes.
+ */
+ CAmount GetFee(size_t size) const;
+ /**
+ * Return the fee in satoshis for a size of 1000 bytes
+ */
+ CAmount GetFeePerK() const { return GetFee(1000); }
friend bool operator<(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK < b.nSatoshisPerK; }
friend bool operator>(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK > b.nSatoshisPerK; }
friend bool operator==(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK == b.nSatoshisPerK; }
diff --git a/src/base58.cpp b/src/base58.cpp
index 5e26cf8d47..d81c26092c 100644
--- a/src/base58.cpp
+++ b/src/base58.cpp
@@ -68,26 +68,31 @@ std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
{
// Skip & count leading zeroes.
int zeroes = 0;
+ int length = 0;
while (pbegin != pend && *pbegin == 0) {
pbegin++;
zeroes++;
}
// Allocate enough space in big-endian base58 representation.
- std::vector<unsigned char> b58((pend - pbegin) * 138 / 100 + 1); // log(256) / log(58), rounded up.
+ int size = (pend - pbegin) * 138 / 100 + 1; // log(256) / log(58), rounded up.
+ std::vector<unsigned char> b58(size);
// Process the bytes.
while (pbegin != pend) {
int carry = *pbegin;
+ int i = 0;
// Apply "b58 = b58 * 256 + ch".
- for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); it != b58.rend(); it++) {
+ for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); (carry != 0 || i < length) && (it != b58.rend()); it++, i++) {
carry += 256 * (*it);
*it = carry % 58;
carry /= 58;
}
+
assert(carry == 0);
+ length = i;
pbegin++;
}
// Skip leading zeroes in base58 result.
- std::vector<unsigned char>::iterator it = b58.begin();
+ std::vector<unsigned char>::iterator it = b58.begin() + (size - length);
while (it != b58.end() && *it == 0)
it++;
// Translate the result into a string.
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index 34980d9ca1..49935699fd 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -43,6 +43,7 @@ std::string HelpMessageCli()
strUsage += HelpMessageOpt("-rpcuser=<user>", _("Username for JSON-RPC connections"));
strUsage += HelpMessageOpt("-rpcpassword=<pw>", _("Password for JSON-RPC connections"));
strUsage += HelpMessageOpt("-rpcclienttimeout=<n>", strprintf(_("Timeout during HTTP requests (default: %d)"), DEFAULT_HTTP_CLIENT_TIMEOUT));
+ strUsage += HelpMessageOpt("-stdin", _("Read extra arguments from standard input, one per line until EOF/Ctrl-D (recommended for sensitive information such as passphrases)"));
return strUsage;
}
@@ -232,15 +233,17 @@ int CommandLineRPC(int argc, char *argv[])
argc--;
argv++;
}
-
- // Method
- if (argc < 2)
- throw runtime_error("too few parameters");
- string strMethod = argv[1];
-
- // Parameters default to strings
- std::vector<std::string> strParams(&argv[2], &argv[argc]);
- UniValue params = RPCConvertValues(strMethod, strParams);
+ std::vector<std::string> args = std::vector<std::string>(&argv[1], &argv[argc]);
+ if (GetBoolArg("-stdin", false)) {
+ // Read one arg per line from stdin and append
+ std::string line;
+ while (std::getline(std::cin,line))
+ args.push_back(line);
+ }
+ if (args.size() < 1)
+ throw runtime_error("too few parameters (need at least command)");
+ std::string strMethod = args[0];
+ UniValue params = RPCConvertValues(strMethod, std::vector<std::string>(args.begin()+1, args.end()));
// Execute and handle connection failures with -rpcwait
const bool fWait = GetBoolArg("-rpcwait", false);
diff --git a/src/chain.h b/src/chain.h
index 9199983565..5b9605a80b 100644
--- a/src/chain.h
+++ b/src/chain.h
@@ -14,8 +14,6 @@
#include <vector>
-#include <boost/foreach.hpp>
-
struct CDiskBlockPos
{
int nFile;
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index b962f6ac0a..965d131695 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -81,7 +81,18 @@ public:
consensus.nPowTargetSpacing = 10 * 60;
consensus.fPowAllowMinDifficultyBlocks = false;
consensus.fPowNoRetargeting = false;
- /**
+ consensus.nRuleChangeActivationThreshold = 1916; // 95% of 2016
+ consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing
+ consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;
+ consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 1199145601; // January 1, 2008
+ consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // December 31, 2008
+
+ // Deployment of BIP68, BIP112, and BIP113.
+ consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0;
+ consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1462060800; // May 1st, 2016
+ consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1493596800; // May 1st, 2017
+
+ /**
* The message start string is designed to be unlikely to occur in normal data.
* The characters are rarely used upper ASCII, not valid as UTF-8, and produce
* a large 32-bit integer with any alignment.
@@ -90,7 +101,6 @@ public:
pchMessageStart[1] = 0xbe;
pchMessageStart[2] = 0xb4;
pchMessageStart[3] = 0xd9;
- vAlertPubKey = ParseHex("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284");
nDefaultPort = 8333;
nPruneAfterHeight = 100000;
@@ -162,11 +172,21 @@ public:
consensus.nPowTargetSpacing = 10 * 60;
consensus.fPowAllowMinDifficultyBlocks = true;
consensus.fPowNoRetargeting = false;
+ consensus.nRuleChangeActivationThreshold = 1512; // 75% for testchains
+ consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing
+ consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;
+ consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 1199145601; // January 1, 2008
+ consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // December 31, 2008
+
+ // Deployment of BIP68, BIP112, and BIP113.
+ consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0;
+ consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1456790400; // March 1st, 2016
+ consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1493596800; // May 1st, 2017
+
pchMessageStart[0] = 0x0b;
pchMessageStart[1] = 0x11;
pchMessageStart[2] = 0x09;
pchMessageStart[3] = 0x07;
- vAlertPubKey = ParseHex("04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a");
nDefaultPort = 18333;
nPruneAfterHeight = 1000;
@@ -225,6 +245,14 @@ public:
consensus.nPowTargetSpacing = 10 * 60;
consensus.fPowAllowMinDifficultyBlocks = true;
consensus.fPowNoRetargeting = true;
+ consensus.nRuleChangeActivationThreshold = 108; // 75% for testchains
+ consensus.nMinerConfirmationWindow = 144; // Faster than normal for regtest (144 instead of 2016)
+ consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;
+ consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 0;
+ consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 999999999999ULL;
+ consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0;
+ consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 0;
+ consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 999999999999ULL;
pchMessageStart[0] = 0xfa;
pchMessageStart[1] = 0xbf;
diff --git a/src/chainparams.h b/src/chainparams.h
index 88bc666765..59202f548a 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -54,7 +54,6 @@ public:
const Consensus::Params& GetConsensus() const { return consensus; }
const CMessageHeader::MessageStartChars& MessageStart() const { return pchMessageStart; }
- const std::vector<unsigned char>& AlertKey() const { return vAlertPubKey; }
int GetDefaultPort() const { return nDefaultPort; }
const CBlock& GenesisBlock() const { return genesis; }
@@ -80,8 +79,6 @@ protected:
Consensus::Params consensus;
CMessageHeader::MessageStartChars pchMessageStart;
- //! Raw pub key bytes for the broadcast alert signing key.
- std::vector<unsigned char> vAlertPubKey;
int nDefaultPort;
uint64_t nPruneAfterHeight;
std::vector<CDNSSeedData> vSeeds;
diff --git a/src/coincontrol.h b/src/coincontrol.h
index 9626ad2c5b..12fe9ce219 100644
--- a/src/coincontrol.h
+++ b/src/coincontrol.h
@@ -38,10 +38,9 @@ public:
return (setSelected.size() > 0);
}
- bool IsSelected(const uint256& hash, unsigned int n) const
+ bool IsSelected(const COutPoint& output) const
{
- COutPoint outpt(hash, n);
- return (setSelected.count(outpt) > 0);
+ return (setSelected.count(output) > 0);
}
void Select(const COutPoint& output)
diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h
index 5a099cf53c..ad9cc26175 100644
--- a/src/consensus/consensus.h
+++ b/src/consensus/consensus.h
@@ -13,8 +13,11 @@ static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
/** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */
static const int COINBASE_MATURITY = 100;
-/** Flags for LockTime() */
+/** Flags for nSequence and nLockTime locks */
enum {
+ /* Interpret sequence numbers as relative lock-time constraints. */
+ LOCKTIME_VERIFY_SEQUENCE = (1 << 0),
+
/* Use GetMedianTimePast() instead of nTime for end point timestamp. */
LOCKTIME_MEDIAN_TIME_PAST = (1 << 1),
};
diff --git a/src/consensus/params.h b/src/consensus/params.h
index 335750fe80..4f3480b89b 100644
--- a/src/consensus/params.h
+++ b/src/consensus/params.h
@@ -7,8 +7,30 @@
#define BITCOIN_CONSENSUS_PARAMS_H
#include "uint256.h"
+#include <map>
+#include <string>
namespace Consensus {
+
+enum DeploymentPos
+{
+ DEPLOYMENT_TESTDUMMY,
+ DEPLOYMENT_CSV, // Deployment of BIP68, BIP112, and BIP113.
+ MAX_VERSION_BITS_DEPLOYMENTS
+};
+
+/**
+ * Struct for each individual consensus rule change using BIP9.
+ */
+struct BIP9Deployment {
+ /** Bit position to select the particular bit in nVersion. */
+ int bit;
+ /** Start MedianTime for version bits miner confirmation. Can be a date in the past */
+ int64_t nStartTime;
+ /** Timeout/expiry MedianTime for the deployment attempt. */
+ int64_t nTimeout;
+};
+
/**
* Parameters that influence chain consensus.
*/
@@ -22,6 +44,14 @@ struct Params {
/** Block height and hash at which BIP34 becomes active */
int BIP34Height;
uint256 BIP34Hash;
+ /**
+ * Minimum blocks including miner confirmation of the total of 2016 blocks in a retargetting period,
+ * (nPowTargetTimespan / nPowTargetSpacing) which is also used for BIP9 deployments.
+ * Examples: 1916 for 95%, 1512 for testchains.
+ */
+ uint32_t nRuleChangeActivationThreshold;
+ uint32_t nMinerConfirmationWindow;
+ BIP9Deployment vDeployments[MAX_VERSION_BITS_DEPLOYMENTS];
/** Proof of work parameters */
uint256 powLimit;
bool fPowAllowMinDifficultyBlocks;
diff --git a/src/httprpc.cpp b/src/httprpc.cpp
index 432a5c0792..04d3386e9a 100644
--- a/src/httprpc.cpp
+++ b/src/httprpc.cpp
@@ -21,6 +21,9 @@
#include <boost/algorithm/string.hpp> // boost::trim
#include <boost/foreach.hpp> //BOOST_FOREACH
+/** WWW-Authenticate to present with 401 Unauthorized response */
+static const char* WWW_AUTH_HEADER_DATA = "Basic realm=\"jsonrpc\"";
+
/** Simple one-shot callback timer to be used by the RPC mechanism to e.g.
* re-lock the wellet.
*/
@@ -151,6 +154,7 @@ static bool HTTPReq_JSONRPC(HTTPRequest* req, const std::string &)
// Check authorization
std::pair<bool, std::string> authHeader = req->GetHeader("authorization");
if (!authHeader.first) {
+ req->WriteHeader("WWW-Authenticate", WWW_AUTH_HEADER_DATA);
req->WriteReply(HTTP_UNAUTHORIZED);
return false;
}
@@ -163,6 +167,7 @@ static bool HTTPReq_JSONRPC(HTTPRequest* req, const std::string &)
shouldn't have their RPC port exposed. */
MilliSleep(250);
+ req->WriteHeader("WWW-Authenticate", WWW_AUTH_HEADER_DATA);
req->WriteReply(HTTP_UNAUTHORIZED);
return false;
}
@@ -214,7 +219,7 @@ static bool InitRPCAuthentication()
return false;
}
} else {
- LogPrintf("Config options rpcuser and rpcpassword will soon be deprecated. Locally-run instances may remove rpcuser to use cookie-based auth, or may be replaced with rpcauth. Please see share/rpcuser for rpcauth auth generation.");
+ LogPrintf("Config options rpcuser and rpcpassword will soon be deprecated. Locally-run instances may remove rpcuser to use cookie-based auth, or may be replaced with rpcauth. Please see share/rpcuser for rpcauth auth generation.\n");
strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
}
return true;
diff --git a/src/init.cpp b/src/init.cpp
index 9ca417b83a..a872abd16c 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -24,9 +24,11 @@
#include "net.h"
#include "policy/policy.h"
#include "rpc/server.h"
+#include "rpc/register.h"
#include "script/standard.h"
#include "script/sigcache.h"
#include "scheduler.h"
+#include "timedata.h"
#include "txdb.h"
#include "txmempool.h"
#include "torcontrol.h"
@@ -72,6 +74,7 @@ static const bool DEFAULT_REST_ENABLE = false;
static const bool DEFAULT_DISABLE_SAFEMODE = false;
static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;
+
#if ENABLE_ZMQ
static CZMQNotificationInterface* pzmqNotificationInterface = NULL;
#endif
@@ -194,7 +197,6 @@ void Shutdown()
if (pwalletMain)
pwalletMain->Flush(false);
#endif
- GenerateBitcoins(false, 0, Params());
StopNode();
StopTorControl();
UnregisterNodeSignals(GetNodeSignals());
@@ -315,7 +317,6 @@ std::string HelpMessage(HelpMessageMode mode)
string strUsage = HelpMessageGroup(_("Options:"));
strUsage += HelpMessageOpt("-?", _("Print this help message and exit"));
strUsage += HelpMessageOpt("-version", _("Print version and exit"));
- strUsage += HelpMessageOpt("-alerts", strprintf(_("Receive and display P2P network alerts (default: %u)"), DEFAULT_ALERTS));
strUsage += HelpMessageOpt("-alertnotify=<cmd>", _("Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)"));
strUsage += HelpMessageOpt("-blocknotify=<cmd>", _("Execute command when the best block changes (%s in cmd is replaced by block hash)"));
if (showDebug)
@@ -331,6 +332,7 @@ std::string HelpMessage(HelpMessageMode mode)
}
strUsage += HelpMessageOpt("-datadir=<dir>", _("Specify data directory"));
strUsage += HelpMessageOpt("-dbcache=<n>", strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache));
+ strUsage += HelpMessageOpt("-feefilter", strprintf(_("Tell other nodes to filter invs to us by our mempool min fee (default: %u)"), DEFAULT_FEEFILTER));
strUsage += HelpMessageOpt("-loadblock=<file>", _("Imports blocks from external blk000??.dat file on startup"));
strUsage += HelpMessageOpt("-maxorphantx=<n>", strprintf(_("Keep at most <n> unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS));
strUsage += HelpMessageOpt("-maxmempool=<n>", strprintf(_("Keep the transaction memory pool below <n> megabytes (default: %u)"), DEFAULT_MAX_MEMPOOL_SIZE));
@@ -365,12 +367,11 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-maxconnections=<n>", strprintf(_("Maintain at most <n> connections to peers (default: %u)"), DEFAULT_MAX_PEER_CONNECTIONS));
strUsage += HelpMessageOpt("-maxreceivebuffer=<n>", strprintf(_("Maximum per-connection receive buffer, <n>*1000 bytes (default: %u)"), DEFAULT_MAXRECEIVEBUFFER));
strUsage += HelpMessageOpt("-maxsendbuffer=<n>", strprintf(_("Maximum per-connection send buffer, <n>*1000 bytes (default: %u)"), DEFAULT_MAXSENDBUFFER));
+ strUsage += HelpMessageOpt("-maxtimeadjustment", strprintf(_("Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)"), DEFAULT_MAX_TIME_ADJUSTMENT));
strUsage += HelpMessageOpt("-onion=<ip:port>", strprintf(_("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)"), "-proxy"));
strUsage += HelpMessageOpt("-onlynet=<net>", _("Only connect to nodes in network <net> (ipv4, ipv6 or onion)"));
strUsage += HelpMessageOpt("-permitbaremultisig", strprintf(_("Relay non-P2SH multisig (default: %u)"), DEFAULT_PERMIT_BAREMULTISIG));
- strUsage += HelpMessageOpt("-peerbloomfilters", strprintf(_("Support filtering of blocks and transaction with bloom filters (default: %u)"), 1));
- if (showDebug)
- strUsage += HelpMessageOpt("-enforcenodebloom", strprintf("Enforce minimum protocol version to limit use of bloom filters (default: %u)", 0));
+ strUsage += HelpMessageOpt("-peerbloomfilters", strprintf(_("Support filtering of blocks and transaction with bloom filters (default: %u)"), DEFAULT_PEERBLOOMFILTERS));
strUsage += HelpMessageOpt("-port=<port>", strprintf(_("Listen for connections on <port> (default: %u or testnet: %u)"), Params(CBaseChainParams::MAIN).GetDefaultPort(), Params(CBaseChainParams::TESTNET).GetDefaultPort()));
strUsage += HelpMessageOpt("-proxy=<ip:port>", _("Connect through SOCKS5 proxy"));
strUsage += HelpMessageOpt("-proxyrandomize", strprintf(_("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)"), DEFAULT_PROXYRANDOMIZE));
@@ -393,26 +394,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-maxuploadtarget=<n>", strprintf(_("Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)"), DEFAULT_MAX_UPLOAD_TARGET));
#ifdef ENABLE_WALLET
- strUsage += HelpMessageGroup(_("Wallet options:"));
- strUsage += HelpMessageOpt("-disablewallet", _("Do not load the wallet and disable wallet RPC calls"));
- strUsage += HelpMessageOpt("-keypool=<n>", strprintf(_("Set key pool size to <n> (default: %u)"), DEFAULT_KEYPOOL_SIZE));
- strUsage += HelpMessageOpt("-fallbackfee=<amt>", strprintf(_("A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)"),
- CURRENCY_UNIT, FormatMoney(DEFAULT_FALLBACK_FEE)));
- strUsage += HelpMessageOpt("-mintxfee=<amt>", strprintf(_("Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)"),
- CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MINFEE)));
- strUsage += HelpMessageOpt("-paytxfee=<amt>", strprintf(_("Fee (in %s/kB) to add to transactions you send (default: %s)"),
- CURRENCY_UNIT, FormatMoney(payTxFee.GetFeePerK())));
- strUsage += HelpMessageOpt("-rescan", _("Rescan the block chain for missing wallet transactions on startup"));
- strUsage += HelpMessageOpt("-salvagewallet", _("Attempt to recover private keys from a corrupt wallet.dat on startup"));
- strUsage += HelpMessageOpt("-sendfreetransactions", strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), DEFAULT_SEND_FREE_TRANSACTIONS));
- strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), DEFAULT_SPEND_ZEROCONF_CHANGE));
- strUsage += HelpMessageOpt("-txconfirmtarget=<n>", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), DEFAULT_TX_CONFIRM_TARGET));
- strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format on startup"));
- strUsage += HelpMessageOpt("-wallet=<file>", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), "wallet.dat"));
- strUsage += HelpMessageOpt("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), DEFAULT_WALLETBROADCAST));
- strUsage += HelpMessageOpt("-walletnotify=<cmd>", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)"));
- strUsage += HelpMessageOpt("-zapwallettxes=<mode>", _("Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup") +
- " " + _("(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)"));
+ strUsage += CWallet::GetWalletHelpString(showDebug);
#endif
#if ENABLE_ZMQ
@@ -430,16 +412,10 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-checkblockindex", strprintf("Do a full consistency check for mapBlockIndex, setBlockIndexCandidates, chainActive and mapBlocksUnlinked occasionally. Also sets -checkmempool (default: %u)", Params(CBaseChainParams::MAIN).DefaultConsistencyChecks()));
strUsage += HelpMessageOpt("-checkmempool=<n>", strprintf("Run checks every <n> transactions (default: %u)", Params(CBaseChainParams::MAIN).DefaultConsistencyChecks()));
strUsage += HelpMessageOpt("-checkpoints", strprintf("Disable expensive verification for known chain history (default: %u)", DEFAULT_CHECKPOINTS_ENABLED));
-#ifdef ENABLE_WALLET
- strUsage += HelpMessageOpt("-dblogsize=<n>", strprintf("Flush wallet database activity from memory to disk log every <n> megabytes (default: %u)", DEFAULT_WALLET_DBLOGSIZE));
-#endif
strUsage += HelpMessageOpt("-disablesafemode", strprintf("Disable safemode, override a real safe mode event (default: %u)", DEFAULT_DISABLE_SAFEMODE));
strUsage += HelpMessageOpt("-testsafemode", strprintf("Force safe mode (default: %u)", DEFAULT_TESTSAFEMODE));
strUsage += HelpMessageOpt("-dropmessagestest=<n>", "Randomly drop 1 of every <n> network messages");
strUsage += HelpMessageOpt("-fuzzmessagestest=<n>", "Randomly fuzz 1 of every <n> network messages");
-#ifdef ENABLE_WALLET
- strUsage += HelpMessageOpt("-flushwallet", strprintf("Run a thread to flush wallet periodically (default: %u)", DEFAULT_FLUSHWALLET));
-#endif
strUsage += HelpMessageOpt("-stopafterblockimport", strprintf("Stop running after importing blocks from disk (default: %u)", DEFAULT_STOPAFTERBLOCKIMPORT));
strUsage += HelpMessageOpt("-limitancestorcount=<n>", strprintf("Do not accept transactions if number of in-mempool ancestors is <n> or more (default: %u)", DEFAULT_ANCESTOR_LIMIT));
strUsage += HelpMessageOpt("-limitancestorsize=<n>", strprintf("Do not accept transactions whose size with all in-mempool ancestors exceeds <n> kilobytes (default: %u)", DEFAULT_ANCESTOR_SIZE_LIMIT));
@@ -453,8 +429,6 @@ std::string HelpMessage(HelpMessageMode mode)
_("If <category> is not supplied or if <category> = 1, output all debugging information.") + _("<category> can be:") + " " + debugCategories + ".");
if (showDebug)
strUsage += HelpMessageOpt("-nodebug", "Turn off debugging messages, same as -debug=0");
- strUsage += HelpMessageOpt("-gen", strprintf(_("Generate coins (default: %u)"), DEFAULT_GENERATE));
- strUsage += HelpMessageOpt("-genproclimit=<n>", strprintf(_("Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)"), DEFAULT_GENERATE_THREADS));
strUsage += HelpMessageOpt("-help-debug", _("Show all debugging options (usage: --help -help-debug)"));
strUsage += HelpMessageOpt("-logips", strprintf(_("Include IP addresses in debug output (default: %u)"), DEFAULT_LOGIPS));
strUsage += HelpMessageOpt("-logtimestamps", strprintf(_("Prepend debug output with timestamp (default: %u)"), DEFAULT_LOGTIMESTAMPS));
@@ -475,9 +449,6 @@ std::string HelpMessage(HelpMessageMode mode)
if (showDebug)
{
strUsage += HelpMessageOpt("-printpriority", strprintf("Log transaction priority and fee per kB when mining blocks (default: %u)", DEFAULT_PRINTPRIORITY));
-#ifdef ENABLE_WALLET
- strUsage += HelpMessageOpt("-privdb", strprintf("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)", DEFAULT_WALLET_PRIVDB));
-#endif
}
strUsage += HelpMessageOpt("-shrinkdebugfile", _("Shrink debug.log file on client startup (default: 1 when no -debug)"));
@@ -496,7 +467,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-blockmaxsize=<n>", strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE));
strUsage += HelpMessageOpt("-blockprioritysize=<n>", strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE));
if (showDebug)
- strUsage += HelpMessageOpt("-blockversion=<n>", strprintf("Override block version to test forking scenarios (default: %d)", (int)CBlock::CURRENT_VERSION));
+ strUsage += HelpMessageOpt("-blockversion=<n>", "Override block version to test forking scenarios");
strUsage += HelpMessageGroup(_("RPC server options:"));
strUsage += HelpMessageOpt("-server", _("Accept command line and JSON-RPC commands"));
@@ -945,10 +916,11 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
fPruneMode = true;
}
+ RegisterAllCoreRPCCommands(tableRPC);
#ifdef ENABLE_WALLET
bool fDisableWallet = GetBoolArg("-disablewallet", false);
if (!fDisableWallet)
- walletRegisterRPCCommands();
+ RegisterWalletRPCCommands(tableRPC);
#endif
nConnectTimeout = GetArg("-timeout", DEFAULT_CONNECT_TIMEOUT);
@@ -1025,19 +997,17 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
bSpendZeroConfChange = GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
fSendFreeTransactions = GetBoolArg("-sendfreetransactions", DEFAULT_SEND_FREE_TRANSACTIONS);
- std::string strWalletFile = GetArg("-wallet", "wallet.dat");
+ std::string strWalletFile = GetArg("-wallet", DEFAULT_WALLET_DAT);
#endif // ENABLE_WALLET
fIsBareMultisigStd = GetBoolArg("-permitbaremultisig", DEFAULT_PERMIT_BAREMULTISIG);
fAcceptDatacarrier = GetBoolArg("-datacarrier", DEFAULT_ACCEPT_DATACARRIER);
nMaxDatacarrierBytes = GetArg("-datacarriersize", nMaxDatacarrierBytes);
- fAlerts = GetBoolArg("-alerts", DEFAULT_ALERTS);
-
// Option to startup with mocktime set (used for regression testing):
SetMockTime(GetArg("-mocktime", 0)); // SetMockTime(0) is a no-op
- if (GetBoolArg("-peerbloomfilters", true))
+ if (GetBoolArg("-peerbloomfilters", DEFAULT_PEERBLOOMFILTERS))
nLocalServices |= NODE_BLOOM;
nMaxTipAge = GetArg("-maxtipage", DEFAULT_MAX_TIP_AGE);
@@ -1089,12 +1059,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (fPrintToDebugLog)
OpenDebugLog();
-#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
- LogPrintf("Using OpenSSL version %s\n", SSLeay_version(SSLEAY_VERSION));
-#else
- LogPrintf("Using OpenSSL version %s\n", OpenSSL_version(OPENSSL_VERSION));
-#endif
-
#ifdef ENABLE_WALLET
LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0));
#endif
@@ -1195,6 +1159,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
// -proxy sets a proxy for all outgoing network traffic
// -noproxy (or -proxy=0) as well as the empty string can be used to not set a proxy, this is the default
std::string proxyArg = GetArg("-proxy", "");
+ SetLimited(NET_TOR);
if (proxyArg != "" && proxyArg != "0") {
proxyType addrProxy = proxyType(CService(proxyArg, 9050), proxyRandomize);
if (!addrProxy.IsValid())
@@ -1204,7 +1169,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
SetProxy(NET_IPV6, addrProxy);
SetProxy(NET_TOR, addrProxy);
SetNameProxy(addrProxy);
- SetReachable(NET_TOR); // by default, -proxy sets onion as reachable, unless -noonion later
+ SetLimited(NET_TOR, false); // by default, -proxy sets onion as reachable, unless -noonion later
}
// -onion can be used to set only a proxy for .onion, or override normal proxy for .onion addresses
@@ -1213,13 +1178,13 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
std::string onionArg = GetArg("-onion", "");
if (onionArg != "") {
if (onionArg == "0") { // Handle -noonion/-onion=0
- SetReachable(NET_TOR, false); // set onions as unreachable
+ SetLimited(NET_TOR); // set onions as unreachable
} else {
proxyType addrOnion = proxyType(CService(onionArg, 9050), proxyRandomize);
if (!addrOnion.IsValid())
return InitError(strprintf(_("Invalid -onion address: '%s'"), onionArg));
SetProxy(NET_TOR, addrOnion);
- SetReachable(NET_TOR);
+ SetLimited(NET_TOR, false);
}
}
@@ -1456,149 +1421,19 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
pwalletMain = NULL;
LogPrintf("Wallet disabled!\n");
} else {
-
- // needed to restore wallet transaction meta data after -zapwallettxes
- std::vector<CWalletTx> vWtx;
-
- if (GetBoolArg("-zapwallettxes", false)) {
- uiInterface.InitMessage(_("Zapping all transactions from wallet..."));
-
- pwalletMain = new CWallet(strWalletFile);
- DBErrors nZapWalletRet = pwalletMain->ZapWalletTx(vWtx);
- if (nZapWalletRet != DB_LOAD_OK) {
- uiInterface.InitMessage(_("Error loading wallet.dat: Wallet corrupted"));
- return false;
- }
-
- delete pwalletMain;
- pwalletMain = NULL;
- }
-
- uiInterface.InitMessage(_("Loading wallet..."));
-
- nStart = GetTimeMillis();
- bool fFirstRun = true;
- pwalletMain = new CWallet(strWalletFile);
- DBErrors nLoadWalletRet = pwalletMain->LoadWallet(fFirstRun);
- if (nLoadWalletRet != DB_LOAD_OK)
- {
- if (nLoadWalletRet == DB_CORRUPT)
- strErrors << _("Error loading wallet.dat: Wallet corrupted") << "\n";
- else if (nLoadWalletRet == DB_NONCRITICAL_ERROR)
- {
- InitWarning(_("Error reading wallet.dat! All keys read correctly, but transaction data"
- " or address book entries might be missing or incorrect."));
- }
- else if (nLoadWalletRet == DB_TOO_NEW)
- strErrors << strprintf(_("Error loading wallet.dat: Wallet requires newer version of %s"), _(PACKAGE_NAME)) << "\n";
- else if (nLoadWalletRet == DB_NEED_REWRITE)
- {
- strErrors << strprintf(_("Wallet needed to be rewritten: restart %s to complete"), _(PACKAGE_NAME)) << "\n";
- LogPrintf("%s", strErrors.str());
- return InitError(strErrors.str());
- }
- else
- strErrors << _("Error loading wallet.dat") << "\n";
- }
-
- if (GetBoolArg("-upgradewallet", fFirstRun))
- {
- int nMaxVersion = GetArg("-upgradewallet", 0);
- if (nMaxVersion == 0) // the -upgradewallet without argument case
- {
- LogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
- nMaxVersion = CLIENT_VERSION;
- pwalletMain->SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately
- }
- else
- LogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
- if (nMaxVersion < pwalletMain->GetVersion())
- strErrors << _("Cannot downgrade wallet") << "\n";
- pwalletMain->SetMaxVersion(nMaxVersion);
- }
-
- if (fFirstRun)
- {
- // Create new keyUser and set as default key
- RandAddSeedPerfmon();
-
- CPubKey newDefaultKey;
- if (pwalletMain->GetKeyFromPool(newDefaultKey)) {
- pwalletMain->SetDefaultKey(newDefaultKey);
- if (!pwalletMain->SetAddressBook(pwalletMain->vchDefaultKey.GetID(), "", "receive"))
- strErrors << _("Cannot write default address") << "\n";
- }
-
- pwalletMain->SetBestChain(chainActive.GetLocator());
- }
-
- LogPrintf("%s", strErrors.str());
- LogPrintf(" wallet %15dms\n", GetTimeMillis() - nStart);
-
- RegisterValidationInterface(pwalletMain);
-
- CBlockIndex *pindexRescan = chainActive.Tip();
- if (GetBoolArg("-rescan", false))
- pindexRescan = chainActive.Genesis();
- else
- {
- CWalletDB walletdb(strWalletFile);
- CBlockLocator locator;
- if (walletdb.ReadBestBlock(locator))
- pindexRescan = FindForkInGlobalIndex(chainActive, locator);
- else
- pindexRescan = chainActive.Genesis();
- }
- if (chainActive.Tip() && chainActive.Tip() != pindexRescan)
+ std::string warningString;
+ std::string errorString;
+ pwalletMain = CWallet::InitLoadWallet(fDisableWallet, strWalletFile, warningString, errorString);
+ if (!warningString.empty())
+ InitWarning(warningString);
+ if (!errorString.empty())
{
- //We can't rescan beyond non-pruned blocks, stop and throw an error
- //this might happen if a user uses a old wallet within a pruned node
- // or if he ran -disablewallet for a longer time, then decided to re-enable
- if (fPruneMode)
- {
- CBlockIndex *block = chainActive.Tip();
- while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA) && block->pprev->nTx > 0 && pindexRescan != block)
- block = block->pprev;
-
- if (pindexRescan != block)
- return InitError(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)"));
- }
-
- uiInterface.InitMessage(_("Rescanning..."));
- LogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height() - pindexRescan->nHeight, pindexRescan->nHeight);
- nStart = GetTimeMillis();
- pwalletMain->ScanForWalletTransactions(pindexRescan, true);
- LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart);
- pwalletMain->SetBestChain(chainActive.GetLocator());
- nWalletDBUpdated++;
-
- // Restore wallet transaction metadata after -zapwallettxes=1
- if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2")
- {
- CWalletDB walletdb(strWalletFile);
-
- BOOST_FOREACH(const CWalletTx& wtxOld, vWtx)
- {
- uint256 hash = wtxOld.GetHash();
- std::map<uint256, CWalletTx>::iterator mi = pwalletMain->mapWallet.find(hash);
- if (mi != pwalletMain->mapWallet.end())
- {
- const CWalletTx* copyFrom = &wtxOld;
- CWalletTx* copyTo = &mi->second;
- copyTo->mapValue = copyFrom->mapValue;
- copyTo->vOrderForm = copyFrom->vOrderForm;
- copyTo->nTimeReceived = copyFrom->nTimeReceived;
- copyTo->nTimeSmart = copyFrom->nTimeSmart;
- copyTo->fFromMe = copyFrom->fFromMe;
- copyTo->strFromAccount = copyFrom->strFromAccount;
- copyTo->nOrderPos = copyFrom->nOrderPos;
- copyTo->WriteToDisk(&walletdb);
- }
- }
- }
+ LogPrintf("%s", errorString);
+ return InitError(errorString);
}
- pwalletMain->SetBroadcastTransactions(GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
- } // (!fDisableWallet)
+ if (!pwalletMain)
+ return false;
+ }
#else // ENABLE_WALLET
LogPrintf("No wallet support compiled in!\n");
#endif // !ENABLE_WALLET
@@ -1670,9 +1505,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
boost::ref(cs_main), boost::cref(pindexBestHeader), nPowTargetSpacing);
scheduler.scheduleEvery(f, nPowTargetSpacing);
- // Generate coins in the background
- GenerateBitcoins(GetBoolArg("-gen", DEFAULT_GENERATE), GetArg("-genproclimit", DEFAULT_GENERATE_THREADS), chainparams);
-
// ********************************************************* Step 12: finished
SetRPCWarmupFinished();
diff --git a/src/main.cpp b/src/main.cpp
index 89b4b2930c..2c0b3bfee7 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -6,7 +6,6 @@
#include "main.h"
#include "addrman.h"
-#include "alert.h"
#include "arith_uint256.h"
#include "chainparams.h"
#include "checkpoints.h"
@@ -18,10 +17,12 @@
#include "init.h"
#include "merkleblock.h"
#include "net.h"
+#include "policy/fees.h"
#include "policy/policy.h"
#include "pow.h"
#include "primitives/block.h"
#include "primitives/transaction.h"
+#include "random.h"
#include "script/script.h"
#include "script/sigcache.h"
#include "script/standard.h"
@@ -34,6 +35,7 @@
#include "utilmoneystr.h"
#include "utilstrencodings.h"
#include "validationinterface.h"
+#include "versionbits.h"
#include <sstream>
@@ -74,7 +76,6 @@ bool fCheckBlockIndex = false;
bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED;
size_t nCoinCacheUsage = 5000 * 300;
uint64_t nPruneTarget = 0;
-bool fAlerts = DEFAULT_ALERTS;
int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE;
bool fEnableReplacement = DEFAULT_ENABLE_REPLACEMENT;
@@ -82,6 +83,7 @@ CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE;
CTxMemPool mempool(::minRelayTxFee);
+FeeFilterRounder filterRounder(::minRelayTxFee);
struct COrphanTx {
CTransaction tx;
@@ -332,8 +334,10 @@ void FinalizeNode(NodeId nodeid) {
AddressCurrentlyConnected(state->address);
}
- BOOST_FOREACH(const QueuedBlock& entry, state->vBlocksInFlight)
+ BOOST_FOREACH(const QueuedBlock& entry, state->vBlocksInFlight) {
+ nQueuedValidatedHeaders -= entry.fValidatedHeaders;
mapBlocksInFlight.erase(entry.hash);
+ }
EraseOrphansFor(nodeid);
nPreferredDownload -= state->fPreferredDownload;
@@ -374,7 +378,7 @@ void MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const Consensus::Pa
mapBlocksInFlight[hash] = std::make_pair(nodeid, it);
}
-/** Check whether the last unknown block a peer advertized is not yet known. */
+/** Check whether the last unknown block a peer advertised is not yet known. */
void ProcessBlockAvailability(NodeId nodeid) {
CNodeState *state = State(nodeid);
assert(state != NULL);
@@ -670,9 +674,10 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
return true;
if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
return true;
- BOOST_FOREACH(const CTxIn& txin, tx.vin)
- if (!txin.IsFinal())
+ BOOST_FOREACH(const CTxIn& txin, tx.vin) {
+ if (!(txin.nSequence == CTxIn::SEQUENCE_FINAL))
return false;
+ }
return true;
}
@@ -708,6 +713,178 @@ bool CheckFinalTx(const CTransaction &tx, int flags)
return IsFinalTx(tx, nBlockHeight, nBlockTime);
}
+/**
+ * Calculates the block height and previous block's median time past at
+ * which the transaction will be considered final in the context of BIP 68.
+ * Also removes from the vector of input heights any entries which did not
+ * correspond to sequence locked inputs as they do not affect the calculation.
+ */
+static std::pair<int, int64_t> CalculateSequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeights, const CBlockIndex& block)
+{
+ assert(prevHeights->size() == tx.vin.size());
+
+ // Will be set to the equivalent height- and time-based nLockTime
+ // values that would be necessary to satisfy all relative lock-
+ // time constraints given our view of block chain history.
+ // The semantics of nLockTime are the last invalid height/time, so
+ // use -1 to have the effect of any height or time being valid.
+ int nMinHeight = -1;
+ int64_t nMinTime = -1;
+
+ // tx.nVersion is signed integer so requires cast to unsigned otherwise
+ // we would be doing a signed comparison and half the range of nVersion
+ // wouldn't support BIP 68.
+ bool fEnforceBIP68 = static_cast<uint32_t>(tx.nVersion) >= 2
+ && flags & LOCKTIME_VERIFY_SEQUENCE;
+
+ // Do not enforce sequence numbers as a relative lock time
+ // unless we have been instructed to
+ if (!fEnforceBIP68) {
+ return std::make_pair(nMinHeight, nMinTime);
+ }
+
+ for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) {
+ const CTxIn& txin = tx.vin[txinIndex];
+
+ // Sequence numbers with the most significant bit set are not
+ // treated as relative lock-times, nor are they given any
+ // consensus-enforced meaning at this point.
+ if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) {
+ // The height of this input is not relevant for sequence locks
+ (*prevHeights)[txinIndex] = 0;
+ continue;
+ }
+
+ int nCoinHeight = (*prevHeights)[txinIndex];
+
+ if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) {
+ int64_t nCoinTime = block.GetAncestor(std::max(nCoinHeight-1, 0))->GetMedianTimePast();
+ // NOTE: Subtract 1 to maintain nLockTime semantics
+ // BIP 68 relative lock times have the semantics of calculating
+ // the first block or time at which the transaction would be
+ // valid. When calculating the effective block time or height
+ // for the entire transaction, we switch to using the
+ // semantics of nLockTime which is the last invalid block
+ // time or height. Thus we subtract 1 from the calculated
+ // time or height.
+
+ // Time-based relative lock-times are measured from the
+ // smallest allowed timestamp of the block containing the
+ // txout being spent, which is the median time past of the
+ // block prior.
+ nMinTime = std::max(nMinTime, nCoinTime + (int64_t)((txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) << CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) - 1);
+ } else {
+ nMinHeight = std::max(nMinHeight, nCoinHeight + (int)(txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) - 1);
+ }
+ }
+
+ return std::make_pair(nMinHeight, nMinTime);
+}
+
+static bool EvaluateSequenceLocks(const CBlockIndex& block, std::pair<int, int64_t> lockPair)
+{
+ assert(block.pprev);
+ int64_t nBlockTime = block.pprev->GetMedianTimePast();
+ if (lockPair.first >= block.nHeight || lockPair.second >= nBlockTime)
+ return false;
+
+ return true;
+}
+
+bool SequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeights, const CBlockIndex& block)
+{
+ return EvaluateSequenceLocks(block, CalculateSequenceLocks(tx, flags, prevHeights, block));
+}
+
+bool TestLockPointValidity(const LockPoints* lp)
+{
+ AssertLockHeld(cs_main);
+ assert(lp);
+ // If there are relative lock times then the maxInputBlock will be set
+ // If there are no relative lock times, the LockPoints don't depend on the chain
+ if (lp->maxInputBlock) {
+ // Check whether chainActive is an extension of the block at which the LockPoints
+ // calculation was valid. If not LockPoints are no longer valid
+ if (!chainActive.Contains(lp->maxInputBlock)) {
+ return false;
+ }
+ }
+
+ // LockPoints still valid
+ return true;
+}
+
+bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp, bool useExistingLockPoints)
+{
+ AssertLockHeld(cs_main);
+ AssertLockHeld(mempool.cs);
+
+ CBlockIndex* tip = chainActive.Tip();
+ CBlockIndex index;
+ index.pprev = tip;
+ // CheckSequenceLocks() uses chainActive.Height()+1 to evaluate
+ // height based locks because when SequenceLocks() is called within
+ // ConnectBlock(), the height of the block *being*
+ // evaluated is what is used.
+ // Thus if we want to know if a transaction can be part of the
+ // *next* block, we need to use one more than chainActive.Height()
+ index.nHeight = tip->nHeight + 1;
+
+ std::pair<int, int64_t> lockPair;
+ if (useExistingLockPoints) {
+ assert(lp);
+ lockPair.first = lp->height;
+ lockPair.second = lp->time;
+ }
+ else {
+ // pcoinsTip contains the UTXO set for chainActive.Tip()
+ CCoinsViewMemPool viewMemPool(pcoinsTip, mempool);
+ std::vector<int> prevheights;
+ prevheights.resize(tx.vin.size());
+ for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) {
+ const CTxIn& txin = tx.vin[txinIndex];
+ CCoins coins;
+ if (!viewMemPool.GetCoins(txin.prevout.hash, coins)) {
+ return error("%s: Missing input", __func__);
+ }
+ if (coins.nHeight == MEMPOOL_HEIGHT) {
+ // Assume all mempool transaction confirm in the next block
+ prevheights[txinIndex] = tip->nHeight + 1;
+ } else {
+ prevheights[txinIndex] = coins.nHeight;
+ }
+ }
+ lockPair = CalculateSequenceLocks(tx, flags, &prevheights, index);
+ if (lp) {
+ lp->height = lockPair.first;
+ lp->time = lockPair.second;
+ // Also store the hash of the block with the highest height of
+ // all the blocks which have sequence locked prevouts.
+ // This hash needs to still be on the chain
+ // for these LockPoint calculations to be valid
+ // Note: It is impossible to correctly calculate a maxInputBlock
+ // if any of the sequence locked inputs depend on unconfirmed txs,
+ // except in the special case where the relative lock time/height
+ // is 0, which is equivalent to no sequence lock. Since we assume
+ // input height of tip+1 for mempool txs and test the resulting
+ // lockPair from CalculateSequenceLocks against tip+1. We know
+ // EvaluateSequenceLocks will fail if there was a non-zero sequence
+ // lock on a mempool input, so we can use the return value of
+ // CheckSequenceLocks to indicate the LockPoints validity
+ int maxInputHeight = 0;
+ BOOST_FOREACH(int height, prevheights) {
+ // Can ignore mempool inputs since we'll fail if they had non-zero locks
+ if (height != tip->nHeight+1) {
+ maxInputHeight = std::max(maxInputHeight, height);
+ }
+ }
+ lp->maxInputBlock = tip->GetAncestor(maxInputHeight);
+ }
+ }
+ return EvaluateSequenceLocks(index, lockPair);
+}
+
+
unsigned int GetLegacySigOpCount(const CTransaction& tx)
{
unsigned int nSigOps = 0;
@@ -813,7 +990,7 @@ std::string FormatStateMessage(const CValidationState &state)
}
bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const CTransaction& tx, bool fLimitFree,
- bool* pfMissingInputs, bool fOverrideMempoolLimit, const CAmount nAbsurdFee,
+ bool* pfMissingInputs, CFeeRate* txFeeRate, bool fOverrideMempoolLimit, const CAmount& nAbsurdFee,
std::vector<uint256>& vHashTxnToUncache)
{
const uint256 hash = tx.GetHash();
@@ -822,7 +999,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
*pfMissingInputs = false;
if (!CheckTransaction(tx, state))
- return error("%s: CheckTransaction: %s, %s", __func__, hash.ToString(), FormatStateMessage(state));
+ return false; // state filled in by CheckTransaction
// Coinbase is only valid in a block, not as a loose transaction
if (tx.IsCoinBase())
@@ -892,6 +1069,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
CCoinsViewCache view(&dummy);
CAmount nValueIn = 0;
+ LockPoints lp;
{
LOCK(pool.cs);
CCoinsViewMemPool viewMemPool(pcoinsTip, pool);
@@ -929,6 +1107,14 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
// we have all inputs cached now, so switch back to dummy, so we don't need to keep lock on mempool
view.SetBackend(dummy);
+
+ // Only accept BIP68 sequence locked transactions that can be mined in the next
+ // block; we don't want our mempool filled up with transactions that can't
+ // be mined yet.
+ // Must keep pool.cs for this unless we change CheckSequenceLocks to take a
+ // CoinsViewCache instead of create its own
+ if (!CheckSequenceLocks(tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp))
+ return state.DoS(0, false, REJECT_NONSTANDARD, "non-BIP68-final");
}
// Check for non-standard pay-to-script-hash in inputs
@@ -959,8 +1145,11 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
}
}
- CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), pool.HasNoInputsOf(tx), inChainInputValue, fSpendsCoinbase, nSigOps);
+ CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainActive.Height(), pool.HasNoInputsOf(tx), inChainInputValue, fSpendsCoinbase, nSigOps, lp);
unsigned int nSize = entry.GetTxSize();
+ if (txFeeRate) {
+ *txFeeRate = CFeeRate(nFees, nSize);
+ }
// Check that the transaction doesn't have an excessive number of
// sigops, making it impossible to mine. Since the coinbase transaction
@@ -1027,10 +1216,11 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
const uint256 &hashAncestor = ancestorIt->GetTx().GetHash();
if (setConflicts.count(hashAncestor))
{
- return state.DoS(10, error("AcceptToMemoryPool: %s spends conflicting transaction %s",
+ return state.DoS(10, false,
+ REJECT_INVALID, "bad-txns-spends-conflicting-tx", false,
+ strprintf("%s spends conflicting transaction %s",
hash.ToString(),
- hashAncestor.ToString()),
- REJECT_INVALID, "bad-txns-spends-conflicting-tx");
+ hashAncestor.ToString()));
}
}
@@ -1060,20 +1250,6 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
// Save these to avoid repeated lookups
setIterConflicting.insert(mi);
- // If this entry is "dirty", then we don't have descendant
- // state for this transaction, which means we probably have
- // lots of in-mempool descendants.
- // Don't allow replacements of dirty transactions, to ensure
- // that we don't spend too much time walking descendants.
- // This should be rare.
- if (mi->IsDirty()) {
- return state.DoS(0,
- error("AcceptToMemoryPool: rejecting replacement %s; cannot replace tx %s with untracked descendants",
- hash.ToString(),
- mi->GetTx().GetHash().ToString()),
- REJECT_NONSTANDARD, "too many potential replacements");
- }
-
// Don't allow the replacement to reduce the feerate of the
// mempool.
//
@@ -1093,12 +1269,12 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
CFeeRate oldFeeRate(mi->GetModifiedFee(), mi->GetTxSize());
if (newFeeRate <= oldFeeRate)
{
- return state.DoS(0,
- error("AcceptToMemoryPool: rejecting replacement %s; new feerate %s <= old feerate %s",
+ return state.DoS(0, false,
+ REJECT_INSUFFICIENTFEE, "insufficient fee", false,
+ strprintf("rejecting replacement %s; new feerate %s <= old feerate %s",
hash.ToString(),
newFeeRate.ToString(),
- oldFeeRate.ToString()),
- REJECT_INSUFFICIENTFEE, "insufficient fee");
+ oldFeeRate.ToString()));
}
BOOST_FOREACH(const CTxIn &txin, mi->GetTx().vin)
@@ -1122,12 +1298,12 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
nConflictingSize += it->GetTxSize();
}
} else {
- return state.DoS(0,
- error("AcceptToMemoryPool: rejecting replacement %s; too many potential replacements (%d > %d)\n",
+ return state.DoS(0, false,
+ REJECT_NONSTANDARD, "too many potential replacements", false,
+ strprintf("rejecting replacement %s; too many potential replacements (%d > %d)\n",
hash.ToString(),
nConflictingCount,
- maxDescendantsToVisit),
- REJECT_NONSTANDARD, "too many potential replacements");
+ maxDescendantsToVisit));
}
for (unsigned int j = 0; j < tx.vin.size(); j++)
@@ -1142,9 +1318,10 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
// it's cheaper to just check if the new input refers to a
// tx that's in the mempool.
if (pool.mapTx.find(tx.vin[j].prevout.hash) != pool.mapTx.end())
- return state.DoS(0, error("AcceptToMemoryPool: replacement %s adds unconfirmed input, idx %d",
- hash.ToString(), j),
- REJECT_NONSTANDARD, "replacement-adds-unconfirmed");
+ return state.DoS(0, false,
+ REJECT_NONSTANDARD, "replacement-adds-unconfirmed", false,
+ strprintf("replacement %s adds unconfirmed input, idx %d",
+ hash.ToString(), j));
}
}
@@ -1153,9 +1330,10 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
// transactions would not be paid for.
if (nModifiedFees < nConflictingFees)
{
- return state.DoS(0, error("AcceptToMemoryPool: rejecting replacement %s, less fees than conflicting txs; %s < %s",
- hash.ToString(), FormatMoney(nModifiedFees), FormatMoney(nConflictingFees)),
- REJECT_INSUFFICIENTFEE, "insufficient fee");
+ return state.DoS(0, false,
+ REJECT_INSUFFICIENTFEE, "insufficient fee", false,
+ strprintf("rejecting replacement %s, less fees than conflicting txs; %s < %s",
+ hash.ToString(), FormatMoney(nModifiedFees), FormatMoney(nConflictingFees)));
}
// Finally in addition to paying more fees than the conflicts the
@@ -1163,19 +1341,19 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
CAmount nDeltaFees = nModifiedFees - nConflictingFees;
if (nDeltaFees < ::minRelayTxFee.GetFee(nSize))
{
- return state.DoS(0,
- error("AcceptToMemoryPool: rejecting replacement %s, not enough additional fees to relay; %s < %s",
+ return state.DoS(0, false,
+ REJECT_INSUFFICIENTFEE, "insufficient fee", false,
+ strprintf("rejecting replacement %s, not enough additional fees to relay; %s < %s",
hash.ToString(),
FormatMoney(nDeltaFees),
- FormatMoney(::minRelayTxFee.GetFee(nSize))),
- REJECT_INSUFFICIENTFEE, "insufficient fee");
+ FormatMoney(::minRelayTxFee.GetFee(nSize))));
}
}
// Check against previous transactions
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
if (!CheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true))
- return error("%s: CheckInputs: %s, %s", __func__, hash.ToString(), FormatStateMessage(state));
+ return false; // state filled in by CheckInputs
// Check again against just the consensus-critical mandatory script
// verification flags, in case of bugs in the standard flags that cause
@@ -1201,7 +1379,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
FormatMoney(nModifiedFees - nConflictingFees),
(int)nSize - (int)nConflictingSize);
}
- pool.RemoveStaged(allConflicting);
+ pool.RemoveStaged(allConflicting, false);
// Store transaction in memory
pool.addUnchecked(hash, entry, setAncestors, !IsInitialBlockDownload());
@@ -1220,10 +1398,10 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
}
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
- bool* pfMissingInputs, bool fOverrideMempoolLimit, const CAmount nAbsurdFee)
+ bool* pfMissingInputs, CFeeRate* txFeeRate, bool fOverrideMempoolLimit, const CAmount nAbsurdFee)
{
std::vector<uint256> vHashTxToUncache;
- bool res = AcceptToMemoryPoolWorker(pool, state, tx, fLimitFree, pfMissingInputs, fOverrideMempoolLimit, nAbsurdFee, vHashTxToUncache);
+ bool res = AcceptToMemoryPoolWorker(pool, state, tx, fLimitFree, pfMissingInputs, txFeeRate, fOverrideMempoolLimit, nAbsurdFee, vHashTxToUncache);
if (!res) {
BOOST_FOREACH(const uint256& hashTx, vHashTxToUncache)
pcoinsTip->Uncache(hashTx);
@@ -1392,6 +1570,26 @@ bool fLargeWorkForkFound = false;
bool fLargeWorkInvalidChainFound = false;
CBlockIndex *pindexBestForkTip = NULL, *pindexBestForkBase = NULL;
+static void AlertNotify(const std::string& strMessage, bool fThread)
+{
+ uiInterface.NotifyAlertChanged();
+ std::string strCmd = GetArg("-alertnotify", "");
+ if (strCmd.empty()) return;
+
+ // Alert text should be plain ascii coming from a trusted source, but to
+ // be safe we first strip anything not in safeChars, then add single quotes around
+ // the whole string before passing it to the shell:
+ std::string singleQuote("'");
+ std::string safeStatus = SanitizeString(strMessage);
+ safeStatus = singleQuote+safeStatus+singleQuote;
+ boost::replace_all(strCmd, "%s", safeStatus);
+
+ if (fThread)
+ boost::thread t(runCommand, strCmd); // thread runs free
+ else
+ runCommand(strCmd);
+}
+
void CheckForkWarningConditions()
{
AssertLockHeld(cs_main);
@@ -1411,7 +1609,7 @@ void CheckForkWarningConditions()
{
std::string warning = std::string("'Warning: Large-work fork detected, forking after block ") +
pindexBestForkBase->phashBlock->ToString() + std::string("'");
- CAlert::Notify(warning, true);
+ AlertNotify(warning, true);
}
if (pindexBestForkTip && pindexBestForkBase)
{
@@ -1942,11 +2140,56 @@ void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const
if (!strWarning.empty())
{
strMiscWarning = strWarning;
- CAlert::Notify(strWarning, true);
+ AlertNotify(strWarning, true);
lastAlertTime = now;
}
}
+// Protected by cs_main
+static VersionBitsCache versionbitscache;
+
+int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params)
+{
+ LOCK(cs_main);
+ int32_t nVersion = VERSIONBITS_TOP_BITS;
+
+ for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
+ ThresholdState state = VersionBitsState(pindexPrev, params, (Consensus::DeploymentPos)i, versionbitscache);
+ if (state == THRESHOLD_LOCKED_IN || state == THRESHOLD_STARTED) {
+ nVersion |= VersionBitsMask(params, (Consensus::DeploymentPos)i);
+ }
+ }
+
+ return nVersion;
+}
+
+/**
+ * Threshold condition checker that triggers when unknown versionbits are seen on the network.
+ */
+class WarningBitsConditionChecker : public AbstractThresholdConditionChecker
+{
+private:
+ int bit;
+
+public:
+ WarningBitsConditionChecker(int bitIn) : bit(bitIn) {}
+
+ int64_t BeginTime(const Consensus::Params& params) const { return 0; }
+ int64_t EndTime(const Consensus::Params& params) const { return std::numeric_limits<int64_t>::max(); }
+ int Period(const Consensus::Params& params) const { return params.nMinerConfirmationWindow; }
+ int Threshold(const Consensus::Params& params) const { return params.nRuleChangeActivationThreshold; }
+
+ bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const
+ {
+ return ((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) &&
+ ((pindex->nVersion >> bit) & 1) != 0 &&
+ ((ComputeBlockVersion(pindex->pprev, params) >> bit) & 1) == 0;
+ }
+};
+
+// Protected by cs_main
+static ThresholdConditionCache warningcache[VERSIONBITS_NUM_BITS];
+
static int64_t nTimeCheck = 0;
static int64_t nTimeForks = 0;
static int64_t nTimeVerify = 0;
@@ -2043,6 +2286,13 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
}
+ // Start enforcing BIP68 (sequence locks) and BIP112 (CHECKSEQUENCEVERIFY) using versionbits logic.
+ int nLockTimeFlags = 0;
+ if (VersionBitsState(pindex->pprev, chainparams.GetConsensus(), Consensus::DEPLOYMENT_CSV, versionbitscache) == THRESHOLD_ACTIVE) {
+ flags |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY;
+ nLockTimeFlags |= LOCKTIME_VERIFY_SEQUENCE;
+ }
+
int64_t nTime2 = GetTimeMicros(); nTimeForks += nTime2 - nTime1;
LogPrint("bench", " - Fork checks: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimeForks * 0.000001);
@@ -2050,6 +2300,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
CCheckQueueControl<CScriptCheck> control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : NULL);
+ std::vector<int> prevheights;
CAmount nFees = 0;
int nInputs = 0;
unsigned int nSigOps = 0;
@@ -2073,6 +2324,19 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
return state.DoS(100, error("ConnectBlock(): inputs missing/spent"),
REJECT_INVALID, "bad-txns-inputs-missingorspent");
+ // Check that transaction is BIP68 final
+ // BIP68 lock checks (as opposed to nLockTime checks) must
+ // be in ConnectBlock because they require the UTXO set
+ prevheights.resize(tx.vin.size());
+ for (size_t j = 0; j < tx.vin.size(); j++) {
+ prevheights[j] = view.AccessCoins(tx.vin[j].prevout.hash)->nHeight;
+ }
+
+ if (!SequenceLocks(tx, nLockTimeFlags, &prevheights, *pindex)) {
+ return state.DoS(100, error("%s: contains a non-BIP68-final transaction", __func__),
+ REJECT_INVALID, "bad-txns-nonfinal");
+ }
+
if (fStrictPayToScriptHash)
{
// Add in sigops done by pay-to-script-hash inputs;
@@ -2260,7 +2524,7 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) {
return AbortNode(state, "Failed to write to coin database");
nLastFlush = nNow;
}
- if ((mode == FLUSH_STATE_ALWAYS || mode == FLUSH_STATE_PERIODIC) && nNow > nLastSetChain + (int64_t)DATABASE_WRITE_INTERVAL * 1000000) {
+ if (fDoFullFlush || ((mode == FLUSH_STATE_ALWAYS || mode == FLUSH_STATE_PERIODIC) && nNow > nLastSetChain + (int64_t)DATABASE_WRITE_INTERVAL * 1000000)) {
// Update best block in wallet (so we can detect restored wallets).
GetMainSignals().SetBestChain(chainActive.GetLocator());
nLastSetChain = nNow;
@@ -2291,8 +2555,8 @@ void static UpdateTip(CBlockIndex *pindexNew) {
nTimeBestReceived = GetTime();
mempool.AddTransactionsUpdated(1);
- LogPrintf("%s: new best=%s height=%d bits=%d log2_work=%.8g tx=%lu date=%s progress=%f cache=%.1fMiB(%utx)\n", __func__,
- chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), chainActive.Tip()->nBits,
+ LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%.8g tx=%lu date='%s' progress=%f cache=%.1fMiB(%utx)\n", __func__,
+ chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), chainActive.Tip()->nVersion,
log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx,
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()),
Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.Tip()), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize());
@@ -2301,24 +2565,42 @@ void static UpdateTip(CBlockIndex *pindexNew) {
// Check the version of the last 100 blocks to see if we need to upgrade:
static bool fWarned = false;
- if (!IsInitialBlockDownload() && !fWarned)
+ if (!IsInitialBlockDownload())
{
int nUpgraded = 0;
const CBlockIndex* pindex = chainActive.Tip();
+ for (int bit = 0; bit < VERSIONBITS_NUM_BITS; bit++) {
+ WarningBitsConditionChecker checker(bit);
+ ThresholdState state = checker.GetStateFor(pindex, chainParams.GetConsensus(), warningcache[bit]);
+ if (state == THRESHOLD_ACTIVE || state == THRESHOLD_LOCKED_IN) {
+ if (state == THRESHOLD_ACTIVE) {
+ strMiscWarning = strprintf(_("Warning: unknown new rules activated (versionbit %i)"), bit);
+ if (!fWarned) {
+ AlertNotify(strMiscWarning, true);
+ fWarned = true;
+ }
+ } else {
+ LogPrintf("%s: unknown new rules are about to activate (versionbit %i)\n", __func__, bit);
+ }
+ }
+ }
for (int i = 0; i < 100 && pindex != NULL; i++)
{
- if (pindex->nVersion > CBlock::CURRENT_VERSION)
+ int32_t nExpectedVersion = ComputeBlockVersion(pindex->pprev, chainParams.GetConsensus());
+ if (pindex->nVersion > VERSIONBITS_LAST_OLD_BLOCK_VERSION && (pindex->nVersion & ~nExpectedVersion) != 0)
++nUpgraded;
pindex = pindex->pprev;
}
if (nUpgraded > 0)
- LogPrintf("%s: %d of last 100 blocks above version %d\n", __func__, nUpgraded, (int)CBlock::CURRENT_VERSION);
+ LogPrintf("%s: %d of last 100 blocks have unexpected version\n", __func__, nUpgraded);
if (nUpgraded > 100/2)
{
// strMiscWarning is read by GetWarnings(), called by Qt and the JSON-RPC code to warn the user:
- strMiscWarning = _("Warning: This version is obsolete; upgrade required!");
- CAlert::Notify(strMiscWarning, true);
- fWarned = true;
+ strMiscWarning = _("Warning: Unknown block versions being mined! It's possible unknown rules are in effect");
+ if (!fWarned) {
+ AlertNotify(strMiscWarning, true);
+ fWarned = true;
+ }
}
}
}
@@ -2350,8 +2632,8 @@ bool static DisconnectTip(CValidationState& state, const Consensus::Params& cons
// ignore validation errors in resurrected transactions
list<CTransaction> removed;
CValidationState stateDummy;
- if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL, true)) {
- mempool.remove(tx, removed, true);
+ if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, NULL, NULL, true)) {
+ mempool.removeRecursive(tx, removed);
} else if (mempool.exists(tx.GetHash())) {
vHashUpdate.push_back(tx.GetHash());
}
@@ -3008,8 +3290,8 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta
// Reject outdated version blocks when 95% (75% on testnet) of the network has upgraded:
for (int32_t version = 2; version < 5; ++version) // check for version 2, 3 and 4 upgrades
if (block.nVersion < version && IsSuperMajority(version, pindexPrev, consensusParams.nMajorityRejectBlockOutdated, consensusParams))
- return state.Invalid(false, REJECT_OBSOLETE, strprintf("bad-version(v%d)", version - 1),
- strprintf("rejected nVersion=%d block", version - 1));
+ return state.Invalid(false, REJECT_OBSOLETE, strprintf("bad-version(0x%08x)", version - 1),
+ strprintf("rejected nVersion=0x%08x block", version - 1));
return true;
}
@@ -3019,12 +3301,18 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
const int nHeight = pindexPrev == NULL ? 0 : pindexPrev->nHeight + 1;
const Consensus::Params& consensusParams = Params().GetConsensus();
+ // Start enforcing BIP113 (Median Time Past) using versionbits logic.
+ int nLockTimeFlags = 0;
+ if (VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_CSV, versionbitscache) == THRESHOLD_ACTIVE) {
+ nLockTimeFlags |= LOCKTIME_MEDIAN_TIME_PAST;
+ }
+
+ int64_t nLockTimeCutoff = (nLockTimeFlags & LOCKTIME_MEDIAN_TIME_PAST)
+ ? pindexPrev->GetMedianTimePast()
+ : block.GetBlockTime();
+
// Check that all transactions are finalized
BOOST_FOREACH(const CTransaction& tx, block.vtx) {
- int nLockTimeFlags = 0;
- int64_t nLockTimeCutoff = (nLockTimeFlags & LOCKTIME_MEDIAN_TIME_PAST)
- ? pindexPrev->GetMedianTimePast()
- : block.GetBlockTime();
if (!IsFinalTx(tx, nHeight, nLockTimeCutoff)) {
return state.DoS(10, false, REJECT_INVALID, "bad-txns-nonfinal", false, "non-final transaction");
}
@@ -3612,6 +3900,10 @@ void UnloadBlockIndex()
setDirtyFileInfo.clear();
mapNodeState.clear();
recentRejects.reset(NULL);
+ versionbitscache.Clear();
+ for (int b = 0; b < VERSIONBITS_NUM_BITS; b++) {
+ warningcache[b].clear();
+ }
BOOST_FOREACH(BlockMap::value_type& entry, mapBlockIndex) {
delete entry.second;
@@ -3957,14 +4249,8 @@ void static CheckBlockIndex(const Consensus::Params& consensusParams)
assert(nNodes == forward.size());
}
-//////////////////////////////////////////////////////////////////////////////
-//
-// CAlert
-//
-
std::string GetWarnings(const std::string& strFor)
{
- int nPriority = 0;
string strStatusBar;
string strRPC;
string strGUI;
@@ -3980,37 +4266,20 @@ std::string GetWarnings(const std::string& strFor)
// Misc warnings like out of disk space and clock is wrong
if (strMiscWarning != "")
{
- nPriority = 1000;
strStatusBar = strGUI = strMiscWarning;
}
if (fLargeWorkForkFound)
{
- nPriority = 2000;
strStatusBar = strRPC = "Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.";
strGUI = _("Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.");
}
else if (fLargeWorkInvalidChainFound)
{
- nPriority = 2000;
strStatusBar = strRPC = "Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.";
strGUI = _("Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.");
}
- // Alerts
- {
- LOCK(cs_mapAlerts);
- BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
- {
- const CAlert& alert = item.second;
- if (alert.AppliesToMe() && alert.nPriority > nPriority)
- {
- nPriority = alert.nPriority;
- strStatusBar = strGUI = alert.strStatusBar;
- }
- }
- }
-
if (strFor == "gui")
return strGUI;
else if (strFor == "statusbar")
@@ -4226,7 +4495,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (pfrom->nVersion >= NO_BLOOM_VERSION) {
Misbehaving(pfrom->GetId(), 100);
return false;
- } else if (GetBoolArg("-enforcenodebloom", false)) {
+ } else {
pfrom->fDisconnect = true;
return false;
}
@@ -4308,11 +4577,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
CAddress addr = GetLocalAddress(&pfrom->addr);
if (addr.IsRoutable())
{
- LogPrintf("ProcessMessages: advertizing address %s\n", addr.ToString());
+ LogPrintf("ProcessMessages: advertising address %s\n", addr.ToString());
pfrom->PushAddress(addr);
} else if (IsPeerAddrLocalGood(pfrom)) {
addr.SetIP(pfrom->addrLocal);
- LogPrintf("ProcessMessages: advertizing address %s\n", addr.ToString());
+ LogPrintf("ProcessMessages: advertising address %s\n", addr.ToString());
pfrom->PushAddress(addr);
}
}
@@ -4332,13 +4601,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
}
- // Relay alerts
- {
- LOCK(cs_mapAlerts);
- BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
- item.second.RelayTo(pfrom);
- }
-
pfrom->fSuccessfullyConnected = true;
string remoteAddr;
@@ -4672,10 +4934,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
pfrom->setAskFor.erase(inv.hash);
mapAlreadyAskedFor.erase(inv);
- if (!AlreadyHave(inv) && AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs))
- {
+ CFeeRate txFeeRate = CFeeRate(0);
+ if (!AlreadyHave(inv) && AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs, &txFeeRate)) {
mempool.check(pcoinsTip);
- RelayTransaction(tx);
+ RelayTransaction(tx, txFeeRate);
vWorkQueue.push_back(inv.hash);
LogPrint("mempool", "AcceptToMemoryPool: peer=%d: accepted %s (poolsz %u txn, %u kB)\n",
@@ -4706,10 +4968,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (setMisbehaving.count(fromPeer))
continue;
- if (AcceptToMemoryPool(mempool, stateDummy, orphanTx, true, &fMissingInputs2))
- {
+ CFeeRate orphanFeeRate = CFeeRate(0);
+ if (AcceptToMemoryPool(mempool, stateDummy, orphanTx, true, &fMissingInputs2, &orphanFeeRate)) {
LogPrint("mempool", " accepted orphan tx %s\n", orphanHash.ToString());
- RelayTransaction(orphanTx);
+ RelayTransaction(orphanTx, orphanFeeRate);
vWorkQueue.push_back(orphanHash);
vEraseQueue.push_back(orphanHash);
}
@@ -4762,7 +5024,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
int nDoS = 0;
if (!state.IsInvalid(nDoS) || nDoS == 0) {
LogPrintf("Force relaying tx %s from whitelisted peer=%d\n", tx.GetHash().ToString(), pfrom->id);
- RelayTransaction(tx);
+ RelayTransaction(tx, txFeeRate);
} else {
LogPrintf("Not relaying invalid transaction %s from whitelisted peer=%d (%s)\n", tx.GetHash().ToString(), pfrom->id, FormatStateMessage(state));
}
@@ -4916,13 +5178,18 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
- // This asymmetric behavior for inbound and outbound connections was introduced
- // to prevent a fingerprinting attack: an attacker can send specific fake addresses
- // to users' AddrMan and later request them by sending getaddr messages.
- // Making nodes which are behind NAT and can only make outgoing connections ignore
- // the getaddr message mitigates the attack.
- else if ((strCommand == NetMsgType::GETADDR) && (pfrom->fInbound))
+ else if (strCommand == NetMsgType::GETADDR)
{
+ // This asymmetric behavior for inbound and outbound connections was introduced
+ // to prevent a fingerprinting attack: an attacker can send specific fake addresses
+ // to users' AddrMan and later request them by sending getaddr messages.
+ // Making nodes which are behind NAT and can only make outgoing connections ignore
+ // the getaddr message mitigates the attack.
+ if (!pfrom->fInbound) {
+ LogPrint("net", "Ignoring \"getaddr\" from outbound connection. peer=%d\n", pfrom->id);
+ return true;
+ }
+
pfrom->vAddrToSend.clear();
vector<CAddress> vAddr = addrman.GetAddr();
BOOST_FOREACH(const CAddress &addr, vAddr)
@@ -4951,6 +5218,13 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (!fInMemPool) continue; // another thread removed since queryHashes, maybe...
if (!pfrom->pfilter->IsRelevantAndUpdate(tx)) continue;
}
+ if (pfrom->minFeeFilter) {
+ CFeeRate feeRate;
+ mempool.lookupFeeRate(hash, feeRate);
+ LOCK(pfrom->cs_feeFilter);
+ if (feeRate.GetFeePerK() < pfrom->minFeeFilter)
+ continue;
+ }
vInv.push_back(inv);
if (vInv.size() == MAX_INV_SZ) {
pfrom->PushMessage(NetMsgType::INV, vInv);
@@ -5041,37 +5315,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
- else if (fAlerts && strCommand == NetMsgType::ALERT)
- {
- CAlert alert;
- vRecv >> alert;
-
- uint256 alertHash = alert.GetHash();
- if (pfrom->setKnown.count(alertHash) == 0)
- {
- if (alert.ProcessAlert(chainparams.AlertKey()))
- {
- // Relay
- pfrom->setKnown.insert(alertHash);
- {
- LOCK(cs_vNodes);
- BOOST_FOREACH(CNode* pnode, vNodes)
- alert.RelayTo(pnode);
- }
- }
- else {
- // Small DoS penalty so peers that send us lots of
- // duplicate/expired/invalid-signature/whatever alerts
- // eventually get banned.
- // This isn't a Misbehaving(100) (immediate ban) because the
- // peer might be an older or different implementation with
- // a different signature key, etc.
- Misbehaving(pfrom->GetId(), 10);
- }
- }
- }
-
-
else if (strCommand == NetMsgType::FILTERLOAD)
{
CBloomFilter filter;
@@ -5144,8 +5387,19 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
}
- else
- {
+ else if (strCommand == NetMsgType::FEEFILTER) {
+ CAmount newFeeFilter = 0;
+ vRecv >> newFeeFilter;
+ if (MoneyRange(newFeeFilter)) {
+ {
+ LOCK(pfrom->cs_feeFilter);
+ pfrom->minFeeFilter = newFeeFilter;
+ }
+ LogPrint("net", "received: feefilter of %s from peer=%d\n", CFeeRate(newFeeFilter).ToString(), pfrom->id);
+ }
+ }
+
+ else {
// Ignore unknown commands for extensibility
LogPrint("net", "Unknown command \"%s\" from peer=%d\n", SanitizeString(strCommand), pfrom->id);
}
@@ -5321,7 +5575,7 @@ bool SendMessages(CNode* pto)
// Address refresh broadcast
int64_t nNow = GetTimeMicros();
if (!IsInitialBlockDownload() && pto->nNextLocalAddrSend < nNow) {
- AdvertizeLocal(pto);
+ AdvertiseLocal(pto);
pto->nNextLocalAddrSend = PoissonNextSend(nNow, AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
}
@@ -5627,6 +5881,29 @@ bool SendMessages(CNode* pto)
if (!vGetData.empty())
pto->PushMessage(NetMsgType::GETDATA, vGetData);
+ //
+ // Message: feefilter
+ //
+ // We don't want white listed peers to filter txs to us if we have -whitelistforcerelay
+ if (pto->nVersion >= FEEFILTER_VERSION && GetBoolArg("-feefilter", DEFAULT_FEEFILTER) &&
+ !(pto->fWhitelisted && GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY))) {
+ CAmount currentFilter = mempool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFeePerK();
+ int64_t timeNow = GetTimeMicros();
+ if (timeNow > pto->nextSendTimeFeeFilter) {
+ CAmount filterToSend = filterRounder.round(currentFilter);
+ if (filterToSend != pto->lastSentFeeFilter) {
+ pto->PushMessage(NetMsgType::FEEFILTER, filterToSend);
+ pto->lastSentFeeFilter = filterToSend;
+ }
+ pto->nextSendTimeFeeFilter = PoissonNextSend(timeNow, AVG_FEEFILTER_BROADCAST_INTERVAL);
+ }
+ // If the fee filter has changed substantially and it's still more than MAX_FEEFILTER_CHANGE_DELAY
+ // until scheduled broadcast, then move the broadcast to within MAX_FEEFILTER_CHANGE_DELAY.
+ else if (timeNow + MAX_FEEFILTER_CHANGE_DELAY * 1000000 < pto->nextSendTimeFeeFilter &&
+ (currentFilter < 3 * pto->lastSentFeeFilter / 4 || currentFilter > 4 * pto->lastSentFeeFilter / 3)) {
+ pto->nextSendTimeFeeFilter = timeNow + (insecure_rand() % MAX_FEEFILTER_CHANGE_DELAY) * 1000000;
+ }
+ }
}
return true;
}
@@ -5635,7 +5912,11 @@ bool SendMessages(CNode* pto)
return strprintf("CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s)", nBlocks, nSize, nHeightFirst, nHeightLast, DateTimeStrFormat("%Y-%m-%d", nTimeFirst), DateTimeStrFormat("%Y-%m-%d", nTimeLast));
}
-
+ThresholdState VersionBitsTipState(const Consensus::Params& params, Consensus::DeploymentPos pos)
+{
+ LOCK(cs_main);
+ return VersionBitsState(chainActive.Tip(), params, pos, versionbitscache);
+}
class CMainCleanup
{
diff --git a/src/main.h b/src/main.h
index 4061daba3b..0bfcfab213 100644
--- a/src/main.h
+++ b/src/main.h
@@ -16,6 +16,7 @@
#include "net.h"
#include "script/script_error.h"
#include "sync.h"
+#include "versionbits.h"
#include <algorithm>
#include <exception>
@@ -39,9 +40,8 @@ class CValidationInterface;
class CValidationState;
struct CNodeStateStats;
+struct LockPoints;
-/** Default for accepting alerts from the P2P network. */
-static const bool DEFAULT_ALERTS = true;
/** Default for DEFAULT_WHITELISTRELAY. */
static const bool DEFAULT_WHITELISTRELAY = true;
/** Default for DEFAULT_WHITELISTFORCERELAY. */
@@ -102,6 +102,10 @@ static const unsigned int AVG_ADDRESS_BROADCAST_INTERVAL = 30;
/** Average delay between trickled inventory broadcasts in seconds.
* Blocks, whitelisted receivers, and a random 25% of transactions bypass this. */
static const unsigned int AVG_INVENTORY_BROADCAST_INTERVAL = 5;
+/** Average delay between feefilter broadcasts in seconds. */
+static const unsigned int AVG_FEEFILTER_BROADCAST_INTERVAL = 10 * 60;
+/** Maximum feefilter broadcast delay after significant change. */
+static const unsigned int MAX_FEEFILTER_CHANGE_DELAY = 5 * 60;
static const unsigned int DEFAULT_LIMITFREERELAY = 15;
static const bool DEFAULT_RELAYPRIORITY = true;
@@ -117,10 +121,14 @@ static const unsigned int DEFAULT_BANSCORE_THRESHOLD = 100;
static const bool DEFAULT_TESTSAFEMODE = false;
/** Default for -mempoolreplacement */
static const bool DEFAULT_ENABLE_REPLACEMENT = true;
+/** Default for using fee filter */
+static const bool DEFAULT_FEEFILTER = true;
/** Maximum number of headers to announce when relaying blocks with headers message.*/
static const unsigned int MAX_BLOCKS_TO_ANNOUNCE = 8;
+static const bool DEFAULT_PEERBLOOMFILTERS = true;
+
struct BlockHasher
{
size_t operator()(const uint256& hash) const { return hash.GetCheapHash(); }
@@ -150,7 +158,6 @@ extern size_t nCoinCacheUsage;
extern CFeeRate minRelayTxFee;
/** Absolute maximum transaction fee (in satoshis) used by wallet and mempool (rejects high fee in sendrawtransaction) */
extern CAmount maxTxFee;
-extern bool fAlerts;
/** If the tip is older than this (in seconds), the node is considered to be in initial block download. */
extern int64_t nMaxTipAge;
extern bool fEnableReplacement;
@@ -281,11 +288,14 @@ void PruneAndFlush();
/** (try to) add transaction to memory pool **/
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
- bool* pfMissingInputs, bool fOverrideMempoolLimit=false, const CAmount nAbsurdFee=0);
+ bool* pfMissingInputs, CFeeRate* txFeeRate, bool fOverrideMempoolLimit=false, const CAmount nAbsurdFee=0);
/** Convert CValidationState to a human-readable message for logging */
std::string FormatStateMessage(const CValidationState &state);
+/** Get the BIP9 state for a given deployment at the current tip. */
+ThresholdState VersionBitsTipState(const Consensus::Params& params, Consensus::DeploymentPos pos);
+
struct CNodeStateStats {
int nMisbehavior;
int nSyncHeight;
@@ -365,7 +375,31 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime);
*/
bool CheckFinalTx(const CTransaction &tx, int flags = -1);
-/**
+/**
+ * Test whether the LockPoints height and time are still valid on the current chain
+ */
+bool TestLockPointValidity(const LockPoints* lp);
+
+/**
+ * Check if transaction is final per BIP 68 sequence numbers and can be included in a block.
+ * Consensus critical. Takes as input a list of heights at which tx's inputs (in order) confirmed.
+ */
+bool SequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeights, const CBlockIndex& block);
+
+/**
+ * Check if transaction will be BIP 68 final in the next block to be created.
+ *
+ * Simulates calling SequenceLocks() with data from the tip of the current active chain.
+ * Optionally stores in LockPoints the resulting height and time calculated and the hash
+ * of the block needed for calculation or skips the calculation and uses the LockPoints
+ * passed in for evaluation.
+ * The LockPoints should not be considered valid if CheckSequenceLocks returns false.
+ *
+ * See consensus/consensus.h for flag definitions.
+ */
+bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp = NULL, bool useExistingLockPoints = false);
+
+/**
* Closure representing one script verification
* Note that this stores references to the spending transaction
*/
@@ -519,6 +553,11 @@ extern CBlockTreeDB *pblocktree;
*/
int GetSpendHeight(const CCoinsViewCache& inputs);
+/**
+ * Determine what nVersion a new block should use.
+ */
+int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params);
+
/** Reject codes greater or equal to this can be returned by AcceptToMemPool
* for transactions, to signal internal conditions. They cannot and should not
* be sent over the P2P network.
diff --git a/src/merkleblock.cpp b/src/merkleblock.cpp
index 8447f924e4..dca4973cc4 100644
--- a/src/merkleblock.cpp
+++ b/src/merkleblock.cpp
@@ -95,7 +95,7 @@ void CPartialMerkleTree::TraverseAndBuild(int height, unsigned int pos, const st
}
}
-uint256 CPartialMerkleTree::TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<uint256> &vMatch) {
+uint256 CPartialMerkleTree::TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<uint256> &vMatch, std::vector<unsigned int> &vnIndex) {
if (nBitsUsed >= vBits.size()) {
// overflowed the bits array - failure
fBad = true;
@@ -110,14 +110,16 @@ uint256 CPartialMerkleTree::TraverseAndExtract(int height, unsigned int pos, uns
return uint256();
}
const uint256 &hash = vHash[nHashUsed++];
- if (height==0 && fParentOfMatch) // in case of height 0, we have a matched txid
+ if (height==0 && fParentOfMatch) { // in case of height 0, we have a matched txid
vMatch.push_back(hash);
+ vnIndex.push_back(pos);
+ }
return hash;
} else {
// otherwise, descend into the subtrees to extract matched txids and hashes
- uint256 left = TraverseAndExtract(height-1, pos*2, nBitsUsed, nHashUsed, vMatch), right;
+ uint256 left = TraverseAndExtract(height-1, pos*2, nBitsUsed, nHashUsed, vMatch, vnIndex), right;
if (pos*2+1 < CalcTreeWidth(height-1)) {
- right = TraverseAndExtract(height-1, pos*2+1, nBitsUsed, nHashUsed, vMatch);
+ right = TraverseAndExtract(height-1, pos*2+1, nBitsUsed, nHashUsed, vMatch, vnIndex);
if (right == left) {
// The left and right branches should never be identical, as the transaction
// hashes covered by them must each be unique.
@@ -147,7 +149,7 @@ CPartialMerkleTree::CPartialMerkleTree(const std::vector<uint256> &vTxid, const
CPartialMerkleTree::CPartialMerkleTree() : nTransactions(0), fBad(true) {}
-uint256 CPartialMerkleTree::ExtractMatches(std::vector<uint256> &vMatch) {
+uint256 CPartialMerkleTree::ExtractMatches(std::vector<uint256> &vMatch, std::vector<unsigned int> &vnIndex) {
vMatch.clear();
// An empty set will not work
if (nTransactions == 0)
@@ -167,7 +169,7 @@ uint256 CPartialMerkleTree::ExtractMatches(std::vector<uint256> &vMatch) {
nHeight++;
// traverse the partial tree
unsigned int nBitsUsed = 0, nHashUsed = 0;
- uint256 hashMerkleRoot = TraverseAndExtract(nHeight, 0, nBitsUsed, nHashUsed, vMatch);
+ uint256 hashMerkleRoot = TraverseAndExtract(nHeight, 0, nBitsUsed, nHashUsed, vMatch, vnIndex);
// verify that no problems occurred during the tree traversal
if (fBad)
return uint256();
diff --git a/src/merkleblock.h b/src/merkleblock.h
index 996cd12624..835cbcce55 100644
--- a/src/merkleblock.h
+++ b/src/merkleblock.h
@@ -75,9 +75,9 @@ protected:
/**
* recursive function that traverses tree nodes, consuming the bits and hashes produced by TraverseAndBuild.
- * it returns the hash of the respective node.
+ * it returns the hash of the respective node and its respective index.
*/
- uint256 TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<uint256> &vMatch);
+ uint256 TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<uint256> &vMatch, std::vector<unsigned int> &vnIndex);
public:
@@ -110,10 +110,11 @@ public:
CPartialMerkleTree();
/**
- * extract the matching txid's represented by this partial merkle tree.
+ * extract the matching txid's represented by this partial merkle tree
+ * and their respective indices within the partial tree.
* returns the merkle root, or 0 in case of failure
*/
- uint256 ExtractMatches(std::vector<uint256> &vMatch);
+ uint256 ExtractMatches(std::vector<uint256> &vMatch, std::vector<unsigned int> &vnIndex);
};
diff --git a/src/miner.cpp b/src/miner.cpp
index c454c0279c..ef8fd4db43 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -79,11 +79,6 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& s
return NULL;
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
- // -regtest only: allow overriding block.nVersion with
- // -blockversion=N to test forking scenarios
- if (chainparams.MineBlocksOnDemand())
- pblock->nVersion = GetArg("-blockversion", pblock->nVersion);
-
// Create coinbase tx
CMutableTransaction txNew;
txNew.vin.resize(1);
@@ -137,6 +132,12 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& s
pblock->nTime = GetAdjustedTime();
const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast();
+ pblock->nVersion = ComputeBlockVersion(pindexPrev, chainparams.GetConsensus());
+ // -regtest only: allow overriding block.nVersion with
+ // -blockversion=N to test forking scenarios
+ if (chainparams.MineBlocksOnDemand())
+ pblock->nVersion = GetArg("-blockversion", pblock->nVersion);
+
int64_t nLockTimeCutoff = (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST)
? nMedianTimePast
: pblock->GetBlockTime();
@@ -155,10 +156,10 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& s
std::make_heap(vecPriority.begin(), vecPriority.end(), pricomparer);
}
- CTxMemPool::indexed_transaction_set::nth_index<3>::type::iterator mi = mempool.mapTx.get<3>().begin();
+ CTxMemPool::indexed_transaction_set::index<mining_score>::type::iterator mi = mempool.mapTx.get<mining_score>().begin();
CTxMemPool::txiter iter;
- while (mi != mempool.mapTx.get<3>().end() || !clearedTxs.empty())
+ while (mi != mempool.mapTx.get<mining_score>().end() || !clearedTxs.empty())
{
bool priorityTx = false;
if (fPriorityBlock && !vecPriority.empty()) { // add a tx from priority queue to fill the blockprioritysize
@@ -315,206 +316,3 @@ void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned
pblock->vtx[0] = txCoinbase;
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// Internal miner
-//
-
-//
-// ScanHash scans nonces looking for a hash with at least some zero bits.
-// The nonce is usually preserved between calls, but periodically or if the
-// nonce is 0xffff0000 or above, the block is rebuilt and nNonce starts over at
-// zero.
-//
-bool static ScanHash(const CBlockHeader *pblock, uint32_t& nNonce, uint256 *phash)
-{
- // Write the first 76 bytes of the block header to a double-SHA256 state.
- CHash256 hasher;
- CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
- ss << *pblock;
- assert(ss.size() == 80);
- hasher.Write((unsigned char*)&ss[0], 76);
-
- while (true) {
- nNonce++;
-
- // Write the last 4 bytes of the block header (the nonce) to a copy of
- // the double-SHA256 state, and compute the result.
- CHash256(hasher).Write((unsigned char*)&nNonce, 4).Finalize((unsigned char*)phash);
-
- // Return the nonce if the hash has at least some zero bits,
- // caller will check if it has enough to reach the target
- if (((uint16_t*)phash)[15] == 0)
- return true;
-
- // If nothing found after trying for a while, return -1
- if ((nNonce & 0xfff) == 0)
- return false;
- }
-}
-
-static bool ProcessBlockFound(const CBlock* pblock, const CChainParams& chainparams)
-{
- LogPrintf("%s\n", pblock->ToString());
- LogPrintf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue));
-
- // Found a solution
- {
- LOCK(cs_main);
- if (pblock->hashPrevBlock != chainActive.Tip()->GetBlockHash())
- return error("BitcoinMiner: generated block is stale");
- }
-
- // Inform about the new block
- GetMainSignals().BlockFound(pblock->GetHash());
-
- // Process this block the same as if we had received it from another node
- CValidationState state;
- if (!ProcessNewBlock(state, chainparams, NULL, pblock, true, NULL))
- return error("BitcoinMiner: ProcessNewBlock, block not accepted");
-
- return true;
-}
-
-void static BitcoinMiner(const CChainParams& chainparams)
-{
- LogPrintf("BitcoinMiner started\n");
- SetThreadPriority(THREAD_PRIORITY_LOWEST);
- RenameThread("bitcoin-miner");
-
- unsigned int nExtraNonce = 0;
-
- boost::shared_ptr<CReserveScript> coinbaseScript;
- GetMainSignals().ScriptForMining(coinbaseScript);
-
- try {
- // Throw an error if no script was provided. This can happen
- // due to some internal error but also if the keypool is empty.
- // In the latter case, already the pointer is NULL.
- if (!coinbaseScript || coinbaseScript->reserveScript.empty())
- throw std::runtime_error("No coinbase script available (mining requires a wallet)");
-
- while (true) {
- if (chainparams.MiningRequiresPeers()) {
- // Busy-wait for the network to come online so we don't waste time mining
- // on an obsolete chain. In regtest mode we expect to fly solo.
- do {
- bool fvNodesEmpty;
- {
- LOCK(cs_vNodes);
- fvNodesEmpty = vNodes.empty();
- }
- if (!fvNodesEmpty && !IsInitialBlockDownload())
- break;
- MilliSleep(1000);
- } while (true);
- }
-
- //
- // Create new block
- //
- unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
- CBlockIndex* pindexPrev = chainActive.Tip();
-
- auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlock(chainparams, coinbaseScript->reserveScript));
- if (!pblocktemplate.get())
- {
- LogPrintf("Error in BitcoinMiner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n");
- return;
- }
- CBlock *pblock = &pblocktemplate->block;
- IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
-
- LogPrintf("Running BitcoinMiner with %u transactions in block (%u bytes)\n", pblock->vtx.size(),
- ::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
-
- //
- // Search
- //
- int64_t nStart = GetTime();
- arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
- uint256 hash;
- uint32_t nNonce = 0;
- while (true) {
- // Check if something found
- if (ScanHash(pblock, nNonce, &hash))
- {
- if (UintToArith256(hash) <= hashTarget)
- {
- // Found a solution
- pblock->nNonce = nNonce;
- assert(hash == pblock->GetHash());
-
- SetThreadPriority(THREAD_PRIORITY_NORMAL);
- LogPrintf("BitcoinMiner:\n");
- LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex(), hashTarget.GetHex());
- ProcessBlockFound(pblock, chainparams);
- SetThreadPriority(THREAD_PRIORITY_LOWEST);
- coinbaseScript->KeepScript();
-
- // In regression test mode, stop mining after a block is found.
- if (chainparams.MineBlocksOnDemand())
- throw boost::thread_interrupted();
-
- break;
- }
- }
-
- // Check for stop or if block needs to be rebuilt
- boost::this_thread::interruption_point();
- // Regtest mode doesn't require peers
- if (vNodes.empty() && chainparams.MiningRequiresPeers())
- break;
- if (nNonce >= 0xffff0000)
- break;
- if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
- break;
- if (pindexPrev != chainActive.Tip())
- break;
-
- // Update nTime every few seconds
- if (UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev) < 0)
- break; // Recreate the block if the clock has run backwards,
- // so that we can use the correct time.
- if (chainparams.GetConsensus().fPowAllowMinDifficultyBlocks)
- {
- // Changing pblock->nTime can change work required on testnet:
- hashTarget.SetCompact(pblock->nBits);
- }
- }
- }
- }
- catch (const boost::thread_interrupted&)
- {
- LogPrintf("BitcoinMiner terminated\n");
- throw;
- }
- catch (const std::runtime_error &e)
- {
- LogPrintf("BitcoinMiner runtime error: %s\n", e.what());
- return;
- }
-}
-
-void GenerateBitcoins(bool fGenerate, int nThreads, const CChainParams& chainparams)
-{
- static boost::thread_group* minerThreads = NULL;
-
- if (nThreads < 0)
- nThreads = GetNumCores();
-
- if (minerThreads != NULL)
- {
- minerThreads->interrupt_all();
- delete minerThreads;
- minerThreads = NULL;
- }
-
- if (nThreads == 0 || !fGenerate)
- return;
-
- minerThreads = new boost::thread_group();
- for (int i = 0; i < nThreads; i++)
- minerThreads->create_thread(boost::bind(&BitcoinMiner, boost::cref(chainparams)));
-}
diff --git a/src/miner.h b/src/miner.h
index 512494198b..cd0f136625 100644
--- a/src/miner.h
+++ b/src/miner.h
@@ -17,9 +17,6 @@ class CScript;
class CWallet;
namespace Consensus { struct Params; };
-static const bool DEFAULT_GENERATE = false;
-static const int DEFAULT_GENERATE_THREADS = 1;
-
static const bool DEFAULT_PRINTPRIORITY = false;
struct CBlockTemplate
@@ -29,8 +26,6 @@ struct CBlockTemplate
std::vector<int64_t> vTxSigOps;
};
-/** Run the miner threads */
-void GenerateBitcoins(bool fGenerate, int nThreads, const CChainParams& chainparams);
/** Generate a new block, without valid proof-of-work */
CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& scriptPubKeyIn);
/** Modify the extranonce in a block */
diff --git a/src/net.cpp b/src/net.cpp
index d9c4c11737..e8cc753a48 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -79,7 +79,6 @@ bool fListen = true;
uint64_t nLocalServices = NODE_NETWORK;
CCriticalSection cs_mapLocalHost;
map<CNetAddr, LocalServiceInfo> mapLocalHost;
-static bool vfReachable[NET_MAX] = {};
static bool vfLimited[NET_MAX] = {};
static CNode* pnodeLocalHost = NULL;
uint64_t nLocalHostNonce = 0;
@@ -205,7 +204,7 @@ bool IsPeerAddrLocalGood(CNode *pnode)
}
// pushes our own address to a peer
-void AdvertizeLocal(CNode *pnode)
+void AdvertiseLocal(CNode *pnode)
{
if (fListen && pnode->fSuccessfullyConnected)
{
@@ -220,20 +219,12 @@ void AdvertizeLocal(CNode *pnode)
}
if (addrLocal.IsRoutable())
{
- LogPrintf("AdvertizeLocal: advertizing address %s\n", addrLocal.ToString());
+ LogPrintf("AdvertiseLocal: advertising address %s\n", addrLocal.ToString());
pnode->PushAddress(addrLocal);
}
}
}
-void SetReachable(enum Network net, bool fFlag)
-{
- LOCK(cs_mapLocalHost);
- vfReachable[net] = fFlag;
- if (net == NET_IPV6 && fFlag)
- vfReachable[NET_IPV4] = true;
-}
-
// learn a new local address
bool AddLocal(const CService& addr, int nScore)
{
@@ -256,7 +247,6 @@ bool AddLocal(const CService& addr, int nScore)
info.nScore = nScore + (fAlready ? 1 : 0);
info.nPort = addr.GetPort();
}
- SetReachable(addr.GetNetwork());
}
return true;
@@ -319,7 +309,7 @@ bool IsLocal(const CService& addr)
bool IsReachable(enum Network net)
{
LOCK(cs_mapLocalHost);
- return vfReachable[net] && !vfLimited[net];
+ return !vfLimited[net];
}
/** check whether a given address is in a network we can probably connect to */
@@ -2063,20 +2053,15 @@ public:
instance_of_cnetcleanup;
-
-
-
-
-
-void RelayTransaction(const CTransaction& tx)
+void RelayTransaction(const CTransaction& tx, CFeeRate feerate)
{
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(10000);
ss << tx;
- RelayTransaction(tx, ss);
+ RelayTransaction(tx, feerate, ss);
}
-void RelayTransaction(const CTransaction& tx, const CDataStream& ss)
+void RelayTransaction(const CTransaction& tx, CFeeRate feerate, const CDataStream& ss)
{
CInv inv(MSG_TX, tx.GetHash());
{
@@ -2097,6 +2082,11 @@ void RelayTransaction(const CTransaction& tx, const CDataStream& ss)
{
if(!pnode->fRelayTxes)
continue;
+ {
+ LOCK(pnode->cs_feeFilter);
+ if (feerate.GetFeePerK() < pnode->minFeeFilter)
+ continue;
+ }
LOCK(pnode->cs_filter);
if (pnode->pfilter)
{
@@ -2400,6 +2390,10 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa
nPingUsecTime = 0;
fPingQueued = false;
nMinPingUsecTime = std::numeric_limits<int64_t>::max();
+ minFeeFilter = 0;
+ lastSentFeeFilter = 0;
+ nextSendTimeFeeFilter = 0;
+
BOOST_FOREACH(const std::string &msg, getAllNetMessageTypes())
mapRecvBytesPerMsgCmd[msg] = 0;
mapRecvBytesPerMsgCmd[NET_MESSAGE_COMMAND_OTHER] = 0;
diff --git a/src/net.h b/src/net.h
index 833c9cf07c..ab9eb68d85 100644
--- a/src/net.h
+++ b/src/net.h
@@ -6,6 +6,7 @@
#ifndef BITCOIN_NET_H
#define BITCOIN_NET_H
+#include "amount.h"
#include "bloom.h"
#include "compat.h"
#include "limitedmap.h"
@@ -134,7 +135,7 @@ enum
};
bool IsPeerAddrLocalGood(CNode *pnode);
-void AdvertizeLocal(CNode *pnode);
+void AdvertiseLocal(CNode *pnode);
void SetLimited(enum Network net, bool fLimited = true);
bool IsLimited(enum Network net);
bool IsLimited(const CNetAddr& addr);
@@ -146,7 +147,6 @@ bool IsLocal(const CService& addr);
bool GetLocal(CService &addr, const CNetAddr *paddrPeer = NULL);
bool IsReachable(enum Network net);
bool IsReachable(const CNetAddr &addr);
-void SetReachable(enum Network net, bool fFlag = true);
CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL);
@@ -416,6 +416,11 @@ public:
int64_t nMinPingUsecTime;
// Whether a ping is requested.
bool fPingQueued;
+ // Minimum fee rate with which to filter inv's to this node
+ CAmount minFeeFilter;
+ CCriticalSection cs_feeFilter;
+ CAmount lastSentFeeFilter;
+ int64_t nextSendTimeFeeFilter;
CNode(SOCKET hSocketIn, const CAddress &addrIn, const std::string &addrNameIn = "", bool fInboundIn = false);
~CNode();
@@ -767,8 +772,8 @@ public:
class CTransaction;
-void RelayTransaction(const CTransaction& tx);
-void RelayTransaction(const CTransaction& tx, const CDataStream& ss);
+void RelayTransaction(const CTransaction& tx, CFeeRate feerate);
+void RelayTransaction(const CTransaction& tx, CFeeRate feerate, const CDataStream& ss);
/** Access to the (IP) address database (peers.dat) */
class CAddrDB
diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp
index de3c060d6a..7b0e8b7d08 100644
--- a/src/policy/fees.cpp
+++ b/src/policy/fees.cpp
@@ -8,6 +8,7 @@
#include "amount.h"
#include "primitives/transaction.h"
+#include "random.h"
#include "streams.h"
#include "txmempool.h"
#include "util.h"
@@ -580,3 +581,21 @@ void CBlockPolicyEstimator::Read(CAutoFile& filein)
priStats.Read(filein);
nBestSeenHeight = nFileBestSeenHeight;
}
+
+FeeFilterRounder::FeeFilterRounder(const CFeeRate& minIncrementalFee)
+{
+ CAmount minFeeLimit = minIncrementalFee.GetFeePerK() / 2;
+ feeset.insert(0);
+ for (double bucketBoundary = minFeeLimit; bucketBoundary <= MAX_FEERATE; bucketBoundary *= FEE_SPACING) {
+ feeset.insert(bucketBoundary);
+ }
+}
+
+CAmount FeeFilterRounder::round(CAmount currentMinFee)
+{
+ std::set<double>::iterator it = feeset.lower_bound(currentMinFee);
+ if ((it != feeset.begin() && insecure_rand() % 3 != 0) || it == feeset.end()) {
+ it--;
+ }
+ return *it;
+}
diff --git a/src/policy/fees.h b/src/policy/fees.h
index 3fa31c39e7..cdd984de7d 100644
--- a/src/policy/fees.h
+++ b/src/policy/fees.h
@@ -286,4 +286,17 @@ private:
CFeeRate feeLikely, feeUnlikely;
double priLikely, priUnlikely;
};
+
+class FeeFilterRounder
+{
+public:
+ /** Create new FeeFilterRounder */
+ FeeFilterRounder(const CFeeRate& minIncrementalFee);
+
+ /** Quantize a minimum fee for privacy purpose before broadcast **/
+ CAmount round(CAmount currentMinFee);
+
+private:
+ std::set<double> feeset;
+};
#endif /*BITCOIN_POLICYESTIMATOR_H */
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index 332abc430e..e3ed7be000 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -55,7 +55,7 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
bool IsStandardTx(const CTransaction& tx, std::string& reason)
{
- if (tx.nVersion > CTransaction::CURRENT_VERSION || tx.nVersion < 1) {
+ if (tx.nVersion > CTransaction::MAX_STANDARD_VERSION || tx.nVersion < 1) {
reason = "version";
return false;
}
diff --git a/src/policy/policy.h b/src/policy/policy.h
index 726864f190..4f9354e36f 100644
--- a/src/policy/policy.h
+++ b/src/policy/policy.h
@@ -40,13 +40,15 @@ static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS |
SCRIPT_VERIFY_CLEANSTACK |
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY |
+ SCRIPT_VERIFY_CHECKSEQUENCEVERIFY |
SCRIPT_VERIFY_LOW_S;
/** For convenience, standard but not mandatory verify flags. */
static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS;
-/** Used as the flags parameter to CheckFinalTx() in non-consensus code */
-static const unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS = LOCKTIME_MEDIAN_TIME_PAST;
+/** Used as the flags parameter to sequence and nLocktime checks in non-consensus code. */
+static const unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS = LOCKTIME_VERIFY_SEQUENCE |
+ LOCKTIME_MEDIAN_TIME_PAST;
bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType);
/**
diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp
index 59e949d71a..6fb33230a5 100644
--- a/src/primitives/block.cpp
+++ b/src/primitives/block.cpp
@@ -18,7 +18,7 @@ uint256 CBlockHeader::GetHash() const
std::string CBlock::ToString() const
{
std::stringstream s;
- s << strprintf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n",
+ s << strprintf("CBlock(hash=%s, ver=0x%08x, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n",
GetHash().ToString(),
nVersion,
hashPrevBlock.ToString(),
diff --git a/src/primitives/block.h b/src/primitives/block.h
index 0e93399c08..42276b2bc2 100644
--- a/src/primitives/block.h
+++ b/src/primitives/block.h
@@ -21,7 +21,6 @@ class CBlockHeader
{
public:
// header
- static const int32_t CURRENT_VERSION=4;
int32_t nVersion;
uint256 hashPrevBlock;
uint256 hashMerkleRoot;
@@ -49,7 +48,7 @@ public:
void SetNull()
{
- nVersion = CBlockHeader::CURRENT_VERSION;
+ nVersion = 0;
hashPrevBlock.SetNull();
hashMerkleRoot.SetNull();
nTime = 0;
diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp
index aea96d8a12..947f2e6a73 100644
--- a/src/primitives/transaction.cpp
+++ b/src/primitives/transaction.cpp
@@ -37,7 +37,7 @@ std::string CTxIn::ToString() const
str += strprintf(", coinbase %s", HexStr(scriptSig));
else
str += strprintf(", scriptSig=%s", HexStr(scriptSig).substr(0, 24));
- if (nSequence != std::numeric_limits<unsigned int>::max())
+ if (nSequence != SEQUENCE_FINAL)
str += strprintf(", nSequence=%u", nSequence);
str += ")";
return str;
diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h
index 8bd6d00e2e..149816406a 100644
--- a/src/primitives/transaction.h
+++ b/src/primitives/transaction.h
@@ -34,7 +34,8 @@ public:
friend bool operator<(const COutPoint& a, const COutPoint& b)
{
- return (a.hash < b.hash || (a.hash == b.hash && a.n < b.n));
+ int cmp = a.hash.Compare(b.hash);
+ return cmp < 0 || (cmp == 0 && a.n < b.n);
}
friend bool operator==(const COutPoint& a, const COutPoint& b)
@@ -61,13 +62,40 @@ public:
CScript scriptSig;
uint32_t nSequence;
+ /* Setting nSequence to this value for every input in a transaction
+ * disables nLockTime. */
+ static const uint32_t SEQUENCE_FINAL = 0xffffffff;
+
+ /* Below flags apply in the context of BIP 68*/
+ /* If this flag set, CTxIn::nSequence is NOT interpreted as a
+ * relative lock-time. */
+ static const uint32_t SEQUENCE_LOCKTIME_DISABLE_FLAG = (1 << 31);
+
+ /* If CTxIn::nSequence encodes a relative lock-time and this flag
+ * is set, the relative lock-time has units of 512 seconds,
+ * otherwise it specifies blocks with a granularity of 1. */
+ static const uint32_t SEQUENCE_LOCKTIME_TYPE_FLAG = (1 << 22);
+
+ /* If CTxIn::nSequence encodes a relative lock-time, this mask is
+ * applied to extract that lock-time from the sequence field. */
+ static const uint32_t SEQUENCE_LOCKTIME_MASK = 0x0000ffff;
+
+ /* In order to use the same number of bits to encode roughly the
+ * same wall-clock duration, and because blocks are naturally
+ * limited to occur every 600s on average, the minimum granularity
+ * for time-based relative lock-time is fixed at 512 seconds.
+ * Converting from CTxIn::nSequence to seconds is performed by
+ * multiplying by 512 = 2^9, or equivalently shifting up by
+ * 9 bits. */
+ static const int SEQUENCE_LOCKTIME_GRANULARITY = 9;
+
CTxIn()
{
- nSequence = std::numeric_limits<unsigned int>::max();
+ nSequence = SEQUENCE_FINAL;
}
- explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=std::numeric_limits<unsigned int>::max());
- CTxIn(uint256 hashPrevTx, uint32_t nOut, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=std::numeric_limits<uint32_t>::max());
+ explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=SEQUENCE_FINAL);
+ CTxIn(uint256 hashPrevTx, uint32_t nOut, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=SEQUENCE_FINAL);
ADD_SERIALIZE_METHODS;
@@ -78,11 +106,6 @@ public:
READWRITE(nSequence);
}
- bool IsFinal() const
- {
- return (nSequence == std::numeric_limits<uint32_t>::max());
- }
-
friend bool operator==(const CTxIn& a, const CTxIn& b)
{
return (a.prevout == b.prevout &&
@@ -184,8 +207,15 @@ private:
void UpdateHash() const;
public:
+ // Default transaction version.
static const int32_t CURRENT_VERSION=1;
+ // Changing the default transaction version requires a two step process: first
+ // adapting relay policy by bumping MAX_STANDARD_VERSION, and then later date
+ // bumping the default CURRENT_VERSION at which point both CURRENT_VERSION and
+ // MAX_STANDARD_VERSION will be equal.
+ static const int32_t MAX_STANDARD_VERSION=2;
+
// The local variables are made const to prevent unintended modification
// without updating the cached hash value. However, CTransaction is not
// actually immutable; deserialization and assignment are implemented,
diff --git a/src/protocol.cpp b/src/protocol.cpp
index c1c7c0b96b..8c4bd05725 100644
--- a/src/protocol.cpp
+++ b/src/protocol.cpp
@@ -28,13 +28,13 @@ const char *GETADDR="getaddr";
const char *MEMPOOL="mempool";
const char *PING="ping";
const char *PONG="pong";
-const char *ALERT="alert";
const char *NOTFOUND="notfound";
const char *FILTERLOAD="filterload";
const char *FILTERADD="filteradd";
const char *FILTERCLEAR="filterclear";
const char *REJECT="reject";
const char *SENDHEADERS="sendheaders";
+const char *FEEFILTER="feefilter";
};
static const char* ppszTypeName[] =
@@ -64,13 +64,13 @@ const static std::string allNetMessageTypes[] = {
NetMsgType::MEMPOOL,
NetMsgType::PING,
NetMsgType::PONG,
- NetMsgType::ALERT,
NetMsgType::NOTFOUND,
NetMsgType::FILTERLOAD,
NetMsgType::FILTERADD,
NetMsgType::FILTERCLEAR,
NetMsgType::REJECT,
- NetMsgType::SENDHEADERS
+ NetMsgType::SENDHEADERS,
+ NetMsgType::FEEFILTER
};
const static std::vector<std::string> allNetMessageTypesVec(allNetMessageTypes, allNetMessageTypes+ARRAYLEN(allNetMessageTypes));
diff --git a/src/protocol.h b/src/protocol.h
index c8b8d20ead..1b049e52af 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -164,13 +164,6 @@ extern const char *PING;
*/
extern const char *PONG;
/**
- * The alert message warns nodes of problems that may affect them or the rest
- * of the network.
- * @since protocol version 311.
- * @see https://bitcoin.org/en/developer-reference#alert
- */
-extern const char *ALERT;
-/**
* The notfound message is a reply to a getdata message which requested an
* object the receiving node does not have available for relay.
* @ince protocol version 70001.
@@ -218,7 +211,12 @@ extern const char *REJECT;
* @see https://bitcoin.org/en/developer-reference#sendheaders
*/
extern const char *SENDHEADERS;
-
+/**
+ * The feefilter message tells the receiving peer not to inv us any txs
+ * which do not meet the specified min fee rate.
+ * @since protocol version 70013 as described by BIP133
+ */
+extern const char *FEEFILTER;
};
/* Get a vector of all valid message types (see above) */
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index fb502b3c81..697736cc88 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -8,7 +8,6 @@
#include "guiconstants.h"
#include "peertablemodel.h"
-#include "alert.h"
#include "chainparams.h"
#include "checkpoints.h"
#include "clientversion.h"
@@ -122,20 +121,8 @@ void ClientModel::updateNumConnections(int numConnections)
Q_EMIT numConnectionsChanged(numConnections);
}
-void ClientModel::updateAlert(const QString &hash, int status)
+void ClientModel::updateAlert()
{
- // Show error message notification for new alert
- if(status == CT_NEW)
- {
- uint256 hash_256;
- hash_256.SetHex(hash.toStdString());
- CAlert alert = CAlert::getAlertByHash(hash_256);
- if(!alert.IsNull())
- {
- Q_EMIT message(tr("Network Alert"), QString::fromStdString(alert.strStatusBar), CClientUIInterface::ICON_ERROR);
- }
- }
-
Q_EMIT alertsChanged(getStatusBarWarnings());
}
@@ -186,11 +173,6 @@ QString ClientModel::formatSubVersion() const
return QString::fromStdString(strSubVersion);
}
-QString ClientModel::formatBuildDate() const
-{
- return QString::fromStdString(CLIENT_DATE);
-}
-
bool ClientModel::isReleaseVersion() const
{
return CLIENT_VERSION_IS_RELEASE;
@@ -206,6 +188,11 @@ QString ClientModel::formatClientStartupTime() const
return QDateTime::fromTime_t(nClientStartupTime).toString();
}
+QString ClientModel::dataDir() const
+{
+ return QString::fromStdString(GetDataDir().string());
+}
+
void ClientModel::updateBanlist()
{
banTableModel->refresh();
@@ -227,12 +214,10 @@ static void NotifyNumConnectionsChanged(ClientModel *clientmodel, int newNumConn
Q_ARG(int, newNumConnections));
}
-static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, ChangeType status)
+static void NotifyAlertChanged(ClientModel *clientmodel)
{
- qDebug() << "NotifyAlertChanged: " + QString::fromStdString(hash.GetHex()) + " status=" + QString::number(status);
- QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection,
- Q_ARG(QString, QString::fromStdString(hash.GetHex())),
- Q_ARG(int, status));
+ qDebug() << "NotifyAlertChanged";
+ QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection);
}
static void BannedListChanged(ClientModel *clientmodel)
@@ -266,7 +251,7 @@ void ClientModel::subscribeToCoreSignals()
// Connect signals to client
uiInterface.ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2));
uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1));
- uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2));
+ uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this));
uiInterface.BannedListChanged.connect(boost::bind(BannedListChanged, this));
uiInterface.NotifyBlockTip.connect(boost::bind(BlockTipChanged, this, _1, _2));
}
@@ -276,7 +261,7 @@ void ClientModel::unsubscribeFromCoreSignals()
// Disconnect signals from client
uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2));
uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1));
- uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2));
+ uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this));
uiInterface.BannedListChanged.disconnect(boost::bind(BannedListChanged, this));
uiInterface.NotifyBlockTip.disconnect(boost::bind(BlockTipChanged, this, _1, _2));
}
diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h
index 62c9f71ac7..109f95a2a7 100644
--- a/src/qt/clientmodel.h
+++ b/src/qt/clientmodel.h
@@ -72,10 +72,10 @@ public:
QString formatFullVersion() const;
QString formatSubVersion() const;
- QString formatBuildDate() const;
bool isReleaseVersion() const;
QString clientName() const;
QString formatClientStartupTime() const;
+ QString dataDir() const;
private:
OptionsModel *optionsModel;
@@ -103,7 +103,7 @@ Q_SIGNALS:
public Q_SLOTS:
void updateTimer();
void updateNumConnections(int numConnections);
- void updateAlert(const QString &hash, int status);
+ void updateAlert();
void updateBanlist();
};
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index 7393c83c7d..f909499952 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -796,7 +796,7 @@ void CoinControlDialog::updateView()
}
// set checkbox
- if (coinControl->IsSelected(txhash, out.i))
+ if (coinControl->IsSelected(COutPoint(txhash, out.i)))
itemOutput->setCheckState(COLUMN_CHECKBOX, Qt::Checked);
}
diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui
index febbaeda1b..c17efcf1b3 100644
--- a/src/qt/forms/debugwindow.ui
+++ b/src/qt/forms/debugwindow.ui
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>740</width>
- <height>450</height>
+ <height>430</height>
</rect>
</property>
<property name="windowTitle">
@@ -113,32 +113,6 @@
</widget>
</item>
<item row="4" column="0">
- <widget class="QLabel" name="label_14">
- <property name="text">
- <string>Using OpenSSL version</string>
- </property>
- <property name="indent">
- <number>10</number>
- </property>
- </widget>
- </item>
- <item row="4" column="1" colspan="2">
- <widget class="QLabel" name="openSSLVersion">
- <property name="cursor">
- <cursorShape>IBeamCursor</cursorShape>
- </property>
- <property name="text">
- <string>N/A</string>
- </property>
- <property name="textFormat">
- <enum>Qt::PlainText</enum>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item row="5" column="0">
<widget class="QLabel" name="label_berkeleyDBVersion">
<property name="text">
<string>Using BerkeleyDB version</string>
@@ -148,7 +122,7 @@
</property>
</widget>
</item>
- <item row="5" column="1" colspan="2">
+ <item row="4" column="1" colspan="2">
<widget class="QLabel" name="berkeleyDBVersion">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -164,15 +138,15 @@
</property>
</widget>
</item>
- <item row="6" column="0">
+ <item row="5" column="0">
<widget class="QLabel" name="label_12">
<property name="text">
- <string>Build date</string>
+ <string>Datadir</string>
</property>
</widget>
</item>
- <item row="6" column="1" colspan="2">
- <widget class="QLabel" name="buildDate">
+ <item row="5" column="1" colspan="2">
+ <widget class="QLabel" name="dataDir">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
@@ -182,19 +156,22 @@
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
- <item row="7" column="0">
+ <item row="6" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Startup time</string>
</property>
</widget>
</item>
- <item row="7" column="1" colspan="2">
+ <item row="6" column="1" colspan="2">
<widget class="QLabel" name="startupTime">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -210,14 +187,27 @@
</property>
</widget>
</item>
- <item row="9" column="0">
+ <item row="7" column="0">
+ <widget class="QLabel" name="labelNetwork">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Network</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
- <item row="9" column="1" colspan="2">
+ <item row="8" column="1" colspan="2">
<widget class="QLabel" name="networkName">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -233,14 +223,14 @@
</property>
</widget>
</item>
- <item row="10" column="0">
+ <item row="9" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Number of connections</string>
</property>
</widget>
</item>
- <item row="10" column="1" colspan="2">
+ <item row="9" column="1" colspan="2">
<widget class="QLabel" name="numberOfConnections">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -256,7 +246,7 @@
</property>
</widget>
</item>
- <item row="11" column="0">
+ <item row="10" column="0">
<widget class="QLabel" name="label_10">
<property name="font">
<font>
@@ -269,14 +259,14 @@
</property>
</widget>
</item>
- <item row="12" column="0">
+ <item row="11" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Current number of blocks</string>
</property>
</widget>
</item>
- <item row="12" column="1" colspan="2">
+ <item row="11" column="1" colspan="2">
<widget class="QLabel" name="numberOfBlocks">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -292,14 +282,14 @@
</property>
</widget>
</item>
- <item row="13" column="0">
+ <item row="12" column="0">
<widget class="QLabel" name="labelLastBlockTime">
<property name="text">
<string>Last block time</string>
</property>
</widget>
</item>
- <item row="13" column="1" colspan="2">
+ <item row="12" column="1" colspan="2">
<widget class="QLabel" name="lastBlockTime">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -315,7 +305,7 @@
</property>
</widget>
</item>
- <item row="14" column="0">
+ <item row="13" column="0">
<widget class="QLabel" name="labelMempoolTitle">
<property name="font">
<font>
@@ -328,14 +318,14 @@
</property>
</widget>
</item>
- <item row="15" column="0">
+ <item row="14" column="0">
<widget class="QLabel" name="labelNumberOfTransactions">
<property name="text">
<string>Current number of transactions</string>
</property>
</widget>
</item>
- <item row="15" column="1">
+ <item row="14" column="1">
<widget class="QLabel" name="mempoolNumberTxs">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -351,27 +341,14 @@
</property>
</widget>
</item>
- <item row="8" column="0">
- <widget class="QLabel" name="labelNetwork">
- <property name="font">
- <font>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>Network</string>
- </property>
- </widget>
- </item>
- <item row="16" column="0">
+ <item row="15" column="0">
<widget class="QLabel" name="labelMemoryUsage">
<property name="text">
<string>Memory usage</string>
</property>
</widget>
</item>
- <item row="16" column="1">
+ <item row="15" column="1">
<widget class="QLabel" name="mempoolSize">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
@@ -387,7 +364,7 @@
</property>
</widget>
</item>
- <item row="14" column="2" rowspan="3">
+ <item row="13" column="2" rowspan="3">
<layout class="QVBoxLayout" name="verticalLayoutDebugButton">
<property name="spacing">
<number>3</number>
@@ -427,7 +404,7 @@
</item>
</layout>
</item>
- <item row="18" column="0">
+ <item row="16" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
diff --git a/src/qt/forms/sendcoinsdialog.ui b/src/qt/forms/sendcoinsdialog.ui
index 8911b41cbf..12d6a62c08 100644
--- a/src/qt/forms/sendcoinsdialog.ui
+++ b/src/qt/forms/sendcoinsdialog.ui
@@ -617,7 +617,7 @@
<x>0</x>
<y>0</y>
<width>830</width>
- <height>68</height>
+ <height>104</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,1">
@@ -1167,59 +1167,6 @@
</item>
</layout>
</item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayoutFee5" stretch="0,0,0">
- <property name="spacing">
- <number>8</number>
- </property>
- <property name="bottomMargin">
- <number>4</number>
- </property>
- <item>
- <widget class="QCheckBox" name="checkBoxFreeTx">
- <property name="text">
- <string>Send as zero-fee transaction if possible</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="labelFreeTx">
- <property name="text">
- <string>(confirmation may take longer)</string>
- </property>
- <property name="margin">
- <number>5</number>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacerFee5">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>1</width>
- <height>1</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item>
- <spacer name="verticalSpacerFee2">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>1</width>
- <height>1</height>
- </size>
- </property>
- </spacer>
- </item>
</layout>
</widget>
</item>
diff --git a/src/qt/res/icons/about.png b/src/qt/res/icons/about.png
index 83eb3c07ee..4143be8bac 100644
--- a/src/qt/res/icons/about.png
+++ b/src/qt/res/icons/about.png
Binary files differ
diff --git a/src/qt/res/icons/chevron.png b/src/qt/res/icons/chevron.png
index ac985052c1..2309fb38e2 100644
--- a/src/qt/res/icons/chevron.png
+++ b/src/qt/res/icons/chevron.png
Binary files differ
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index c18c405256..d8647d902a 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -36,6 +36,7 @@
#include <QThread>
#include <QTime>
#include <QTimer>
+#include <QStringList>
#if QT_VERSION < 0x050000
#include <QUrl>
@@ -275,13 +276,6 @@ RPCConsole::RPCConsole(const PlatformStyle *platformStyle, QWidget *parent) :
connect(ui->btnClearTrafficGraph, SIGNAL(clicked()), ui->trafficGraph, SLOT(clear()));
// set library version labels
-
-#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
- ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION));
-#else
- ui->openSSLVersion->setText(OpenSSL_version(OPENSSL_VERSION));
-#endif
-
#ifdef ENABLE_WALLET
ui->berkeleyDBVersion->setText(DbEnv::version(0, 0, 0));
#else
@@ -450,9 +444,23 @@ void RPCConsole::setClientModel(ClientModel *model)
ui->clientVersion->setText(model->formatFullVersion());
ui->clientUserAgent->setText(model->formatSubVersion());
ui->clientName->setText(model->clientName());
- ui->buildDate->setText(model->formatBuildDate());
+ ui->dataDir->setText(model->dataDir());
ui->startupTime->setText(model->formatClientStartupTime());
ui->networkName->setText(QString::fromStdString(Params().NetworkIDString()));
+
+ //Setup autocomplete and attach it
+ QStringList wordList;
+ std::vector<std::string> commandList = tableRPC.listCommands();
+ for (size_t i = 0; i < commandList.size(); ++i)
+ {
+ wordList << commandList[i].c_str();
+ }
+
+ autoCompleter = new QCompleter(wordList, this);
+ ui->lineEdit->setCompleter(autoCompleter);
+
+ // clear the lineEdit after activating from QCompleter
+ connect(autoCompleter, SIGNAL(activated(const QString&)), ui->lineEdit, SLOT(clear()), Qt::QueuedConnection);
}
}
@@ -497,16 +505,19 @@ void RPCConsole::setFontSize(int newSize)
// clear console (reset icon sizes, default stylesheet) and re-add the content
float oldPosFactor = 1.0 / ui->messagesWidget->verticalScrollBar()->maximum() * ui->messagesWidget->verticalScrollBar()->value();
- clear();
+ clear(false);
ui->messagesWidget->setHtml(str);
ui->messagesWidget->verticalScrollBar()->setValue(oldPosFactor * ui->messagesWidget->verticalScrollBar()->maximum());
}
-void RPCConsole::clear()
+void RPCConsole::clear(bool clearHistory)
{
ui->messagesWidget->clear();
- history.clear();
- historyPtr = 0;
+ if(clearHistory)
+ {
+ history.clear();
+ historyPtr = 0;
+ }
ui->lineEdit->clear();
ui->lineEdit->setFocus();
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index 648e32638f..2923587bc8 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -11,6 +11,7 @@
#include "net.h"
#include <QWidget>
+#include <QCompleter>
class ClientModel;
class PlatformStyle;
@@ -77,7 +78,7 @@ private Q_SLOTS:
void clearSelectedNode();
public Q_SLOTS:
- void clear();
+ void clear(bool clearHistory = true);
void fontBigger();
void fontSmaller();
void setFontSize(int newSize);
@@ -138,6 +139,7 @@ private:
QMenu *peersTableContextMenu;
QMenu *banTableContextMenu;
int consoleFontSize;
+ QCompleter *autoCompleter;
};
#endif // BITCOIN_QT_RPCCONSOLE_H
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 5fc7b57a41..780a6c9709 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -104,8 +104,6 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *platformStyle, QWidget *pa
settings.setValue("nTransactionFee", (qint64)DEFAULT_TRANSACTION_FEE);
if (!settings.contains("fPayOnlyMinFee"))
settings.setValue("fPayOnlyMinFee", false);
- if (!settings.contains("fSendFreeTransactions"))
- settings.setValue("fSendFreeTransactions", false);
ui->groupFee->setId(ui->radioSmartFee, 0);
ui->groupFee->setId(ui->radioCustomFee, 1);
ui->groupFee->button((int)std::max(0, std::min(1, settings.value("nFeeRadio").toInt())))->setChecked(true);
@@ -115,7 +113,6 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *platformStyle, QWidget *pa
ui->sliderSmartFee->setValue(settings.value("nSmartFeeSliderPosition").toInt());
ui->customFee->setValue(settings.value("nTransactionFee").toLongLong());
ui->checkBoxMinimumFee->setChecked(settings.value("fPayOnlyMinFee").toBool());
- ui->checkBoxFreeTx->setChecked(settings.value("fSendFreeTransactions").toBool());
minimizeFeeSection(settings.value("fFeeSectionMinimized").toBool());
}
@@ -170,8 +167,6 @@ void SendCoinsDialog::setModel(WalletModel *model)
connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(updateFeeSectionControls()));
connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(updateGlobalFeeVariables()));
connect(ui->checkBoxMinimumFee, SIGNAL(stateChanged(int)), this, SLOT(coinControlUpdateLabels()));
- connect(ui->checkBoxFreeTx, SIGNAL(stateChanged(int)), this, SLOT(updateGlobalFeeVariables()));
- connect(ui->checkBoxFreeTx, SIGNAL(stateChanged(int)), this, SLOT(coinControlUpdateLabels()));
ui->customFee->setSingleStep(CWallet::GetRequiredFee(1000));
updateFeeSectionControls();
updateMinFeeLabel();
@@ -189,7 +184,6 @@ SendCoinsDialog::~SendCoinsDialog()
settings.setValue("nSmartFeeSliderPosition", ui->sliderSmartFee->value());
settings.setValue("nTransactionFee", (qint64)ui->customFee->value());
settings.setValue("fPayOnlyMinFee", ui->checkBoxMinimumFee->isChecked());
- settings.setValue("fSendFreeTransactions", ui->checkBoxFreeTx->isChecked());
delete ui;
}
@@ -605,8 +599,6 @@ void SendCoinsDialog::updateGlobalFeeVariables()
// set nMinimumTotalFee to 0 in case of user has selected that the fee is per KB
CoinControlDialog::coinControl->nMinimumTotalFee = ui->radioCustomAtLeast->isChecked() ? ui->customFee->value() : 0;
}
-
- fSendFreeTransactions = ui->checkBoxFreeTx->isChecked();
}
void SendCoinsDialog::updateFeeMinimizedLabel()
diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp
index 5cb4cd5af7..5abefc144e 100644
--- a/src/qt/transactiondesc.cpp
+++ b/src/qt/transactiondesc.cpp
@@ -240,7 +240,8 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
if (wtx.mapValue.count("comment") && !wtx.mapValue["comment"].empty())
strHTML += "<br><b>" + tr("Comment") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "<br>";
- strHTML += "<b>" + tr("Transaction ID") + ":</b> " + TransactionRecord::formatSubTxId(wtx.GetHash(), rec->idx) + "<br>";
+ strHTML += "<b>" + tr("Transaction ID") + ":</b> " + rec->getTxID() + "<br>";
+ strHTML += "<b>" + tr("Output index") + ":</b> " + QString::number(rec->getOutputIndex()) + "<br>";
// Message from normal bitcoin:URI (bitcoin:123...?message=example)
Q_FOREACH (const PAIRTYPE(std::string, std::string)& r, wtx.vOrderForm)
diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp
index 5b16b108e6..97b77cc93d 100644
--- a/src/qt/transactionrecord.cpp
+++ b/src/qt/transactionrecord.cpp
@@ -260,11 +260,10 @@ bool TransactionRecord::statusUpdateNeeded()
QString TransactionRecord::getTxID() const
{
- return formatSubTxId(hash, idx);
+ return QString::fromStdString(hash.ToString());
}
-QString TransactionRecord::formatSubTxId(const uint256 &hash, int vout)
+int TransactionRecord::getOutputIndex() const
{
- return QString::fromStdString(hash.ToString() + strprintf("-%03d", vout));
+ return idx;
}
-
diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h
index 49753ee31f..95ab98c10d 100644
--- a/src/qt/transactionrecord.h
+++ b/src/qt/transactionrecord.h
@@ -128,8 +128,8 @@ public:
/** Return the unique identifier for this transaction (part) */
QString getTxID() const;
- /** Format subtransaction id */
- static QString formatSubTxId(const uint256 &hash, int vout);
+ /** Return the output index of the subtransaction */
+ int getOutputIndex() const;
/** Update status from core wallet tx.
*/
diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp
index 1647b2a6fe..d2a52b3022 100644
--- a/src/qt/transactiontablemodel.cpp
+++ b/src/qt/transactiontablemodel.cpp
@@ -609,6 +609,34 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
return QString::fromStdString(rec->hash.ToString());
case TxHexRole:
return priv->getTxHex(rec);
+ case TxPlainTextRole:
+ {
+ QString details;
+ QDateTime date = QDateTime::fromTime_t(static_cast<uint>(rec->time));
+ QString txLabel = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(rec->address));
+
+ details.append(date.toString("M/d/yy HH:mm"));
+ details.append(" ");
+ details.append(formatTxStatus(rec));
+ details.append(". ");
+ if(!formatTxType(rec).isEmpty()) {
+ details.append(formatTxType(rec));
+ details.append(" ");
+ }
+ if(!rec->address.empty()) {
+ if(txLabel.isEmpty())
+ details.append(tr("(no label)") + " ");
+ else {
+ details.append("(");
+ details.append(txLabel);
+ details.append(") ");
+ }
+ details.append(QString::fromStdString(rec->address));
+ details.append(" ");
+ }
+ details.append(formatTxAmount(rec, false, BitcoinUnits::separatorNever));
+ return details;
+ }
case ConfirmedRole:
return rec->status.countsForBalance;
case FormattedAmountRole:
diff --git a/src/qt/transactiontablemodel.h b/src/qt/transactiontablemodel.h
index fe59a15f6a..6932646e1e 100644
--- a/src/qt/transactiontablemodel.h
+++ b/src/qt/transactiontablemodel.h
@@ -62,6 +62,8 @@ public:
TxHashRole,
/** Transaction data, hex-encoded */
TxHexRole,
+ /** Whole transaction as plain text */
+ TxPlainTextRole,
/** Is transaction confirmed? */
ConfirmedRole,
/** Formatted amount, without brackets when unconfirmed */
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index 4a9a198216..a4d4c7a35f 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -142,6 +142,7 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa
QAction *copyAmountAction = new QAction(tr("Copy amount"), this);
QAction *copyTxIDAction = new QAction(tr("Copy transaction ID"), this);
QAction *copyTxHexAction = new QAction(tr("Copy raw transaction"), this);
+ QAction *copyTxPlainText = new QAction(tr("Copy full transaction details"), this);
QAction *editLabelAction = new QAction(tr("Edit label"), this);
QAction *showDetailsAction = new QAction(tr("Show transaction details"), this);
@@ -151,6 +152,7 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa
contextMenu->addAction(copyAmountAction);
contextMenu->addAction(copyTxIDAction);
contextMenu->addAction(copyTxHexAction);
+ contextMenu->addAction(copyTxPlainText);
contextMenu->addAction(editLabelAction);
contextMenu->addAction(showDetailsAction);
@@ -173,6 +175,7 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa
connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount()));
connect(copyTxIDAction, SIGNAL(triggered()), this, SLOT(copyTxID()));
connect(copyTxHexAction, SIGNAL(triggered()), this, SLOT(copyTxHex()));
+ connect(copyTxPlainText, SIGNAL(triggered()), this, SLOT(copyTxPlainText()));
connect(editLabelAction, SIGNAL(triggered()), this, SLOT(editLabel()));
connect(showDetailsAction, SIGNAL(triggered()), this, SLOT(showDetails()));
}
@@ -388,6 +391,11 @@ void TransactionView::copyTxHex()
GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::TxHexRole);
}
+void TransactionView::copyTxPlainText()
+{
+ GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::TxPlainTextRole);
+}
+
void TransactionView::editLabel()
{
if(!transactionView->selectionModel() ||!model)
@@ -526,12 +534,8 @@ bool TransactionView::eventFilter(QObject *obj, QEvent *event)
QKeyEvent *ke = static_cast<QKeyEvent *>(event);
if (ke->key() == Qt::Key_C && ke->modifiers().testFlag(Qt::ControlModifier))
{
- QModelIndex i = this->transactionView->currentIndex();
- if (i.isValid() && i.column() == TransactionTableModel::Amount)
- {
- GUIUtil::setClipboard(i.data(TransactionTableModel::FormattedAmountRole).toString());
- return true;
- }
+ GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::TxPlainTextRole);
+ return true;
}
}
return QWidget::eventFilter(obj, event);
diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h
index cf2b8fbcd4..2cfbd471b0 100644
--- a/src/qt/transactionview.h
+++ b/src/qt/transactionview.h
@@ -94,6 +94,7 @@ private Q_SLOTS:
void copyAmount();
void copyTxID();
void copyTxHex();
+ void copyTxPlainText();
void openThirdPartyTxUrl(QString url);
void updateWatchOnlyColumn(bool fHaveWatchOnly);
diff --git a/src/rest.cpp b/src/rest.cpp
index ebdccc9402..2dff8d7dad 100644
--- a/src/rest.cpp
+++ b/src/rest.cpp
@@ -273,6 +273,9 @@ static bool rest_block_notxdetails(HTTPRequest* req, const std::string& strURIPa
return rest_block(req, strURIPart, false);
}
+// A bit of a hack - dependency on a function defined in rpc/blockchain.cpp
+UniValue getblockchaininfo(const UniValue& params, bool fHelp);
+
static bool rest_chaininfo(HTTPRequest* req, const std::string& strURIPart)
{
if (!CheckWarmup(req))
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index de6bda4ea1..f1c9d9f7ab 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -89,7 +89,7 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex)
UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false)
{
UniValue result(UniValue::VOBJ);
- result.push_back(Pair("hash", block.GetHash().GetHex()));
+ result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex()));
int confirmations = -1;
// Only report confirmations if the block is on the main chain
if (chainActive.Contains(blockindex))
@@ -604,6 +604,20 @@ static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex*
return rv;
}
+static UniValue BIP9SoftForkDesc(const std::string& name, const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
+{
+ UniValue rv(UniValue::VOBJ);
+ rv.push_back(Pair("id", name));
+ switch (VersionBitsTipState(consensusParams, id)) {
+ case THRESHOLD_DEFINED: rv.push_back(Pair("status", "defined")); break;
+ case THRESHOLD_STARTED: rv.push_back(Pair("status", "started")); break;
+ case THRESHOLD_LOCKED_IN: rv.push_back(Pair("status", "locked_in")); break;
+ case THRESHOLD_ACTIVE: rv.push_back(Pair("status", "active")); break;
+ case THRESHOLD_FAILED: rv.push_back(Pair("status", "failed")); break;
+ }
+ return rv;
+}
+
UniValue getblockchaininfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
@@ -634,6 +648,12 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp)
" },\n"
" \"reject\": { ... } (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n"
" }, ...\n"
+ " ],\n"
+ " \"bip9_softforks\": [ (array) status of BIP9 softforks in progress\n"
+ " {\n"
+ " \"id\": \"xxxx\", (string) name of the softfork\n"
+ " \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"lockedin\", \"active\", \"failed\"\n"
+ " }\n"
" ]\n"
"}\n"
"\nExamples:\n"
@@ -657,10 +677,13 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp)
const Consensus::Params& consensusParams = Params().GetConsensus();
CBlockIndex* tip = chainActive.Tip();
UniValue softforks(UniValue::VARR);
+ UniValue bip9_softforks(UniValue::VARR);
softforks.push_back(SoftForkDesc("bip34", 2, tip, consensusParams));
softforks.push_back(SoftForkDesc("bip66", 3, tip, consensusParams));
softforks.push_back(SoftForkDesc("bip65", 4, tip, consensusParams));
+ bip9_softforks.push_back(BIP9SoftForkDesc("csv", consensusParams, Consensus::DEPLOYMENT_CSV));
obj.push_back(Pair("softforks", softforks));
+ obj.push_back(Pair("bip9_softforks", bip9_softforks));
if (fPruneMode)
{
@@ -889,3 +912,31 @@ UniValue reconsiderblock(const UniValue& params, bool fHelp)
return NullUniValue;
}
+
+static const CRPCCommand commands[] =
+{ // category name actor (function) okSafeMode
+ // --------------------- ------------------------ ----------------------- ----------
+ { "blockchain", "getblockchaininfo", &getblockchaininfo, true },
+ { "blockchain", "getbestblockhash", &getbestblockhash, true },
+ { "blockchain", "getblockcount", &getblockcount, true },
+ { "blockchain", "getblock", &getblock, true },
+ { "blockchain", "getblockhash", &getblockhash, true },
+ { "blockchain", "getblockheader", &getblockheader, true },
+ { "blockchain", "getchaintips", &getchaintips, true },
+ { "blockchain", "getdifficulty", &getdifficulty, true },
+ { "blockchain", "getmempoolinfo", &getmempoolinfo, true },
+ { "blockchain", "getrawmempool", &getrawmempool, true },
+ { "blockchain", "gettxout", &gettxout, true },
+ { "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true },
+ { "blockchain", "verifychain", &verifychain, true },
+
+ /* Not shown in help */
+ { "hidden", "invalidateblock", &invalidateblock, true },
+ { "hidden", "reconsiderblock", &reconsiderblock, true },
+};
+
+void RegisterBlockchainRPCCommands(CRPCTable &tableRPC)
+{
+ for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
+ tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
+}
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index b0e9b6f153..89420b93d7 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -27,9 +27,11 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "stop", 0 },
{ "setmocktime", 0 },
{ "getaddednodeinfo", 0 },
- { "setgenerate", 0 },
- { "setgenerate", 1 },
{ "generate", 0 },
+ { "generate", 1 },
+ { "generatetoaddress", 0 },
+ { "generatetoaddress", 1 },
+ { "generatetoaddress", 2 },
{ "getnetworkhashps", 0 },
{ "getnetworkhashps", 1 },
{ "sendtoaddress", 1 },
@@ -160,4 +162,3 @@ UniValue RPCConvertValues(const std::string &strMethod, const std::vector<std::s
return params;
}
-
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index 996b7f9cbd..b63ee22889 100644
--- a/src/rpc/mining.cpp
+++ b/src/rpc/mining.cpp
@@ -3,6 +3,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include "base58.h"
#include "amount.h"
#include "chain.h"
#include "chainparams.h"
@@ -68,7 +69,7 @@ UniValue GetNetworkHashPS(int lookup, int height) {
arith_uint256 workDiff = pb->nChainWork - pb0->nChainWork;
int64_t timeDiff = maxTime - minTime;
- return (int64_t)(workDiff.getdouble() / timeDiff);
+ return workDiff.getdouble() / timeDiff;
}
UniValue getnetworkhashps(const UniValue& params, bool fHelp)
@@ -93,59 +94,12 @@ UniValue getnetworkhashps(const UniValue& params, bool fHelp)
return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1);
}
-UniValue getgenerate(const UniValue& params, bool fHelp)
+UniValue generateBlocks(boost::shared_ptr<CReserveScript> coinbaseScript, int nGenerate, uint64_t nMaxTries, bool keepScript)
{
- if (fHelp || params.size() != 0)
- throw runtime_error(
- "getgenerate\n"
- "\nReturn if the server is set to generate coins or not. The default is false.\n"
- "It is set with the command line argument -gen (or " + std::string(BITCOIN_CONF_FILENAME) + " setting gen)\n"
- "It can also be set with the setgenerate call.\n"
- "\nResult\n"
- "true|false (boolean) If the server is set to generate coins or not\n"
- "\nExamples:\n"
- + HelpExampleCli("getgenerate", "")
- + HelpExampleRpc("getgenerate", "")
- );
-
- LOCK(cs_main);
- return GetBoolArg("-gen", DEFAULT_GENERATE);
-}
-
-UniValue generate(const UniValue& params, bool fHelp)
-{
- if (fHelp || params.size() < 1 || params.size() > 1)
- throw runtime_error(
- "generate numblocks\n"
- "\nMine blocks immediately (before the RPC call returns)\n"
- "\nNote: this function can only be used on the regtest network\n"
- "\nArguments:\n"
- "1. numblocks (numeric, required) How many blocks are generated immediately.\n"
- "\nResult\n"
- "[ blockhashes ] (array) hashes of blocks generated\n"
- "\nExamples:\n"
- "\nGenerate 11 blocks\n"
- + HelpExampleCli("generate", "11")
- );
-
- if (!Params().MineBlocksOnDemand())
- throw JSONRPCError(RPC_METHOD_NOT_FOUND, "This method can only be used on regtest");
-
+ static const int nInnerLoopCount = 0x10000;
int nHeightStart = 0;
int nHeightEnd = 0;
int nHeight = 0;
- int nGenerate = params[0].get_int();
-
- boost::shared_ptr<CReserveScript> coinbaseScript;
- GetMainSignals().ScriptForMining(coinbaseScript);
-
- // If the keypool is exhausted, no script is returned at all. Catch this.
- if (!coinbaseScript)
- throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
-
- //throw an error if no script was provided
- if (coinbaseScript->reserveScript.empty())
- throw JSONRPCError(RPC_INTERNAL_ERROR, "No coinbase script available (mining requires a wallet)");
{ // Don't keep cs_main locked
LOCK(cs_main);
@@ -165,10 +119,15 @@ UniValue generate(const UniValue& params, bool fHelp)
LOCK(cs_main);
IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce);
}
- while (!CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus())) {
- // Yes, there is a chance every nonce could fail to satisfy the -regtest
- // target -- 1 in 2^(2^32). That ain't gonna happen.
+ while (nMaxTries > 0 && pblock->nNonce < nInnerLoopCount && !CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus())) {
++pblock->nNonce;
+ --nMaxTries;
+ }
+ if (nMaxTries == 0) {
+ break;
+ }
+ if (pblock->nNonce == nInnerLoopCount) {
+ continue;
}
CValidationState state;
if (!ProcessNewBlock(state, Params(), NULL, pblock, true, NULL))
@@ -176,54 +135,82 @@ UniValue generate(const UniValue& params, bool fHelp)
++nHeight;
blockHashes.push_back(pblock->GetHash().GetHex());
- //mark script as important because it was used at least for one coinbase output
- coinbaseScript->KeepScript();
+ //mark script as important because it was used at least for one coinbase output if the script came from the wallet
+ if (keepScript)
+ {
+ coinbaseScript->KeepScript();
+ }
}
return blockHashes;
}
-UniValue setgenerate(const UniValue& params, bool fHelp)
+UniValue generate(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
- "setgenerate generate ( genproclimit )\n"
- "\nSet 'generate' true or false to turn generation on or off.\n"
- "Generation is limited to 'genproclimit' processors, -1 is unlimited.\n"
- "See the getgenerate call for the current setting.\n"
+ "generate numblocks ( maxtries )\n"
+ "\nMine up to numblocks blocks immediately (before the RPC call returns)\n"
"\nArguments:\n"
- "1. generate (boolean, required) Set to true to turn on generation, off to turn off.\n"
- "2. genproclimit (numeric, optional) Set the processor limit for when generation is on. Can be -1 for unlimited.\n"
+ "1. numblocks (numeric, required) How many blocks are generated immediately.\n"
+ "2. maxtries (numeric, optional) How many iterations to try (default = 1000000).\n"
+ "\nResult\n"
+ "[ blockhashes ] (array) hashes of blocks generated\n"
"\nExamples:\n"
- "\nSet the generation on with a limit of one processor\n"
- + HelpExampleCli("setgenerate", "true 1") +
- "\nCheck the setting\n"
- + HelpExampleCli("getgenerate", "") +
- "\nTurn off generation\n"
- + HelpExampleCli("setgenerate", "false") +
- "\nUsing json rpc\n"
- + HelpExampleRpc("setgenerate", "true, 1")
+ "\nGenerate 11 blocks\n"
+ + HelpExampleCli("generate", "11")
);
- if (Params().MineBlocksOnDemand())
- throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Use the generate method instead of setgenerate on this network");
+ int nGenerate = params[0].get_int();
+ uint64_t nMaxTries = 1000000;
+ if (params.size() > 1) {
+ nMaxTries = params[1].get_int();
+ }
- bool fGenerate = true;
- if (params.size() > 0)
- fGenerate = params[0].get_bool();
+ boost::shared_ptr<CReserveScript> coinbaseScript;
+ GetMainSignals().ScriptForMining(coinbaseScript);
- int nGenProcLimit = GetArg("-genproclimit", DEFAULT_GENERATE_THREADS);
- if (params.size() > 1)
- {
- nGenProcLimit = params[1].get_int();
- if (nGenProcLimit == 0)
- fGenerate = false;
+ // If the keypool is exhausted, no script is returned at all. Catch this.
+ if (!coinbaseScript)
+ throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
+
+ //throw an error if no script was provided
+ if (coinbaseScript->reserveScript.empty())
+ throw JSONRPCError(RPC_INTERNAL_ERROR, "No coinbase script available (mining requires a wallet)");
+
+ return generateBlocks(coinbaseScript, nGenerate, nMaxTries, true);
+}
+
+UniValue generatetoaddress(const UniValue& params, bool fHelp)
+{
+ if (fHelp || params.size() < 2 || params.size() > 3)
+ throw runtime_error(
+ "generatetoaddress numblocks address (maxtries)\n"
+ "\nMine blocks immediately to a specified address (before the RPC call returns)\n"
+ "\nArguments:\n"
+ "1. numblocks (numeric, required) How many blocks are generated immediately.\n"
+ "2. address (string, required) The address to send the newly generated bitcoin to.\n"
+ "3. maxtries (numeric, optional) How many iterations to try (default = 1000000).\n"
+ "\nResult\n"
+ "[ blockhashes ] (array) hashes of blocks generated\n"
+ "\nExamples:\n"
+ "\nGenerate 11 blocks to myaddress\n"
+ + HelpExampleCli("generatetoaddress", "11 \"myaddress\"")
+ );
+
+ int nGenerate = params[0].get_int();
+ uint64_t nMaxTries = 1000000;
+ if (params.size() > 2) {
+ nMaxTries = params[2].get_int();
}
- mapArgs["-gen"] = (fGenerate ? "1" : "0");
- mapArgs ["-genproclimit"] = itostr(nGenProcLimit);
- GenerateBitcoins(fGenerate, nGenProcLimit, Params());
+ CBitcoinAddress address(params[1].get_str());
+ if (!address.IsValid())
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Error: Invalid address");
+
+ boost::shared_ptr<CReserveScript> coinbaseScript(new CReserveScript());
+ coinbaseScript->reserveScript = GetScriptForDestination(address.Get());
- return NullUniValue;
+ return generateBlocks(coinbaseScript, nGenerate, nMaxTries, false);
}
UniValue getmininginfo(const UniValue& params, bool fHelp)
@@ -239,8 +226,6 @@ UniValue getmininginfo(const UniValue& params, bool fHelp)
" \"currentblocktx\": nnn, (numeric) The last block transaction\n"
" \"difficulty\": xxx.xxxxx (numeric) The current difficulty\n"
" \"errors\": \"...\" (string) Current errors\n"
- " \"generate\": true|false (boolean) If the generation is on or off (see getgenerate or setgenerate calls)\n"
- " \"genproclimit\": n (numeric) The processor limit for generation. -1 if no generation. (see getgenerate or setgenerate calls)\n"
" \"pooledtx\": n (numeric) The size of the mem pool\n"
" \"testnet\": true|false (boolean) If using testnet or not\n"
" \"chain\": \"xxxx\", (string) current network name as defined in BIP70 (main, test, regtest)\n"
@@ -259,12 +244,10 @@ UniValue getmininginfo(const UniValue& params, bool fHelp)
obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx));
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
obj.push_back(Pair("errors", GetWarnings("statusbar")));
- obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", DEFAULT_GENERATE_THREADS)));
obj.push_back(Pair("networkhashps", getnetworkhashps(params, false)));
obj.push_back(Pair("pooledtx", (uint64_t)mempool.size()));
obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));
obj.push_back(Pair("chain", Params().NetworkIDString()));
- obj.push_back(Pair("generate", getgenerate(params, false)));
return obj;
}
@@ -798,3 +781,27 @@ UniValue estimatesmartpriority(const UniValue& params, bool fHelp)
result.push_back(Pair("blocks", answerFound));
return result;
}
+
+static const CRPCCommand commands[] =
+{ // category name actor (function) okSafeMode
+ // --------------------- ------------------------ ----------------------- ----------
+ { "mining", "getnetworkhashps", &getnetworkhashps, true },
+ { "mining", "getmininginfo", &getmininginfo, true },
+ { "mining", "prioritisetransaction", &prioritisetransaction, true },
+ { "mining", "getblocktemplate", &getblocktemplate, true },
+ { "mining", "submitblock", &submitblock, true },
+
+ { "generating", "generate", &generate, true },
+ { "generating", "generatetoaddress", &generatetoaddress, true },
+
+ { "util", "estimatefee", &estimatefee, true },
+ { "util", "estimatepriority", &estimatepriority, true },
+ { "util", "estimatesmartfee", &estimatesmartfee, true },
+ { "util", "estimatesmartpriority", &estimatesmartpriority, true },
+};
+
+void RegisterMiningRPCCommands(CRPCTable &tableRPC)
+{
+ for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
+ tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
+}
diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index 0aab9c3043..e8a099b445 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -396,3 +396,21 @@ UniValue setmocktime(const UniValue& params, bool fHelp)
return NullUniValue;
}
+
+static const CRPCCommand commands[] =
+{ // category name actor (function) okSafeMode
+ // --------------------- ------------------------ ----------------------- ----------
+ { "control", "getinfo", &getinfo, true }, /* uses wallet if enabled */
+ { "util", "validateaddress", &validateaddress, true }, /* uses wallet if enabled */
+ { "util", "createmultisig", &createmultisig, true },
+ { "util", "verifymessage", &verifymessage, true },
+
+ /* Not shown in help */
+ { "hidden", "setmocktime", &setmocktime, true },
+};
+
+void RegisterMiscRPCCommands(CRPCTable &tableRPC)
+{
+ for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
+ tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
+}
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index 065214a98a..017cd6ca32 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -626,3 +626,25 @@ UniValue clearbanned(const UniValue& params, bool fHelp)
return NullUniValue;
}
+
+static const CRPCCommand commands[] =
+{ // category name actor (function) okSafeMode
+ // --------------------- ------------------------ ----------------------- ----------
+ { "network", "getconnectioncount", &getconnectioncount, true },
+ { "network", "ping", &ping, true },
+ { "network", "getpeerinfo", &getpeerinfo, true },
+ { "network", "addnode", &addnode, true },
+ { "network", "disconnectnode", &disconnectnode, true },
+ { "network", "getaddednodeinfo", &getaddednodeinfo, true },
+ { "network", "getnettotals", &getnettotals, true },
+ { "network", "getnetworkinfo", &getnetworkinfo, true },
+ { "network", "setban", &setban, true },
+ { "network", "listbanned", &listbanned, true },
+ { "network", "clearbanned", &clearbanned, true },
+};
+
+void RegisterNetRPCCommands(CRPCTable &tableRPC)
+{
+ for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
+ tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
+}
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index de89fdeb0f..de8cd68f66 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -303,7 +303,8 @@ UniValue verifytxoutproof(const UniValue& params, bool fHelp)
UniValue res(UniValue::VARR);
vector<uint256> vMatch;
- if (merkleBlock.txn.ExtractMatches(vMatch) != merkleBlock.header.hashMerkleRoot)
+ vector<unsigned int> vIndex;
+ if (merkleBlock.txn.ExtractMatches(vMatch, vIndex) != merkleBlock.header.hashMerkleRoot)
return res;
LOCK(cs_main);
@@ -818,11 +819,12 @@ UniValue sendrawtransaction(const UniValue& params, bool fHelp)
const CCoins* existingCoins = view.AccessCoins(hashTx);
bool fHaveMempool = mempool.exists(hashTx);
bool fHaveChain = existingCoins && existingCoins->nHeight < 1000000000;
+ CFeeRate txFeeRate = CFeeRate(0);
if (!fHaveMempool && !fHaveChain) {
// push to local node and sync with wallets
CValidationState state;
bool fMissingInputs;
- if (!AcceptToMemoryPool(mempool, state, tx, false, &fMissingInputs, false, nMaxRawTxFee)) {
+ if (!AcceptToMemoryPool(mempool, state, tx, false, &fMissingInputs, &txFeeRate, false, nMaxRawTxFee)) {
if (state.IsInvalid()) {
throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
} else {
@@ -835,7 +837,27 @@ UniValue sendrawtransaction(const UniValue& params, bool fHelp)
} else if (fHaveChain) {
throw JSONRPCError(RPC_TRANSACTION_ALREADY_IN_CHAIN, "transaction already in block chain");
}
- RelayTransaction(tx);
+ RelayTransaction(tx, txFeeRate);
return hashTx.GetHex();
}
+
+static const CRPCCommand commands[] =
+{ // category name actor (function) okSafeMode
+ // --------------------- ------------------------ ----------------------- ----------
+ { "rawtransactions", "getrawtransaction", &getrawtransaction, true },
+ { "rawtransactions", "createrawtransaction", &createrawtransaction, true },
+ { "rawtransactions", "decoderawtransaction", &decoderawtransaction, true },
+ { "rawtransactions", "decodescript", &decodescript, true },
+ { "rawtransactions", "sendrawtransaction", &sendrawtransaction, false },
+ { "rawtransactions", "signrawtransaction", &signrawtransaction, false }, /* uses wallet if enabled */
+
+ { "blockchain", "gettxoutproof", &gettxoutproof, true },
+ { "blockchain", "verifytxoutproof", &verifytxoutproof, true },
+};
+
+void RegisterRawTransactionRPCCommands(CRPCTable &tableRPC)
+{
+ for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
+ tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
+}
diff --git a/src/rpc/register.h b/src/rpc/register.h
new file mode 100644
index 0000000000..01aa58a25d
--- /dev/null
+++ b/src/rpc/register.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2009-2016 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_RPCREGISTER_H
+#define BITCOIN_RPCREGISTER_H
+
+/** These are in one header file to avoid creating tons of single-function
+ * headers for everything under src/rpc/ */
+class CRPCTable;
+
+/** Register block chain RPC commands */
+void RegisterBlockchainRPCCommands(CRPCTable &tableRPC);
+/** Register P2P networking RPC commands */
+void RegisterNetRPCCommands(CRPCTable &tableRPC);
+/** Register miscellaneous RPC commands */
+void RegisterMiscRPCCommands(CRPCTable &tableRPC);
+/** Register mining RPC commands */
+void RegisterMiningRPCCommands(CRPCTable &tableRPC);
+/** Register raw transaction RPC commands */
+void RegisterRawTransactionRPCCommands(CRPCTable &tableRPC);
+
+static inline void RegisterAllCoreRPCCommands(CRPCTable &tableRPC)
+{
+ RegisterBlockchainRPCCommands(tableRPC);
+ RegisterNetRPCCommands(tableRPC);
+ RegisterMiscRPCCommands(tableRPC);
+ RegisterMiningRPCCommands(tableRPC);
+ RegisterRawTransactionRPCCommands(tableRPC);
+}
+
+#endif
diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp
index b2d4559ccd..8326fe14d2 100644
--- a/src/rpc/server.cpp
+++ b/src/rpc/server.cpp
@@ -256,73 +256,8 @@ static const CRPCCommand vRPCCommands[] =
{ // category name actor (function) okSafeMode
// --------------------- ------------------------ ----------------------- ----------
/* Overall control/query calls */
- { "control", "getinfo", &getinfo, true }, /* uses wallet if enabled */
{ "control", "help", &help, true },
{ "control", "stop", &stop, true },
-
- /* P2P networking */
- { "network", "getnetworkinfo", &getnetworkinfo, true },
- { "network", "addnode", &addnode, true },
- { "network", "disconnectnode", &disconnectnode, true },
- { "network", "getaddednodeinfo", &getaddednodeinfo, true },
- { "network", "getconnectioncount", &getconnectioncount, true },
- { "network", "getnettotals", &getnettotals, true },
- { "network", "getpeerinfo", &getpeerinfo, true },
- { "network", "ping", &ping, true },
- { "network", "setban", &setban, true },
- { "network", "listbanned", &listbanned, true },
- { "network", "clearbanned", &clearbanned, true },
-
- /* Block chain and UTXO */
- { "blockchain", "getblockchaininfo", &getblockchaininfo, true },
- { "blockchain", "getbestblockhash", &getbestblockhash, true },
- { "blockchain", "getblockcount", &getblockcount, true },
- { "blockchain", "getblock", &getblock, true },
- { "blockchain", "getblockhash", &getblockhash, true },
- { "blockchain", "getblockheader", &getblockheader, true },
- { "blockchain", "getchaintips", &getchaintips, true },
- { "blockchain", "getdifficulty", &getdifficulty, true },
- { "blockchain", "getmempoolinfo", &getmempoolinfo, true },
- { "blockchain", "getrawmempool", &getrawmempool, true },
- { "blockchain", "gettxout", &gettxout, true },
- { "blockchain", "gettxoutproof", &gettxoutproof, true },
- { "blockchain", "verifytxoutproof", &verifytxoutproof, true },
- { "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true },
- { "blockchain", "verifychain", &verifychain, true },
-
- /* Mining */
- { "mining", "getblocktemplate", &getblocktemplate, true },
- { "mining", "getmininginfo", &getmininginfo, true },
- { "mining", "getnetworkhashps", &getnetworkhashps, true },
- { "mining", "prioritisetransaction", &prioritisetransaction, true },
- { "mining", "submitblock", &submitblock, true },
-
- /* Coin generation */
- { "generating", "getgenerate", &getgenerate, true },
- { "generating", "setgenerate", &setgenerate, true },
- { "generating", "generate", &generate, true },
-
- /* Raw transactions */
- { "rawtransactions", "createrawtransaction", &createrawtransaction, true },
- { "rawtransactions", "decoderawtransaction", &decoderawtransaction, true },
- { "rawtransactions", "decodescript", &decodescript, true },
- { "rawtransactions", "getrawtransaction", &getrawtransaction, true },
- { "rawtransactions", "sendrawtransaction", &sendrawtransaction, false },
- { "rawtransactions", "signrawtransaction", &signrawtransaction, false }, /* uses wallet if enabled */
-
- /* Utility functions */
- { "util", "createmultisig", &createmultisig, true },
- { "util", "validateaddress", &validateaddress, true }, /* uses wallet if enabled */
- { "util", "verifymessage", &verifymessage, true },
- { "util", "estimatefee", &estimatefee, true },
- { "util", "estimatepriority", &estimatepriority, true },
- { "util", "estimatesmartfee", &estimatesmartfee, true },
- { "util", "estimatesmartpriority", &estimatesmartpriority, true },
-
- /* Not shown in help */
- { "hidden", "invalidateblock", &invalidateblock, true },
- { "hidden", "reconsiderblock", &reconsiderblock, true },
- { "hidden", "setmocktime", &setmocktime, true },
};
CRPCTable::CRPCTable()
@@ -499,6 +434,17 @@ UniValue CRPCTable::execute(const std::string &strMethod, const UniValue &params
g_rpcSignals.PostCommand(*pcmd);
}
+std::vector<std::string> CRPCTable::listCommands() const
+{
+ std::vector<std::string> commandList;
+ typedef std::map<std::string, const CRPCCommand*> commandMap;
+
+ std::transform( mapCommands.begin(), mapCommands.end(),
+ std::back_inserter(commandList),
+ boost::bind(&commandMap::value_type::first,_1) );
+ return commandList;
+}
+
std::string HelpExampleCli(const std::string& methodname, const std::string& args)
{
return "> bitcoin-cli " + methodname + " " + args + "\n";
diff --git a/src/rpc/server.h b/src/rpc/server.h
index 99ffad5d40..a7ed710ce6 100644
--- a/src/rpc/server.h
+++ b/src/rpc/server.h
@@ -145,6 +145,12 @@ public:
*/
UniValue execute(const std::string &method, const UniValue &params) const;
+ /**
+ * Returns a list of registered commands
+ * @returns List of registered commands.
+ */
+ std::vector<std::string> listCommands() const;
+
/**
* Appends a CRPCCommand to the dispatch table.
@@ -175,66 +181,6 @@ extern std::string HelpExampleRpc(const std::string& methodname, const std::stri
extern void EnsureWalletIsUnlocked();
-extern UniValue getconnectioncount(const UniValue& params, bool fHelp); // in rpc/net.cpp
-extern UniValue getpeerinfo(const UniValue& params, bool fHelp);
-extern UniValue ping(const UniValue& params, bool fHelp);
-extern UniValue addnode(const UniValue& params, bool fHelp);
-extern UniValue disconnectnode(const UniValue& params, bool fHelp);
-extern UniValue getaddednodeinfo(const UniValue& params, bool fHelp);
-extern UniValue getnettotals(const UniValue& params, bool fHelp);
-extern UniValue setban(const UniValue& params, bool fHelp);
-extern UniValue listbanned(const UniValue& params, bool fHelp);
-extern UniValue clearbanned(const UniValue& params, bool fHelp);
-
-extern UniValue getgenerate(const UniValue& params, bool fHelp); // in rpc/mining.cpp
-extern UniValue setgenerate(const UniValue& params, bool fHelp);
-extern UniValue generate(const UniValue& params, bool fHelp);
-extern UniValue getnetworkhashps(const UniValue& params, bool fHelp);
-extern UniValue getmininginfo(const UniValue& params, bool fHelp);
-extern UniValue prioritisetransaction(const UniValue& params, bool fHelp);
-extern UniValue getblocktemplate(const UniValue& params, bool fHelp);
-extern UniValue submitblock(const UniValue& params, bool fHelp);
-extern UniValue estimatefee(const UniValue& params, bool fHelp);
-extern UniValue estimatepriority(const UniValue& params, bool fHelp);
-extern UniValue estimatesmartfee(const UniValue& params, bool fHelp);
-extern UniValue estimatesmartpriority(const UniValue& params, bool fHelp);
-
-extern UniValue verifymessage(const UniValue& params, bool fHelp);
-extern UniValue createmultisig(const UniValue& params, bool fHelp);
-extern UniValue validateaddress(const UniValue& params, bool fHelp);
-extern UniValue getinfo(const UniValue& params, bool fHelp);
-extern UniValue getblockchaininfo(const UniValue& params, bool fHelp);
-extern UniValue getnetworkinfo(const UniValue& params, bool fHelp);
-extern UniValue setmocktime(const UniValue& params, bool fHelp);
-
-extern UniValue getrawtransaction(const UniValue& params, bool fHelp); // in rpc/rawtransaction.cpp
-extern UniValue listunspent(const UniValue& params, bool fHelp);
-extern UniValue lockunspent(const UniValue& params, bool fHelp);
-extern UniValue listlockunspent(const UniValue& params, bool fHelp);
-extern UniValue createrawtransaction(const UniValue& params, bool fHelp);
-extern UniValue decoderawtransaction(const UniValue& params, bool fHelp);
-extern UniValue decodescript(const UniValue& params, bool fHelp);
-extern UniValue signrawtransaction(const UniValue& params, bool fHelp);
-extern UniValue sendrawtransaction(const UniValue& params, bool fHelp);
-extern UniValue gettxoutproof(const UniValue& params, bool fHelp);
-extern UniValue verifytxoutproof(const UniValue& params, bool fHelp);
-
-extern UniValue getblockcount(const UniValue& params, bool fHelp); // in rpc/blockchain.cpp
-extern UniValue getbestblockhash(const UniValue& params, bool fHelp);
-extern UniValue getdifficulty(const UniValue& params, bool fHelp);
-extern UniValue settxfee(const UniValue& params, bool fHelp);
-extern UniValue getmempoolinfo(const UniValue& params, bool fHelp);
-extern UniValue getrawmempool(const UniValue& params, bool fHelp);
-extern UniValue getblockhash(const UniValue& params, bool fHelp);
-extern UniValue getblockheader(const UniValue& params, bool fHelp);
-extern UniValue getblock(const UniValue& params, bool fHelp);
-extern UniValue gettxoutsetinfo(const UniValue& params, bool fHelp);
-extern UniValue gettxout(const UniValue& params, bool fHelp);
-extern UniValue verifychain(const UniValue& params, bool fHelp);
-extern UniValue getchaintips(const UniValue& params, bool fHelp);
-extern UniValue invalidateblock(const UniValue& params, bool fHelp);
-extern UniValue reconsiderblock(const UniValue& params, bool fHelp);
-
bool StartRPC();
void InterruptRPC();
void StopRPC();
diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
index a928223268..149a4f0156 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -165,7 +165,10 @@ bool static IsLowDERSignature(const valtype &vchSig, ScriptError* serror) {
return set_error(serror, SCRIPT_ERR_SIG_DER);
}
std::vector<unsigned char> vchSigCopy(vchSig.begin(), vchSig.begin() + vchSig.size() - 1);
- return CPubKey::CheckLowS(vchSigCopy);
+ if (!CPubKey::CheckLowS(vchSigCopy)) {
+ return set_error(serror, SCRIPT_ERR_SIG_HIGH_S);
+ }
+ return true;
}
bool static IsDefinedHashtypeSignature(const valtype &vchSig) {
@@ -370,7 +373,44 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
break;
}
- case OP_NOP1: case OP_NOP3: case OP_NOP4: case OP_NOP5:
+ case OP_CHECKSEQUENCEVERIFY:
+ {
+ if (!(flags & SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)) {
+ // not enabled; treat as a NOP3
+ if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
+ return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
+ }
+ break;
+ }
+
+ if (stack.size() < 1)
+ return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
+
+ // nSequence, like nLockTime, is a 32-bit unsigned integer
+ // field. See the comment in CHECKLOCKTIMEVERIFY regarding
+ // 5-byte numeric operands.
+ const CScriptNum nSequence(stacktop(-1), fRequireMinimal, 5);
+
+ // In the rare event that the argument may be < 0 due to
+ // some arithmetic being done first, you can always use
+ // 0 MAX CHECKSEQUENCEVERIFY.
+ if (nSequence < 0)
+ return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME);
+
+ // To provide for future soft-fork extensibility, if the
+ // operand has the disabled lock-time flag set,
+ // CHECKSEQUENCEVERIFY behaves as a NOP.
+ if ((nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0)
+ break;
+
+ // Compare the specified sequence number with the input.
+ if (!checker.CheckSequence(nSequence))
+ return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME);
+
+ break;
+ }
+
+ case OP_NOP1: case OP_NOP4: case OP_NOP5:
case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10:
{
if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
@@ -1147,12 +1187,57 @@ bool TransactionSignatureChecker::CheckLockTime(const CScriptNum& nLockTime) con
// prevent this condition. Alternatively we could test all
// inputs, but testing just this input minimizes the data
// required to prove correct CHECKLOCKTIMEVERIFY execution.
- if (txTo->vin[nIn].IsFinal())
+ if (CTxIn::SEQUENCE_FINAL == txTo->vin[nIn].nSequence)
return false;
return true;
}
+bool TransactionSignatureChecker::CheckSequence(const CScriptNum& nSequence) const
+{
+ // Relative lock times are supported by comparing the passed
+ // in operand to the sequence number of the input.
+ const int64_t txToSequence = (int64_t)txTo->vin[nIn].nSequence;
+
+ // Fail if the transaction's version number is not set high
+ // enough to trigger BIP 68 rules.
+ if (static_cast<uint32_t>(txTo->nVersion) < 2)
+ return false;
+
+ // Sequence numbers with their most significant bit set are not
+ // consensus constrained. Testing that the transaction's sequence
+ // number do not have this bit set prevents using this property
+ // to get around a CHECKSEQUENCEVERIFY check.
+ if (txToSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG)
+ return false;
+
+ // Mask off any bits that do not have consensus-enforced meaning
+ // before doing the integer comparisons
+ const uint32_t nLockTimeMask = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | CTxIn::SEQUENCE_LOCKTIME_MASK;
+ const int64_t txToSequenceMasked = txToSequence & nLockTimeMask;
+ const CScriptNum nSequenceMasked = nSequence & nLockTimeMask;
+
+ // There are two kinds of nSequence: lock-by-blockheight
+ // and lock-by-blocktime, distinguished by whether
+ // nSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG.
+ //
+ // We want to compare apples to apples, so fail the script
+ // unless the type of nSequenceMasked being tested is the same as
+ // the nSequenceMasked in the transaction.
+ if (!(
+ (txToSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) ||
+ (txToSequenceMasked >= CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked >= CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG)
+ )) {
+ return false;
+ }
+
+ // Now that we know we're comparing apples-to-apples, the
+ // comparison is a simple numeric one.
+ if (nSequenceMasked > txToSequenceMasked)
+ return false;
+
+ return true;
+}
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
{
diff --git a/src/script/interpreter.h b/src/script/interpreter.h
index 7b34547ffb..e5cb7290f2 100644
--- a/src/script/interpreter.h
+++ b/src/script/interpreter.h
@@ -81,6 +81,11 @@ enum
//
// See BIP65 for details.
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9),
+
+ // support CHECKSEQUENCEVERIFY opcode
+ //
+ // See BIP112 for details
+ SCRIPT_VERIFY_CHECKSEQUENCEVERIFY = (1U << 10),
};
bool CheckSignatureEncoding(const std::vector<unsigned char> &vchSig, unsigned int flags, ScriptError* serror);
@@ -100,6 +105,11 @@ public:
return false;
}
+ virtual bool CheckSequence(const CScriptNum& nSequence) const
+ {
+ return false;
+ }
+
virtual ~BaseSignatureChecker() {}
};
@@ -116,6 +126,7 @@ public:
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn) : txTo(txToIn), nIn(nInIn) {}
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode) const;
bool CheckLockTime(const CScriptNum& nLockTime) const;
+ bool CheckSequence(const CScriptNum& nSequence) const;
};
class MutableTransactionSignatureChecker : public TransactionSignatureChecker
diff --git a/src/script/script.h b/src/script/script.h
index 6551eea30d..d2a68a07ba 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -165,6 +165,7 @@ enum opcodetype
OP_CHECKLOCKTIMEVERIFY = 0xb1,
OP_NOP2 = OP_CHECKLOCKTIMEVERIFY,
OP_NOP3 = 0xb2,
+ OP_CHECKSEQUENCEVERIFY = OP_NOP3,
OP_NOP4 = 0xb3,
OP_NOP5 = 0xb4,
OP_NOP6 = 0xb5,
@@ -259,6 +260,11 @@ public:
inline CScriptNum& operator+=( const CScriptNum& rhs) { return operator+=(rhs.m_value); }
inline CScriptNum& operator-=( const CScriptNum& rhs) { return operator-=(rhs.m_value); }
+ inline CScriptNum operator&( const int64_t& rhs) const { return CScriptNum(m_value & rhs);}
+ inline CScriptNum operator&( const CScriptNum& rhs) const { return operator&(rhs.m_value); }
+
+ inline CScriptNum& operator&=( const CScriptNum& rhs) { return operator&=(rhs.m_value); }
+
inline CScriptNum operator-() const
{
assert(m_value != std::numeric_limits<int64_t>::min());
@@ -287,6 +293,12 @@ public:
return *this;
}
+ inline CScriptNum& operator&=( const int64_t& rhs)
+ {
+ m_value &= rhs;
+ return *this;
+ }
+
int getint() const
{
if (m_value > std::numeric_limits<int>::max())
diff --git a/src/script/script_error.h b/src/script/script_error.h
index bb10b8a293..26df33932f 100644
--- a/src/script/script_error.h
+++ b/src/script/script_error.h
@@ -35,7 +35,7 @@ typedef enum ScriptError_t
SCRIPT_ERR_INVALID_ALTSTACK_OPERATION,
SCRIPT_ERR_UNBALANCED_CONDITIONAL,
- /* OP_CHECKLOCKTIMEVERIFY */
+ /* CHECKLOCKTIMEVERIFY and CHECKSEQUENCEVERIFY */
SCRIPT_ERR_NEGATIVE_LOCKTIME,
SCRIPT_ERR_UNSATISFIED_LOCKTIME,
diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp
index 0895ef3326..70f1f12273 100644
--- a/src/test/alert_tests.cpp
+++ b/src/test/alert_tests.cpp
@@ -4,193 +4,16 @@
// Unit tests for alert system
-#include "alert.h"
-#include "chain.h"
#include "chainparams.h"
-#include "clientversion.h"
-#include "data/alertTests.raw.h"
#include "main.h" // For PartitionCheck
-#include "serialize.h"
-#include "streams.h"
-#include "util.h"
-#include "utilstrencodings.h"
+#include "test/testutil.h"
#include "test/test_bitcoin.h"
-#include <fstream>
-
-#include <boost/filesystem/operations.hpp>
-#include <boost/foreach.hpp>
#include <boost/test/unit_test.hpp>
-#if 0
-//
-// alertTests contains 7 alerts, generated with this code:
-// (SignAndSave code not shown, alert signing key is secret)
-//
-{
- CAlert alert;
- alert.nRelayUntil = 60;
- alert.nExpiration = 24 * 60 * 60;
- alert.nID = 1;
- alert.nCancel = 0; // cancels previous messages up to this ID number
- alert.nMinVer = 0; // These versions are protocol versions
- alert.nMaxVer = 999001;
- alert.nPriority = 1;
- alert.strComment = "Alert comment";
- alert.strStatusBar = "Alert 1";
-
- SignAndSave(alert, "test/alertTests");
-
- alert.setSubVer.insert(std::string("/Satoshi:0.1.0/"));
- alert.strStatusBar = "Alert 1 for Satoshi 0.1.0";
- SignAndSave(alert, "test/alertTests");
-
- alert.setSubVer.insert(std::string("/Satoshi:0.2.0/"));
- alert.strStatusBar = "Alert 1 for Satoshi 0.1.0, 0.2.0";
- SignAndSave(alert, "test/alertTests");
-
- alert.setSubVer.clear();
- ++alert.nID;
- alert.nCancel = 1;
- alert.nPriority = 100;
- alert.strStatusBar = "Alert 2, cancels 1";
- SignAndSave(alert, "test/alertTests");
-
- alert.nExpiration += 60;
- ++alert.nID;
- SignAndSave(alert, "test/alertTests");
-
- ++alert.nID;
- alert.nMinVer = 11;
- alert.nMaxVer = 22;
- SignAndSave(alert, "test/alertTests");
-
- ++alert.nID;
- alert.strStatusBar = "Alert 2 for Satoshi 0.1.0";
- alert.setSubVer.insert(std::string("/Satoshi:0.1.0/"));
- SignAndSave(alert, "test/alertTests");
-
- ++alert.nID;
- alert.nMinVer = 0;
- alert.nMaxVer = 999999;
- alert.strStatusBar = "Evil Alert'; /bin/ls; echo '";
- alert.setSubVer.clear();
- SignAndSave(alert, "test/alertTests");
-}
-#endif
-
-struct ReadAlerts : public TestingSetup
-{
- ReadAlerts()
- {
- std::vector<unsigned char> vch(alert_tests::alertTests, alert_tests::alertTests + sizeof(alert_tests::alertTests));
- CDataStream stream(vch, SER_DISK, CLIENT_VERSION);
- try {
- while (!stream.eof())
- {
- CAlert alert;
- stream >> alert;
- alerts.push_back(alert);
- }
- }
- catch (const std::exception&) { }
- }
- ~ReadAlerts() { }
-
- static std::vector<std::string> read_lines(boost::filesystem::path filepath)
- {
- std::vector<std::string> result;
-
- std::ifstream f(filepath.string().c_str());
- std::string line;
- while (std::getline(f,line))
- result.push_back(line);
-
- return result;
- }
-
- std::vector<CAlert> alerts;
-};
-
-BOOST_FIXTURE_TEST_SUITE(Alert_tests, ReadAlerts)
-
-
-BOOST_AUTO_TEST_CASE(AlertApplies)
-{
- SetMockTime(11);
- const std::vector<unsigned char>& alertKey = Params(CBaseChainParams::MAIN).AlertKey();
+BOOST_FIXTURE_TEST_SUITE(Alert_tests, TestingSetup)
- BOOST_FOREACH(const CAlert& alert, alerts)
- {
- BOOST_CHECK(alert.CheckSignature(alertKey));
- }
-
- BOOST_CHECK(alerts.size() >= 3);
-
- // Matches:
- BOOST_CHECK(alerts[0].AppliesTo(1, ""));
- BOOST_CHECK(alerts[0].AppliesTo(999001, ""));
- BOOST_CHECK(alerts[0].AppliesTo(1, "/Satoshi:11.11.11/"));
-
- BOOST_CHECK(alerts[1].AppliesTo(1, "/Satoshi:0.1.0/"));
- BOOST_CHECK(alerts[1].AppliesTo(999001, "/Satoshi:0.1.0/"));
-
- BOOST_CHECK(alerts[2].AppliesTo(1, "/Satoshi:0.1.0/"));
- BOOST_CHECK(alerts[2].AppliesTo(1, "/Satoshi:0.2.0/"));
-
- // Don't match:
- BOOST_CHECK(!alerts[0].AppliesTo(-1, ""));
- BOOST_CHECK(!alerts[0].AppliesTo(999002, ""));
-
- BOOST_CHECK(!alerts[1].AppliesTo(1, ""));
- BOOST_CHECK(!alerts[1].AppliesTo(1, "Satoshi:0.1.0"));
- BOOST_CHECK(!alerts[1].AppliesTo(1, "/Satoshi:0.1.0"));
- BOOST_CHECK(!alerts[1].AppliesTo(1, "Satoshi:0.1.0/"));
- BOOST_CHECK(!alerts[1].AppliesTo(-1, "/Satoshi:0.1.0/"));
- BOOST_CHECK(!alerts[1].AppliesTo(999002, "/Satoshi:0.1.0/"));
- BOOST_CHECK(!alerts[1].AppliesTo(1, "/Satoshi:0.2.0/"));
-
- BOOST_CHECK(!alerts[2].AppliesTo(1, "/Satoshi:0.3.0/"));
-
- SetMockTime(0);
-}
-
-
-BOOST_AUTO_TEST_CASE(AlertNotify)
-{
- SetMockTime(11);
- const std::vector<unsigned char>& alertKey = Params(CBaseChainParams::MAIN).AlertKey();
-
- boost::filesystem::path temp = GetTempPath() /
- boost::filesystem::unique_path("alertnotify-%%%%.txt");
-
- mapArgs["-alertnotify"] = std::string("echo %s >> ") + temp.string();
-
- BOOST_FOREACH(CAlert alert, alerts)
- alert.ProcessAlert(alertKey, false);
-
- std::vector<std::string> r = read_lines(temp);
- BOOST_CHECK_EQUAL(r.size(), 4u);
-
-// Windows built-in echo semantics are different than posixy shells. Quotes and
-// whitespace are printed literally.
-
-#ifndef WIN32
- BOOST_CHECK_EQUAL(r[0], "Alert 1");
- BOOST_CHECK_EQUAL(r[1], "Alert 2, cancels 1");
- BOOST_CHECK_EQUAL(r[2], "Alert 2, cancels 1");
- BOOST_CHECK_EQUAL(r[3], "Evil Alert; /bin/ls; echo "); // single-quotes should be removed
-#else
- BOOST_CHECK_EQUAL(r[0], "'Alert 1' ");
- BOOST_CHECK_EQUAL(r[1], "'Alert 2, cancels 1' ");
- BOOST_CHECK_EQUAL(r[2], "'Alert 2, cancels 1' ");
- BOOST_CHECK_EQUAL(r[3], "'Evil Alert; /bin/ls; echo ' ");
-#endif
- boost::filesystem::remove(temp);
-
- SetMockTime(0);
-}
static bool falseFunc() { return false; }
@@ -253,4 +76,4 @@ BOOST_AUTO_TEST_CASE(PartitionAlert)
SetMockTime(0);
}
-BOOST_AUTO_TEST_SUITE_END()
+BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file
diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp
new file mode 100644
index 0000000000..59dab20633
--- /dev/null
+++ b/src/test/amount_tests.cpp
@@ -0,0 +1,42 @@
+// Copyright (c) 2016 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "amount.h"
+#include "test/test_bitcoin.h"
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(amount_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(GetFeeTest)
+{
+ CFeeRate feeRate;
+
+ feeRate = CFeeRate(0);
+ // Must always return 0
+ BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(1e5), 0);
+
+ feeRate = CFeeRate(1000);
+ // Must always just return the arg
+ BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(1), 1);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(121), 121);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(999), 999);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), 1e3);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), 9e3);
+
+ feeRate = CFeeRate(123);
+ // Truncates the result, if not integer
+ BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(8), 1); // Special case: returns 1 instead of 0
+ BOOST_CHECK_EQUAL(feeRate.GetFee(9), 1);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(121), 14);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(122), 15);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(999), 122);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), 123);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), 1107);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/bctest.py b/src/test/bctest.py
index 3a8d0ea51b..8105b87ffa 100644
--- a/src/test/bctest.py
+++ b/src/test/bctest.py
@@ -1,7 +1,7 @@
# Copyright 2014 BitPay, Inc.
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
+from __future__ import division,print_function,unicode_literals
import subprocess
import os
import json
diff --git a/src/test/bitcoin-util-test.py b/src/test/bitcoin-util-test.py
index 20afb16a9e..95dd3e81b4 100755
--- a/src/test/bitcoin-util-test.py
+++ b/src/test/bitcoin-util-test.py
@@ -2,7 +2,7 @@
# Copyright 2014 BitPay, Inc.
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
+from __future__ import division,print_function,unicode_literals
import os
import bctest
import buildenv
diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp
index 98f9de7673..9557000ddc 100644
--- a/src/test/bloom_tests.cpp
+++ b/src/test/bloom_tests.cpp
@@ -204,7 +204,8 @@ BOOST_AUTO_TEST_CASE(merkle_block_1)
BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 8);
vector<uint256> vMatched;
- BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot);
+ vector<unsigned int> vIndex;
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot);
BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
for (unsigned int i = 0; i < vMatched.size(); i++)
BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
@@ -221,7 +222,7 @@ BOOST_AUTO_TEST_CASE(merkle_block_1)
BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256S("0xdd1fd2a6fc16404faf339881a90adbde7f4f728691ac62e8f168809cdfae1053"));
BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 7);
- BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot);
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot);
BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
for (unsigned int i = 0; i < vMatched.size(); i++)
BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
@@ -249,7 +250,8 @@ BOOST_AUTO_TEST_CASE(merkle_block_2)
BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 0);
vector<uint256> vMatched;
- BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot);
+ vector<unsigned int> vIndex;
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot);
BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
for (unsigned int i = 0; i < vMatched.size(); i++)
BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
@@ -275,7 +277,7 @@ BOOST_AUTO_TEST_CASE(merkle_block_2)
BOOST_CHECK(merkleBlock.vMatchedTxn[3].second == uint256S("0x3c1d7e82342158e4109df2e0b6348b6e84e403d8b4046d7007663ace63cddb23"));
BOOST_CHECK(merkleBlock.vMatchedTxn[3].first == 3);
- BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot);
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot);
BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
for (unsigned int i = 0; i < vMatched.size(); i++)
BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
@@ -303,7 +305,8 @@ BOOST_AUTO_TEST_CASE(merkle_block_2_with_update_none)
BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 0);
vector<uint256> vMatched;
- BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot);
+ vector<unsigned int> vIndex;
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot);
BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
for (unsigned int i = 0; i < vMatched.size(); i++)
BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
@@ -326,7 +329,7 @@ BOOST_AUTO_TEST_CASE(merkle_block_2_with_update_none)
BOOST_CHECK(merkleBlock.vMatchedTxn[2].second == uint256S("0x3c1d7e82342158e4109df2e0b6348b6e84e403d8b4046d7007663ace63cddb23"));
BOOST_CHECK(merkleBlock.vMatchedTxn[2].first == 3);
- BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot);
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot);
BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
for (unsigned int i = 0; i < vMatched.size(); i++)
BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
@@ -353,7 +356,8 @@ BOOST_AUTO_TEST_CASE(merkle_block_3_and_serialize)
BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 0);
vector<uint256> vMatched;
- BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot);
+ vector<unsigned int> vIndex;
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot);
BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
for (unsigned int i = 0; i < vMatched.size(); i++)
BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
@@ -392,7 +396,8 @@ BOOST_AUTO_TEST_CASE(merkle_block_4)
BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 6);
vector<uint256> vMatched;
- BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot);
+ vector<unsigned int> vIndex;
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot);
BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
for (unsigned int i = 0; i < vMatched.size(); i++)
BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
@@ -409,7 +414,7 @@ BOOST_AUTO_TEST_CASE(merkle_block_4)
BOOST_CHECK(merkleBlock.vMatchedTxn[1] == pair);
- BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched) == block.hashMerkleRoot);
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot);
BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
for (unsigned int i = 0; i < vMatched.size(); i++)
BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
diff --git a/src/test/checkblock_tests.cpp b/src/test/checkblock_tests.cpp
deleted file mode 100644
index c945a95adc..0000000000
--- a/src/test/checkblock_tests.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2013-2015 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#include "clientversion.h"
-#include "consensus/validation.h"
-#include "main.h" // For CheckBlock
-#include "primitives/block.h"
-#include "test/test_bitcoin.h"
-#include "utiltime.h"
-
-#include <cstdio>
-
-#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/path.hpp>
-#include <boost/test/unit_test.hpp>
-
-
-BOOST_FIXTURE_TEST_SUITE(CheckBlock_tests, BasicTestingSetup)
-
-bool read_block(const std::string& filename, CBlock& block)
-{
- namespace fs = boost::filesystem;
- fs::path testFile = fs::current_path() / "data" / filename;
-#ifdef TEST_DATA_DIR
- if (!fs::exists(testFile))
- {
- testFile = fs::path(BOOST_PP_STRINGIZE(TEST_DATA_DIR)) / filename;
- }
-#endif
- FILE* fp = fopen(testFile.string().c_str(), "rb");
- if (!fp) return false;
-
- fseek(fp, 8, SEEK_SET); // skip msgheader/size
-
- CAutoFile filein(fp, SER_DISK, CLIENT_VERSION);
- if (filein.IsNull()) return false;
-
- filein >> block;
-
- return true;
-}
-
-BOOST_AUTO_TEST_CASE(May15)
-{
- // Putting a 1MB binary file in the git repository is not a great
- // idea, so this test is only run if you manually download
- // test/data/Mar12Fork.dat from
- // http://sourceforge.net/projects/bitcoin/files/Bitcoin/blockchain/Mar12Fork.dat/download
- unsigned int tMay15 = 1368576000;
- SetMockTime(tMay15); // Test as if it was right at May 15
-
- CBlock forkingBlock;
- if (read_block("Mar12Fork.dat", forkingBlock))
- {
- CValidationState state;
-
- // After May 15'th, big blocks are OK:
- forkingBlock.nTime = tMay15; // Invalidates PoW
- BOOST_CHECK(CheckBlock(forkingBlock, state, false, false));
- }
-
- SetMockTime(0);
-}
-
-BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/data/alertTests.raw b/src/test/data/alertTests.raw
deleted file mode 100644
index 01f50680b9..0000000000
--- a/src/test/data/alertTests.raw
+++ /dev/null
Binary files differ
diff --git a/src/test/data/script_invalid.json b/src/test/data/script_invalid.json
index 7ce7e0879c..9e91132984 100644
--- a/src/test/data/script_invalid.json
+++ b/src/test/data/script_invalid.json
@@ -6,504 +6,519 @@
["correct prevout hash), using the given scriptSig. All nLockTimes are 0, all"],
["nSequences are max."],
-["", "DEPTH", "P2SH,STRICTENC", "Test the test: we should have an empty stack after scriptSig evaluation"],
-[" ", "DEPTH", "P2SH,STRICTENC", "and multiple spaces should not change that."],
-[" ", "DEPTH", "P2SH,STRICTENC"],
-[" ", "DEPTH", "P2SH,STRICTENC"],
-
-["", "", "P2SH,STRICTENC"],
-["", "NOP", "P2SH,STRICTENC"],
-["", "NOP DEPTH", "P2SH,STRICTENC"],
-["NOP", "", "P2SH,STRICTENC"],
-["NOP", "DEPTH", "P2SH,STRICTENC"],
-["NOP","NOP", "P2SH,STRICTENC"],
-["NOP","NOP DEPTH", "P2SH,STRICTENC"],
-
-["DEPTH", "", "P2SH,STRICTENC"],
-
-["0x4c01","0x01 NOP", "P2SH,STRICTENC", "PUSHDATA1 with not enough bytes"],
-["0x4d0200ff","0x01 NOP", "P2SH,STRICTENC", "PUSHDATA2 with not enough bytes"],
-["0x4e03000000ffff","0x01 NOP", "P2SH,STRICTENC", "PUSHDATA4 with not enough bytes"],
-
-["1", "IF 0x50 ENDIF 1", "P2SH,STRICTENC", "0x50 is reserved"],
-["0x52", "0x5f ADD 0x60 EQUAL", "P2SH,STRICTENC", "0x51 through 0x60 push 1 through 16 onto stack"],
-["0","NOP", "P2SH,STRICTENC"],
-["1", "IF VER ELSE 1 ENDIF", "P2SH,STRICTENC", "VER non-functional"],
-["0", "IF VERIF ELSE 1 ENDIF", "P2SH,STRICTENC", "VERIF illegal everywhere"],
-["0", "IF ELSE 1 ELSE VERIF ENDIF", "P2SH,STRICTENC", "VERIF illegal everywhere"],
-["0", "IF VERNOTIF ELSE 1 ENDIF", "P2SH,STRICTENC", "VERNOTIF illegal everywhere"],
-["0", "IF ELSE 1 ELSE VERNOTIF ENDIF", "P2SH,STRICTENC", "VERNOTIF illegal everywhere"],
-
-["1 IF", "1 ENDIF", "P2SH,STRICTENC", "IF/ENDIF can't span scriptSig/scriptPubKey"],
-["1 IF 0 ENDIF", "1 ENDIF", "P2SH,STRICTENC"],
-["1 ELSE 0 ENDIF", "1", "P2SH,STRICTENC"],
-["0 NOTIF", "123", "P2SH,STRICTENC"],
-
-["0", "DUP IF ENDIF", "P2SH,STRICTENC"],
-["0", "IF 1 ENDIF", "P2SH,STRICTENC"],
-["0", "DUP IF ELSE ENDIF", "P2SH,STRICTENC"],
-["0", "IF 1 ELSE ENDIF", "P2SH,STRICTENC"],
-["0", "NOTIF ELSE 1 ENDIF", "P2SH,STRICTENC"],
-
-["0 1", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"],
-["0 0", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"],
-["1 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"],
-["0 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"],
-
-["0 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"],
-["0 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"],
-["1 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"],
-["0 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"],
-
-["1", "IF RETURN ELSE ELSE 1 ENDIF", "P2SH,STRICTENC", "Multiple ELSEs"],
-["1", "IF 1 ELSE ELSE RETURN ENDIF", "P2SH,STRICTENC"],
-
-["1", "ENDIF", "P2SH,STRICTENC", "Malformed IF/ELSE/ENDIF sequence"],
-["1", "ELSE ENDIF", "P2SH,STRICTENC"],
-["1", "ENDIF ELSE", "P2SH,STRICTENC"],
-["1", "ENDIF ELSE IF", "P2SH,STRICTENC"],
-["1", "IF ELSE ENDIF ELSE", "P2SH,STRICTENC"],
-["1", "IF ELSE ENDIF ELSE ENDIF", "P2SH,STRICTENC"],
-["1", "IF ENDIF ENDIF", "P2SH,STRICTENC"],
-["1", "IF ELSE ELSE ENDIF ENDIF", "P2SH,STRICTENC"],
-
-["1", "RETURN", "P2SH,STRICTENC"],
-["1", "DUP IF RETURN ENDIF", "P2SH,STRICTENC"],
-
-["1", "RETURN 'data'", "P2SH,STRICTENC", "canonical prunable txout format"],
-["0 IF", "RETURN ENDIF 1", "P2SH,STRICTENC", "still prunable because IF/ENDIF can't span scriptSig/scriptPubKey"],
-
-["0", "VERIFY 1", "P2SH,STRICTENC"],
-["1", "VERIFY", "P2SH,STRICTENC"],
-["1", "VERIFY 0", "P2SH,STRICTENC"],
-
-["1 TOALTSTACK", "FROMALTSTACK 1", "P2SH,STRICTENC", "alt stack not shared between sig/pubkey"],
-
-["IFDUP", "DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["DROP", "DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["DUP", "DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["1", "DUP 1 ADD 2 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC"],
-["NOP", "NIP", "P2SH,STRICTENC"],
-["NOP", "1 NIP", "P2SH,STRICTENC"],
-["NOP", "1 0 NIP", "P2SH,STRICTENC"],
-["NOP", "OVER 1", "P2SH,STRICTENC"],
-["1", "OVER", "P2SH,STRICTENC"],
-["0 1", "OVER DEPTH 3 EQUALVERIFY", "P2SH,STRICTENC"],
-["19 20 21", "PICK 19 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"],
-["NOP", "0 PICK", "P2SH,STRICTENC"],
-["1", "-1 PICK", "P2SH,STRICTENC"],
-["19 20 21", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC"],
-["19 20 21", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC"],
-["19 20 21", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC"],
-["NOP", "0 ROLL", "P2SH,STRICTENC"],
-["1", "-1 ROLL", "P2SH,STRICTENC"],
-["19 20 21", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"],
-["19 20 21", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"],
-["19 20 21", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"],
-["NOP", "ROT 1", "P2SH,STRICTENC"],
-["NOP", "1 ROT 1", "P2SH,STRICTENC"],
-["NOP", "1 2 ROT 1", "P2SH,STRICTENC"],
-["NOP", "0 1 2 ROT", "P2SH,STRICTENC"],
-["NOP", "SWAP 1", "P2SH,STRICTENC"],
-["1", "SWAP 1", "P2SH,STRICTENC"],
-["0 1", "SWAP 1 EQUALVERIFY", "P2SH,STRICTENC"],
-["NOP", "TUCK 1", "P2SH,STRICTENC"],
-["1", "TUCK 1", "P2SH,STRICTENC"],
-["1 0", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP", "P2SH,STRICTENC"],
-["NOP", "2DUP 1", "P2SH,STRICTENC"],
-["1", "2DUP 1", "P2SH,STRICTENC"],
-["NOP", "3DUP 1", "P2SH,STRICTENC"],
-["1", "3DUP 1", "P2SH,STRICTENC"],
-["1 2", "3DUP 1", "P2SH,STRICTENC"],
-["NOP", "2OVER 1", "P2SH,STRICTENC"],
-["1", "2 3 2OVER 1", "P2SH,STRICTENC"],
-["NOP", "2SWAP 1", "P2SH,STRICTENC"],
-["1", "2 3 2SWAP 1", "P2SH,STRICTENC"],
-
-["'a' 'b'", "CAT", "P2SH,STRICTENC", "CAT disabled"],
-["'a' 'b' 0", "IF CAT ELSE 1 ENDIF", "P2SH,STRICTENC", "CAT disabled"],
-["'abc' 1 1", "SUBSTR", "P2SH,STRICTENC", "SUBSTR disabled"],
-["'abc' 1 1 0", "IF SUBSTR ELSE 1 ENDIF", "P2SH,STRICTENC", "SUBSTR disabled"],
-["'abc' 2 0", "IF LEFT ELSE 1 ENDIF", "P2SH,STRICTENC", "LEFT disabled"],
-["'abc' 2 0", "IF RIGHT ELSE 1 ENDIF", "P2SH,STRICTENC", "RIGHT disabled"],
-
-["NOP", "SIZE 1", "P2SH,STRICTENC"],
-
-["'abc'", "IF INVERT ELSE 1 ENDIF", "P2SH,STRICTENC", "INVERT disabled"],
-["1 2 0 IF AND ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "AND disabled"],
-["1 2 0 IF OR ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "OR disabled"],
-["1 2 0 IF XOR ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "XOR disabled"],
-["2 0 IF 2MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "2MUL disabled"],
-["2 0 IF 2DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "2DIV disabled"],
-["2 2 0 IF MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "MUL disabled"],
-["2 2 0 IF DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DIV disabled"],
-["2 2 0 IF MOD ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "MOD disabled"],
-["2 2 0 IF LSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "LSHIFT disabled"],
-["2 2 0 IF RSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "RSHIFT disabled"],
-
-["", "EQUAL NOT", "P2SH,STRICTENC", "EQUAL must error when there are no stack items"],
-["0", "EQUAL NOT", "P2SH,STRICTENC", "EQUAL must error when there are not 2 stack items"],
-["0 1","EQUAL", "P2SH,STRICTENC"],
-["1 1 ADD", "0 EQUAL", "P2SH,STRICTENC"],
-["11 1 ADD 12 SUB", "11 EQUAL", "P2SH,STRICTENC"],
-
-["2147483648 0 ADD", "NOP", "P2SH,STRICTENC", "arithmetic operands must be in range [-2^31...2^31] "],
-["-2147483648 0 ADD", "NOP", "P2SH,STRICTENC", "arithmetic operands must be in range [-2^31...2^31] "],
-["2147483647 DUP ADD", "4294967294 NUMEQUAL", "P2SH,STRICTENC", "NUMEQUAL must be in numeric range"],
-["'abcdef' NOT", "0 EQUAL", "P2SH,STRICTENC", "NOT is an arithmetic operand"],
-
-["2 DUP MUL", "4 EQUAL", "P2SH,STRICTENC", "disabled"],
-["2 DUP DIV", "1 EQUAL", "P2SH,STRICTENC", "disabled"],
-["2 2MUL", "4 EQUAL", "P2SH,STRICTENC", "disabled"],
-["2 2DIV", "1 EQUAL", "P2SH,STRICTENC", "disabled"],
-["7 3 MOD", "1 EQUAL", "P2SH,STRICTENC", "disabled"],
-["2 2 LSHIFT", "8 EQUAL", "P2SH,STRICTENC", "disabled"],
-["2 1 RSHIFT", "1 EQUAL", "P2SH,STRICTENC", "disabled"],
-
-["1","NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC"],
-["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC"],
+["", "DEPTH", "P2SH,STRICTENC", "Test the test: we should have an empty stack after scriptSig evaluation", "EVAL_FALSE"],
+[" ", "DEPTH", "P2SH,STRICTENC", "and multiple spaces should not change that.", "EVAL_FALSE"],
+[" ", "DEPTH", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+[" ", "DEPTH", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+
+["", "", "P2SH,STRICTENC","", "EVAL_FALSE"],
+["", "NOP", "P2SH,STRICTENC","", "EVAL_FALSE"],
+["", "NOP DEPTH", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+["NOP", "", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+["NOP", "DEPTH", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+["NOP","NOP", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+["NOP","NOP DEPTH", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+
+["DEPTH", "", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+
+["0x4c01","0x01 NOP", "P2SH,STRICTENC", "PUSHDATA1 with not enough bytes","BAD_OPCODE"],
+["0x4d0200ff","0x01 NOP", "P2SH,STRICTENC", "PUSHDATA2 with not enough bytes","BAD_OPCODE"],
+["0x4e03000000ffff","0x01 NOP", "P2SH,STRICTENC", "PUSHDATA4 with not enough bytes","BAD_OPCODE"],
+
+["1", "IF 0x50 ENDIF 1", "P2SH,STRICTENC", "0x50 is reserved","BAD_OPCODE"],
+["0x52", "0x5f ADD 0x60 EQUAL", "P2SH,STRICTENC", "0x51 through 0x60 push 1 through 16 onto stack","EVAL_FALSE"],
+["0","NOP", "P2SH,STRICTENC","","EVAL_FALSE"],
+["1", "IF VER ELSE 1 ENDIF", "P2SH,STRICTENC", "VER non-functional", "BAD_OPCODE"],
+["0", "IF VERIF ELSE 1 ENDIF", "P2SH,STRICTENC", "VERIF illegal everywhere", "BAD_OPCODE"],
+["0", "IF ELSE 1 ELSE VERIF ENDIF", "P2SH,STRICTENC", "VERIF illegal everywhere", "BAD_OPCODE"],
+["0", "IF VERNOTIF ELSE 1 ENDIF", "P2SH,STRICTENC", "VERNOTIF illegal everywhere", "BAD_OPCODE"],
+["0", "IF ELSE 1 ELSE VERNOTIF ENDIF", "P2SH,STRICTENC", "VERNOTIF illegal everywhere", "BAD_OPCODE"],
+
+["1 IF", "1 ENDIF", "P2SH,STRICTENC", "IF/ENDIF can't span scriptSig/scriptPubKey", "UNBALANCED_CONDITIONAL"],
+["1 IF 0 ENDIF", "1 ENDIF", "P2SH,STRICTENC", "", "UNBALANCED_CONDITIONAL"],
+["1 ELSE 0 ENDIF", "1", "P2SH,STRICTENC", "", "UNBALANCED_CONDITIONAL"],
+["0 NOTIF", "123", "P2SH,STRICTENC", "", "UNBALANCED_CONDITIONAL"],
+
+["0", "DUP IF ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+["0", "IF 1 ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+["0", "DUP IF ELSE ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+["0", "IF 1 ELSE ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+["0", "NOTIF ELSE 1 ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+
+["0 1", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+["0 0", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+["1 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+["0 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+
+["0 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+["0 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+["1 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+["0 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+
+["1", "IF RETURN ELSE ELSE 1 ENDIF", "P2SH,STRICTENC", "Multiple ELSEs", "OP_RETURN"],
+["1", "IF 1 ELSE ELSE RETURN ENDIF", "P2SH,STRICTENC", "", "OP_RETURN"],
+
+["1", "ENDIF", "P2SH,STRICTENC", "Malformed IF/ELSE/ENDIF sequence", "UNBALANCED_CONDITIONAL"],
+["1", "ELSE ENDIF", "P2SH,STRICTENC", "", "UNBALANCED_CONDITIONAL"],
+["1", "ENDIF ELSE", "P2SH,STRICTENC", "", "UNBALANCED_CONDITIONAL"],
+["1", "ENDIF ELSE IF", "P2SH,STRICTENC", "", "UNBALANCED_CONDITIONAL"],
+["1", "IF ELSE ENDIF ELSE", "P2SH,STRICTENC", "", "UNBALANCED_CONDITIONAL"],
+["1", "IF ELSE ENDIF ELSE ENDIF", "P2SH,STRICTENC", "", "UNBALANCED_CONDITIONAL"],
+["1", "IF ENDIF ENDIF", "P2SH,STRICTENC", "", "UNBALANCED_CONDITIONAL"],
+["1", "IF ELSE ELSE ENDIF ENDIF", "P2SH,STRICTENC", "", "UNBALANCED_CONDITIONAL"],
+
+["1", "RETURN", "P2SH,STRICTENC", "", "OP_RETURN"],
+["1", "DUP IF RETURN ENDIF", "P2SH,STRICTENC", "", "OP_RETURN"],
+
+["1", "RETURN 'data'", "P2SH,STRICTENC", "canonical prunable txout format", "OP_RETURN"],
+["0 IF", "RETURN ENDIF 1", "P2SH,STRICTENC", "still prunable because IF/ENDIF can't span scriptSig/scriptPubKey", "UNBALANCED_CONDITIONAL"],
+
+["0", "VERIFY 1", "P2SH,STRICTENC", "", "VERIFY"],
+["1", "VERIFY", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+["1", "VERIFY 0", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+
+["1 TOALTSTACK", "FROMALTSTACK 1", "P2SH,STRICTENC", "alt stack not shared between sig/pubkey", "INVALID_ALTSTACK_OPERATION"],
+
+["IFDUP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["DROP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["DUP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "DUP 1 ADD 2 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+["NOP", "NIP", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "1 NIP", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "1 0 NIP", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+["NOP", "OVER 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "OVER", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["0 1", "OVER DEPTH 3 EQUALVERIFY", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+["19 20 21", "PICK 19 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "0 PICK", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "-1 PICK", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["19 20 21", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "", "EQUALVERIFY"],
+["19 20 21", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "", "EQUALVERIFY"],
+["19 20 21", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "", "EQUALVERIFY"],
+["NOP", "0 ROLL", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "-1 ROLL", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["19 20 21", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "", "EQUALVERIFY"],
+["19 20 21", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "", "EQUALVERIFY"],
+["19 20 21", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "", "EQUALVERIFY"],
+["NOP", "ROT 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "1 ROT 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "1 2 ROT 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "0 1 2 ROT", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+["NOP", "SWAP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "SWAP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["0 1", "SWAP 1 EQUALVERIFY", "P2SH,STRICTENC", "", "EQUALVERIFY"],
+["NOP", "TUCK 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "TUCK 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1 0", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+["NOP", "2DUP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "2DUP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "3DUP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "3DUP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1 2", "3DUP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "2OVER 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "2 3 2OVER 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "2SWAP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "2 3 2SWAP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+
+["'a' 'b'", "CAT", "P2SH,STRICTENC", "CAT disabled", "DISABLED_OPCODE"],
+["'a' 'b' 0", "IF CAT ELSE 1 ENDIF", "P2SH,STRICTENC", "CAT disabled", "DISABLED_OPCODE"],
+["'abc' 1 1", "SUBSTR", "P2SH,STRICTENC", "SUBSTR disabled", "DISABLED_OPCODE"],
+["'abc' 1 1 0", "IF SUBSTR ELSE 1 ENDIF", "P2SH,STRICTENC", "SUBSTR disabled", "DISABLED_OPCODE"],
+["'abc' 2 0", "IF LEFT ELSE 1 ENDIF", "P2SH,STRICTENC", "LEFT disabled", "DISABLED_OPCODE"],
+["'abc' 2 0", "IF RIGHT ELSE 1 ENDIF", "P2SH,STRICTENC", "RIGHT disabled", "DISABLED_OPCODE"],
+
+["NOP", "SIZE 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+
+["'abc'", "IF INVERT ELSE 1 ENDIF", "P2SH,STRICTENC", "INVERT disabled", "DISABLED_OPCODE"],
+["1 2 0 IF AND ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "AND disabled", "DISABLED_OPCODE"],
+["1 2 0 IF OR ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "OR disabled", "DISABLED_OPCODE"],
+["1 2 0 IF XOR ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "XOR disabled", "DISABLED_OPCODE"],
+["2 0 IF 2MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "2MUL disabled", "DISABLED_OPCODE"],
+["2 0 IF 2DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "2DIV disabled", "DISABLED_OPCODE"],
+["2 2 0 IF MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "MUL disabled", "DISABLED_OPCODE"],
+["2 2 0 IF DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DIV disabled", "DISABLED_OPCODE"],
+["2 2 0 IF MOD ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "MOD disabled", "DISABLED_OPCODE"],
+["2 2 0 IF LSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "LSHIFT disabled", "DISABLED_OPCODE"],
+["2 2 0 IF RSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "RSHIFT disabled", "DISABLED_OPCODE"],
+
+["", "EQUAL NOT", "P2SH,STRICTENC", "EQUAL must error when there are no stack items", "INVALID_STACK_OPERATION"],
+["0", "EQUAL NOT", "P2SH,STRICTENC", "EQUAL must error when there are not 2 stack items", "INVALID_STACK_OPERATION"],
+["0 1","EQUAL", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+["1 1 ADD", "0 EQUAL", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+["11 1 ADD 12 SUB", "11 EQUAL", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+
+["2147483648 0 ADD", "NOP", "P2SH,STRICTENC", "arithmetic operands must be in range [-2^31...2^31] ", "UNKNOWN_ERROR"],
+["-2147483648 0 ADD", "NOP", "P2SH,STRICTENC", "arithmetic operands must be in range [-2^31...2^31] ", "UNKNOWN_ERROR"],
+["2147483647 DUP ADD", "4294967294 NUMEQUAL", "P2SH,STRICTENC", "NUMEQUAL must be in numeric range", "UNKNOWN_ERROR"],
+["'abcdef' NOT", "0 EQUAL", "P2SH,STRICTENC", "NOT is an arithmetic operand", "UNKNOWN_ERROR"],
+
+["2 DUP MUL", "4 EQUAL", "P2SH,STRICTENC", "disabled", "DISABLED_OPCODE"],
+["2 DUP DIV", "1 EQUAL", "P2SH,STRICTENC", "disabled", "DISABLED_OPCODE"],
+["2 2MUL", "4 EQUAL", "P2SH,STRICTENC", "disabled", "DISABLED_OPCODE"],
+["2 2DIV", "1 EQUAL", "P2SH,STRICTENC", "disabled", "DISABLED_OPCODE"],
+["7 3 MOD", "1 EQUAL", "P2SH,STRICTENC", "disabled", "DISABLED_OPCODE"],
+["2 2 LSHIFT", "8 EQUAL", "P2SH,STRICTENC", "disabled", "DISABLED_OPCODE"],
+["2 1 RSHIFT", "1 EQUAL", "P2SH,STRICTENC", "disabled", "DISABLED_OPCODE"],
+
+["1","NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC", "", "EVAL_FALSE"],
["Ensure 100% coverage of discouraged NOPS"],
-["1", "NOP1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"],
-["1", "CHECKLOCKTIMEVERIFY", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"],
-["1", "NOP3", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"],
-["1", "NOP4", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"],
-["1", "NOP5", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"],
-["1", "NOP6", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"],
-["1", "NOP7", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"],
-["1", "NOP8", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"],
-["1", "NOP9", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"],
-["1", "NOP10", "P2SH,DISCOURAGE_UPGRADABLE_NOPS"],
-
-["NOP10", "1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in scriptSig"],
+["1", "NOP1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "", "DISCOURAGE_UPGRADABLE_NOPS"],
+["1", "CHECKLOCKTIMEVERIFY", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "", "DISCOURAGE_UPGRADABLE_NOPS"],
+["1", "NOP3", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "", "DISCOURAGE_UPGRADABLE_NOPS"],
+["1", "NOP4", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "", "DISCOURAGE_UPGRADABLE_NOPS"],
+["1", "NOP5", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "", "DISCOURAGE_UPGRADABLE_NOPS"],
+["1", "NOP6", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "", "DISCOURAGE_UPGRADABLE_NOPS"],
+["1", "NOP7", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "", "DISCOURAGE_UPGRADABLE_NOPS"],
+["1", "NOP8", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "", "DISCOURAGE_UPGRADABLE_NOPS"],
+["1", "NOP9", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "", "DISCOURAGE_UPGRADABLE_NOPS"],
+["1", "NOP10", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "", "DISCOURAGE_UPGRADABLE_NOPS"],
+
+["NOP10", "1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in scriptSig", "DISCOURAGE_UPGRADABLE_NOPS"],
["1 0x01 0xb9", "HASH160 0x14 0x15727299b05b45fdaf9ac9ecf7565cfe27c3e567 EQUAL",
- "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in redeemScript"],
-
-["0x50","1", "P2SH,STRICTENC", "opcode 0x50 is reserved"],
-["1", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "opcodes above NOP10 invalid if executed"],
-["1", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xc0 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xc4 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xc5 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xc6 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xc7 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xc8 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xc9 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xca ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xcb ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xcc ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xcd ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xce ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xcf ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xd0 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xd1 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xd2 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xd3 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xd4 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xd5 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xd6 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xd7 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xd8 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xd9 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xda ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xdb ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xdc ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xdd ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xde ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xdf ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xe0 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xe1 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xe2 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xe3 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xe4 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xe5 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xe6 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xe7 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xe8 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xe9 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xea ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xeb ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xec ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xed ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xee ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xef ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xf0 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xf1 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xf2 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xf3 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xf4 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xf5 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xf6 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xf7 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xf8 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xf9 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xfa ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xfb ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xfc ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xfd ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xfe ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 0xff ELSE 1 ENDIF", "P2SH,STRICTENC"],
-
-["1 IF 1 ELSE", "0xff ENDIF", "P2SH,STRICTENC", "invalid because scriptSig and scriptPubKey are processed separately"],
-
-["NOP", "RIPEMD160", "P2SH,STRICTENC"],
-["NOP", "SHA1", "P2SH,STRICTENC"],
-["NOP", "SHA256", "P2SH,STRICTENC"],
-["NOP", "HASH160", "P2SH,STRICTENC"],
-["NOP", "HASH256", "P2SH,STRICTENC"],
+ "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in redeemScript", "DISCOURAGE_UPGRADABLE_NOPS"],
+
+["0x50","1", "P2SH,STRICTENC", "opcode 0x50 is reserved", "BAD_OPCODE"],
+["1", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "opcodes above NOP10 invalid if executed", "BAD_OPCODE"],
+["1", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xc0 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xc4 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xc5 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xc6 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xc7 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xc8 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xc9 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xca ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xcb ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xcc ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xcd ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xce ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xcf ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xd0 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xd1 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xd2 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xd3 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xd4 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xd5 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xd6 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xd7 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xd8 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xd9 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xda ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xdb ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xdc ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xdd ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xde ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xdf ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xe0 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xe1 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xe2 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xe3 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xe4 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xe5 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xe6 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xe7 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xe8 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xe9 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xea ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xeb ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xec ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xed ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xee ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xef ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xf0 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xf1 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xf2 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xf3 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xf4 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xf5 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xf6 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xf7 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xf8 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xf9 ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xfa ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xfb ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xfc ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xfd ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xfe ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+["1", "IF 0xff ELSE 1 ENDIF", "P2SH,STRICTENC", "", "BAD_OPCODE"],
+
+["1 IF 1 ELSE", "0xff ENDIF", "P2SH,STRICTENC", "invalid because scriptSig and scriptPubKey are processed separately", "UNBALANCED_CONDITIONAL"],
+
+["NOP", "RIPEMD160", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "SHA1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "SHA256", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "HASH160", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "HASH256", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
["NOP",
"'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'",
"P2SH,STRICTENC",
-">520 byte push"],
+">520 byte push",
+"PUSH_SIZE"],
["0",
"IF 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' ENDIF 1",
"P2SH,STRICTENC",
-">520 byte push in non-executed IF branch"],
+">520 byte push in non-executed IF branch",
+"PUSH_SIZE"],
["1",
"0x61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161",
"P2SH,STRICTENC",
-">201 opcodes executed. 0x61 is NOP"],
+">201 opcodes executed. 0x61 is NOP",
+"OP_COUNT"],
["0",
"IF 0x6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161 ENDIF 1",
"P2SH,STRICTENC",
-">201 opcodes including non-executed IF branch. 0x61 is NOP"],
+">201 opcodes including non-executed IF branch. 0x61 is NOP",
+"OP_COUNT"],
["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
"1 2 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
"P2SH,STRICTENC",
-">1,000 stack size (0x6f is 3DUP)"],
+">1,000 stack size (0x6f is 3DUP)",
+"STACK_SIZE"],
["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
"1 TOALTSTACK 2 TOALTSTACK 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
"P2SH,STRICTENC",
-">1,000 stack+altstack size"],
+">1,000 stack+altstack size",
+"STACK_SIZE"],
["NOP",
"0 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f 2DUP 0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161",
"P2SH,STRICTENC",
-"10,001-byte scriptPubKey"],
-
-["NOP1","NOP10", "P2SH,STRICTENC"],
-
-["1","VER", "P2SH,STRICTENC", "OP_VER is reserved"],
-["1","VERIF", "P2SH,STRICTENC", "OP_VERIF is reserved"],
-["1","VERNOTIF", "P2SH,STRICTENC", "OP_VERNOTIF is reserved"],
-["1","RESERVED", "P2SH,STRICTENC", "OP_RESERVED is reserved"],
-["1","RESERVED1", "P2SH,STRICTENC", "OP_RESERVED1 is reserved"],
-["1","RESERVED2", "P2SH,STRICTENC", "OP_RESERVED2 is reserved"],
-["1","0xba", "P2SH,STRICTENC", "0xba == OP_NOP10 + 1"],
-
-["2147483648", "1ADD 1", "P2SH,STRICTENC", "We cannot do math on 5-byte integers"],
-["2147483648", "NEGATE 1", "P2SH,STRICTENC", "We cannot do math on 5-byte integers"],
-["-2147483648", "1ADD 1", "P2SH,STRICTENC", "Because we use a sign bit, -2147483648 is also 5 bytes"],
-["2147483647", "1ADD 1SUB 1", "P2SH,STRICTENC", "We cannot do math on 5-byte integers, even if the result is 4-bytes"],
-["2147483648", "1SUB 1", "P2SH,STRICTENC", "We cannot do math on 5-byte integers, even if the result is 4-bytes"],
-
-["2147483648 1", "BOOLOR 1", "P2SH,STRICTENC", "We cannot do BOOLOR on 5-byte integers (but we can still do IF etc)"],
-["2147483648 1", "BOOLAND 1", "P2SH,STRICTENC", "We cannot do BOOLAND on 5-byte integers"],
-
-["1", "1 ENDIF", "P2SH,STRICTENC", "ENDIF without IF"],
-["1", "IF 1", "P2SH,STRICTENC", "IF without ENDIF"],
-["1 IF 1", "ENDIF", "P2SH,STRICTENC", "IFs don't carry over"],
-
-["NOP", "IF 1 ENDIF", "P2SH,STRICTENC", "The following tests check the if(stack.size() < N) tests in each opcode"],
-["NOP", "NOTIF 1 ENDIF", "P2SH,STRICTENC", "They are here to catch copy-and-paste errors"],
-["NOP", "VERIFY 1", "P2SH,STRICTENC", "Most of them are duplicated elsewhere,"],
-
-["NOP", "TOALTSTACK 1", "P2SH,STRICTENC", "but, hey, more is always better, right?"],
-["1", "FROMALTSTACK", "P2SH,STRICTENC"],
-["1", "2DROP 1", "P2SH,STRICTENC"],
-["1", "2DUP", "P2SH,STRICTENC"],
-["1 1", "3DUP", "P2SH,STRICTENC"],
-["1 1 1", "2OVER", "P2SH,STRICTENC"],
-["1 1 1 1 1", "2ROT", "P2SH,STRICTENC"],
-["1 1 1", "2SWAP", "P2SH,STRICTENC"],
-["NOP", "IFDUP 1", "P2SH,STRICTENC"],
-["NOP", "DROP 1", "P2SH,STRICTENC"],
-["NOP", "DUP 1", "P2SH,STRICTENC"],
-["1", "NIP", "P2SH,STRICTENC"],
-["1", "OVER", "P2SH,STRICTENC"],
-["1 1 1 3", "PICK", "P2SH,STRICTENC"],
-["0", "PICK 1", "P2SH,STRICTENC"],
-["1 1 1 3", "ROLL", "P2SH,STRICTENC"],
-["0", "ROLL 1", "P2SH,STRICTENC"],
-["1 1", "ROT", "P2SH,STRICTENC"],
-["1", "SWAP", "P2SH,STRICTENC"],
-["1", "TUCK", "P2SH,STRICTENC"],
-
-["NOP", "SIZE 1", "P2SH,STRICTENC"],
-
-["1", "EQUAL 1", "P2SH,STRICTENC"],
-["1", "EQUALVERIFY 1", "P2SH,STRICTENC"],
-
-["NOP", "1ADD 1", "P2SH,STRICTENC"],
-["NOP", "1SUB 1", "P2SH,STRICTENC"],
-["NOP", "NEGATE 1", "P2SH,STRICTENC"],
-["NOP", "ABS 1", "P2SH,STRICTENC"],
-["NOP", "NOT 1", "P2SH,STRICTENC"],
-["NOP", "0NOTEQUAL 1", "P2SH,STRICTENC"],
-
-["1", "ADD", "P2SH,STRICTENC"],
-["1", "SUB", "P2SH,STRICTENC"],
-["1", "BOOLAND", "P2SH,STRICTENC"],
-["1", "BOOLOR", "P2SH,STRICTENC"],
-["1", "NUMEQUAL", "P2SH,STRICTENC"],
-["1", "NUMEQUALVERIFY 1", "P2SH,STRICTENC"],
-["1", "NUMNOTEQUAL", "P2SH,STRICTENC"],
-["1", "LESSTHAN", "P2SH,STRICTENC"],
-["1", "GREATERTHAN", "P2SH,STRICTENC"],
-["1", "LESSTHANOREQUAL", "P2SH,STRICTENC"],
-["1", "GREATERTHANOREQUAL", "P2SH,STRICTENC"],
-["1", "MIN", "P2SH,STRICTENC"],
-["1", "MAX", "P2SH,STRICTENC"],
-["1 1", "WITHIN", "P2SH,STRICTENC"],
-
-["NOP", "RIPEMD160 1", "P2SH,STRICTENC"],
-["NOP", "SHA1 1", "P2SH,STRICTENC"],
-["NOP", "SHA256 1", "P2SH,STRICTENC"],
-["NOP", "HASH160 1", "P2SH,STRICTENC"],
-["NOP", "HASH256 1", "P2SH,STRICTENC"],
+"10,001-byte scriptPubKey",
+"SCRIPT_SIZE"],
+
+["NOP1","NOP10", "P2SH,STRICTENC", "", "EVAL_FALSE"],
+
+["1","VER", "P2SH,STRICTENC", "OP_VER is reserved", "BAD_OPCODE"],
+["1","VERIF", "P2SH,STRICTENC", "OP_VERIF is reserved", "BAD_OPCODE"],
+["1","VERNOTIF", "P2SH,STRICTENC", "OP_VERNOTIF is reserved", "BAD_OPCODE"],
+["1","RESERVED", "P2SH,STRICTENC", "OP_RESERVED is reserved", "BAD_OPCODE"],
+["1","RESERVED1", "P2SH,STRICTENC", "OP_RESERVED1 is reserved", "BAD_OPCODE"],
+["1","RESERVED2", "P2SH,STRICTENC", "OP_RESERVED2 is reserved", "BAD_OPCODE"],
+["1","0xba", "P2SH,STRICTENC", "0xba == OP_NOP10 + 1", "BAD_OPCODE"],
+
+["2147483648", "1ADD 1", "P2SH,STRICTENC", "We cannot do math on 5-byte integers", "UNKNOWN_ERROR"],
+["2147483648", "NEGATE 1", "P2SH,STRICTENC", "We cannot do math on 5-byte integers", "UNKNOWN_ERROR"],
+["-2147483648", "1ADD 1", "P2SH,STRICTENC", "Because we use a sign bit, -2147483648 is also 5 bytes", "UNKNOWN_ERROR"],
+["2147483647", "1ADD 1SUB 1", "P2SH,STRICTENC", "We cannot do math on 5-byte integers, even if the result is 4-bytes", "UNKNOWN_ERROR"],
+["2147483648", "1SUB 1", "P2SH,STRICTENC", "We cannot do math on 5-byte integers, even if the result is 4-bytes", "UNKNOWN_ERROR"],
+
+["2147483648 1", "BOOLOR 1", "P2SH,STRICTENC", "We cannot do BOOLOR on 5-byte integers (but we can still do IF etc)", "UNKNOWN_ERROR"],
+["2147483648 1", "BOOLAND 1", "P2SH,STRICTENC", "We cannot do BOOLAND on 5-byte integers", "UNKNOWN_ERROR"],
+
+["1", "1 ENDIF", "P2SH,STRICTENC", "ENDIF without IF", "UNBALANCED_CONDITIONAL"],
+["1", "IF 1", "P2SH,STRICTENC", "IF without ENDIF", "UNBALANCED_CONDITIONAL"],
+["1 IF 1", "ENDIF", "P2SH,STRICTENC", "IFs don't carry over", "UNBALANCED_CONDITIONAL"],
+
+["NOP", "IF 1 ENDIF", "P2SH,STRICTENC", "The following tests check the if(stack.size() < N) tests in each opcode", "UNBALANCED_CONDITIONAL"],
+["NOP", "NOTIF 1 ENDIF", "P2SH,STRICTENC", "They are here to catch copy-and-paste errors", "UNBALANCED_CONDITIONAL"],
+["NOP", "VERIFY 1", "P2SH,STRICTENC", "Most of them are duplicated elsewhere,", "INVALID_STACK_OPERATION"],
+
+["NOP", "TOALTSTACK 1", "P2SH,STRICTENC", "but, hey, more is always better, right?", "INVALID_STACK_OPERATION"],
+["1", "FROMALTSTACK", "P2SH,STRICTENC", "", "INVALID_ALTSTACK_OPERATION"],
+["1", "2DROP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "2DUP", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1 1", "3DUP", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1 1 1", "2OVER", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1 1 1 1 1", "2ROT", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1 1 1", "2SWAP", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "IFDUP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "DROP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "DUP 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "NIP", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "OVER", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1 1 1 3", "PICK", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["0", "PICK 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1 1 1 3", "ROLL", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["0", "ROLL 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1 1", "ROT", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "SWAP", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "TUCK", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+
+["NOP", "SIZE 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+
+["1", "EQUAL 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "EQUALVERIFY 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+
+["NOP", "1ADD 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "1SUB 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "NEGATE 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "ABS 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "NOT 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "0NOTEQUAL 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+
+["1", "ADD", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "SUB", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "BOOLAND", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "BOOLOR", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "NUMEQUAL", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "NUMEQUALVERIFY 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "NUMNOTEQUAL", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "LESSTHAN", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "GREATERTHAN", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "LESSTHANOREQUAL", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "GREATERTHANOREQUAL", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "MIN", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1", "MAX", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["1 1", "WITHIN", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+
+["NOP", "RIPEMD160 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "SHA1 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "SHA256 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "HASH160 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
+["NOP", "HASH256 1", "P2SH,STRICTENC", "", "INVALID_STACK_OPERATION"],
["Increase CHECKSIG and CHECKMULTISIG negative test coverage"],
-["", "CHECKSIG NOT", "STRICTENC", "CHECKSIG must error when there are no stack items"],
-["0", "CHECKSIG NOT", "STRICTENC", "CHECKSIG must error when there are not 2 stack items"],
-["", "CHECKMULTISIG NOT", "STRICTENC", "CHECKMULTISIG must error when there are no stack items"],
-["", "-1 CHECKMULTISIG NOT", "STRICTENC", "CHECKMULTISIG must error when the specified number of pubkeys is negative"],
-["", "1 CHECKMULTISIG NOT", "STRICTENC", "CHECKMULTISIG must error when there are not enough pubkeys on the stack"],
-["", "-1 0 CHECKMULTISIG NOT", "STRICTENC", "CHECKMULTISIG must error when the specified number of signatures is negative"],
-["", "1 'pk1' 1 CHECKMULTISIG NOT", "STRICTENC", "CHECKMULTISIG must error when there are not enough signatures on the stack"],
-["", "'dummy' 'sig1' 1 'pk1' 1 CHECKMULTISIG IF 1 ENDIF", "", "CHECKMULTISIG must push false to stack when signature is invalid when NOT in strict enc mode"],
+["", "CHECKSIG NOT", "STRICTENC", "CHECKSIG must error when there are no stack items", "INVALID_STACK_OPERATION"],
+["0", "CHECKSIG NOT", "STRICTENC", "CHECKSIG must error when there are not 2 stack items", "INVALID_STACK_OPERATION"],
+["", "CHECKMULTISIG NOT", "STRICTENC", "CHECKMULTISIG must error when there are no stack items", "INVALID_STACK_OPERATION"],
+["", "-1 CHECKMULTISIG NOT", "STRICTENC", "CHECKMULTISIG must error when the specified number of pubkeys is negative", "PUBKEY_COUNT"],
+["", "1 CHECKMULTISIG NOT", "STRICTENC", "CHECKMULTISIG must error when there are not enough pubkeys on the stack", "INVALID_STACK_OPERATION"],
+["", "-1 0 CHECKMULTISIG NOT", "STRICTENC", "CHECKMULTISIG must error when the specified number of signatures is negative", "SIG_COUNT"],
+["", "1 'pk1' 1 CHECKMULTISIG NOT", "STRICTENC", "CHECKMULTISIG must error when there are not enough signatures on the stack", "INVALID_STACK_OPERATION"],
+["", "'dummy' 'sig1' 1 'pk1' 1 CHECKMULTISIG IF 1 ENDIF", "", "CHECKMULTISIG must push false to stack when signature is invalid when NOT in strict enc mode","EVAL_FALSE"],
["",
"0 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG",
"P2SH,STRICTENC",
-"202 CHECKMULTISIGS, fails due to 201 op limit"],
+"202 CHECKMULTISIGS, fails due to 201 op limit",
+"OP_COUNT"],
["1",
"0 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY",
-"P2SH,STRICTENC"],
+"P2SH,STRICTENC",
+"",
+"INVALID_STACK_OPERATION"],
["",
"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG",
"P2SH,STRICTENC",
-"Fails due to 201 sig op limit"],
+"Fails due to 201 sig op limit",
+"OP_COUNT"],
["1",
"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY",
-"P2SH,STRICTENC"],
+"P2SH,STRICTENC",
+"",
+"OP_COUNT"],
-["0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21", "21 CHECKMULTISIG 1", "P2SH,STRICTENC", "nPubKeys > 20"],
-["0 'sig' 1 0", "CHECKMULTISIG 1", "P2SH,STRICTENC", "nSigs > nPubKeys"],
+["0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21", "21 CHECKMULTISIG 1", "P2SH,STRICTENC", "nPubKeys > 20", "PUBKEY_COUNT"],
+["0 'sig' 1 0", "CHECKMULTISIG 1", "P2SH,STRICTENC", "nSigs > nPubKeys", "SIG_COUNT"],
-["NOP 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "Tests for Script.IsPushOnly()"],
-["NOP1 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC"],
+["NOP 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "Tests for Script.IsPushOnly()", "SIG_PUSHONLY"],
+["NOP1 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "", "SIG_PUSHONLY"],
-["0 0x01 0x50", "HASH160 0x14 0xece424a6bb6ddf4db592c0faed60685047a361b1 EQUAL", "P2SH,STRICTENC", "OP_RESERVED in P2SH should fail"],
-["0 0x01 VER", "HASH160 0x14 0x0f4d7845db968f2a81b530b6f3c1d6246d4c7e01 EQUAL", "P2SH,STRICTENC", "OP_VER in P2SH should fail"],
+["0 0x01 0x50", "HASH160 0x14 0xece424a6bb6ddf4db592c0faed60685047a361b1 EQUAL", "P2SH,STRICTENC", "OP_RESERVED in P2SH should fail", "BAD_OPCODE"],
+["0 0x01 VER", "HASH160 0x14 0x0f4d7845db968f2a81b530b6f3c1d6246d4c7e01 EQUAL", "P2SH,STRICTENC", "OP_VER in P2SH should fail", "BAD_OPCODE"],
-["0x00", "'00' EQUAL", "P2SH,STRICTENC", "Basic OP_0 execution"],
+["0x00", "'00' EQUAL", "P2SH,STRICTENC", "Basic OP_0 execution", "EVAL_FALSE"],
["MINIMALDATA enforcement for PUSHDATAs"],
-["0x4c 0x00", "DROP 1", "MINIMALDATA", "Empty vector minimally represented by OP_0"],
-["0x01 0x81", "DROP 1", "MINIMALDATA", "-1 minimally represented by OP_1NEGATE"],
-["0x01 0x01", "DROP 1", "MINIMALDATA", "1 to 16 minimally represented by OP_1 to OP_16"],
-["0x01 0x02", "DROP 1", "MINIMALDATA"],
-["0x01 0x03", "DROP 1", "MINIMALDATA"],
-["0x01 0x04", "DROP 1", "MINIMALDATA"],
-["0x01 0x05", "DROP 1", "MINIMALDATA"],
-["0x01 0x06", "DROP 1", "MINIMALDATA"],
-["0x01 0x07", "DROP 1", "MINIMALDATA"],
-["0x01 0x08", "DROP 1", "MINIMALDATA"],
-["0x01 0x09", "DROP 1", "MINIMALDATA"],
-["0x01 0x0a", "DROP 1", "MINIMALDATA"],
-["0x01 0x0b", "DROP 1", "MINIMALDATA"],
-["0x01 0x0c", "DROP 1", "MINIMALDATA"],
-["0x01 0x0d", "DROP 1", "MINIMALDATA"],
-["0x01 0x0e", "DROP 1", "MINIMALDATA"],
-["0x01 0x0f", "DROP 1", "MINIMALDATA"],
-["0x01 0x10", "DROP 1", "MINIMALDATA"],
+["0x4c 0x00", "DROP 1", "MINIMALDATA", "Empty vector minimally represented by OP_0", "MINIMALDATA"],
+["0x01 0x81", "DROP 1", "MINIMALDATA", "-1 minimally represented by OP_1NEGATE", "MINIMALDATA"],
+["0x01 0x01", "DROP 1", "MINIMALDATA", "1 to 16 minimally represented by OP_1 to OP_16", "MINIMALDATA"],
+["0x01 0x02", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"],
+["0x01 0x03", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"],
+["0x01 0x04", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"],
+["0x01 0x05", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"],
+["0x01 0x06", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"],
+["0x01 0x07", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"],
+["0x01 0x08", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"],
+["0x01 0x09", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"],
+["0x01 0x0a", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"],
+["0x01 0x0b", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"],
+["0x01 0x0c", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"],
+["0x01 0x0d", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"],
+["0x01 0x0e", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"],
+["0x01 0x0f", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"],
+["0x01 0x10", "DROP 1", "MINIMALDATA", "", "MINIMALDATA"],
["0x4c 0x48 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA",
- "PUSHDATA1 of 72 bytes minimally represented by direct push"],
+ "PUSHDATA1 of 72 bytes minimally represented by direct push",
+ "MINIMALDATA"],
["0x4d 0xFF00 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA",
- "PUSHDATA2 of 255 bytes minimally represented by PUSHDATA1"],
+ "PUSHDATA2 of 255 bytes minimally represented by PUSHDATA1",
+ "MINIMALDATA"],
["0x4e 0x00010000 0x11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA",
- "PUSHDATA4 of 256 bytes minimally represented by PUSHDATA2"],
-
+ "PUSHDATA4 of 256 bytes minimally represented by PUSHDATA2",
+ "MINIMALDATA"],
["MINIMALDATA enforcement for numeric arguments"],
-["0x01 0x00", "NOT DROP 1", "MINIMALDATA", "numequals 0"],
-["0x02 0x0000", "NOT DROP 1", "MINIMALDATA", "numequals 0"],
-["0x01 0x80", "NOT DROP 1", "MINIMALDATA", "0x80 (negative zero) numequals 0"],
-["0x02 0x0080", "NOT DROP 1", "MINIMALDATA", "numequals 0"],
-["0x02 0x0500", "NOT DROP 1", "MINIMALDATA", "numequals 5"],
-["0x03 0x050000", "NOT DROP 1", "MINIMALDATA", "numequals 5"],
-["0x02 0x0580", "NOT DROP 1", "MINIMALDATA", "numequals -5"],
-["0x03 0x050080", "NOT DROP 1", "MINIMALDATA", "numequals -5"],
-["0x03 0xff7f80", "NOT DROP 1", "MINIMALDATA", "Minimal encoding is 0xffff"],
-["0x03 0xff7f00", "NOT DROP 1", "MINIMALDATA", "Minimal encoding is 0xff7f"],
-["0x04 0xffff7f80", "NOT DROP 1", "MINIMALDATA", "Minimal encoding is 0xffffff"],
-["0x04 0xffff7f00", "NOT DROP 1", "MINIMALDATA", "Minimal encoding is 0xffff7f"],
+["0x01 0x00", "NOT DROP 1", "MINIMALDATA", "numequals 0", "UNKNOWN_ERROR"],
+["0x02 0x0000", "NOT DROP 1", "MINIMALDATA", "numequals 0", "UNKNOWN_ERROR"],
+["0x01 0x80", "NOT DROP 1", "MINIMALDATA", "0x80 (negative zero) numequals 0", "UNKNOWN_ERROR"],
+["0x02 0x0080", "NOT DROP 1", "MINIMALDATA", "numequals 0", "UNKNOWN_ERROR"],
+["0x02 0x0500", "NOT DROP 1", "MINIMALDATA", "numequals 5", "UNKNOWN_ERROR"],
+["0x03 0x050000", "NOT DROP 1", "MINIMALDATA", "numequals 5", "UNKNOWN_ERROR"],
+["0x02 0x0580", "NOT DROP 1", "MINIMALDATA", "numequals -5", "UNKNOWN_ERROR"],
+["0x03 0x050080", "NOT DROP 1", "MINIMALDATA", "numequals -5", "UNKNOWN_ERROR"],
+["0x03 0xff7f80", "NOT DROP 1", "MINIMALDATA", "Minimal encoding is 0xffff", "UNKNOWN_ERROR"],
+["0x03 0xff7f00", "NOT DROP 1", "MINIMALDATA", "Minimal encoding is 0xff7f", "UNKNOWN_ERROR"],
+["0x04 0xffff7f80", "NOT DROP 1", "MINIMALDATA", "Minimal encoding is 0xffffff", "UNKNOWN_ERROR"],
+["0x04 0xffff7f00", "NOT DROP 1", "MINIMALDATA", "Minimal encoding is 0xffff7f", "UNKNOWN_ERROR"],
["Test every numeric-accepting opcode for correct handling of the numeric minimal encoding rule"],
-["1 0x02 0x0000", "PICK DROP", "MINIMALDATA"],
-["1 0x02 0x0000", "ROLL DROP 1", "MINIMALDATA"],
-["0x02 0x0000", "1ADD DROP 1", "MINIMALDATA"],
-["0x02 0x0000", "1SUB DROP 1", "MINIMALDATA"],
-["0x02 0x0000", "NEGATE DROP 1", "MINIMALDATA"],
-["0x02 0x0000", "ABS DROP 1", "MINIMALDATA"],
-["0x02 0x0000", "NOT DROP 1", "MINIMALDATA"],
-["0x02 0x0000", "0NOTEQUAL DROP 1", "MINIMALDATA"],
-
-["0 0x02 0x0000", "ADD DROP 1", "MINIMALDATA"],
-["0x02 0x0000 0", "ADD DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000", "SUB DROP 1", "MINIMALDATA"],
-["0x02 0x0000 0", "SUB DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000", "BOOLAND DROP 1", "MINIMALDATA"],
-["0x02 0x0000 0", "BOOLAND DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000", "BOOLOR DROP 1", "MINIMALDATA"],
-["0x02 0x0000 0", "BOOLOR DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000", "NUMEQUAL DROP 1", "MINIMALDATA"],
-["0x02 0x0000 1", "NUMEQUAL DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000", "NUMEQUALVERIFY 1", "MINIMALDATA"],
-["0x02 0x0000 0", "NUMEQUALVERIFY 1", "MINIMALDATA"],
-["0 0x02 0x0000", "NUMNOTEQUAL DROP 1", "MINIMALDATA"],
-["0x02 0x0000 0", "NUMNOTEQUAL DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000", "LESSTHAN DROP 1", "MINIMALDATA"],
-["0x02 0x0000 0", "LESSTHAN DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000", "GREATERTHAN DROP 1", "MINIMALDATA"],
-["0x02 0x0000 0", "GREATERTHAN DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000", "LESSTHANOREQUAL DROP 1", "MINIMALDATA"],
-["0x02 0x0000 0", "LESSTHANOREQUAL DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000", "GREATERTHANOREQUAL DROP 1", "MINIMALDATA"],
-["0x02 0x0000 0", "GREATERTHANOREQUAL DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000", "MIN DROP 1", "MINIMALDATA"],
-["0x02 0x0000 0", "MIN DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000", "MAX DROP 1", "MINIMALDATA"],
-["0x02 0x0000 0", "MAX DROP 1", "MINIMALDATA"],
-
-["0x02 0x0000 0 0", "WITHIN DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000 0", "WITHIN DROP 1", "MINIMALDATA"],
-["0 0 0x02 0x0000", "WITHIN DROP 1", "MINIMALDATA"],
-
-["0 0 0x02 0x0000", "CHECKMULTISIG DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000 0", "CHECKMULTISIG DROP 1", "MINIMALDATA"],
-["0 0x02 0x0000 0 1", "CHECKMULTISIG DROP 1", "MINIMALDATA"],
-["0 0 0x02 0x0000", "CHECKMULTISIGVERIFY 1", "MINIMALDATA"],
-["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", "MINIMALDATA"],
+["1 0x02 0x0000", "PICK DROP", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["1 0x02 0x0000", "ROLL DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0x02 0x0000", "1ADD DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0x02 0x0000", "1SUB DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0x02 0x0000", "NEGATE DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0x02 0x0000", "ABS DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0x02 0x0000", "NOT DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0x02 0x0000", "0NOTEQUAL DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+
+["0 0x02 0x0000", "ADD DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0x02 0x0000 0", "ADD DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0 0x02 0x0000", "SUB DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0x02 0x0000 0", "SUB DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0 0x02 0x0000", "BOOLAND DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0x02 0x0000 0", "BOOLAND DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0 0x02 0x0000", "BOOLOR DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0x02 0x0000 0", "BOOLOR DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0 0x02 0x0000", "NUMEQUAL DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0x02 0x0000 1", "NUMEQUAL DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0 0x02 0x0000", "NUMEQUALVERIFY 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0x02 0x0000 0", "NUMEQUALVERIFY 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0 0x02 0x0000", "NUMNOTEQUAL DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0x02 0x0000 0", "NUMNOTEQUAL DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0 0x02 0x0000", "LESSTHAN DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0x02 0x0000 0", "LESSTHAN DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0 0x02 0x0000", "GREATERTHAN DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0x02 0x0000 0", "GREATERTHAN DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0 0x02 0x0000", "LESSTHANOREQUAL DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0x02 0x0000 0", "LESSTHANOREQUAL DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0 0x02 0x0000", "GREATERTHANOREQUAL DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0x02 0x0000 0", "GREATERTHANOREQUAL DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0 0x02 0x0000", "MIN DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0x02 0x0000 0", "MIN DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0 0x02 0x0000", "MAX DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0x02 0x0000 0", "MAX DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+
+["0x02 0x0000 0 0", "WITHIN DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0 0x02 0x0000 0", "WITHIN DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0 0 0x02 0x0000", "WITHIN DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+
+["0 0 0x02 0x0000", "CHECKMULTISIG DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0 0x02 0x0000 0", "CHECKMULTISIG DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0 0x02 0x0000 0 1", "CHECKMULTISIG DROP 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0 0 0x02 0x0000", "CHECKMULTISIGVERIFY 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
+["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", "MINIMALDATA", "", "UNKNOWN_ERROR"],
["Order of CHECKMULTISIG evaluation tests, inverted by swapping the order of"],
@@ -513,301 +528,349 @@
"0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501",
"2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0 2 CHECKMULTISIG NOT",
"STRICTENC",
- "2-of-2 CHECKMULTISIG NOT with the first pubkey invalid, and both signatures validly encoded."
+ "2-of-2 CHECKMULTISIG NOT with the first pubkey invalid, and both signatures validly encoded.",
+ "PUBKEYTYPE"
],
[
"0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 1",
"2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT",
"STRICTENC",
- "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but first signature invalid."
+ "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but first signature invalid.",
+ "SIG_DER"
+],
+[
+ "0 0x47 0x304402205451ce65ad844dbb978b8bdedf5082e33b43cae8279c30f2c74d9e9ee49a94f802203fe95a7ccf74da7a232ee523ef4a53cb4d14bdd16289680cdb97a63819b8f42f01 0x46 0x304402205451ce65ad844dbb978b8bdedf5082e33b43cae8279c30f2c74d9e9ee49a94f802203fe95a7ccf74da7a232ee523ef4a53cb4d14bdd16289680cdb97a63819b8f42f",
+ "2 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 3 CHECKMULTISIG",
+ "P2SH,STRICTENC",
+ "2-of-3 with one valid and one invalid signature due to parse error, nSigs > validSigs",
+ "SIG_DER"
],
["Increase DERSIG test coverage"],
-["0x4a 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "DERSIG", "Overly long signature is incorrectly encoded for DERSIG"],
-["0x25 0x30220220000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "DERSIG", "Missing S is incorrectly encoded for DERSIG"],
-["0x27 0x3024021077777777777777777777777777777777020a7777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "S with invalid S length is incorrectly encoded for DERSIG"],
-["0x27 0x302403107777777777777777777777777777777702107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "Non-integer R is incorrectly encoded for DERSIG"],
-["0x27 0x302402107777777777777777777777777777777703107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "Non-integer S is incorrectly encoded for DERSIG"],
-["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "Zero-length R is incorrectly encoded for DERSIG"],
-["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "DERSIG", "Zero-length S is incorrectly encoded for DERSIG"],
-["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "Negative S is incorrectly encoded for DERSIG"],
+["0x4a 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "DERSIG", "Overly long signature is incorrectly encoded for DERSIG", "SIG_DER"],
+["0x25 0x30220220000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "DERSIG", "Missing S is incorrectly encoded for DERSIG", "SIG_DER"],
+["0x27 0x3024021077777777777777777777777777777777020a7777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "S with invalid S length is incorrectly encoded for DERSIG", "SIG_DER"],
+["0x27 0x302403107777777777777777777777777777777702107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "Non-integer R is incorrectly encoded for DERSIG", "SIG_DER"],
+["0x27 0x302402107777777777777777777777777777777703107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "Non-integer S is incorrectly encoded for DERSIG", "SIG_DER"],
+["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "Zero-length R is incorrectly encoded for DERSIG", "SIG_DER"],
+["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "DERSIG", "Zero-length S is incorrectly encoded for DERSIG", "SIG_DER"],
+["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "Negative S is incorrectly encoded for DERSIG", "SIG_DER"],
["Automatically generated test cases"],
[
"0x47 0x304402200a5c6163f07b8c3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001",
"0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
"",
- "P2PK, bad sig"
+ "P2PK, bad sig",
+ "EVAL_FALSE"
],
[
"0x47 0x3044022034bb0494b50b8ef130e2185bb220265b9284ef5b4b8a8da4d8415df489c83b5102206259a26d9cc0a125ac26af6153b17c02956855ebe1467412f066e402f5f05d1201 0x21 0x03363d90d446b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640",
"DUP HASH160 0x14 0xc0834c0c158f53be706d234c38fd52de7eece656 EQUALVERIFY CHECKSIG",
"",
- "P2PKH, bad pubkey"
+ "P2PKH, bad pubkey",
+ "EQUALVERIFY"
],
[
"0x47 0x304402204710a85181663b32d25c70ec2bbd14adff5ddfff6cb50d09e155ef5f541fc86c0220056b0cc949be9386ecc5f6c2ac0493269031dbb185781db90171b54ac127790201",
"0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
"",
- "P2PK anyonecanpay marked with normal hashtype"
+ "P2PK anyonecanpay marked with normal hashtype",
+ "EVAL_FALSE"
],
[
"0x47 0x3044022003fef42ed6c7be8917441218f525a60e2431be978e28b7aca4d7a532cc413ae8022067a1f82c74e8d69291b90d148778405c6257bbcfc2353cc38a3e1f22bf44254601 0x23 0x210279be667ef9dcbbac54a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac",
"HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL",
"P2SH",
- "P2SH(P2PK), bad redeemscript"
+ "P2SH(P2PK), bad redeemscript",
+ "EVAL_FALSE"
],
[
"0x47 0x304402204e2eb034be7b089534ac9e798cf6a2c79f38bcb34d1b179efd6f2de0841735db022071461beb056b5a7be1819da6a3e3ce3662831ecc298419ca101eb6887b5dd6a401 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac",
"HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL",
"P2SH",
- "P2SH(P2PKH), bad sig"
+ "P2SH(P2PKH), bad sig",
+ "EQUALVERIFY"
],
[
"0 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0",
"3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
"",
- "3-of-3, 2 sigs"
+ "3-of-3, 2 sigs",
+ "EVAL_FALSE"
],
[
"0 0x47 0x304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001 0 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae",
"HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL",
"P2SH",
- "P2SH(2-of-3), 1 sig"
+ "P2SH(2-of-3), 1 sig",
+ "EVAL_FALSE"
],
[
"0x47 0x304402200060558477337b9022e70534f1fea71a318caf836812465a2509931c5e7c4987022078ec32bd50ac9e03a349ba953dfd9fe1c8d2dd8bdb1d38ddca844d3d5c78c11801",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
"DERSIG",
- "P2PK with too much R padding"
+ "P2PK with too much R padding",
+ "SIG_DER"
],
[
"0x48 0x304502202de8c03fc525285c9c535631019a5f2af7c6454fa9eb392a3756a4917c420edd02210046130bf2baf7cfc065067c8b9e33a066d9c15edcea9feb0ca2d233e3597925b401",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
"DERSIG",
- "P2PK with too much S padding"
+ "P2PK with too much S padding",
+ "SIG_DER"
],
[
"0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
"DERSIG",
- "P2PK with too little R padding"
+ "P2PK with too little R padding",
+ "SIG_DER"
],
[
"0x47 0x30440220005ece1335e7f757a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
"DERSIG",
- "P2PK NOT with bad sig with too much R padding"
+ "P2PK NOT with bad sig with too much R padding",
+ "SIG_DER"
],
[
"0x47 0x30440220005ece1335e7f657a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
"",
- "P2PK NOT with too much R padding but no DERSIG"
+ "P2PK NOT with too much R padding but no DERSIG",
+ "EVAL_FALSE"
],
[
"0x47 0x30440220005ece1335e7f657a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
"DERSIG",
- "P2PK NOT with too much R padding"
+ "P2PK NOT with too much R padding",
+ "SIG_DER"
],
[
"0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
"DERSIG",
- "BIP66 example 1, with DERSIG"
+ "BIP66 example 1, with DERSIG",
+ "SIG_DER"
],
[
"0x47 0x304402208e43c0b91f7c1e5bc58e41c8185f8a6086e111b0090187968a86f2822462d3c902200a58f4076b1133b18ff1dc83ee51676e44c60cc608d9534e0df5ace0424fc0be01",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
"",
- "BIP66 example 2, without DERSIG"
+ "BIP66 example 2, without DERSIG",
+ "EVAL_FALSE"
],
[
"0x47 0x304402208e43c0b91f7c1e5bc58e41c8185f8a6086e111b0090187968a86f2822462d3c902200a58f4076b1133b18ff1dc83ee51676e44c60cc608d9534e0df5ace0424fc0be01",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
"DERSIG",
- "BIP66 example 2, with DERSIG"
+ "BIP66 example 2, with DERSIG",
+ "SIG_DER"
],
[
"0",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
"",
- "BIP66 example 3, without DERSIG"
+ "BIP66 example 3, without DERSIG",
+ "EVAL_FALSE"
],
[
"0",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
"DERSIG",
- "BIP66 example 3, with DERSIG"
+ "BIP66 example 3, with DERSIG",
+ "EVAL_FALSE"
],
[
"1",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
"",
- "BIP66 example 5, without DERSIG"
+ "BIP66 example 5, without DERSIG",
+ "EVAL_FALSE"
],
[
"1",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
"DERSIG",
- "BIP66 example 5, with DERSIG"
+ "BIP66 example 5, with DERSIG",
+ "SIG_DER"
],
[
"1",
"0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
"DERSIG",
- "BIP66 example 6, with DERSIG"
+ "BIP66 example 6, with DERSIG",
+ "SIG_DER"
],
[
"0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0x47 0x3044022027c2714269ca5aeecc4d70edc88ba5ee0e3da4986e9216028f489ab4f1b8efce022022bd545b4951215267e4c5ceabd4c5350331b2e4a0b6494c56f361fa5a57a1a201",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
"DERSIG",
- "BIP66 example 7, with DERSIG"
+ "BIP66 example 7, with DERSIG",
+ "SIG_DER"
],
[
"0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0x47 0x3044022079ea80afd538d9ada421b5101febeb6bc874e01dde5bca108c1d0479aec339a4022004576db8f66130d1df686ccf00935703689d69cf539438da1edab208b0d63c4801",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
"",
- "BIP66 example 8, without DERSIG"
+ "BIP66 example 8, without DERSIG",
+ "EVAL_FALSE"
],
[
"0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0x47 0x3044022079ea80afd538d9ada421b5101febeb6bc874e01dde5bca108c1d0479aec339a4022004576db8f66130d1df686ccf00935703689d69cf539438da1edab208b0d63c4801",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
"DERSIG",
- "BIP66 example 8, with DERSIG"
+ "BIP66 example 8, with DERSIG",
+ "SIG_DER"
],
[
"0 0 0x47 0x3044022081aa9d436f2154e8b6d600516db03d78de71df685b585a9807ead4210bd883490220534bb6bdf318a419ac0749660b60e78d17d515558ef369bf872eff405b676b2e01",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
"",
- "BIP66 example 9, without DERSIG"
+ "BIP66 example 9, without DERSIG",
+ "EVAL_FALSE"
],
[
"0 0 0x47 0x3044022081aa9d436f2154e8b6d600516db03d78de71df685b585a9807ead4210bd883490220534bb6bdf318a419ac0749660b60e78d17d515558ef369bf872eff405b676b2e01",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
"DERSIG",
- "BIP66 example 9, with DERSIG"
+ "BIP66 example 9, with DERSIG",
+ "SIG_DER"
],
[
"0 0 0x47 0x30440220da6f441dc3b4b2c84cfa8db0cd5b34ed92c9e01686de5a800d40498b70c0dcac02207c2cf91b0c32b860c4cd4994be36cfb84caf8bb7c3a8e4d96a31b2022c5299c501",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
"DERSIG",
- "BIP66 example 10, with DERSIG"
+ "BIP66 example 10, with DERSIG",
+ "SIG_DER"
],
[
"0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
"",
- "BIP66 example 11, without DERSIG"
+ "BIP66 example 11, without DERSIG",
+ "EVAL_FALSE"
],
[
"0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
"DERSIG",
- "BIP66 example 11, with DERSIG"
+ "BIP66 example 11, with DERSIG",
+ "EVAL_FALSE"
],
[
"0x48 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb12510101",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
"DERSIG",
- "P2PK with multi-byte hashtype, with DERSIG"
+ "P2PK with multi-byte hashtype, with DERSIG",
+ "SIG_DER"
],
[
"0x48 0x304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef001",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
"LOW_S",
- "P2PK with high S"
+ "P2PK with high S",
+ "SIG_HIGH_S"
],
[
"0x47 0x3044022057292e2d4dfe775becdd0a9e6547997c728cdf35390f6a017da56d654d374e4902206b643be2fc53763b4e284845bfea2c597d2dc7759941dce937636c9d341b71ed01",
"0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
"STRICTENC",
- "P2PK with hybrid pubkey"
+ "P2PK with hybrid pubkey",
+ "PUBKEYTYPE"
],
[
"0x47 0x30440220035d554e3153c14950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101",
"0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
"",
- "P2PK NOT with hybrid pubkey but no STRICTENC"
+ "P2PK NOT with hybrid pubkey but no STRICTENC",
+ "EVAL_FALSE"
],
[
"0x47 0x30440220035d554e3153c14950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101",
"0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
"STRICTENC",
- "P2PK NOT with hybrid pubkey"
+ "P2PK NOT with hybrid pubkey",
+ "PUBKEYTYPE"
],
[
"0x47 0x30440220035d554e3153c04950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101",
"0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
"STRICTENC",
- "P2PK NOT with invalid hybrid pubkey"
+ "P2PK NOT with invalid hybrid pubkey",
+ "PUBKEYTYPE"
],
[
"0 0x47 0x3044022079c7824d6c868e0e1a273484e28c2654a27d043c8a27f49f52cb72efed0759090220452bbbf7089574fa082095a4fc1b3a16bafcf97a3a34d745fafc922cce66b27201",
"1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 2 CHECKMULTISIG",
"STRICTENC",
- "1-of-2 with the first 1 hybrid pubkey"
+ "1-of-2 with the first 1 hybrid pubkey",
+ "PUBKEYTYPE"
],
[
"0x47 0x304402206177d513ec2cda444c021a1f4f656fc4c72ba108ae063e157eb86dc3575784940220666fc66702815d0e5413bb9b1df22aed44f5f1efb8b99d41dd5dc9a5be6d205205",
"0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
"STRICTENC",
- "P2PK with undefined hashtype"
+ "P2PK with undefined hashtype",
+ "SIG_HASHTYPE"
],
[
"0x47 0x304402207409b5b320296e5e2136a7b281a7f803028ca4ca44e2b83eebd46932677725de02202d4eea1c8d3c98e6f42614f54764e6e5e6542e213eb4d079737e9a8b6e9812ec05",
"0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT",
"STRICTENC",
- "P2PK NOT with invalid sig and undefined hashtype"
+ "P2PK NOT with invalid sig and undefined hashtype",
+ "SIG_HASHTYPE"
],
[
"1 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901",
"3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
"NULLDUMMY",
- "3-of-3 with nonzero dummy"
+ "3-of-3 with nonzero dummy",
+ "SIG_NULLDUMMY"
],
[
"1 0x47 0x304402201bb2edab700a5d020236df174fefed78087697143731f659bea59642c759c16d022061f42cdbae5bcd3e8790f20bf76687443436e94a634321c16a72aa54cbc7c2ea01 0x47 0x304402204bb4a64f2a6e5c7fb2f07fef85ee56fde5e6da234c6a984262307a20e99842d702206f8303aaba5e625d223897e2ffd3f88ef1bcffef55f38dc3768e5f2e94c923f901 0x47 0x3044022040c2809b71fffb155ec8b82fe7a27f666bd97f941207be4e14ade85a1249dd4d02204d56c85ec525dd18e29a0533d5ddf61b6b1bb32980c2f63edf951aebf7a27bfe01",
"3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT",
"NULLDUMMY",
- "3-of-3 NOT with invalid sig with nonzero dummy"
+ "3-of-3 NOT with invalid sig with nonzero dummy",
+ "SIG_NULLDUMMY"
],
[
"0 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901 DUP",
"2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
"SIGPUSHONLY",
- "2-of-2 with two identical keys and sigs pushed using OP_DUP"
+ "2-of-2 with two identical keys and sigs pushed using OP_DUP",
+ "SIG_PUSHONLY"
],
[
"0x47 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb125101 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
"",
- "P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY"
+ "P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY",
+ "EVAL_FALSE"
],
[
"0x47 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb125101 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac",
"0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
"SIGPUSHONLY",
- "P2SH(P2PK) with non-push scriptSig"
-],
-[
- "0 0x47 0x304402205451ce65ad844dbb978b8bdedf5082e33b43cae8279c30f2c74d9e9ee49a94f802203fe95a7ccf74da7a232ee523ef4a53cb4d14bdd16289680cdb97a63819b8f42f01 0x46 0x304402205451ce65ad844dbb978b8bdedf5082e33b43cae8279c30f2c74d9e9ee49a94f802203fe95a7ccf74da7a232ee523ef4a53cb4d14bdd16289680cdb97a63819b8f42f",
- "2 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 3 CHECKMULTISIG",
- "P2SH,STRICTENC",
- "2-of-3 with one valid and one invalid signature due to parse error, nSigs > validSigs"
+ "P2SH(P2PK) with non-push scriptSig",
+ "EVAL_FALSE"
],
[
"11 0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001",
"0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
"CLEANSTACK,P2SH",
- "P2PK with unnecessary input"
+ "P2PK with unnecessary input",
+ "CLEANSTACK"
],
[
"11 0x47 0x304402202f7505132be14872581f35d74b759212d9da40482653f1ffa3116c3294a4a51702206adbf347a2240ca41c66522b1a22a41693610b76a8e7770645dc721d1635854f01 0x43 0x410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
"HASH160 0x14 0x31edc23bdafda4639e669f89ad6b2318dd79d032 EQUAL",
"CLEANSTACK,P2SH",
- "P2SH with unnecessary input"
+ "P2SH with unnecessary input",
+ "CLEANSTACK"
],
["The End"]
diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json
index 9025841949..2d7d9b9585 100644
--- a/src/test/data/tx_invalid.json
+++ b/src/test/data/tx_invalid.json
@@ -201,5 +201,59 @@
[[["b1dbc81696c8a9c0fccd0693ab66d7c368dbc38c0def4e800685560ddd1b2132", 0, "DUP HASH160 0x14 0x4b3bd7eba3bc0284fd3007be7f3be275e94f5826 EQUALVERIFY CHECKSIG"]],
"010000000132211bdd0d568506804eef0d8cc3db68c3d766ab9306cdfcc0a9c89616c8dbb1000000006c493045022100c7bb0faea0522e74ff220c20c022d2cb6033f8d167fb89e75a50e237a35fd6d202203064713491b1f8ad5f79e623d0219ad32510bfaa1009ab30cbee77b59317d6e30001210237af13eb2d84e4545af287b919c2282019c9691cc509e78e196a9d8274ed1be0ffffffff0100000000000000001976a914f1b3ed2eda9a2ebe5a9374f692877cdf87c0f95b88ac00000000", "P2SH,DERSIG"],
+["CHECKSEQUENCEVERIFY tests"],
+
+["By-height locks, with argument just beyond txin.nSequence"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000feff40000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["By-time locks, with argument just beyond txin.nSequence (but within numerical boundries)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194305 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000feff40000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Argument missing"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Argument negative with by-blockheight txin.nSequence=0"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Argument negative with by-blocktime txin.nSequence=CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Argument/tx height/time mismatch, both versions"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["6 byte non-minimally-encoded arguments are invalid even if their contents are valid"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x06 0x000000000000 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff00000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Failure due to failing CHECKSEQUENCEVERIFY in scriptSig"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]],
+"02000000010001000000000000000000000000000000000000000000000000000000000000000000000251b2000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Failure due to failing CHECKSEQUENCEVERIFY in redeemScript"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7c17aff532f22beb54069942f9bf567a66133eaf EQUAL"]],
+"0200000001000100000000000000000000000000000000000000000000000000000000000000000000030251b2000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Failure due to insufficient tx.nVersion (<2)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP3 1"]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 NOP3 1"]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
["Make diffs cleaner by leaving a comment here without comma at the end"]
]
diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json
index 76d29bcf26..717ad19549 100644
--- a/src/test/data/tx_valid.json
+++ b/src/test/data/tx_valid.json
@@ -233,5 +233,89 @@
[[["b1dbc81696c8a9c0fccd0693ab66d7c368dbc38c0def4e800685560ddd1b2132", 0, "DUP HASH160 0x14 0x4b3bd7eba3bc0284fd3007be7f3be275e94f5826 EQUALVERIFY CHECKSIG"]],
"010000000132211bdd0d568506804eef0d8cc3db68c3d766ab9306cdfcc0a9c89616c8dbb1000000006c493045022100c7bb0faea0522e74ff220c20c022d2cb6033f8d167fb89e75a50e237a35fd6d202203064713491b1f8ad5f79e623d0219ad32510bfaa1009ab30cbee77b59317d6e30001210237af13eb2d84e4545af287b919c2282019c9691cc509e78e196a9d8274ed1be0ffffffff0100000000000000001976a914f1b3ed2eda9a2ebe5a9374f692877cdf87c0f95b88ac00000000", "P2SH"],
+["CHECKSEQUENCEVERIFY tests"],
+
+["By-height locks, with argument == 0 and == txin.nSequence"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff00000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["By-time locks, with argument == 0 and == txin.nSequence"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff40000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Upper sequence with upper sequence is fine"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000800100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000800100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Argument 2^31 with various nSequence"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Argument 2^32-1 with various nSequence"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Argument 3<<31 with various nSequence"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["5 byte non-minimally-encoded operandss are valid"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x05 0x0000000000 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["The argument can be calculated rather than created directly by a PUSHDATA"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194303 1ADD NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 1SUB NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff00000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["An ADD producing a 5-byte result that sets CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 65536 NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 4259840 ADD NOP3 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Valid CHECKSEQUENCEVERIFY in scriptSig"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]],
+"02000000010001000000000000000000000000000000000000000000000000000000000000000000000251b2010000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Valid CHECKSEQUENCEVERIFY in redeemScript"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7c17aff532f22beb54069942f9bf567a66133eaf EQUAL"]],
+"0200000001000100000000000000000000000000000000000000000000000000000000000000000000030251b2010000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
["Make diffs cleaner by leaving a comment here without comma at the end"]
]
diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp
index 1347d23656..c8b43df26c 100644
--- a/src/test/mempool_tests.cpp
+++ b/src/test/mempool_tests.cpp
@@ -57,12 +57,12 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
std::list<CTransaction> removed;
// Nothing in pool, remove should do nothing:
- testPool.remove(txParent, removed, true);
+ testPool.removeRecursive(txParent, removed);
BOOST_CHECK_EQUAL(removed.size(), 0);
// Just the parent:
testPool.addUnchecked(txParent.GetHash(), entry.FromTx(txParent));
- testPool.remove(txParent, removed, true);
+ testPool.removeRecursive(txParent, removed);
BOOST_CHECK_EQUAL(removed.size(), 1);
removed.clear();
@@ -74,16 +74,16 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
testPool.addUnchecked(txGrandChild[i].GetHash(), entry.FromTx(txGrandChild[i]));
}
// Remove Child[0], GrandChild[0] should be removed:
- testPool.remove(txChild[0], removed, true);
+ testPool.removeRecursive(txChild[0], removed);
BOOST_CHECK_EQUAL(removed.size(), 2);
removed.clear();
// ... make sure grandchild and child are gone:
- testPool.remove(txGrandChild[0], removed, true);
+ testPool.removeRecursive(txGrandChild[0], removed);
BOOST_CHECK_EQUAL(removed.size(), 0);
- testPool.remove(txChild[0], removed, true);
+ testPool.removeRecursive(txChild[0], removed);
BOOST_CHECK_EQUAL(removed.size(), 0);
// Remove parent, all children/grandchildren should go:
- testPool.remove(txParent, removed, true);
+ testPool.removeRecursive(txParent, removed);
BOOST_CHECK_EQUAL(removed.size(), 5);
BOOST_CHECK_EQUAL(testPool.size(), 0);
removed.clear();
@@ -96,19 +96,19 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
}
// Now remove the parent, as might happen if a block-re-org occurs but the parent cannot be
// put into the mempool (maybe because it is non-standard):
- testPool.remove(txParent, removed, true);
+ testPool.removeRecursive(txParent, removed);
BOOST_CHECK_EQUAL(removed.size(), 6);
BOOST_CHECK_EQUAL(testPool.size(), 0);
removed.clear();
}
-template<int index>
+template<typename name>
void CheckSort(CTxMemPool &pool, std::vector<std::string> &sortedOrder)
{
BOOST_CHECK_EQUAL(pool.size(), sortedOrder.size());
- typename CTxMemPool::indexed_transaction_set::nth_index<index>::type::iterator it = pool.mapTx.get<index>().begin();
+ typename CTxMemPool::indexed_transaction_set::index<name>::type::iterator it = pool.mapTx.get<name>().begin();
int count=0;
- for (; it != pool.mapTx.get<index>().end(); ++it, ++count) {
+ for (; it != pool.mapTx.get<name>().end(); ++it, ++count) {
BOOST_CHECK_EQUAL(it->GetTx().GetHash().ToString(), sortedOrder[count]);
}
}
@@ -164,7 +164,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
sortedOrder[2] = tx1.GetHash().ToString(); // 10000
sortedOrder[3] = tx4.GetHash().ToString(); // 15000
sortedOrder[4] = tx2.GetHash().ToString(); // 20000
- CheckSort<1>(pool, sortedOrder);
+ CheckSort<descendant_score>(pool, sortedOrder);
/* low fee but with high fee child */
/* tx6 -> tx7 -> tx8, tx9 -> tx10 */
@@ -176,7 +176,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
BOOST_CHECK_EQUAL(pool.size(), 6);
// Check that at this point, tx6 is sorted low
sortedOrder.insert(sortedOrder.begin(), tx6.GetHash().ToString());
- CheckSort<1>(pool, sortedOrder);
+ CheckSort<descendant_score>(pool, sortedOrder);
CTxMemPool::setEntries setAncestors;
setAncestors.insert(pool.mapTx.find(tx6.GetHash()));
@@ -202,7 +202,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
sortedOrder.erase(sortedOrder.begin());
sortedOrder.push_back(tx6.GetHash().ToString());
sortedOrder.push_back(tx7.GetHash().ToString());
- CheckSort<1>(pool, sortedOrder);
+ CheckSort<descendant_score>(pool, sortedOrder);
/* low fee child of tx7 */
CMutableTransaction tx8 = CMutableTransaction();
@@ -217,7 +217,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
// Now tx8 should be sorted low, but tx6/tx both high
sortedOrder.insert(sortedOrder.begin(), tx8.GetHash().ToString());
- CheckSort<1>(pool, sortedOrder);
+ CheckSort<descendant_score>(pool, sortedOrder);
/* low fee child of tx7 */
CMutableTransaction tx9 = CMutableTransaction();
@@ -232,7 +232,7 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
// tx9 should be sorted low
BOOST_CHECK_EQUAL(pool.size(), 9);
sortedOrder.insert(sortedOrder.begin(), tx9.GetHash().ToString());
- CheckSort<1>(pool, sortedOrder);
+ CheckSort<descendant_score>(pool, sortedOrder);
std::vector<std::string> snapshotOrder = sortedOrder;
@@ -274,18 +274,18 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
sortedOrder.insert(sortedOrder.begin()+5, tx9.GetHash().ToString());
sortedOrder.insert(sortedOrder.begin()+6, tx8.GetHash().ToString());
sortedOrder.insert(sortedOrder.begin()+7, tx10.GetHash().ToString()); // tx10 is just before tx6
- CheckSort<1>(pool, sortedOrder);
+ CheckSort<descendant_score>(pool, sortedOrder);
// there should be 10 transactions in the mempool
BOOST_CHECK_EQUAL(pool.size(), 10);
// Now try removing tx10 and verify the sort order returns to normal
std::list<CTransaction> removed;
- pool.remove(pool.mapTx.find(tx10.GetHash())->GetTx(), removed, true);
- CheckSort<1>(pool, snapshotOrder);
+ pool.removeRecursive(pool.mapTx.find(tx10.GetHash())->GetTx(), removed);
+ CheckSort<descendant_score>(pool, snapshotOrder);
- pool.remove(pool.mapTx.find(tx9.GetHash())->GetTx(), removed, true);
- pool.remove(pool.mapTx.find(tx8.GetHash())->GetTx(), removed, true);
+ pool.removeRecursive(pool.mapTx.find(tx9.GetHash())->GetTx(), removed);
+ pool.removeRecursive(pool.mapTx.find(tx8.GetHash())->GetTx(), removed);
/* Now check the sort on the mining score index.
* Final order should be:
*
@@ -314,7 +314,111 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
sortedOrder.push_back(tx3.GetHash().ToString());
sortedOrder.push_back(tx6.GetHash().ToString());
}
- CheckSort<3>(pool, sortedOrder);
+ CheckSort<mining_score>(pool, sortedOrder);
+}
+
+BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
+{
+ CTxMemPool pool(CFeeRate(0));
+ TestMemPoolEntryHelper entry;
+ entry.hadNoDependencies = true;
+
+ /* 3rd highest fee */
+ CMutableTransaction tx1 = CMutableTransaction();
+ tx1.vout.resize(1);
+ tx1.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx1.vout[0].nValue = 10 * COIN;
+ pool.addUnchecked(tx1.GetHash(), entry.Fee(10000LL).Priority(10.0).FromTx(tx1));
+
+ /* highest fee */
+ CMutableTransaction tx2 = CMutableTransaction();
+ tx2.vout.resize(1);
+ tx2.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx2.vout[0].nValue = 2 * COIN;
+ pool.addUnchecked(tx2.GetHash(), entry.Fee(20000LL).Priority(9.0).FromTx(tx2));
+ uint64_t tx2Size = ::GetSerializeSize(tx2, SER_NETWORK, PROTOCOL_VERSION);
+
+ /* lowest fee */
+ CMutableTransaction tx3 = CMutableTransaction();
+ tx3.vout.resize(1);
+ tx3.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx3.vout[0].nValue = 5 * COIN;
+ pool.addUnchecked(tx3.GetHash(), entry.Fee(0LL).Priority(100.0).FromTx(tx3));
+
+ /* 2nd highest fee */
+ CMutableTransaction tx4 = CMutableTransaction();
+ tx4.vout.resize(1);
+ tx4.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx4.vout[0].nValue = 6 * COIN;
+ pool.addUnchecked(tx4.GetHash(), entry.Fee(15000LL).Priority(1.0).FromTx(tx4));
+
+ /* equal fee rate to tx1, but newer */
+ CMutableTransaction tx5 = CMutableTransaction();
+ tx5.vout.resize(1);
+ tx5.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx5.vout[0].nValue = 11 * COIN;
+ pool.addUnchecked(tx5.GetHash(), entry.Fee(10000LL).FromTx(tx5));
+ BOOST_CHECK_EQUAL(pool.size(), 5);
+
+ std::vector<std::string> sortedOrder;
+ sortedOrder.resize(5);
+ sortedOrder[0] = tx2.GetHash().ToString(); // 20000
+ sortedOrder[1] = tx4.GetHash().ToString(); // 15000
+ // tx1 and tx5 are both 10000
+ // Ties are broken by hash, not timestamp, so determine which
+ // hash comes first.
+ if (tx1.GetHash() < tx5.GetHash()) {
+ sortedOrder[2] = tx1.GetHash().ToString();
+ sortedOrder[3] = tx5.GetHash().ToString();
+ } else {
+ sortedOrder[2] = tx5.GetHash().ToString();
+ sortedOrder[3] = tx1.GetHash().ToString();
+ }
+ sortedOrder[4] = tx3.GetHash().ToString(); // 0
+
+ CheckSort<ancestor_score>(pool, sortedOrder);
+
+ /* low fee parent with high fee child */
+ /* tx6 (0) -> tx7 (high) */
+ CMutableTransaction tx6 = CMutableTransaction();
+ tx6.vout.resize(1);
+ tx6.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx6.vout[0].nValue = 20 * COIN;
+ uint64_t tx6Size = ::GetSerializeSize(tx6, SER_NETWORK, PROTOCOL_VERSION);
+
+ pool.addUnchecked(tx6.GetHash(), entry.Fee(0LL).FromTx(tx6));
+ BOOST_CHECK_EQUAL(pool.size(), 6);
+ sortedOrder.push_back(tx6.GetHash().ToString());
+ CheckSort<ancestor_score>(pool, sortedOrder);
+
+ CMutableTransaction tx7 = CMutableTransaction();
+ tx7.vin.resize(1);
+ tx7.vin[0].prevout = COutPoint(tx6.GetHash(), 0);
+ tx7.vin[0].scriptSig = CScript() << OP_11;
+ tx7.vout.resize(1);
+ tx7.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx7.vout[0].nValue = 10 * COIN;
+ uint64_t tx7Size = ::GetSerializeSize(tx7, SER_NETWORK, PROTOCOL_VERSION);
+
+ /* set the fee to just below tx2's feerate when including ancestor */
+ CAmount fee = (20000/tx2Size)*(tx7Size + tx6Size) - 1;
+
+ //CTxMemPoolEntry entry7(tx7, fee, 2, 10.0, 1, true);
+ pool.addUnchecked(tx7.GetHash(), entry.Fee(fee).FromTx(tx7));
+ BOOST_CHECK_EQUAL(pool.size(), 7);
+ sortedOrder.insert(sortedOrder.begin()+1, tx7.GetHash().ToString());
+ CheckSort<ancestor_score>(pool, sortedOrder);
+
+ /* after tx6 is mined, tx7 should move up in the sort */
+ std::vector<CTransaction> vtx;
+ vtx.push_back(tx6);
+ std::list<CTransaction> dummy;
+ pool.removeForBlock(vtx, 1, dummy, false);
+
+ sortedOrder.erase(sortedOrder.begin()+1);
+ sortedOrder.pop_back();
+ sortedOrder.insert(sortedOrder.begin(), tx7.GetHash().ToString());
+ CheckSort<ancestor_score>(pool, sortedOrder);
}
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index 71b52409b3..ab6485081c 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -57,6 +57,20 @@ struct {
{2, 0xbbbeb305}, {2, 0xfe1c810a},
};
+CBlockIndex CreateBlockIndex(int nHeight)
+{
+ CBlockIndex index;
+ index.nHeight = nHeight;
+ index.pprev = chainActive.Tip();
+ return index;
+}
+
+bool TestSequenceLocks(const CTransaction &tx, int flags)
+{
+ LOCK(mempool.cs);
+ return CheckSequenceLocks(tx, flags);
+}
+
// NOTE: These tests rely on CreateNewBlock doing its own self-validation!
BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
{
@@ -79,6 +93,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
// We can't make transactions until we have inputs
// Therefore, load 100 blocks :)
+ int baseheight = 0;
std::vector<CTransaction*>txFirst;
for (unsigned int i = 0; i < sizeof(blockinfo)/sizeof(*blockinfo); ++i)
{
@@ -92,7 +107,9 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
txCoinbase.vin[0].scriptSig.push_back(chainActive.Height());
txCoinbase.vout[0].scriptPubKey = CScript();
pblock->vtx[0] = CTransaction(txCoinbase);
- if (txFirst.size() < 2)
+ if (txFirst.size() == 0)
+ baseheight = chainActive.Height();
+ if (txFirst.size() < 4)
txFirst.push_back(new CTransaction(pblock->vtx[0]));
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
pblock->nNonce = blockinfo[i].nonce;
@@ -230,59 +247,133 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
// subsidy changing
int nHeight = chainActive.Height();
- chainActive.Tip()->nHeight = 209999;
+ // Create an actual 209999-long block chain (without valid blocks).
+ while (chainActive.Tip()->nHeight < 209999) {
+ CBlockIndex* prev = chainActive.Tip();
+ CBlockIndex* next = new CBlockIndex();
+ next->phashBlock = new uint256(GetRandHash());
+ pcoinsTip->SetBestBlock(next->GetBlockHash());
+ next->pprev = prev;
+ next->nHeight = prev->nHeight + 1;
+ next->BuildSkip();
+ chainActive.SetTip(next);
+ }
BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey));
delete pblocktemplate;
- chainActive.Tip()->nHeight = 210000;
+ // Extend to a 210000-long block chain.
+ while (chainActive.Tip()->nHeight < 210000) {
+ CBlockIndex* prev = chainActive.Tip();
+ CBlockIndex* next = new CBlockIndex();
+ next->phashBlock = new uint256(GetRandHash());
+ pcoinsTip->SetBestBlock(next->GetBlockHash());
+ next->pprev = prev;
+ next->nHeight = prev->nHeight + 1;
+ next->BuildSkip();
+ chainActive.SetTip(next);
+ }
BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey));
delete pblocktemplate;
- chainActive.Tip()->nHeight = nHeight;
+ // Delete the dummy blocks again.
+ while (chainActive.Tip()->nHeight > nHeight) {
+ CBlockIndex* del = chainActive.Tip();
+ chainActive.SetTip(del->pprev);
+ pcoinsTip->SetBestBlock(del->pprev->GetBlockHash());
+ delete del->phashBlock;
+ delete del;
+ }
// non-final txs in mempool
SetMockTime(chainActive.Tip()->GetMedianTimePast()+1);
+ int flags = LOCKTIME_VERIFY_SEQUENCE|LOCKTIME_MEDIAN_TIME_PAST;
+ // height map
+ std::vector<int> prevheights;
- // height locked
- tx.vin[0].prevout.hash = txFirst[0]->GetHash();
+ // relative height locked
+ tx.nVersion = 2;
+ tx.vin.resize(1);
+ prevheights.resize(1);
+ tx.vin[0].prevout.hash = txFirst[0]->GetHash(); // only 1 transaction
+ tx.vin[0].prevout.n = 0;
tx.vin[0].scriptSig = CScript() << OP_1;
- tx.vin[0].nSequence = 0;
+ tx.vin[0].nSequence = chainActive.Tip()->nHeight + 1; // txFirst[0] is the 2nd block
+ prevheights[0] = baseheight + 1;
+ tx.vout.resize(1);
tx.vout[0].nValue = 4900000000LL;
tx.vout[0].scriptPubKey = CScript() << OP_1;
- tx.nLockTime = chainActive.Tip()->nHeight+1;
+ tx.nLockTime = 0;
hash = tx.GetHash();
mempool.addUnchecked(hash, entry.Fee(100000000L).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
- BOOST_CHECK(!CheckFinalTx(tx, LOCKTIME_MEDIAN_TIME_PAST));
-
- // time locked
- tx2.vin.resize(1);
- tx2.vin[0].prevout.hash = txFirst[1]->GetHash();
- tx2.vin[0].prevout.n = 0;
- tx2.vin[0].scriptSig = CScript() << OP_1;
- tx2.vin[0].nSequence = 0;
- tx2.vout.resize(1);
- tx2.vout[0].nValue = 4900000000LL;
- tx2.vout[0].scriptPubKey = CScript() << OP_1;
- tx2.nLockTime = chainActive.Tip()->GetMedianTimePast()+1;
- hash = tx2.GetHash();
- mempool.addUnchecked(hash, entry.Fee(100000000L).Time(GetTime()).SpendsCoinbase(true).FromTx(tx2));
- BOOST_CHECK(!CheckFinalTx(tx2, LOCKTIME_MEDIAN_TIME_PAST));
+ BOOST_CHECK(CheckFinalTx(tx, flags)); // Locktime passes
+ BOOST_CHECK(!TestSequenceLocks(tx, flags)); // Sequence locks fail
+ BOOST_CHECK(SequenceLocks(tx, flags, &prevheights, CreateBlockIndex(chainActive.Tip()->nHeight + 2))); // Sequence locks pass on 2nd block
+
+ // relative time locked
+ tx.vin[0].prevout.hash = txFirst[1]->GetHash();
+ tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | (((chainActive.Tip()->GetMedianTimePast()+1-chainActive[1]->GetMedianTimePast()) >> CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) + 1); // txFirst[1] is the 3rd block
+ prevheights[0] = baseheight + 2;
+ hash = tx.GetHash();
+ mempool.addUnchecked(hash, entry.Time(GetTime()).FromTx(tx));
+ BOOST_CHECK(CheckFinalTx(tx, flags)); // Locktime passes
+ BOOST_CHECK(!TestSequenceLocks(tx, flags)); // Sequence locks fail
+
+ for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++)
+ chainActive.Tip()->GetAncestor(chainActive.Tip()->nHeight - i)->nTime += 512; //Trick the MedianTimePast
+ BOOST_CHECK(SequenceLocks(tx, flags, &prevheights, CreateBlockIndex(chainActive.Tip()->nHeight + 1))); // Sequence locks pass 512 seconds later
+ for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++)
+ chainActive.Tip()->GetAncestor(chainActive.Tip()->nHeight - i)->nTime -= 512; //undo tricked MTP
+
+ // absolute height locked
+ tx.vin[0].prevout.hash = txFirst[2]->GetHash();
+ tx.vin[0].nSequence = CTxIn::SEQUENCE_FINAL - 1;
+ prevheights[0] = baseheight + 3;
+ tx.nLockTime = chainActive.Tip()->nHeight + 1;
+ hash = tx.GetHash();
+ mempool.addUnchecked(hash, entry.Time(GetTime()).FromTx(tx));
+ BOOST_CHECK(!CheckFinalTx(tx, flags)); // Locktime fails
+ BOOST_CHECK(TestSequenceLocks(tx, flags)); // Sequence locks pass
+ BOOST_CHECK(IsFinalTx(tx, chainActive.Tip()->nHeight + 2, chainActive.Tip()->GetMedianTimePast())); // Locktime passes on 2nd block
+
+ // absolute time locked
+ tx.vin[0].prevout.hash = txFirst[3]->GetHash();
+ tx.nLockTime = chainActive.Tip()->GetMedianTimePast();
+ prevheights.resize(1);
+ prevheights[0] = baseheight + 4;
+ hash = tx.GetHash();
+ mempool.addUnchecked(hash, entry.Time(GetTime()).FromTx(tx));
+ BOOST_CHECK(!CheckFinalTx(tx, flags)); // Locktime fails
+ BOOST_CHECK(TestSequenceLocks(tx, flags)); // Sequence locks pass
+ BOOST_CHECK(IsFinalTx(tx, chainActive.Tip()->nHeight + 2, chainActive.Tip()->GetMedianTimePast() + 1)); // Locktime passes 1 second later
+
+ // mempool-dependent transactions (not added)
+ tx.vin[0].prevout.hash = hash;
+ prevheights[0] = chainActive.Tip()->nHeight + 1;
+ tx.nLockTime = 0;
+ tx.vin[0].nSequence = 0;
+ BOOST_CHECK(CheckFinalTx(tx, flags)); // Locktime passes
+ BOOST_CHECK(TestSequenceLocks(tx, flags)); // Sequence locks pass
+ tx.vin[0].nSequence = 1;
+ BOOST_CHECK(!TestSequenceLocks(tx, flags)); // Sequence locks fail
+ tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG;
+ BOOST_CHECK(TestSequenceLocks(tx, flags)); // Sequence locks pass
+ tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | 1;
+ BOOST_CHECK(!TestSequenceLocks(tx, flags)); // Sequence locks fail
BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey));
- // Neither tx should have make it into the template.
- BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 1);
+ // None of the of the absolute height/time locked tx should have made
+ // it into the template because we still check IsFinalTx in CreateNewBlock,
+ // but relative locked txs will if inconsistently added to mempool.
+ // For now these will still generate a valid template until BIP68 soft fork
+ BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 3);
delete pblocktemplate;
-
- // However if we advance height and time by one, both will.
+ // However if we advance height by 1 and time by 512, all of them should be mined
+ for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++)
+ chainActive.Tip()->GetAncestor(chainActive.Tip()->nHeight - i)->nTime += 512; //Trick the MedianTimePast
chainActive.Tip()->nHeight++;
- SetMockTime(chainActive.Tip()->GetMedianTimePast()+2);
-
- // FIXME: we should *actually* create a new block so the following test
- // works; CheckFinalTx() isn't fooled by monkey-patching nHeight.
- //BOOST_CHECK(CheckFinalTx(tx));
- //BOOST_CHECK(CheckFinalTx(tx2));
+ SetMockTime(chainActive.Tip()->GetMedianTimePast() + 1);
BOOST_CHECK(pblocktemplate = CreateNewBlock(chainparams, scriptPubKey));
- BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 2);
+ BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 5);
delete pblocktemplate;
chainActive.Tip()->nHeight--;
diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp
index 113b9437e0..2f3f607889 100644
--- a/src/test/pmt_tests.cpp
+++ b/src/test/pmt_tests.cpp
@@ -88,7 +88,8 @@ BOOST_AUTO_TEST_CASE(pmt_test1)
// extract merkle root and matched txids from copy
std::vector<uint256> vMatchTxid2;
- uint256 merkleRoot2 = pmt2.ExtractMatches(vMatchTxid2);
+ std::vector<unsigned int> vIndex;
+ uint256 merkleRoot2 = pmt2.ExtractMatches(vMatchTxid2, vIndex);
// check that it has the same merkle root as the original, and a valid one
BOOST_CHECK(merkleRoot1 == merkleRoot2);
@@ -102,7 +103,7 @@ BOOST_AUTO_TEST_CASE(pmt_test1)
CPartialMerkleTreeTester pmt3(pmt2);
pmt3.Damage();
std::vector<uint256> vMatchTxid3;
- uint256 merkleRoot3 = pmt3.ExtractMatches(vMatchTxid3);
+ uint256 merkleRoot3 = pmt3.ExtractMatches(vMatchTxid3, vIndex);
BOOST_CHECK(merkleRoot3 != merkleRoot1);
}
}
@@ -122,7 +123,8 @@ BOOST_AUTO_TEST_CASE(pmt_malleability)
CPartialMerkleTree tree(vTxid, vMatch);
std::vector<uint256> vTxid2;
- BOOST_CHECK(tree.ExtractMatches(vTxid).IsNull());
+ std::vector<unsigned int> vIndex;
+ BOOST_CHECK(tree.ExtractMatches(vTxid, vIndex).IsNull());
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index d6309ca384..1976ee2cb6 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -36,7 +36,7 @@ UniValue CallRPC(string args)
string strMethod = vArgs[0];
vArgs.erase(vArgs.begin());
UniValue params = RPCConvertValues(strMethod, vArgs);
-
+ BOOST_CHECK(tableRPC[strMethod]);
rpcfn_type method = tableRPC[strMethod]->actor;
try {
UniValue result = (*method)(params, false);
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 10175ebe8e..30e3f37e14 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -52,6 +52,64 @@ read_json(const std::string& jsondata)
return v.get_array();
}
+struct ScriptErrorDesc
+{
+ ScriptError_t err;
+ const char *name;
+};
+
+static ScriptErrorDesc script_errors[]={
+ {SCRIPT_ERR_OK, "OK"},
+ {SCRIPT_ERR_UNKNOWN_ERROR, "UNKNOWN_ERROR"},
+ {SCRIPT_ERR_EVAL_FALSE, "EVAL_FALSE"},
+ {SCRIPT_ERR_OP_RETURN, "OP_RETURN"},
+ {SCRIPT_ERR_SCRIPT_SIZE, "SCRIPT_SIZE"},
+ {SCRIPT_ERR_PUSH_SIZE, "PUSH_SIZE"},
+ {SCRIPT_ERR_OP_COUNT, "OP_COUNT"},
+ {SCRIPT_ERR_STACK_SIZE, "STACK_SIZE"},
+ {SCRIPT_ERR_SIG_COUNT, "SIG_COUNT"},
+ {SCRIPT_ERR_PUBKEY_COUNT, "PUBKEY_COUNT"},
+ {SCRIPT_ERR_VERIFY, "VERIFY"},
+ {SCRIPT_ERR_EQUALVERIFY, "EQUALVERIFY"},
+ {SCRIPT_ERR_CHECKMULTISIGVERIFY, "CHECKMULTISIGVERIFY"},
+ {SCRIPT_ERR_CHECKSIGVERIFY, "CHECKSIGVERIFY"},
+ {SCRIPT_ERR_NUMEQUALVERIFY, "NUMEQUALVERIFY"},
+ {SCRIPT_ERR_BAD_OPCODE, "BAD_OPCODE"},
+ {SCRIPT_ERR_DISABLED_OPCODE, "DISABLED_OPCODE"},
+ {SCRIPT_ERR_INVALID_STACK_OPERATION, "INVALID_STACK_OPERATION"},
+ {SCRIPT_ERR_INVALID_ALTSTACK_OPERATION, "INVALID_ALTSTACK_OPERATION"},
+ {SCRIPT_ERR_UNBALANCED_CONDITIONAL, "UNBALANCED_CONDITIONAL"},
+ {SCRIPT_ERR_NEGATIVE_LOCKTIME, "NEGATIVE_LOCKTIME"},
+ {SCRIPT_ERR_UNSATISFIED_LOCKTIME, "UNSATISFIED_LOCKTIME"},
+ {SCRIPT_ERR_SIG_HASHTYPE, "SIG_HASHTYPE"},
+ {SCRIPT_ERR_SIG_DER, "SIG_DER"},
+ {SCRIPT_ERR_MINIMALDATA, "MINIMALDATA"},
+ {SCRIPT_ERR_SIG_PUSHONLY, "SIG_PUSHONLY"},
+ {SCRIPT_ERR_SIG_HIGH_S, "SIG_HIGH_S"},
+ {SCRIPT_ERR_SIG_NULLDUMMY, "SIG_NULLDUMMY"},
+ {SCRIPT_ERR_PUBKEYTYPE, "PUBKEYTYPE"},
+ {SCRIPT_ERR_CLEANSTACK, "CLEANSTACK"},
+ {SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS, "DISCOURAGE_UPGRADABLE_NOPS"}
+};
+
+const char *FormatScriptError(ScriptError_t err)
+{
+ for (unsigned int i=0; i<ARRAYLEN(script_errors); ++i)
+ if (script_errors[i].err == err)
+ return script_errors[i].name;
+ BOOST_ERROR("Unknown scripterror enumeration value, update script_errors in script_tests.cpp.");
+ return "";
+}
+
+ScriptError_t ParseScriptError(const std::string &name)
+{
+ for (unsigned int i=0; i<ARRAYLEN(script_errors); ++i)
+ if (script_errors[i].name == name)
+ return script_errors[i].err;
+ BOOST_ERROR("Unknown scripterror \"" << name << "\" in test description");
+ return SCRIPT_ERR_UNKNOWN_ERROR;
+}
+
BOOST_FIXTURE_TEST_SUITE(script_tests, BasicTestingSetup)
CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey)
@@ -63,7 +121,7 @@ CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey)
txCredit.vout.resize(1);
txCredit.vin[0].prevout.SetNull();
txCredit.vin[0].scriptSig = CScript() << CScriptNum(0) << CScriptNum(0);
- txCredit.vin[0].nSequence = std::numeric_limits<unsigned int>::max();
+ txCredit.vin[0].nSequence = CTxIn::SEQUENCE_FINAL;
txCredit.vout[0].scriptPubKey = scriptPubKey;
txCredit.vout[0].nValue = 0;
@@ -80,20 +138,20 @@ CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CMu
txSpend.vin[0].prevout.hash = txCredit.GetHash();
txSpend.vin[0].prevout.n = 0;
txSpend.vin[0].scriptSig = scriptSig;
- txSpend.vin[0].nSequence = std::numeric_limits<unsigned int>::max();
+ txSpend.vin[0].nSequence = CTxIn::SEQUENCE_FINAL;
txSpend.vout[0].scriptPubKey = CScript();
txSpend.vout[0].nValue = 0;
return txSpend;
}
-void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, bool expect, const std::string& message)
+void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, bool expect, const std::string& message, int scriptError)
{
ScriptError err;
CMutableTransaction tx = BuildSpendingTransaction(scriptSig, BuildCreditingTransaction(scriptPubKey));
CMutableTransaction tx2 = tx;
BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, flags, MutableTransactionSignatureChecker(&tx, 0), &err) == expect, message);
- BOOST_CHECK_MESSAGE(expect == (err == SCRIPT_ERR_OK), std::string(ScriptErrorString(err)) + ": " + message);
+ BOOST_CHECK_MESSAGE(scriptError == -1 || err == scriptError, std::string(FormatScriptError(err)) + " where " + std::string(FormatScriptError((ScriptError_t)scriptError)) + " expected: " + message);
#if defined(HAVE_CONSENSUS_LIB)
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
stream << tx2;
@@ -187,6 +245,7 @@ private:
std::vector<unsigned char> push;
std::string comment;
int flags;
+ int scriptError;
void DoPush()
{
@@ -204,7 +263,7 @@ private:
}
public:
- TestBuilder(const CScript& redeemScript, const std::string& comment_, int flags_, bool P2SH = false) : scriptPubKey(redeemScript), havePush(false), comment(comment_), flags(flags_)
+ TestBuilder(const CScript& redeemScript, const std::string& comment_, int flags_, bool P2SH = false) : scriptPubKey(redeemScript), havePush(false), comment(comment_), flags(flags_), scriptError(-1)
{
if (P2SH) {
creditTx = BuildCreditingTransaction(CScript() << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL);
@@ -214,6 +273,12 @@ public:
spendTx = BuildSpendingTransaction(CScript(), creditTx);
}
+ TestBuilder& ScriptError(ScriptError_t err)
+ {
+ scriptError = err;
+ return *this;
+ }
+
TestBuilder& Add(const CScript& script)
{
DoPush();
@@ -288,7 +353,7 @@ public:
{
TestBuilder copy = *this; // Make a copy so we can rollback the push.
DoPush();
- DoTest(creditTx.vout[0].scriptPubKey, spendTx.vin[0].scriptSig, flags, expect, comment);
+ DoTest(creditTx.vout[0].scriptPubKey, spendTx.vin[0].scriptSig, flags, expect, comment, expect ? SCRIPT_ERR_OK : scriptError);
*this = copy;
return *this;
}
@@ -301,6 +366,8 @@ public:
array.push_back(FormatScript(creditTx.vout[0].scriptPubKey));
array.push_back(FormatScriptFlags(flags));
array.push_back(comment);
+ if (scriptError != -1)
+ array.push_back(FormatScriptError((ScriptError_t)scriptError));
return array;
}
@@ -328,99 +395,99 @@ BOOST_AUTO_TEST_CASE(script_build)
).PushSig(keys.key0));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"P2PK, bad sig", 0
- ).PushSig(keys.key0).DamagePush(10));
+ ).PushSig(keys.key0).DamagePush(10).ScriptError(SCRIPT_ERR_EVAL_FALSE));
good.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey1C.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG,
"P2PKH", 0
).PushSig(keys.key1).Push(keys.pubkey1C));
bad.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey2C.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG,
"P2PKH, bad pubkey", 0
- ).PushSig(keys.key2).Push(keys.pubkey2C).DamagePush(5));
+ ).PushSig(keys.key2).Push(keys.pubkey2C).DamagePush(5).ScriptError(SCRIPT_ERR_EQUALVERIFY));
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
"P2PK anyonecanpay", 0
).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_ANYONECANPAY));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
"P2PK anyonecanpay marked with normal hashtype", 0
- ).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_ANYONECANPAY).EditPush(70, "81", "01"));
+ ).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_ANYONECANPAY).EditPush(70, "81", "01").ScriptError(SCRIPT_ERR_EVAL_FALSE));
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG,
"P2SH(P2PK)", SCRIPT_VERIFY_P2SH, true
).PushSig(keys.key0).PushRedeem());
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG,
"P2SH(P2PK), bad redeemscript", SCRIPT_VERIFY_P2SH, true
- ).PushSig(keys.key0).PushRedeem().DamagePush(10));
+ ).PushSig(keys.key0).PushRedeem().DamagePush(10).ScriptError(SCRIPT_ERR_EVAL_FALSE));
good.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey1.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG,
"P2SH(P2PKH), bad sig but no VERIFY_P2SH", 0, true
).PushSig(keys.key0).DamagePush(10).PushRedeem());
bad.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey1.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG,
"P2SH(P2PKH), bad sig", SCRIPT_VERIFY_P2SH, true
- ).PushSig(keys.key0).DamagePush(10).PushRedeem());
+ ).PushSig(keys.key0).DamagePush(10).PushRedeem().ScriptError(SCRIPT_ERR_EQUALVERIFY));
good.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG,
"3-of-3", 0
).Num(0).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2));
bad.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG,
"3-of-3, 2 sigs", 0
- ).Num(0).PushSig(keys.key0).PushSig(keys.key1).Num(0));
+ ).Num(0).PushSig(keys.key0).PushSig(keys.key1).Num(0).ScriptError(SCRIPT_ERR_EVAL_FALSE));
good.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG,
"P2SH(2-of-3)", SCRIPT_VERIFY_P2SH, true
).Num(0).PushSig(keys.key1).PushSig(keys.key2).PushRedeem());
bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG,
"P2SH(2-of-3), 1 sig", SCRIPT_VERIFY_P2SH, true
- ).Num(0).PushSig(keys.key1).Num(0).PushRedeem());
+ ).Num(0).PushSig(keys.key1).Num(0).PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"P2PK with too much R padding but no DERSIG", 0
).PushSig(keys.key1, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000"));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"P2PK with too much R padding", SCRIPT_VERIFY_DERSIG
- ).PushSig(keys.key1, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000"));
+ ).PushSig(keys.key1, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").ScriptError(SCRIPT_ERR_SIG_DER));
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"P2PK with too much S padding but no DERSIG", 0
).PushSig(keys.key1, SIGHASH_ALL).EditPush(1, "44", "45").EditPush(37, "20", "2100"));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"P2PK with too much S padding", SCRIPT_VERIFY_DERSIG
- ).PushSig(keys.key1, SIGHASH_ALL).EditPush(1, "44", "45").EditPush(37, "20", "2100"));
+ ).PushSig(keys.key1, SIGHASH_ALL).EditPush(1, "44", "45").EditPush(37, "20", "2100").ScriptError(SCRIPT_ERR_SIG_DER));
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"P2PK with too little R padding but no DERSIG", 0
).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"P2PK with too little R padding", SCRIPT_VERIFY_DERSIG
- ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
+ ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_SIG_DER));
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG << OP_NOT,
"P2PK NOT with bad sig with too much R padding but no DERSIG", 0
).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").DamagePush(10));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG << OP_NOT,
"P2PK NOT with bad sig with too much R padding", SCRIPT_VERIFY_DERSIG
- ).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").DamagePush(10));
+ ).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").DamagePush(10).ScriptError(SCRIPT_ERR_SIG_DER));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG << OP_NOT,
"P2PK NOT with too much R padding but no DERSIG", 0
- ).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000"));
+ ).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").ScriptError(SCRIPT_ERR_EVAL_FALSE));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG << OP_NOT,
"P2PK NOT with too much R padding", SCRIPT_VERIFY_DERSIG
- ).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000"));
+ ).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").ScriptError(SCRIPT_ERR_SIG_DER));
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"BIP66 example 1, without DERSIG", 0
).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"BIP66 example 1, with DERSIG", SCRIPT_VERIFY_DERSIG
- ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
+ ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_SIG_DER));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT,
"BIP66 example 2, without DERSIG", 0
- ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
+ ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_EVAL_FALSE));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT,
"BIP66 example 2, with DERSIG", SCRIPT_VERIFY_DERSIG
- ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
+ ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_SIG_DER));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"BIP66 example 3, without DERSIG", 0
- ).Num(0));
+ ).Num(0).ScriptError(SCRIPT_ERR_EVAL_FALSE));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"BIP66 example 3, with DERSIG", SCRIPT_VERIFY_DERSIG
- ).Num(0));
+ ).Num(0).ScriptError(SCRIPT_ERR_EVAL_FALSE));
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT,
"BIP66 example 4, without DERSIG", 0
).Num(0));
@@ -429,46 +496,46 @@ BOOST_AUTO_TEST_CASE(script_build)
).Num(0));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"BIP66 example 5, without DERSIG", 0
- ).Num(1));
+ ).Num(1).ScriptError(SCRIPT_ERR_EVAL_FALSE));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
"BIP66 example 5, with DERSIG", SCRIPT_VERIFY_DERSIG
- ).Num(1));
+ ).Num(1).ScriptError(SCRIPT_ERR_SIG_DER));
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT,
"BIP66 example 6, without DERSIG", 0
).Num(1));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT,
"BIP66 example 6, with DERSIG", SCRIPT_VERIFY_DERSIG
- ).Num(1));
+ ).Num(1).ScriptError(SCRIPT_ERR_SIG_DER));
good.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG,
"BIP66 example 7, without DERSIG", 0
).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2));
bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG,
"BIP66 example 7, with DERSIG", SCRIPT_VERIFY_DERSIG
- ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2));
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2).ScriptError(SCRIPT_ERR_SIG_DER));
bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT,
"BIP66 example 8, without DERSIG", 0
- ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2));
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2).ScriptError(SCRIPT_ERR_EVAL_FALSE));
bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT,
"BIP66 example 8, with DERSIG", SCRIPT_VERIFY_DERSIG
- ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2));
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2).ScriptError(SCRIPT_ERR_SIG_DER));
bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG,
"BIP66 example 9, without DERSIG", 0
- ).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
+ ).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_EVAL_FALSE));
bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG,
"BIP66 example 9, with DERSIG", SCRIPT_VERIFY_DERSIG
- ).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
+ ).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_SIG_DER));
good.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT,
"BIP66 example 10, without DERSIG", 0
).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT,
"BIP66 example 10, with DERSIG", SCRIPT_VERIFY_DERSIG
- ).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
+ ).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_SIG_DER));
bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG,
"BIP66 example 11, without DERSIG", 0
- ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0));
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0).ScriptError(SCRIPT_ERR_EVAL_FALSE));
bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG,
"BIP66 example 11, with DERSIG", SCRIPT_VERIFY_DERSIG
- ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0));
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0).ScriptError(SCRIPT_ERR_EVAL_FALSE));
good.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT,
"BIP66 example 12, without DERSIG", 0
).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0));
@@ -480,33 +547,33 @@ BOOST_AUTO_TEST_CASE(script_build)
).PushSig(keys.key2, SIGHASH_ALL).EditPush(70, "01", "0101"));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
"P2PK with multi-byte hashtype, with DERSIG", SCRIPT_VERIFY_DERSIG
- ).PushSig(keys.key2, SIGHASH_ALL).EditPush(70, "01", "0101"));
+ ).PushSig(keys.key2, SIGHASH_ALL).EditPush(70, "01", "0101").ScriptError(SCRIPT_ERR_SIG_DER));
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
"P2PK with high S but no LOW_S", 0
).PushSig(keys.key2, SIGHASH_ALL, 32, 33));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
"P2PK with high S", SCRIPT_VERIFY_LOW_S
- ).PushSig(keys.key2, SIGHASH_ALL, 32, 33));
+ ).PushSig(keys.key2, SIGHASH_ALL, 32, 33).ScriptError(SCRIPT_ERR_SIG_HIGH_S));
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG,
"P2PK with hybrid pubkey but no STRICTENC", 0
).PushSig(keys.key0, SIGHASH_ALL));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG,
"P2PK with hybrid pubkey", SCRIPT_VERIFY_STRICTENC
- ).PushSig(keys.key0, SIGHASH_ALL));
+ ).PushSig(keys.key0, SIGHASH_ALL).ScriptError(SCRIPT_ERR_PUBKEYTYPE));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT,
"P2PK NOT with hybrid pubkey but no STRICTENC", 0
- ).PushSig(keys.key0, SIGHASH_ALL));
+ ).PushSig(keys.key0, SIGHASH_ALL).ScriptError(SCRIPT_ERR_EVAL_FALSE));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT,
"P2PK NOT with hybrid pubkey", SCRIPT_VERIFY_STRICTENC
- ).PushSig(keys.key0, SIGHASH_ALL));
+ ).PushSig(keys.key0, SIGHASH_ALL).ScriptError(SCRIPT_ERR_PUBKEYTYPE));
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT,
"P2PK NOT with invalid hybrid pubkey but no STRICTENC", 0
).PushSig(keys.key0, SIGHASH_ALL).DamagePush(10));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT,
"P2PK NOT with invalid hybrid pubkey", SCRIPT_VERIFY_STRICTENC
- ).PushSig(keys.key0, SIGHASH_ALL).DamagePush(10));
+ ).PushSig(keys.key0, SIGHASH_ALL).DamagePush(10).ScriptError(SCRIPT_ERR_PUBKEYTYPE));
good.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey0H) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG,
"1-of-2 with the second 1 hybrid pubkey and no STRICTENC", 0
).Num(0).PushSig(keys.key1, SIGHASH_ALL));
@@ -515,62 +582,61 @@ BOOST_AUTO_TEST_CASE(script_build)
).Num(0).PushSig(keys.key1, SIGHASH_ALL));
bad.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0H) << OP_2 << OP_CHECKMULTISIG,
"1-of-2 with the first 1 hybrid pubkey", SCRIPT_VERIFY_STRICTENC
- ).Num(0).PushSig(keys.key1, SIGHASH_ALL));
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL).ScriptError(SCRIPT_ERR_PUBKEYTYPE));
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
"P2PK with undefined hashtype but no STRICTENC", 0
).PushSig(keys.key1, 5));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
"P2PK with undefined hashtype", SCRIPT_VERIFY_STRICTENC
- ).PushSig(keys.key1, 5));
+ ).PushSig(keys.key1, 5).ScriptError(SCRIPT_ERR_SIG_HASHTYPE));
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG << OP_NOT,
"P2PK NOT with invalid sig and undefined hashtype but no STRICTENC", 0
).PushSig(keys.key1, 5).DamagePush(10));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG << OP_NOT,
"P2PK NOT with invalid sig and undefined hashtype", SCRIPT_VERIFY_STRICTENC
- ).PushSig(keys.key1, 5).DamagePush(10));
+ ).PushSig(keys.key1, 5).DamagePush(10).ScriptError(SCRIPT_ERR_SIG_HASHTYPE));
good.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG,
"3-of-3 with nonzero dummy but no NULLDUMMY", 0
).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2));
bad.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG,
"3-of-3 with nonzero dummy", SCRIPT_VERIFY_NULLDUMMY
- ).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2));
+ ).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2).ScriptError(SCRIPT_ERR_SIG_NULLDUMMY));
good.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG << OP_NOT,
"3-of-3 NOT with invalid sig and nonzero dummy but no NULLDUMMY", 0
).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2).DamagePush(10));
bad.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG << OP_NOT,
"3-of-3 NOT with invalid sig with nonzero dummy", SCRIPT_VERIFY_NULLDUMMY
- ).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2).DamagePush(10));
+ ).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2).DamagePush(10).ScriptError(SCRIPT_ERR_SIG_NULLDUMMY));
good.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG,
"2-of-2 with two identical keys and sigs pushed using OP_DUP but no SIGPUSHONLY", 0
).Num(0).PushSig(keys.key1).Add(CScript() << OP_DUP));
bad.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG,
"2-of-2 with two identical keys and sigs pushed using OP_DUP", SCRIPT_VERIFY_SIGPUSHONLY
- ).Num(0).PushSig(keys.key1).Add(CScript() << OP_DUP));
+ ).Num(0).PushSig(keys.key1).Add(CScript() << OP_DUP).ScriptError(SCRIPT_ERR_SIG_PUSHONLY));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
"P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY", 0
- ).PushSig(keys.key2).PushRedeem());
+ ).PushSig(keys.key2).PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
"P2SH(P2PK) with non-push scriptSig", SCRIPT_VERIFY_SIGPUSHONLY
- ).PushSig(keys.key2).PushRedeem());
+ ).PushSig(keys.key2).PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
good.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG,
"2-of-2 with two identical keys and sigs pushed", SCRIPT_VERIFY_SIGPUSHONLY
).Num(0).PushSig(keys.key1).PushSig(keys.key1));
-
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"P2PK with unnecessary input but no CLEANSTACK", SCRIPT_VERIFY_P2SH
).Num(11).PushSig(keys.key0));
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"P2PK with unnecessary input", SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH
- ).Num(11).PushSig(keys.key0));
+ ).Num(11).PushSig(keys.key0).ScriptError(SCRIPT_ERR_CLEANSTACK));
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"P2SH with unnecessary input but no CLEANSTACK", SCRIPT_VERIFY_P2SH, true
).Num(11).PushSig(keys.key0).PushRedeem());
bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"P2SH with unnecessary input", SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH, true
- ).Num(11).PushSig(keys.key0).PushRedeem());
+ ).Num(11).PushSig(keys.key0).PushRedeem().ScriptError(SCRIPT_ERR_CLEANSTACK));
good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
"P2SH with CLEANSTACK", SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH, true
).PushSig(keys.key0).PushRedeem());
@@ -585,11 +651,11 @@ BOOST_AUTO_TEST_CASE(script_build)
for (unsigned int idx = 0; idx < json_good.size(); idx++) {
const UniValue& tv = json_good[idx];
- tests_good.insert(tv.get_array().write());
+ tests_good.insert(tv.get_array().write(1,4));
}
for (unsigned int idx = 0; idx < json_bad.size(); idx++) {
const UniValue& tv = json_bad[idx];
- tests_bad.insert(tv.get_array().write());
+ tests_bad.insert(tv.get_array().write(1,4));
}
}
@@ -598,7 +664,7 @@ BOOST_AUTO_TEST_CASE(script_build)
BOOST_FOREACH(TestBuilder& test, good) {
test.Test(true);
- std::string str = test.GetJSON().write();
+ std::string str = test.GetJSON().write(1,4);
#ifndef UPDATE_JSON_TESTS
if (tests_good.count(str) == 0) {
BOOST_CHECK_MESSAGE(false, "Missing auto script_valid test: " + test.GetComment());
@@ -608,7 +674,7 @@ BOOST_AUTO_TEST_CASE(script_build)
}
BOOST_FOREACH(TestBuilder& test, bad) {
test.Test(false);
- std::string str = test.GetJSON().write();
+ std::string str = test.GetJSON().write(1,4);
#ifndef UPDATE_JSON_TESTS
if (tests_bad.count(str) == 0) {
BOOST_CHECK_MESSAGE(false, "Missing auto script_invalid test: " + test.GetComment());
@@ -652,7 +718,7 @@ BOOST_AUTO_TEST_CASE(script_valid)
CScript scriptPubKey = ParseScript(scriptPubKeyString);
unsigned int scriptflags = ParseScriptFlags(test[2].get_str());
- DoTest(scriptPubKey, scriptSig, scriptflags, true, strTest);
+ DoTest(scriptPubKey, scriptSig, scriptflags, true, strTest, SCRIPT_ERR_OK);
}
}
@@ -660,7 +726,6 @@ BOOST_AUTO_TEST_CASE(script_invalid)
{
// Scripts that should evaluate as invalid
UniValue tests = read_json(std::string(json_tests::script_invalid, json_tests::script_invalid + sizeof(json_tests::script_invalid)));
-
for (unsigned int idx = 0; idx < tests.size(); idx++) {
UniValue test = tests[idx];
string strTest = test.write();
@@ -676,8 +741,12 @@ BOOST_AUTO_TEST_CASE(script_invalid)
string scriptPubKeyString = test[1].get_str();
CScript scriptPubKey = ParseScript(scriptPubKeyString);
unsigned int scriptflags = ParseScriptFlags(test[2].get_str());
+ int scriptError = -1; // Expected script error is optional, and follows comment
+ if (test.size() >= 5 && test[4].get_str() != "") {
+ scriptError = ParseScriptError(test[4].get_str());
+ }
- DoTest(scriptPubKey, scriptSig, scriptflags, false, strTest);
+ DoTest(scriptPubKey, scriptSig, scriptflags, false, strTest, scriptError);
}
}
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index 0416d0c926..1f2e034b01 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -17,12 +17,15 @@
#include "txdb.h"
#include "txmempool.h"
#include "ui_interface.h"
-#include "util.h"
+#include "rpc/server.h"
+#include "rpc/register.h"
#ifdef ENABLE_WALLET
#include "wallet/db.h"
#include "wallet/wallet.h"
#endif
+#include "test/testutil.h"
+
#include <boost/filesystem.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/thread.hpp>
@@ -52,9 +55,12 @@ BasicTestingSetup::~BasicTestingSetup()
TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(chainName)
{
const CChainParams& chainparams = Params();
+ // Ideally we'd move all the RPC tests to the functional testing framework
+ // instead of unit tests, but for now we need these here.
+ RegisterAllCoreRPCCommands(tableRPC);
#ifdef ENABLE_WALLET
bitdb.MakeMock();
- walletRegisterRPCCommands();
+ RegisterWalletRPCCommands(tableRPC);
#endif
ClearDatadirCache();
pathTemp = GetTempPath() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000)));
@@ -151,7 +157,7 @@ CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(CMutableTransaction &tx, CTxMemPo
CAmount inChainValue = hasNoDependencies ? txn.GetValueOut() : 0;
return CTxMemPoolEntry(txn, nFee, nTime, dPriority, nHeight,
- hasNoDependencies, inChainValue, spendsCoinbase, sigOpCount);
+ hasNoDependencies, inChainValue, spendsCoinbase, sigOpCount, lp);
}
void Shutdown(void* parg)
diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h
index c623920880..769ae5a132 100644
--- a/src/test/test_bitcoin.h
+++ b/src/test/test_bitcoin.h
@@ -9,6 +9,7 @@
#include "key.h"
#include "pubkey.h"
#include "txdb.h"
+#include "txmempool.h"
#include <boost/filesystem.hpp>
#include <boost/thread.hpp>
@@ -71,7 +72,8 @@ struct TestMemPoolEntryHelper
bool hadNoDependencies;
bool spendsCoinbase;
unsigned int sigOpCount;
-
+ LockPoints lp;
+
TestMemPoolEntryHelper() :
nFee(0), nTime(0), dPriority(0.0), nHeight(1),
hadNoDependencies(false), spendsCoinbase(false), sigOpCount(1) { }
diff --git a/src/test/testutil.cpp b/src/test/testutil.cpp
new file mode 100644
index 0000000000..304cffb798
--- /dev/null
+++ b/src/test/testutil.cpp
@@ -0,0 +1,33 @@
+// Copyright (c) 2009-2016 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "testutil.h"
+
+#ifdef WIN32
+#include <shlobj.h>
+#endif
+
+#include <boost/filesystem.hpp>
+
+boost::filesystem::path GetTempPath() {
+#if BOOST_FILESYSTEM_VERSION == 3
+ return boost::filesystem::temp_directory_path();
+#else
+ // TODO: remove when we don't support filesystem v2 anymore
+ boost::filesystem::path path;
+#ifdef WIN32
+ char pszPath[MAX_PATH] = "";
+
+ if (GetTempPathA(MAX_PATH, pszPath))
+ path = boost::filesystem::path(pszPath);
+#else
+ path = boost::filesystem::path("/tmp");
+#endif
+ if (path.empty() || !boost::filesystem::is_directory(path)) {
+ LogPrintf("GetTempPath(): failed to find temp path\n");
+ return boost::filesystem::path("");
+ }
+ return path;
+#endif
+}
diff --git a/src/test/testutil.h b/src/test/testutil.h
new file mode 100644
index 0000000000..5875dc50e6
--- /dev/null
+++ b/src/test/testutil.h
@@ -0,0 +1,15 @@
+// Copyright (c) 2009-2016 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+/**
+ * Utility functions shared by unit tests
+ */
+#ifndef BITCOIN_TEST_TESTUTIL_H
+#define BITCOIN_TEST_TESTUTIL_H
+
+#include <boost/filesystem/path.hpp>
+
+boost::filesystem::path GetTempPath();
+
+#endif // BITCOIN_TEST_TESTUTIL_H
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index c27f194b55..d9195bf345 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -44,7 +44,8 @@ static std::map<string, unsigned int> mapFlagNames = boost::assign::map_list_of
(string("NULLDUMMY"), (unsigned int)SCRIPT_VERIFY_NULLDUMMY)
(string("DISCOURAGE_UPGRADABLE_NOPS"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS)
(string("CLEANSTACK"), (unsigned int)SCRIPT_VERIFY_CLEANSTACK)
- (string("CHECKLOCKTIMEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY);
+ (string("CHECKLOCKTIMEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)
+ (string("CHECKSEQUENCEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKSEQUENCEVERIFY);
unsigned int ParseScriptFlags(string strFlags)
{
diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp
index c29e30792a..237b26329b 100644
--- a/src/test/txvalidationcache_tests.cpp
+++ b/src/test/txvalidationcache_tests.cpp
@@ -23,7 +23,7 @@ ToMemPool(CMutableTransaction& tx)
LOCK(cs_main);
CValidationState state;
- return AcceptToMemoryPool(mempool, state, tx, false, NULL, true, 0);
+ return AcceptToMemoryPool(mempool, state, tx, false, NULL, NULL, true, 0);
}
BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 01bc2032d0..b99f952a0d 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -60,6 +60,10 @@ BOOST_AUTO_TEST_CASE(util_ParseHex)
result = ParseHex("12 34 56 78");
BOOST_CHECK(result.size() == 4 && result[0] == 0x12 && result[1] == 0x34 && result[2] == 0x56 && result[3] == 0x78);
+ // Leading space must be supported (used in CDBEnv::Salvage)
+ result = ParseHex(" 89 34 56 78");
+ BOOST_CHECK(result.size() == 4 && result[0] == 0x89 && result[1] == 0x34 && result[2] == 0x56 && result[3] == 0x78);
+
// Stop parsing at invalid value
result = ParseHex("1234 invalid 1234");
BOOST_CHECK(result.size() == 2 && result[0] == 0x12 && result[1] == 0x34);
@@ -196,6 +200,8 @@ BOOST_AUTO_TEST_CASE(util_ParseMoney)
BOOST_CHECK_EQUAL(ret, COIN*10);
BOOST_CHECK(ParseMoney("1.00", ret));
BOOST_CHECK_EQUAL(ret, COIN);
+ BOOST_CHECK(ParseMoney("1", ret));
+ BOOST_CHECK_EQUAL(ret, COIN);
BOOST_CHECK(ParseMoney("0.1", ret));
BOOST_CHECK_EQUAL(ret, COIN/10);
BOOST_CHECK(ParseMoney("0.01", ret));
@@ -215,6 +221,9 @@ BOOST_AUTO_TEST_CASE(util_ParseMoney)
// Attempted 63 bit overflow should fail
BOOST_CHECK(!ParseMoney("92233720368.54775808", ret));
+
+ // Parsing negative amounts must fail
+ BOOST_CHECK(!ParseMoney("-1", ret));
}
BOOST_AUTO_TEST_CASE(util_IsHex)
diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp
new file mode 100644
index 0000000000..1f86a06a3f
--- /dev/null
+++ b/src/test/versionbits_tests.cpp
@@ -0,0 +1,316 @@
+// 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.
+
+#include "chain.h"
+#include "random.h"
+#include "versionbits.h"
+#include "test/test_bitcoin.h"
+#include "chainparams.h"
+#include "main.h"
+#include "consensus/params.h"
+
+#include <boost/test/unit_test.hpp>
+
+/* Define a virtual block time, one block per 10 minutes after Nov 14 2014, 0:55:36am */
+int32_t TestTime(int nHeight) { return 1415926536 + 600 * nHeight; }
+
+static const Consensus::Params paramsDummy = Consensus::Params();
+
+class TestConditionChecker : public AbstractThresholdConditionChecker
+{
+private:
+ mutable ThresholdConditionCache cache;
+
+public:
+ int64_t BeginTime(const Consensus::Params& params) const { return TestTime(10000); }
+ int64_t EndTime(const Consensus::Params& params) const { return TestTime(20000); }
+ int Period(const Consensus::Params& params) const { return 1000; }
+ int Threshold(const Consensus::Params& params) const { return 900; }
+ bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const { return (pindex->nVersion & 0x100); }
+
+ ThresholdState GetStateFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateFor(pindexPrev, paramsDummy, cache); }
+};
+
+#define CHECKERS 6
+
+class VersionBitsTester
+{
+ // A fake blockchain
+ std::vector<CBlockIndex*> vpblock;
+
+ // 6 independent checkers for the same bit.
+ // The first one performs all checks, the second only 50%, the third only 25%, etc...
+ // This is to test whether lack of cached information leads to the same results.
+ TestConditionChecker checker[CHECKERS];
+
+ // Test counter (to identify failures)
+ int num;
+
+public:
+ VersionBitsTester() : num(0) {}
+
+ VersionBitsTester& Reset() {
+ for (unsigned int i = 0; i < vpblock.size(); i++) {
+ delete vpblock[i];
+ }
+ for (unsigned int i = 0; i < CHECKERS; i++) {
+ checker[i] = TestConditionChecker();
+ }
+ vpblock.clear();
+ return *this;
+ }
+
+ ~VersionBitsTester() {
+ Reset();
+ }
+
+ VersionBitsTester& Mine(unsigned int height, int32_t nTime, int32_t nVersion) {
+ while (vpblock.size() < height) {
+ CBlockIndex* pindex = new CBlockIndex();
+ pindex->nHeight = vpblock.size();
+ pindex->pprev = vpblock.size() > 0 ? vpblock.back() : NULL;
+ pindex->nTime = nTime;
+ pindex->nVersion = nVersion;
+ pindex->BuildSkip();
+ vpblock.push_back(pindex);
+ }
+ return *this;
+ }
+
+ VersionBitsTester& TestDefined() {
+ for (int i = 0; i < CHECKERS; i++) {
+ if ((insecure_rand() & ((1 << i) - 1)) == 0) {
+ BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_DEFINED, strprintf("Test %i for DEFINED", num));
+ }
+ }
+ num++;
+ return *this;
+ }
+
+ VersionBitsTester& TestStarted() {
+ for (int i = 0; i < CHECKERS; i++) {
+ if ((insecure_rand() & ((1 << i) - 1)) == 0) {
+ BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_STARTED, strprintf("Test %i for STARTED", num));
+ }
+ }
+ num++;
+ return *this;
+ }
+
+ VersionBitsTester& TestLockedIn() {
+ for (int i = 0; i < CHECKERS; i++) {
+ if ((insecure_rand() & ((1 << i) - 1)) == 0) {
+ BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_LOCKED_IN, strprintf("Test %i for LOCKED_IN", num));
+ }
+ }
+ num++;
+ return *this;
+ }
+
+ VersionBitsTester& TestActive() {
+ for (int i = 0; i < CHECKERS; i++) {
+ if ((insecure_rand() & ((1 << i) - 1)) == 0) {
+ BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_ACTIVE, strprintf("Test %i for ACTIVE", num));
+ }
+ }
+ num++;
+ return *this;
+ }
+
+ VersionBitsTester& TestFailed() {
+ for (int i = 0; i < CHECKERS; i++) {
+ if ((insecure_rand() & ((1 << i) - 1)) == 0) {
+ BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_FAILED, strprintf("Test %i for FAILED", num));
+ }
+ }
+ num++;
+ return *this;
+ }
+
+ CBlockIndex * Tip() { return vpblock.size() ? vpblock.back() : NULL; }
+};
+
+BOOST_FIXTURE_TEST_SUITE(versionbits_tests, TestingSetup)
+
+BOOST_AUTO_TEST_CASE(versionbits_test)
+{
+ for (int i = 0; i < 64; i++) {
+ // DEFINED -> FAILED
+ VersionBitsTester().TestDefined()
+ .Mine(1, TestTime(1), 0x100).TestDefined()
+ .Mine(11, TestTime(11), 0x100).TestDefined()
+ .Mine(989, TestTime(989), 0x100).TestDefined()
+ .Mine(999, TestTime(20000), 0x100).TestDefined()
+ .Mine(1000, TestTime(20000), 0x100).TestFailed()
+ .Mine(1999, TestTime(30001), 0x100).TestFailed()
+ .Mine(2000, TestTime(30002), 0x100).TestFailed()
+ .Mine(2001, TestTime(30003), 0x100).TestFailed()
+ .Mine(2999, TestTime(30004), 0x100).TestFailed()
+ .Mine(3000, TestTime(30005), 0x100).TestFailed()
+
+ // DEFINED -> STARTED -> FAILED
+ .Reset().TestDefined()
+ .Mine(1, TestTime(1), 0).TestDefined()
+ .Mine(1000, TestTime(10000) - 1, 0x100).TestDefined() // One second more and it would be defined
+ .Mine(2000, TestTime(10000), 0x100).TestStarted() // So that's what happens the next period
+ .Mine(2051, TestTime(10010), 0).TestStarted() // 51 old blocks
+ .Mine(2950, TestTime(10020), 0x100).TestStarted() // 899 new blocks
+ .Mine(3000, TestTime(20000), 0).TestFailed() // 50 old blocks (so 899 out of the past 1000)
+ .Mine(4000, TestTime(20010), 0x100).TestFailed()
+
+ // DEFINED -> STARTED -> FAILED while threshold reached
+ .Reset().TestDefined()
+ .Mine(1, TestTime(1), 0).TestDefined()
+ .Mine(1000, TestTime(10000) - 1, 0x101).TestDefined() // One second more and it would be defined
+ .Mine(2000, TestTime(10000), 0x101).TestStarted() // So that's what happens the next period
+ .Mine(2999, TestTime(30000), 0x100).TestStarted() // 999 new blocks
+ .Mine(3000, TestTime(30000), 0x100).TestFailed() // 1 new block (so 1000 out of the past 1000 are new)
+ .Mine(3999, TestTime(30001), 0).TestFailed()
+ .Mine(4000, TestTime(30002), 0).TestFailed()
+ .Mine(14333, TestTime(30003), 0).TestFailed()
+ .Mine(24000, TestTime(40000), 0).TestFailed()
+
+ // DEFINED -> STARTED -> LOCKEDIN at the last minute -> ACTIVE
+ .Reset().TestDefined()
+ .Mine(1, TestTime(1), 0).TestDefined()
+ .Mine(1000, TestTime(10000) - 1, 0x101).TestDefined() // One second more and it would be defined
+ .Mine(2000, TestTime(10000), 0x101).TestStarted() // So that's what happens the next period
+ .Mine(2050, TestTime(10010), 0x200).TestStarted() // 50 old blocks
+ .Mine(2950, TestTime(10020), 0x100).TestStarted() // 900 new blocks
+ .Mine(2999, TestTime(19999), 0x200).TestStarted() // 49 old blocks
+ .Mine(3000, TestTime(29999), 0x200).TestLockedIn() // 1 old block (so 900 out of the past 1000)
+ .Mine(3999, TestTime(30001), 0).TestLockedIn()
+ .Mine(4000, TestTime(30002), 0).TestActive()
+ .Mine(14333, TestTime(30003), 0).TestActive()
+ .Mine(24000, TestTime(40000), 0).TestActive();
+ }
+
+ // Sanity checks of version bit deployments
+ const Consensus::Params &mainnetParams = Params(CBaseChainParams::MAIN).GetConsensus();
+ for (int i=0; i<(int) Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
+ uint32_t bitmask = VersionBitsMask(mainnetParams, (Consensus::DeploymentPos)i);
+ // Make sure that no deployment tries to set an invalid bit.
+ BOOST_CHECK_EQUAL(bitmask & ~(uint32_t)VERSIONBITS_TOP_MASK, bitmask);
+
+ // Verify that the deployment windows of different deployment using the
+ // same bit are disjoint.
+ // This test may need modification at such time as a new deployment
+ // is proposed that reuses the bit of an activated soft fork, before the
+ // end time of that soft fork. (Alternatively, the end time of that
+ // activated soft fork could be later changed to be earlier to avoid
+ // overlap.)
+ for (int j=i+1; j<(int) Consensus::MAX_VERSION_BITS_DEPLOYMENTS; j++) {
+ if (VersionBitsMask(mainnetParams, (Consensus::DeploymentPos)j) == bitmask) {
+ BOOST_CHECK(mainnetParams.vDeployments[j].nStartTime > mainnetParams.vDeployments[i].nTimeout ||
+ mainnetParams.vDeployments[i].nStartTime > mainnetParams.vDeployments[j].nTimeout);
+ }
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(versionbits_computeblockversion)
+{
+ // Check that ComputeBlockVersion will set the appropriate bit correctly
+ // on mainnet.
+ const Consensus::Params &mainnetParams = Params(CBaseChainParams::MAIN).GetConsensus();
+
+ // Use the TESTDUMMY deployment for testing purposes.
+ int64_t bit = mainnetParams.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit;
+ int64_t nStartTime = mainnetParams.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime;
+ int64_t nTimeout = mainnetParams.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout;
+
+ assert(nStartTime < nTimeout);
+
+ // In the first chain, test that the bit is set by CBV until it has failed.
+ // In the second chain, test the bit is set by CBV while STARTED and
+ // LOCKED-IN, and then no longer set while ACTIVE.
+ VersionBitsTester firstChain, secondChain;
+
+ // Start generating blocks before nStartTime
+ int64_t nTime = nStartTime - 1;
+
+ // Before MedianTimePast of the chain has crossed nStartTime, the bit
+ // should not be set.
+ CBlockIndex *lastBlock = NULL;
+ lastBlock = firstChain.Mine(2016, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
+ BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, mainnetParams) & (1<<bit), 0);
+
+ // Mine 2011 more blocks at the old time, and check that CBV isn't setting the bit yet.
+ for (int i=1; i<2012; i++) {
+ lastBlock = firstChain.Mine(2016+i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
+ // This works because VERSIONBITS_LAST_OLD_BLOCK_VERSION happens
+ // to be 4, and the bit we're testing happens to be bit 28.
+ BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, mainnetParams) & (1<<bit), 0);
+ }
+ // Now mine 5 more blocks at the start time -- MTP should not have passed yet, so
+ // CBV should still not yet set the bit.
+ nTime = nStartTime;
+ for (int i=2012; i<=2016; i++) {
+ lastBlock = firstChain.Mine(2016+i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
+ BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, mainnetParams) & (1<<bit), 0);
+ }
+
+ // Advance to the next period and transition to STARTED,
+ lastBlock = firstChain.Mine(6048, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
+ // so ComputeBlockVersion should now set the bit,
+ BOOST_CHECK((ComputeBlockVersion(lastBlock, mainnetParams) & (1<<bit)) != 0);
+ // and should also be using the VERSIONBITS_TOP_BITS.
+ BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, mainnetParams) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
+
+ // Check that ComputeBlockVersion will set the bit until nTimeout
+ nTime += 600;
+ int blocksToMine = 4032; // test blocks for up to 2 time periods
+ int nHeight = 6048;
+ // These blocks are all before nTimeout is reached.
+ while (nTime < nTimeout && blocksToMine > 0) {
+ lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
+ BOOST_CHECK((ComputeBlockVersion(lastBlock, mainnetParams) & (1<<bit)) != 0);
+ BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, mainnetParams) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
+ blocksToMine--;
+ nTime += 600;
+ nHeight += 1;
+ };
+
+ nTime = nTimeout;
+ // FAILED is only triggered at the end of a period, so CBV should be setting
+ // the bit until the period transition.
+ for (int i=0; i<2015; i++) {
+ lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
+ BOOST_CHECK((ComputeBlockVersion(lastBlock, mainnetParams) & (1<<bit)) != 0);
+ nHeight += 1;
+ }
+ // The next block should trigger no longer setting the bit.
+ lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
+ BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, mainnetParams) & (1<<bit), 0);
+
+ // On a new chain:
+ // verify that the bit will be set after lock-in, and then stop being set
+ // after activation.
+ nTime = nStartTime;
+
+ // Mine one period worth of blocks, and check that the bit will be on for the
+ // next period.
+ lastBlock = secondChain.Mine(2016, nStartTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
+ BOOST_CHECK((ComputeBlockVersion(lastBlock, mainnetParams) & (1<<bit)) != 0);
+
+ // Mine another period worth of blocks, signaling the new bit.
+ lastBlock = secondChain.Mine(4032, nStartTime, VERSIONBITS_TOP_BITS | (1<<bit)).Tip();
+ // After one period of setting the bit on each block, it should have locked in.
+ // We keep setting the bit for one more period though, until activation.
+ BOOST_CHECK((ComputeBlockVersion(lastBlock, mainnetParams) & (1<<bit)) != 0);
+
+ // Now check that we keep mining the block until the end of this period, and
+ // then stop at the beginning of the next period.
+ lastBlock = secondChain.Mine(6047, nStartTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
+ BOOST_CHECK((ComputeBlockVersion(lastBlock, mainnetParams) & (1<<bit)) != 0);
+ lastBlock = secondChain.Mine(6048, nStartTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
+ BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, mainnetParams) & (1<<bit), 0);
+
+ // Finally, verify that after a soft fork has activated, CBV no longer uses
+ // VERSIONBITS_LAST_OLD_BLOCK_VERSION.
+ //BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, mainnetParams) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
+}
+
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/timedata.cpp b/src/timedata.cpp
index 4d2f8d1e3b..b6bcf86fbf 100644
--- a/src/timedata.cpp
+++ b/src/timedata.cpp
@@ -83,7 +83,7 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
int64_t nMedian = vTimeOffsets.median();
std::vector<int64_t> vSorted = vTimeOffsets.sorted();
// Only let other nodes change our time by so much
- if (abs64(nMedian) < 70 * 60)
+ if (abs64(nMedian) <= std::max<int64_t>(0, GetArg("-maxtimeadjustment", DEFAULT_MAX_TIME_ADJUSTMENT)))
{
nTimeOffset = nMedian;
}
diff --git a/src/timedata.h b/src/timedata.h
index 2296baf11b..9f2499c85c 100644
--- a/src/timedata.h
+++ b/src/timedata.h
@@ -10,6 +10,8 @@
#include <stdint.h>
#include <vector>
+static const int64_t DEFAULT_MAX_TIME_ADJUSTMENT = 70 * 60;
+
class CNetAddr;
/**
diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp
index 2c68526df4..1c7bc2dbee 100644
--- a/src/torcontrol.cpp
+++ b/src/torcontrol.cpp
@@ -393,11 +393,14 @@ private:
static void reconnect_cb(evutil_socket_t fd, short what, void *arg);
};
-TorController::TorController(struct event_base* base, const std::string& target):
- base(base),
+TorController::TorController(struct event_base* baseIn, const std::string& target):
+ base(baseIn),
target(target), conn(base), reconnect(true), reconnect_ev(0),
reconnect_timeout(RECONNECT_TIMEOUT_START)
{
+ reconnect_ev = event_new(base, -1, 0, reconnect_cb, this);
+ if (!reconnect_ev)
+ LogPrintf("tor: Failed to create event for reconnection: out of memory?\n");
// Start connection attempts immediately
if (!conn.Connect(target, boost::bind(&TorController::connected_cb, this, _1),
boost::bind(&TorController::disconnected_cb, this, _1) )) {
@@ -413,8 +416,10 @@ TorController::TorController(struct event_base* base, const std::string& target)
TorController::~TorController()
{
- if (reconnect_ev)
- event_del(reconnect_ev);
+ if (reconnect_ev) {
+ event_free(reconnect_ev);
+ reconnect_ev = 0;
+ }
if (service.IsValid()) {
RemoveLocal(service);
}
@@ -434,7 +439,7 @@ void TorController::add_onion_cb(TorControlConnection& conn, const TorControlRep
}
service = CService(service_id+".onion", GetListenPort(), false);
- LogPrintf("tor: Got service ID %s, advertizing service %s\n", service_id, service.ToString());
+ LogPrintf("tor: Got service ID %s, advertising service %s\n", service_id, service.ToString());
if (WriteBinaryFile(GetPrivateKeyFile(), private_key)) {
LogPrint("tor", "tor: Cached service private key to %s\n", GetPrivateKeyFile());
} else {
@@ -459,7 +464,7 @@ void TorController::auth_cb(TorControlConnection& conn, const TorControlReply& r
if (GetArg("-onion", "") == "") {
proxyType addrOnion = proxyType(CService("127.0.0.1", 9050), true);
SetProxy(NET_TOR, addrOnion);
- SetReachable(NET_TOR);
+ SetLimited(NET_TOR, false);
}
// Finally - now create the service
@@ -615,7 +620,7 @@ void TorController::connected_cb(TorControlConnection& conn)
void TorController::disconnected_cb(TorControlConnection& conn)
{
- // Stop advertizing service when disconnected
+ // Stop advertising service when disconnected
if (service.IsValid())
RemoveLocal(service);
service = CService();
@@ -626,8 +631,8 @@ void TorController::disconnected_cb(TorControlConnection& conn)
// Single-shot timer for reconnect. Use exponential backoff.
struct timeval time = MillisToTimeval(int64_t(reconnect_timeout * 1000.0));
- reconnect_ev = event_new(base, -1, 0, reconnect_cb, this);
- event_add(reconnect_ev, &time);
+ if (reconnect_ev)
+ event_add(reconnect_ev, &time);
reconnect_timeout *= RECONNECT_TIMEOUT_EXP;
}
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index f8e03c2533..52c7793118 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -22,10 +22,10 @@ using namespace std;
CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
int64_t _nTime, double _entryPriority, unsigned int _entryHeight,
bool poolHasNoInputsOf, CAmount _inChainInputValue,
- bool _spendsCoinbase, unsigned int _sigOps):
+ bool _spendsCoinbase, unsigned int _sigOps, LockPoints lp):
tx(_tx), nFee(_nFee), nTime(_nTime), entryPriority(_entryPriority), entryHeight(_entryHeight),
hadNoDependencies(poolHasNoInputsOf), inChainInputValue(_inChainInputValue),
- spendsCoinbase(_spendsCoinbase), sigOpCount(_sigOps)
+ spendsCoinbase(_spendsCoinbase), sigOpCount(_sigOps), lockPoints(lp)
{
nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
nModSize = tx.CalculateModifiedSize(nTxSize);
@@ -38,6 +38,11 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
assert(inChainInputValue <= nValueIn);
feeDelta = 0;
+
+ nCountWithAncestors = 1;
+ nSizeWithAncestors = nTxSize;
+ nModFeesWithAncestors = nFee;
+ nSigOpCountWithAncestors = sigOpCount;
}
CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry& other)
@@ -58,27 +63,25 @@ CTxMemPoolEntry::GetPriority(unsigned int currentHeight) const
void CTxMemPoolEntry::UpdateFeeDelta(int64_t newFeeDelta)
{
nModFeesWithDescendants += newFeeDelta - feeDelta;
+ nModFeesWithAncestors += newFeeDelta - feeDelta;
feeDelta = newFeeDelta;
}
+void CTxMemPoolEntry::UpdateLockPoints(const LockPoints& lp)
+{
+ lockPoints = lp;
+}
+
// Update the given tx for any in-mempool descendants.
// Assumes that setMemPoolChildren is correct for the given tx and all
// descendants.
-bool CTxMemPool::UpdateForDescendants(txiter updateIt, int maxDescendantsToVisit, cacheMap &cachedDescendants, const std::set<uint256> &setExclude)
+void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap &cachedDescendants, const std::set<uint256> &setExclude)
{
- // Track the number of entries (outside setExclude) that we'd need to visit
- // (will bail out if it exceeds maxDescendantsToVisit)
- int nChildrenToVisit = 0;
-
setEntries stageEntries, setAllDescendants;
stageEntries = GetMemPoolChildren(updateIt);
while (!stageEntries.empty()) {
const txiter cit = *stageEntries.begin();
- if (cit->IsDirty()) {
- // Don't consider any more children if any descendant is dirty
- return false;
- }
setAllDescendants.insert(cit);
stageEntries.erase(cit);
const setEntries &setChildren = GetMemPoolChildren(cit);
@@ -88,22 +91,11 @@ bool CTxMemPool::UpdateForDescendants(txiter updateIt, int maxDescendantsToVisit
// We've already calculated this one, just add the entries for this set
// but don't traverse again.
BOOST_FOREACH(const txiter cacheEntry, cacheIt->second) {
- // update visit count only for new child transactions
- // (outside of setExclude and stageEntries)
- if (setAllDescendants.insert(cacheEntry).second &&
- !setExclude.count(cacheEntry->GetTx().GetHash()) &&
- !stageEntries.count(cacheEntry)) {
- nChildrenToVisit++;
- }
+ setAllDescendants.insert(cacheEntry);
}
} else if (!setAllDescendants.count(childEntry)) {
- // Schedule for later processing and update our visit count
- if (stageEntries.insert(childEntry).second && !setExclude.count(childEntry->GetTx().GetHash())) {
- nChildrenToVisit++;
- }
- }
- if (nChildrenToVisit > maxDescendantsToVisit) {
- return false;
+ // Schedule for later processing
+ stageEntries.insert(childEntry);
}
}
}
@@ -118,16 +110,18 @@ bool CTxMemPool::UpdateForDescendants(txiter updateIt, int maxDescendantsToVisit
modifyFee += cit->GetModifiedFee();
modifyCount++;
cachedDescendants[updateIt].insert(cit);
+ // Update ancestor state for each descendant
+ mapTx.modify(cit, update_ancestor_state(updateIt->GetTxSize(), updateIt->GetModifiedFee(), 1, updateIt->GetSigOpCount()));
}
}
mapTx.modify(updateIt, update_descendant_state(modifySize, modifyFee, modifyCount));
- return true;
}
// vHashesToUpdate is the set of transaction hashes from a disconnected block
// which has been re-added to the mempool.
// for each entry, look for descendants that are outside hashesToUpdate, and
// add fee/size information for such descendants to the parent.
+// for each such descendant, also update the ancestor state to include the parent.
void CTxMemPool::UpdateTransactionsFromBlock(const std::vector<uint256> &vHashesToUpdate)
{
LOCK(cs);
@@ -167,14 +161,11 @@ void CTxMemPool::UpdateTransactionsFromBlock(const std::vector<uint256> &vHashes
UpdateParent(childIter, it, true);
}
}
- if (!UpdateForDescendants(it, 100, mapMemPoolDescendantsToUpdate, setAlreadyIncluded)) {
- // Mark as dirty if we can't do the calculation.
- mapTx.modify(it, set_dirty());
- }
+ UpdateForDescendants(it, mapMemPoolDescendantsToUpdate, setAlreadyIncluded);
}
}
-bool CTxMemPool::CalculateMemPoolAncestors(const CTxMemPoolEntry &entry, setEntries &setAncestors, uint64_t limitAncestorCount, uint64_t limitAncestorSize, uint64_t limitDescendantCount, uint64_t limitDescendantSize, std::string &errString, bool fSearchForParents /* = true */)
+bool CTxMemPool::CalculateMemPoolAncestors(const CTxMemPoolEntry &entry, setEntries &setAncestors, uint64_t limitAncestorCount, uint64_t limitAncestorSize, uint64_t limitDescendantCount, uint64_t limitDescendantSize, std::string &errString, bool fSearchForParents /* = true */) const
{
setEntries parentHashes;
const CTransaction &tx = entry.GetTx();
@@ -251,6 +242,20 @@ void CTxMemPool::UpdateAncestorsOf(bool add, txiter it, setEntries &setAncestors
}
}
+void CTxMemPool::UpdateEntryForAncestors(txiter it, const setEntries &setAncestors)
+{
+ int64_t updateCount = setAncestors.size();
+ int64_t updateSize = 0;
+ CAmount updateFee = 0;
+ int updateSigOps = 0;
+ BOOST_FOREACH(txiter ancestorIt, setAncestors) {
+ updateSize += ancestorIt->GetTxSize();
+ updateFee += ancestorIt->GetModifiedFee();
+ updateSigOps += ancestorIt->GetSigOpCount();
+ }
+ mapTx.modify(it, update_ancestor_state(updateSize, updateFee, updateCount, updateSigOps));
+}
+
void CTxMemPool::UpdateChildrenForRemoval(txiter it)
{
const setEntries &setMemPoolChildren = GetMemPoolChildren(it);
@@ -259,11 +264,30 @@ void CTxMemPool::UpdateChildrenForRemoval(txiter it)
}
}
-void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove)
+void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove, bool updateDescendants)
{
// For each entry, walk back all ancestors and decrement size associated with this
// transaction
const uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
+ if (updateDescendants) {
+ // updateDescendants should be true whenever we're not recursively
+ // removing a tx and all its descendants, eg when a transaction is
+ // confirmed in a block.
+ // Here we only update statistics and not data in mapLinks (which
+ // we need to preserve until we're finished with all operations that
+ // need to traverse the mempool).
+ BOOST_FOREACH(txiter removeIt, entriesToRemove) {
+ setEntries setDescendants;
+ CalculateDescendants(removeIt, setDescendants);
+ setDescendants.erase(removeIt); // don't update state for self
+ int64_t modifySize = -((int64_t)removeIt->GetTxSize());
+ CAmount modifyFee = -removeIt->GetModifiedFee();
+ int modifySigOps = -removeIt->GetSigOpCount();
+ BOOST_FOREACH(txiter dit, setDescendants) {
+ mapTx.modify(dit, update_ancestor_state(modifySize, modifyFee, -1, modifySigOps));
+ }
+ }
+ }
BOOST_FOREACH(txiter removeIt, entriesToRemove) {
setEntries setAncestors;
const CTxMemPoolEntry &entry = *removeIt;
@@ -287,10 +311,7 @@ void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove)
// transactions as the set of things to update for removal.
CalculateMemPoolAncestors(entry, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy, false);
// Note that UpdateAncestorsOf severs the child links that point to
- // removeIt in the entries for the parents of removeIt. This is
- // fine since we don't need to use the mempool children of any entries
- // to walk back over our ancestors (but we do need the mempool
- // parents!)
+ // removeIt in the entries for the parents of removeIt.
UpdateAncestorsOf(false, removeIt, setAncestors);
}
// After updating all the ancestor sizes, we can now sever the link between each
@@ -301,22 +322,24 @@ void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove)
}
}
-void CTxMemPoolEntry::SetDirty()
+void CTxMemPoolEntry::UpdateDescendantState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount)
{
- nCountWithDescendants = 0;
- nSizeWithDescendants = nTxSize;
- nModFeesWithDescendants = GetModifiedFee();
+ nSizeWithDescendants += modifySize;
+ assert(int64_t(nSizeWithDescendants) > 0);
+ nModFeesWithDescendants += modifyFee;
+ nCountWithDescendants += modifyCount;
+ assert(int64_t(nCountWithDescendants) > 0);
}
-void CTxMemPoolEntry::UpdateState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount)
+void CTxMemPoolEntry::UpdateAncestorState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount, int modifySigOps)
{
- if (!IsDirty()) {
- nSizeWithDescendants += modifySize;
- assert(int64_t(nSizeWithDescendants) > 0);
- nModFeesWithDescendants += modifyFee;
- nCountWithDescendants += modifyCount;
- assert(int64_t(nCountWithDescendants) > 0);
- }
+ nSizeWithAncestors += modifySize;
+ assert(int64_t(nSizeWithAncestors) > 0);
+ nModFeesWithAncestors += modifyFee;
+ nCountWithAncestors += modifyCount;
+ assert(int64_t(nCountWithAncestors) > 0);
+ nSigOpCountWithAncestors += modifySigOps;
+ assert(int(nSigOpCountWithAncestors) >= 0);
}
CTxMemPool::CTxMemPool(const CFeeRate& _minReasonableRelayFee) :
@@ -409,6 +432,7 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry,
}
}
UpdateAncestorsOf(true, newit, setAncestors);
+ UpdateEntryForAncestors(newit, setAncestors);
nTransactionsUpdated++;
totalTxSize += entry.GetTxSize();
@@ -461,7 +485,7 @@ void CTxMemPool::CalculateDescendants(txiter entryit, setEntries &setDescendants
}
}
-void CTxMemPool::remove(const CTransaction &origTx, std::list<CTransaction>& removed, bool fRecursive)
+void CTxMemPool::removeRecursive(const CTransaction &origTx, std::list<CTransaction>& removed)
{
// Remove transaction from memory pool
{
@@ -470,8 +494,8 @@ void CTxMemPool::remove(const CTransaction &origTx, std::list<CTransaction>& rem
txiter origit = mapTx.find(origTx.GetHash());
if (origit != mapTx.end()) {
txToRemove.insert(origit);
- } else if (fRecursive) {
- // If recursively removing but origTx isn't in the mempool
+ } else {
+ // When recursively removing but origTx isn't in the mempool
// be sure to remove any children that are in the pool. This can
// happen during chain re-orgs if origTx isn't re-accepted into
// the mempool for any reason.
@@ -485,17 +509,13 @@ void CTxMemPool::remove(const CTransaction &origTx, std::list<CTransaction>& rem
}
}
setEntries setAllRemoves;
- if (fRecursive) {
- BOOST_FOREACH(txiter it, txToRemove) {
- CalculateDescendants(it, setAllRemoves);
- }
- } else {
- setAllRemoves.swap(txToRemove);
+ BOOST_FOREACH(txiter it, txToRemove) {
+ CalculateDescendants(it, setAllRemoves);
}
BOOST_FOREACH(txiter it, setAllRemoves) {
removed.push_back(it->GetTx());
}
- RemoveStaged(setAllRemoves);
+ RemoveStaged(setAllRemoves, false);
}
}
@@ -506,7 +526,11 @@ void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMem
list<CTransaction> transactionsToRemove;
for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
const CTransaction& tx = it->GetTx();
- if (!CheckFinalTx(tx, flags)) {
+ LockPoints lp = it->GetLockPoints();
+ bool validLP = TestLockPointValidity(&lp);
+ if (!CheckFinalTx(tx, flags) || !CheckSequenceLocks(tx, flags, &lp, validLP)) {
+ // Note if CheckSequenceLocks fails the LockPoints may still be invalid
+ // So it's critical that we remove the tx and not depend on the LockPoints.
transactionsToRemove.push_back(tx);
} else if (it->GetSpendsCoinbase()) {
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
@@ -521,10 +545,13 @@ void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMem
}
}
}
+ if (!validLP) {
+ mapTx.modify(it, update_lock_points(lp));
+ }
}
BOOST_FOREACH(const CTransaction& tx, transactionsToRemove) {
list<CTransaction> removed;
- remove(tx, removed, true);
+ removeRecursive(tx, removed);
}
}
@@ -539,7 +566,7 @@ void CTxMemPool::removeConflicts(const CTransaction &tx, std::list<CTransaction>
const CTransaction &txConflict = *it->second.ptx;
if (txConflict != tx)
{
- remove(txConflict, removed, true);
+ removeRecursive(txConflict, removed);
ClearPrioritisation(txConflict.GetHash());
}
}
@@ -564,8 +591,12 @@ void CTxMemPool::removeForBlock(const std::vector<CTransaction>& vtx, unsigned i
}
BOOST_FOREACH(const CTransaction& tx, vtx)
{
- std::list<CTransaction> dummy;
- remove(tx, dummy, false);
+ txiter it = mapTx.find(tx.GetHash());
+ if (it != mapTx.end()) {
+ setEntries stage;
+ stage.insert(it);
+ RemoveStaged(stage, true);
+ }
removeConflicts(tx, conflicts);
ClearPrioritisation(tx.GetHash());
}
@@ -622,6 +653,8 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
innerUsage += memusage::DynamicUsage(links.parents) + memusage::DynamicUsage(links.children);
bool fDependsWait = false;
setEntries setParentCheck;
+ int64_t parentSizes = 0;
+ unsigned int parentSigOpCount = 0;
BOOST_FOREACH(const CTxIn &txin, tx.vin) {
// Check that every mempool transaction's inputs refer to available coins, or other mempool tx's.
indexed_transaction_set::const_iterator it2 = mapTx.find(txin.prevout.hash);
@@ -629,7 +662,10 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
const CTransaction& tx2 = it2->GetTx();
assert(tx2.vout.size() > txin.prevout.n && !tx2.vout[txin.prevout.n].IsNull());
fDependsWait = true;
- setParentCheck.insert(it2);
+ if (setParentCheck.insert(it2).second) {
+ parentSizes += it2->GetTxSize();
+ parentSigOpCount += it2->GetSigOpCount();
+ }
} else {
const CCoins* coins = pcoins->AccessCoins(txin.prevout.hash);
assert(coins && coins->IsAvailable(txin.prevout.n));
@@ -642,28 +678,42 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
i++;
}
assert(setParentCheck == GetMemPoolParents(it));
+ // Verify ancestor state is correct.
+ setEntries setAncestors;
+ uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
+ std::string dummy;
+ CalculateMemPoolAncestors(*it, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy);
+ uint64_t nCountCheck = setAncestors.size() + 1;
+ uint64_t nSizeCheck = it->GetTxSize();
+ CAmount nFeesCheck = it->GetModifiedFee();
+ unsigned int nSigOpCheck = it->GetSigOpCount();
+
+ BOOST_FOREACH(txiter ancestorIt, setAncestors) {
+ nSizeCheck += ancestorIt->GetTxSize();
+ nFeesCheck += ancestorIt->GetModifiedFee();
+ nSigOpCheck += ancestorIt->GetSigOpCount();
+ }
+
+ assert(it->GetCountWithAncestors() == nCountCheck);
+ assert(it->GetSizeWithAncestors() == nSizeCheck);
+ assert(it->GetSigOpCountWithAncestors() == nSigOpCheck);
+ assert(it->GetModFeesWithAncestors() == nFeesCheck);
+
// Check children against mapNextTx
CTxMemPool::setEntries setChildrenCheck;
std::map<COutPoint, CInPoint>::const_iterator iter = mapNextTx.lower_bound(COutPoint(it->GetTx().GetHash(), 0));
int64_t childSizes = 0;
- CAmount childModFee = 0;
for (; iter != mapNextTx.end() && iter->first.hash == it->GetTx().GetHash(); ++iter) {
txiter childit = mapTx.find(iter->second.ptx->GetHash());
assert(childit != mapTx.end()); // mapNextTx points to in-mempool transactions
if (setChildrenCheck.insert(childit).second) {
childSizes += childit->GetTxSize();
- childModFee += childit->GetModifiedFee();
}
}
assert(setChildrenCheck == GetMemPoolChildren(it));
// Also check to make sure size is greater than sum with immediate children.
// just a sanity check, not definitive that this calc is correct...
- if (!it->IsDirty()) {
- assert(it->GetSizeWithDescendants() >= childSizes + it->GetTxSize());
- } else {
- assert(it->GetSizeWithDescendants() == it->GetTxSize());
- assert(it->GetModFeesWithDescendants() == it->GetModifiedFee());
- }
+ assert(it->GetSizeWithDescendants() >= childSizes + it->GetTxSize());
if (fDependsWait)
waitingOnDependants.push_back(&(*it));
@@ -721,6 +771,16 @@ bool CTxMemPool::lookup(uint256 hash, CTransaction& result) const
return true;
}
+bool CTxMemPool::lookupFeeRate(const uint256& hash, CFeeRate& feeRate) const
+{
+ LOCK(cs);
+ indexed_transaction_set::const_iterator i = mapTx.find(hash);
+ if (i == mapTx.end())
+ return false;
+ feeRate = CFeeRate(i->GetFee(), i->GetTxSize());
+ return true;
+}
+
CFeeRate CTxMemPool::estimateFee(int nBlocks) const
{
LOCK(cs);
@@ -845,13 +905,13 @@ bool CCoinsViewMemPool::HaveCoins(const uint256 &txid) const {
size_t CTxMemPool::DynamicMemoryUsage() const {
LOCK(cs);
- // Estimate the overhead of mapTx to be 12 pointers + an allocation, as no exact formula for boost::multi_index_contained is implemented.
- return memusage::MallocUsage(sizeof(CTxMemPoolEntry) + 12 * sizeof(void*)) * mapTx.size() + memusage::DynamicUsage(mapNextTx) + memusage::DynamicUsage(mapDeltas) + memusage::DynamicUsage(mapLinks) + cachedInnerUsage;
+ // Estimate the overhead of mapTx to be 15 pointers + an allocation, as no exact formula for boost::multi_index_contained is implemented.
+ return memusage::MallocUsage(sizeof(CTxMemPoolEntry) + 15 * sizeof(void*)) * mapTx.size() + memusage::DynamicUsage(mapNextTx) + memusage::DynamicUsage(mapDeltas) + memusage::DynamicUsage(mapLinks) + cachedInnerUsage;
}
-void CTxMemPool::RemoveStaged(setEntries &stage) {
+void CTxMemPool::RemoveStaged(setEntries &stage, bool updateDescendants) {
AssertLockHeld(cs);
- UpdateForRemoveFromMempool(stage);
+ UpdateForRemoveFromMempool(stage, updateDescendants);
BOOST_FOREACH(const txiter& it, stage) {
removeUnchecked(it);
}
@@ -859,9 +919,9 @@ void CTxMemPool::RemoveStaged(setEntries &stage) {
int CTxMemPool::Expire(int64_t time) {
LOCK(cs);
- indexed_transaction_set::nth_index<2>::type::iterator it = mapTx.get<2>().begin();
+ indexed_transaction_set::index<entry_time>::type::iterator it = mapTx.get<entry_time>().begin();
setEntries toremove;
- while (it != mapTx.get<2>().end() && it->GetTime() < time) {
+ while (it != mapTx.get<entry_time>().end() && it->GetTime() < time) {
toremove.insert(mapTx.project<0>(it));
it++;
}
@@ -869,7 +929,7 @@ int CTxMemPool::Expire(int64_t time) {
BOOST_FOREACH(txiter removeit, toremove) {
CalculateDescendants(removeit, stage);
}
- RemoveStaged(stage);
+ RemoveStaged(stage, false);
return stage.size();
}
@@ -957,7 +1017,7 @@ void CTxMemPool::TrimToSize(size_t sizelimit, std::vector<uint256>* pvNoSpendsRe
unsigned nTxnRemoved = 0;
CFeeRate maxFeeRateRemoved(0);
while (DynamicMemoryUsage() > sizelimit) {
- indexed_transaction_set::nth_index<1>::type::iterator it = mapTx.get<1>().begin();
+ indexed_transaction_set::index<descendant_score>::type::iterator it = mapTx.get<descendant_score>().begin();
// We set the new mempool min fee to the feerate of the removed set, plus the
// "minimum reasonable fee rate" (ie some value under which we consider txn
@@ -978,7 +1038,7 @@ void CTxMemPool::TrimToSize(size_t sizelimit, std::vector<uint256>* pvNoSpendsRe
BOOST_FOREACH(txiter it, stage)
txn.push_back(it->GetTx());
}
- RemoveStaged(stage);
+ RemoveStaged(stage, false);
if (pvNoSpendsRemaining) {
BOOST_FOREACH(const CTransaction& tx, txn) {
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
diff --git a/src/txmempool.h b/src/txmempool.h
index 386cb26d25..9dbb37dad0 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -19,6 +19,7 @@
#include "boost/multi_index/ordered_index.hpp"
class CAutoFile;
+class CBlockIndex;
inline double AllowFreeThreshold()
{
@@ -35,6 +36,21 @@ inline bool AllowFree(double dPriority)
/** Fake height value used in CCoins to signify they are only in the memory pool (since 0.8) */
static const unsigned int MEMPOOL_HEIGHT = 0x7FFFFFFF;
+struct LockPoints
+{
+ // Will be set to the blockchain height and median time past
+ // values that would be necessary to satisfy all relative locktime
+ // constraints (BIP68) of this tx given our view of block chain history
+ int height;
+ int64_t time;
+ // As long as the current chain descends from the highest height block
+ // containing one of the inputs used in the calculation, then the cached
+ // values are still valid even after a reorg.
+ CBlockIndex* maxInputBlock;
+
+ LockPoints() : height(0), time(0), maxInputBlock(NULL) { }
+};
+
class CTxMemPool;
/** \class CTxMemPoolEntry
@@ -70,6 +86,7 @@ private:
bool spendsCoinbase; //! keep track of transactions that spend a coinbase
unsigned int sigOpCount; //! Legacy sig ops plus P2SH sig op count
int64_t feeDelta; //! Used for determining the priority of the transaction for mining in a block
+ LockPoints lockPoints; //! Track the height and time at which tx was final
// Information about descendants of this transaction that are in the
// mempool; if we remove this transaction we must remove all of these
@@ -80,11 +97,17 @@ private:
uint64_t nSizeWithDescendants; //! ... and size
CAmount nModFeesWithDescendants; //! ... and total fees (all including us)
+ // Analogous statistics for ancestor transactions
+ uint64_t nCountWithAncestors;
+ uint64_t nSizeWithAncestors;
+ CAmount nModFeesWithAncestors;
+ unsigned int nSigOpCountWithAncestors;
+
public:
CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
int64_t _nTime, double _entryPriority, unsigned int _entryHeight,
bool poolHasNoInputsOf, CAmount _inChainInputValue, bool spendsCoinbase,
- unsigned int nSigOps);
+ unsigned int nSigOps, LockPoints lp);
CTxMemPoolEntry(const CTxMemPoolEntry& other);
const CTransaction& GetTx() const { return this->tx; }
@@ -101,25 +124,28 @@ public:
unsigned int GetSigOpCount() const { return sigOpCount; }
int64_t GetModifiedFee() const { return nFee + feeDelta; }
size_t DynamicMemoryUsage() const { return nUsageSize; }
+ const LockPoints& GetLockPoints() const { return lockPoints; }
// Adjusts the descendant state, if this entry is not dirty.
- void UpdateState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount);
+ void UpdateDescendantState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount);
+ // Adjusts the ancestor state
+ void UpdateAncestorState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount, int modifySigOps);
// Updates the fee delta used for mining priority score, and the
// modified fees with descendants.
void UpdateFeeDelta(int64_t feeDelta);
-
- /** We can set the entry to be dirty if doing the full calculation of in-
- * mempool descendants will be too expensive, which can potentially happen
- * when re-adding transactions from a block back to the mempool.
- */
- void SetDirty();
- bool IsDirty() const { return nCountWithDescendants == 0; }
+ // Update the LockPoints after a reorg
+ void UpdateLockPoints(const LockPoints& lp);
uint64_t GetCountWithDescendants() const { return nCountWithDescendants; }
uint64_t GetSizeWithDescendants() const { return nSizeWithDescendants; }
CAmount GetModFeesWithDescendants() const { return nModFeesWithDescendants; }
bool GetSpendsCoinbase() const { return spendsCoinbase; }
+
+ uint64_t GetCountWithAncestors() const { return nCountWithAncestors; }
+ uint64_t GetSizeWithAncestors() const { return nSizeWithAncestors; }
+ CAmount GetModFeesWithAncestors() const { return nModFeesWithAncestors; }
+ unsigned int GetSigOpCountWithAncestors() const { return nSigOpCountWithAncestors; }
};
// Helpers for modifying CTxMemPool::mapTx, which is a boost multi_index.
@@ -130,7 +156,7 @@ struct update_descendant_state
{}
void operator() (CTxMemPoolEntry &e)
- { e.UpdateState(modifySize, modifyFee, modifyCount); }
+ { e.UpdateDescendantState(modifySize, modifyFee, modifyCount); }
private:
int64_t modifySize;
@@ -138,10 +164,20 @@ struct update_descendant_state
int64_t modifyCount;
};
-struct set_dirty
+struct update_ancestor_state
{
+ update_ancestor_state(int64_t _modifySize, CAmount _modifyFee, int64_t _modifyCount, int _modifySigOps) :
+ modifySize(_modifySize), modifyFee(_modifyFee), modifyCount(_modifyCount), modifySigOps(_modifySigOps)
+ {}
+
void operator() (CTxMemPoolEntry &e)
- { e.SetDirty(); }
+ { e.UpdateAncestorState(modifySize, modifyFee, modifyCount, modifySigOps); }
+
+ private:
+ int64_t modifySize;
+ CAmount modifyFee;
+ int64_t modifyCount;
+ int modifySigOps;
};
struct update_fee_delta
@@ -154,6 +190,16 @@ private:
int64_t feeDelta;
};
+struct update_lock_points
+{
+ update_lock_points(const LockPoints& _lp) : lp(_lp) { }
+
+ void operator() (CTxMemPoolEntry &e) { e.UpdateLockPoints(lp); }
+
+private:
+ const LockPoints& lp;
+};
+
// extracts a TxMemPoolEntry's transaction hash
struct mempoolentry_txid
{
@@ -228,6 +274,35 @@ public:
}
};
+class CompareTxMemPoolEntryByAncestorFee
+{
+public:
+ bool operator()(const CTxMemPoolEntry& a, const CTxMemPoolEntry& b)
+ {
+ double aFees = a.GetModFeesWithAncestors();
+ double aSize = a.GetSizeWithAncestors();
+
+ double bFees = b.GetModFeesWithAncestors();
+ double bSize = b.GetSizeWithAncestors();
+
+ // Avoid division by rewriting (a/b > c/d) as (a*d > c*b).
+ double f1 = aFees * bSize;
+ double f2 = aSize * bFees;
+
+ if (f1 == f2) {
+ return a.GetTx().GetHash() < b.GetTx().GetHash();
+ }
+
+ return f1 > f2;
+ }
+};
+
+// Multi_index tag names
+struct descendant_score {};
+struct entry_time {};
+struct mining_score {};
+struct ancestor_score {};
+
class CBlockPolicyEstimator;
/** An inpoint - a combination of a transaction and an index n into its vin */
@@ -350,18 +425,27 @@ public:
boost::multi_index::ordered_unique<mempoolentry_txid>,
// sorted by fee rate
boost::multi_index::ordered_non_unique<
+ boost::multi_index::tag<descendant_score>,
boost::multi_index::identity<CTxMemPoolEntry>,
CompareTxMemPoolEntryByDescendantScore
>,
// sorted by entry time
boost::multi_index::ordered_non_unique<
+ boost::multi_index::tag<entry_time>,
boost::multi_index::identity<CTxMemPoolEntry>,
CompareTxMemPoolEntryByEntryTime
- >,
+ >,
// sorted by score (for mining prioritization)
boost::multi_index::ordered_unique<
+ boost::multi_index::tag<mining_score>,
boost::multi_index::identity<CTxMemPoolEntry>,
CompareTxMemPoolEntryByScore
+ >,
+ // sorted by fee rate with ancestors
+ boost::multi_index::ordered_non_unique<
+ boost::multi_index::tag<ancestor_score>,
+ boost::multi_index::identity<CTxMemPoolEntry>,
+ CompareTxMemPoolEntryByAncestorFee
>
>
> indexed_transaction_set;
@@ -420,7 +504,7 @@ public:
bool addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, bool fCurrentEstimate = true);
bool addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, setEntries &setAncestors, bool fCurrentEstimate = true);
- void remove(const CTransaction &tx, std::list<CTransaction>& removed, bool fRecursive = false);
+ void removeRecursive(const CTransaction &tx, std::list<CTransaction>& removed);
void removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags);
void removeConflicts(const CTransaction &tx, std::list<CTransaction>& removed);
void removeForBlock(const std::vector<CTransaction>& vtx, unsigned int nBlockHeight,
@@ -445,8 +529,12 @@ public:
public:
/** Remove a set of transactions from the mempool.
* If a transaction is in this set, then all in-mempool descendants must
- * also be in the set.*/
- void RemoveStaged(setEntries &stage);
+ * also be in the set, unless this transaction is being removed for being
+ * in a block.
+ * Set updateDescendants to true when removing a tx that was in a block, so
+ * that any in-mempool descendants have their ancestor state updated.
+ */
+ void RemoveStaged(setEntries &stage, bool updateDescendants);
/** When adding transactions from a disconnected block back to the mempool,
* new mempool entries may have children in the mempool (which is generally
@@ -469,7 +557,7 @@ public:
* fSearchForParents = whether to search a tx's vin for in-mempool parents, or
* look up parents from mapLinks. Must be true for entries not in the mempool
*/
- bool CalculateMemPoolAncestors(const CTxMemPoolEntry &entry, setEntries &setAncestors, uint64_t limitAncestorCount, uint64_t limitAncestorSize, uint64_t limitDescendantCount, uint64_t limitDescendantSize, std::string &errString, bool fSearchForParents = true);
+ bool CalculateMemPoolAncestors(const CTxMemPoolEntry &entry, setEntries &setAncestors, uint64_t limitAncestorCount, uint64_t limitAncestorSize, uint64_t limitDescendantCount, uint64_t limitDescendantSize, std::string &errString, bool fSearchForParents = true) const;
/** Populate setDescendants with all in-mempool descendants of hash.
* Assumes that setDescendants includes all in-mempool descendants of anything
@@ -512,6 +600,7 @@ public:
}
bool lookup(uint256 hash, CTransaction& result) const;
+ bool lookupFeeRate(const uint256& hash, CFeeRate& feeRate) const;
/** Estimate fee rate needed to get into the next nBlocks
* If no answer can be given at nBlocks, return an estimate
@@ -547,21 +636,21 @@ private:
* updated and hence their state is already reflected in the parent
* state).
*
- * If updating an entry requires looking at more than maxDescendantsToVisit
- * transactions, outside of the ones in setExclude, then give up.
- *
* cachedDescendants will be updated with the descendants of the transaction
* being updated, so that future invocations don't need to walk the
* same transaction again, if encountered in another transaction chain.
*/
- bool UpdateForDescendants(txiter updateIt,
- int maxDescendantsToVisit,
+ void UpdateForDescendants(txiter updateIt,
cacheMap &cachedDescendants,
const std::set<uint256> &setExclude);
/** Update ancestors of hash to add/remove it as a descendant transaction. */
void UpdateAncestorsOf(bool add, txiter hash, setEntries &setAncestors);
- /** For each transaction being removed, update ancestors and any direct children. */
- void UpdateForRemoveFromMempool(const setEntries &entriesToRemove);
+ /** Set ancestor state for an entry */
+ void UpdateEntryForAncestors(txiter it, const setEntries &setAncestors);
+ /** For each transaction being removed, update ancestors and any direct children.
+ * If updateDescendants is true, then also update in-mempool descendants'
+ * ancestor state. */
+ void UpdateForRemoveFromMempool(const setEntries &entriesToRemove, bool updateDescendants);
/** Sever link between specified transaction and direct children. */
void UpdateChildrenForRemoval(txiter entry);
diff --git a/src/ui_interface.h b/src/ui_interface.h
index 967d243270..0b51d52e65 100644
--- a/src/ui_interface.h
+++ b/src/ui_interface.h
@@ -83,10 +83,9 @@ public:
boost::signals2::signal<void (int newNumConnections)> NotifyNumConnectionsChanged;
/**
- * New, updated or cancelled alert.
- * @note called with lock cs_mapAlerts held.
+ * Status bar alerts changed.
*/
- boost::signals2::signal<void (const uint256 &hash, ChangeType status)> NotifyAlertChanged;
+ boost::signals2::signal<void ()> NotifyAlertChanged;
/** A wallet has been loaded. */
boost::signals2::signal<void (CWallet* wallet)> LoadWallet;
diff --git a/src/uint256.h b/src/uint256.h
index 4495000f2f..bcdb6dd7c2 100644
--- a/src/uint256.h
+++ b/src/uint256.h
@@ -42,9 +42,11 @@ public:
memset(data, 0, sizeof(data));
}
- friend inline bool operator==(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) == 0; }
- friend inline bool operator!=(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) != 0; }
- friend inline bool operator<(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) < 0; }
+ inline int Compare(const base_blob& other) const { return memcmp(data, other.data, sizeof(data)); }
+
+ friend inline bool operator==(const base_blob& a, const base_blob& b) { return a.Compare(b) == 0; }
+ friend inline bool operator!=(const base_blob& a, const base_blob& b) { return a.Compare(b) != 0; }
+ friend inline bool operator<(const base_blob& a, const base_blob& b) { return a.Compare(b) < 0; }
std::string GetHex() const;
void SetHex(const char* psz);
diff --git a/src/util.cpp b/src/util.cpp
index 492697e12f..59f58f2c55 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -738,28 +738,6 @@ boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate)
}
#endif
-boost::filesystem::path GetTempPath() {
-#if BOOST_FILESYSTEM_VERSION == 3
- return boost::filesystem::temp_directory_path();
-#else
- // TODO: remove when we don't support filesystem v2 anymore
- boost::filesystem::path path;
-#ifdef WIN32
- char pszPath[MAX_PATH] = "";
-
- if (GetTempPathA(MAX_PATH, pszPath))
- path = boost::filesystem::path(pszPath);
-#else
- path = boost::filesystem::path("/tmp");
-#endif
- if (path.empty() || !boost::filesystem::is_directory(path)) {
- LogPrintf("GetTempPath(): failed to find temp path\n");
- return boost::filesystem::path("");
- }
- return path;
-#endif
-}
-
void runCommand(const std::string& strCommand)
{
int nErr = ::system(strCommand.c_str());
diff --git a/src/util.h b/src/util.h
index 9da8fdf87a..ac099f1184 100644
--- a/src/util.h
+++ b/src/util.h
@@ -133,7 +133,6 @@ void ReadConfigFile(std::map<std::string, std::string>& mapSettingsRet, std::map
#ifdef WIN32
boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true);
#endif
-boost::filesystem::path GetTempPath();
void OpenDebugLog();
void ShrinkDebugFile();
void runCommand(const std::string& strCommand);
diff --git a/src/version.h b/src/version.h
index f7cf18d0b6..0e1d8a63ce 100644
--- a/src/version.h
+++ b/src/version.h
@@ -9,7 +9,7 @@
* network protocol versioning
*/
-static const int PROTOCOL_VERSION = 70012;
+static const int PROTOCOL_VERSION = 70013;
//! initial proto version, to be increased after version/verack negotiation
static const int INIT_PROTO_VERSION = 209;
@@ -24,10 +24,6 @@ static const int MIN_PEER_PROTO_VERSION = GETHEADERS_VERSION;
//! if possible, avoid requesting addresses nodes older than this
static const int CADDR_TIME_VERSION = 31402;
-//! only request blocks from nodes outside this range of versions
-static const int NOBLKS_VERSION_START = 32000;
-static const int NOBLKS_VERSION_END = 32400;
-
//! BIP 0031, pong message, is enabled for all versions AFTER this one
static const int BIP0031_VERSION = 60000;
@@ -40,4 +36,7 @@ static const int NO_BLOOM_VERSION = 70011;
//! "sendheaders" command and announcing blocks with headers starts with this version
static const int SENDHEADERS_VERSION = 70012;
+//! "feefilter" tells peers to filter invs to you by fee starts with this version
+static const int FEEFILTER_VERSION = 70013;
+
#endif // BITCOIN_VERSION_H
diff --git a/src/versionbits.cpp b/src/versionbits.cpp
new file mode 100644
index 0000000000..fbb60c0fc5
--- /dev/null
+++ b/src/versionbits.cpp
@@ -0,0 +1,133 @@
+// Copyright (c) 2016 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "versionbits.h"
+
+ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const
+{
+ int nPeriod = Period(params);
+ int nThreshold = Threshold(params);
+ int64_t nTimeStart = BeginTime(params);
+ int64_t nTimeTimeout = EndTime(params);
+
+ // A block's state is always the same as that of the first of its period, so it is computed based on a pindexPrev whose height equals a multiple of nPeriod - 1.
+ if (pindexPrev != NULL) {
+ pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod));
+ }
+
+ // Walk backwards in steps of nPeriod to find a pindexPrev whose information is known
+ std::vector<const CBlockIndex*> vToCompute;
+ while (cache.count(pindexPrev) == 0) {
+ if (pindexPrev == NULL) {
+ // The genesis block is by definition defined.
+ cache[pindexPrev] = THRESHOLD_DEFINED;
+ break;
+ }
+ if (pindexPrev->GetMedianTimePast() < nTimeStart) {
+ // Optimizaton: don't recompute down further, as we know every earlier block will be before the start time
+ cache[pindexPrev] = THRESHOLD_DEFINED;
+ break;
+ }
+ vToCompute.push_back(pindexPrev);
+ pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - nPeriod);
+ }
+
+ // At this point, cache[pindexPrev] is known
+ assert(cache.count(pindexPrev));
+ ThresholdState state = cache[pindexPrev];
+
+ // Now walk forward and compute the state of descendants of pindexPrev
+ while (!vToCompute.empty()) {
+ ThresholdState stateNext = state;
+ pindexPrev = vToCompute.back();
+ vToCompute.pop_back();
+
+ switch (state) {
+ case THRESHOLD_DEFINED: {
+ if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
+ stateNext = THRESHOLD_FAILED;
+ } else if (pindexPrev->GetMedianTimePast() >= nTimeStart) {
+ stateNext = THRESHOLD_STARTED;
+ }
+ break;
+ }
+ case THRESHOLD_STARTED: {
+ if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
+ stateNext = THRESHOLD_FAILED;
+ break;
+ }
+ // We need to count
+ const CBlockIndex* pindexCount = pindexPrev;
+ int count = 0;
+ for (int i = 0; i < nPeriod; i++) {
+ if (Condition(pindexCount, params)) {
+ count++;
+ }
+ pindexCount = pindexCount->pprev;
+ }
+ if (count >= nThreshold) {
+ stateNext = THRESHOLD_LOCKED_IN;
+ }
+ break;
+ }
+ case THRESHOLD_LOCKED_IN: {
+ // Always progresses into ACTIVE.
+ stateNext = THRESHOLD_ACTIVE;
+ break;
+ }
+ case THRESHOLD_FAILED:
+ case THRESHOLD_ACTIVE: {
+ // Nothing happens, these are terminal states.
+ break;
+ }
+ }
+ cache[pindexPrev] = state = stateNext;
+ }
+
+ return state;
+}
+
+namespace
+{
+/**
+ * Class to implement versionbits logic.
+ */
+class VersionBitsConditionChecker : public AbstractThresholdConditionChecker {
+private:
+ const Consensus::DeploymentPos id;
+
+protected:
+ int64_t BeginTime(const Consensus::Params& params) const { return params.vDeployments[id].nStartTime; }
+ int64_t EndTime(const Consensus::Params& params) const { return params.vDeployments[id].nTimeout; }
+ int Period(const Consensus::Params& params) const { return params.nMinerConfirmationWindow; }
+ int Threshold(const Consensus::Params& params) const { return params.nRuleChangeActivationThreshold; }
+
+ bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const
+ {
+ return (((pindex->nVersion & VERSIONBITS_TOP_MASK) == VERSIONBITS_TOP_BITS) && (pindex->nVersion & Mask(params)) != 0);
+ }
+
+public:
+ VersionBitsConditionChecker(Consensus::DeploymentPos id_) : id(id_) {}
+ uint32_t Mask(const Consensus::Params& params) const { return ((uint32_t)1) << params.vDeployments[id].bit; }
+};
+
+}
+
+ThresholdState VersionBitsState(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache)
+{
+ return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, cache.caches[pos]);
+}
+
+uint32_t VersionBitsMask(const Consensus::Params& params, Consensus::DeploymentPos pos)
+{
+ return VersionBitsConditionChecker(pos).Mask(params);
+}
+
+void VersionBitsCache::Clear()
+{
+ for (unsigned int d = 0; d < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; d++) {
+ caches[d].clear();
+ }
+}
diff --git a/src/versionbits.h b/src/versionbits.h
new file mode 100644
index 0000000000..04f4738272
--- /dev/null
+++ b/src/versionbits.h
@@ -0,0 +1,59 @@
+// Copyright (c) 2016 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_CONSENSUS_VERSIONBITS
+#define BITCOIN_CONSENSUS_VERSIONBITS
+
+#include "chain.h"
+#include <map>
+
+/** What block version to use for new blocks (pre versionbits) */
+static const int32_t VERSIONBITS_LAST_OLD_BLOCK_VERSION = 4;
+/** What bits to set in version for versionbits blocks */
+static const int32_t VERSIONBITS_TOP_BITS = 0x20000000UL;
+/** What bitmask determines whether versionbits is in use */
+static const int32_t VERSIONBITS_TOP_MASK = 0xE0000000UL;
+/** Total bits available for versionbits */
+static const int32_t VERSIONBITS_NUM_BITS = 29;
+
+enum ThresholdState {
+ THRESHOLD_DEFINED,
+ THRESHOLD_STARTED,
+ THRESHOLD_LOCKED_IN,
+ THRESHOLD_ACTIVE,
+ THRESHOLD_FAILED,
+};
+
+// A map that gives the state for blocks whose height is a multiple of Period().
+// The map is indexed by the block's parent, however, so all keys in the map
+// will either be NULL or a block with (height + 1) % Period() == 0.
+typedef std::map<const CBlockIndex*, ThresholdState> ThresholdConditionCache;
+
+/**
+ * Abstract class that implements BIP9-style threshold logic, and caches results.
+ */
+class AbstractThresholdConditionChecker {
+protected:
+ virtual bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const =0;
+ virtual int64_t BeginTime(const Consensus::Params& params) const =0;
+ virtual int64_t EndTime(const Consensus::Params& params) const =0;
+ virtual int Period(const Consensus::Params& params) const =0;
+ virtual int Threshold(const Consensus::Params& params) const =0;
+
+public:
+ // Note that the function below takes a pindexPrev as input: they compute information for block B based on its parent.
+ ThresholdState GetStateFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const;
+};
+
+struct VersionBitsCache
+{
+ ThresholdConditionCache caches[Consensus::MAX_VERSION_BITS_DEPLOYMENTS];
+
+ void Clear();
+};
+
+ThresholdState VersionBitsState(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache);
+uint32_t VersionBitsMask(const Consensus::Params& params, Consensus::DeploymentPos pos);
+
+#endif
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index 50b0f40a6a..c906785e9e 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -165,6 +165,11 @@ CDBEnv::VerifyResult CDBEnv::Verify(const std::string& strFile, bool (*recoverFu
return (fRecovered ? RECOVER_OK : RECOVER_FAIL);
}
+/* End of headers, beginning of key/value data */
+static const char *HEADER_END = "HEADER=END";
+/* End of key/value data */
+static const char *DATA_END = "DATA=END";
+
bool CDBEnv::Salvage(const std::string& strFile, bool fAggressive, std::vector<CDBEnv::KeyValPair>& vResult)
{
LOCK(cs_db);
@@ -193,24 +198,35 @@ bool CDBEnv::Salvage(const std::string& strFile, bool fAggressive, std::vector<C
// Format of bdb dump is ascii lines:
// header lines...
// HEADER=END
- // hexadecimal key
- // hexadecimal value
- // ... repeated
+ // hexadecimal key
+ // hexadecimal value
+ // ... repeated
// DATA=END
string strLine;
- while (!strDump.eof() && strLine != "HEADER=END")
+ while (!strDump.eof() && strLine != HEADER_END)
getline(strDump, strLine); // Skip past header
std::string keyHex, valueHex;
- while (!strDump.eof() && keyHex != "DATA=END") {
+ while (!strDump.eof() && keyHex != DATA_END) {
getline(strDump, keyHex);
- if (keyHex != "DATA=END") {
+ if (keyHex != DATA_END) {
+ if (strDump.eof())
+ break;
getline(strDump, valueHex);
+ if (valueHex == DATA_END) {
+ LogPrintf("CDBEnv::Salvage: WARNING: Number of keys in data does not match number of values.\n");
+ break;
+ }
vResult.push_back(make_pair(ParseHex(keyHex), ParseHex(valueHex)));
}
}
+ if (keyHex != DATA_END) {
+ LogPrintf("CDBEnv::Salvage: WARNING: Unexpected end of file while reading salvage output.\n");
+ return false;
+ }
+
return (result == 0);
}
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index 9ec28e7b91..bb40cf7245 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -13,6 +13,8 @@
#include "util.h"
#include "utiltime.h"
#include "wallet.h"
+#include "merkleblock.h"
+#include "core_io.h"
#include <fstream>
#include <stdint.h>
@@ -192,7 +194,7 @@ UniValue importaddress(const UniValue& params, bool fHelp)
"3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n"
"4. p2sh (boolean, optional, default=false) Add the P2SH version of the script as well\n"
"\nNote: This call can take minutes to complete if rescan is true.\n"
- "If you have the full public key, you should call importpublickey instead of this.\n"
+ "If you have the full public key, you should call importpubkey instead of this.\n"
"\nExamples:\n"
"\nImport a script with rescan\n"
+ HelpExampleCli("importaddress", "\"myscript\"") +
@@ -243,6 +245,109 @@ UniValue importaddress(const UniValue& params, bool fHelp)
return NullUniValue;
}
+UniValue importprunedfunds(const UniValue& params, bool fHelp)
+{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
+ if (fHelp || params.size() < 2 || params.size() > 3)
+ throw runtime_error(
+ "importprunedfunds\n"
+ "\nImports funds without rescan. Corresponding address or script must previously be included in wallet. Aimed towards pruned wallets. The end-user is responsible to import additional transactions that subsequently spend the imported outputs or rescan after the point in the blockchain the transaction is included.\n"
+ "\nArguments:\n"
+ "1. \"rawtransaction\" (string, required) A raw transaction in hex funding an already-existing address in wallet\n"
+ "2. \"txoutproof\" (string, required) The hex output from gettxoutproof that contains the transaction\n"
+ "3. \"label\" (string, optional) An optional label\n"
+ );
+
+ CTransaction tx;
+ if (!DecodeHexTx(tx, params[0].get_str()))
+ throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
+ uint256 hashTx = tx.GetHash();
+ CWalletTx wtx(pwalletMain,tx);
+
+ CDataStream ssMB(ParseHexV(params[1], "proof"), SER_NETWORK, PROTOCOL_VERSION);
+ CMerkleBlock merkleBlock;
+ ssMB >> merkleBlock;
+
+ string strLabel = "";
+ if (params.size() == 3)
+ strLabel = params[2].get_str();
+
+ //Search partial merkle tree in proof for our transaction and index in valid block
+ vector<uint256> vMatch;
+ vector<unsigned int> vIndex;
+ unsigned int txnIndex = 0;
+ if (merkleBlock.txn.ExtractMatches(vMatch, vIndex) == merkleBlock.header.hashMerkleRoot) {
+
+ LOCK(cs_main);
+
+ if (!mapBlockIndex.count(merkleBlock.header.GetHash()) || !chainActive.Contains(mapBlockIndex[merkleBlock.header.GetHash()]))
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found in chain");
+
+ vector<uint256>::const_iterator it;
+ if ((it = std::find(vMatch.begin(), vMatch.end(), hashTx))==vMatch.end()) {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction given doesn't exist in proof");
+ }
+
+ txnIndex = vIndex[it - vMatch.begin()];
+ }
+ else {
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Something wrong with merkleblock");
+ }
+
+ wtx.nIndex = txnIndex;
+ wtx.hashBlock = merkleBlock.header.GetHash();
+
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
+ if (pwalletMain->IsMine(tx)) {
+ CWalletDB walletdb(pwalletMain->strWalletFile, "r+", false);
+ pwalletMain->AddToWallet(wtx, false, &walletdb);
+ return NullUniValue;
+ }
+
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No addresses in wallet correspond to included transaction");
+}
+
+UniValue removeprunedfunds(const UniValue& params, bool fHelp)
+{
+ if (!EnsureWalletIsAvailable(fHelp))
+ return NullUniValue;
+
+ if (fHelp || params.size() != 1)
+ throw runtime_error(
+ "removeprunedfunds \"txid\"\n"
+ "\nDeletes the specified transaction from the wallet. Meant for use with pruned wallets and as a companion to importprunedfunds. This will effect wallet balances.\n"
+ "\nArguments:\n"
+ "1. \"txid\" (string, required) The hex-encoded id of the transaction you are deleting\n"
+ "\nExamples:\n"
+ + HelpExampleCli("removeprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"") +
+ "\nAs a JSON-RPC call\n"
+ + HelpExampleRpc("removprunedfunds", "\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"")
+ );
+
+ LOCK2(cs_main, pwalletMain->cs_wallet);
+
+ uint256 hash;
+ hash.SetHex(params[0].get_str());
+ vector<uint256> vHash;
+ vHash.push_back(hash);
+ vector<uint256> vHashOut;
+
+ if(pwalletMain->ZapSelectTx(vHash, vHashOut) != DB_LOAD_OK) {
+ throw JSONRPCError(RPC_INTERNAL_ERROR, "Could not properly delete the transaction.");
+ }
+
+ if(vHashOut.empty()) {
+ throw JSONRPCError(RPC_INTERNAL_ERROR, "Transaction does not exist in wallet.");
+ }
+
+ ThreadFlushWalletDB(pwalletMain->strWalletFile);
+
+ return NullUniValue;
+}
+
UniValue importpubkey(const UniValue& params, bool fHelp)
{
if (!EnsureWalletIsAvailable(fHelp))
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 857a3a77e2..61c9846e11 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -394,7 +394,7 @@ static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtr
throw JSONRPCError(RPC_WALLET_ERROR, strError);
}
if (!pwalletMain->CommitTransaction(wtxNew, reservekey))
- throw JSONRPCError(RPC_WALLET_ERROR, "Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
+ throw JSONRPCError(RPC_WALLET_ERROR, "Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of the wallet and coins were spent in the copy but not marked as spent here.");
}
UniValue sendtoaddress(const UniValue& params, bool fHelp)
@@ -1245,7 +1245,7 @@ UniValue listreceivedbyaddress(const UniValue& params, bool fHelp)
"\nList balances by receiving address.\n"
"\nArguments:\n"
"1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
- "2. includeempty (numeric, optional, default=false) Whether to include addresses that haven't received any payments.\n"
+ "2. includeempty (bool, optional, default=false) Whether to include addresses that haven't received any payments.\n"
"3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
"\nResult:\n"
@@ -1283,7 +1283,7 @@ UniValue listreceivedbyaccount(const UniValue& params, bool fHelp)
"\nDEPRECATED. List balances by account.\n"
"\nArguments:\n"
"1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n"
- "2. includeempty (boolean, optional, default=false) Whether to include accounts that haven't received any payments.\n"
+ "2. includeempty (bool, optional, default=false) Whether to include accounts that haven't received any payments.\n"
"3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n"
"\nResult:\n"
@@ -1346,6 +1346,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe
entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
if (fLong)
WalletTxToJSON(wtx, entry);
+ entry.push_back(Pair("abandoned", wtx.isAbandoned()));
ret.push_back(entry);
}
}
@@ -1438,13 +1439,14 @@ UniValue listtransactions(const UniValue& params, bool fHelp)
" \"vout\": n, (numeric) the vout value\n"
" \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n"
" 'send' category of transactions.\n"
+ " \"abandoned\": xxx (bool) 'true' if the transaction has been abandoned (inputs are respendable).\n"
" \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and \n"
" 'receive' category of transactions. Negative confirmations indicate the\n"
" transaction conflicts with the block chain\n"
" \"trusted\": xxx (bool) Whether we consider the outputs of this unconfirmed transaction safe to spend.\n"
" \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive'\n"
" category of transactions.\n"
- " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive'\n"
+ " \"blockindex\": n, (numeric) The index of the transaction in the block that includes it. Available for 'send' and 'receive'\n"
" category of transactions.\n"
" \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
" \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
@@ -1637,7 +1639,7 @@ UniValue listsinceblock(const UniValue& params, bool fHelp)
" \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the 'send' category of transactions.\n"
" \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.\n"
" \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
- " \"blockindex\": n, (numeric) The block index containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
+ " \"blockindex\": n, (numeric) The index of the transaction in the block that includes it. Available for 'send' and 'receive' category of transactions.\n"
" \"blocktime\": xxx, (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
" \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
" \"time\": xxx, (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n"
@@ -1721,7 +1723,7 @@ UniValue gettransaction(const UniValue& params, bool fHelp)
" \"amount\" : x.xxx, (numeric) The transaction amount in " + CURRENCY_UNIT + "\n"
" \"confirmations\" : n, (numeric) The number of confirmations\n"
" \"blockhash\" : \"hash\", (string) The block hash\n"
- " \"blockindex\" : xx, (numeric) The block index\n"
+ " \"blockindex\" : xx, (numeric) The index of the transaction in the block that includes it\n"
" \"blocktime\" : ttt, (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n"
" \"txid\" : \"transactionid\", (string) The transaction id.\n"
" \"time\" : ttt, (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n"
@@ -1827,7 +1829,7 @@ UniValue backupwallet(const UniValue& params, bool fHelp)
if (fHelp || params.size() != 1)
throw runtime_error(
"backupwallet \"destination\"\n"
- "\nSafely copies wallet.dat to destination, which can be a directory or a path with filename.\n"
+ "\nSafely copies current wallet file to destination, which can be a directory or a path with filename.\n"
"\nArguments:\n"
"1. \"destination\" (string) The destination directory or file\n"
"\nExamples:\n"
@@ -2098,16 +2100,17 @@ UniValue lockunspent(const UniValue& params, bool fHelp)
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
- "lockunspent unlock [{\"txid\":\"txid\",\"vout\":n},...]\n"
+ "lockunspent unlock ([{\"txid\":\"txid\",\"vout\":n},...])\n"
"\nUpdates list of temporarily unspendable outputs.\n"
"Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
+ "If no transaction outputs are specified when unlocking then all current locked transaction outputs are unlocked.\n"
"A locked transaction output will not be chosen by automatic coin selection, when spending bitcoins.\n"
"Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n"
"is always cleared (by virtue of process exit) when a node stops or fails.\n"
"Also see the listunspent call\n"
"\nArguments:\n"
"1. unlock (boolean, required) Whether to unlock (true) or lock (false) the specified transactions\n"
- "2. \"transactions\" (string, required) A json array of objects. Each object the txid (string) vout (numeric)\n"
+ "2. \"transactions\" (string, optional) A json array of objects. Each object the txid (string) vout (numeric)\n"
" [ (json array of json objects)\n"
" {\n"
" \"txid\":\"id\", (string) The transaction id\n"
@@ -2503,8 +2506,10 @@ extern UniValue importaddress(const UniValue& params, bool fHelp);
extern UniValue importpubkey(const UniValue& params, bool fHelp);
extern UniValue dumpwallet(const UniValue& params, bool fHelp);
extern UniValue importwallet(const UniValue& params, bool fHelp);
+extern UniValue importprunedfunds(const UniValue& params, bool fHelp);
+extern UniValue removeprunedfunds(const UniValue& params, bool fHelp);
-const CRPCCommand vWalletRPCCommands[] =
+static const CRPCCommand commands[] =
{ // category name actor (function) okSafeMode
// --------------------- ------------------------ ----------------------- ----------
{ "rawtransactions", "fundrawtransaction", &fundrawtransaction, false },
@@ -2529,6 +2534,7 @@ const CRPCCommand vWalletRPCCommands[] =
{ "wallet", "importprivkey", &importprivkey, true },
{ "wallet", "importwallet", &importwallet, true },
{ "wallet", "importaddress", &importaddress, true },
+ { "wallet", "importprunedfunds", &importprunedfunds, true },
{ "wallet", "importpubkey", &importpubkey, true },
{ "wallet", "keypoolrefill", &keypoolrefill, true },
{ "wallet", "listaccounts", &listaccounts, false },
@@ -2550,16 +2556,11 @@ const CRPCCommand vWalletRPCCommands[] =
{ "wallet", "walletlock", &walletlock, true },
{ "wallet", "walletpassphrasechange", &walletpassphrasechange, true },
{ "wallet", "walletpassphrase", &walletpassphrase, true },
+ { "wallet", "removeprunedfunds", &removeprunedfunds, true },
};
-void walletRegisterRPCCommands()
+void RegisterWalletRPCCommands(CRPCTable &tableRPC)
{
- unsigned int vcidx;
- for (vcidx = 0; vcidx < ARRAYLEN(vWalletRPCCommands); vcidx++)
- {
- const CRPCCommand *pcmd;
-
- pcmd = &vWalletRPCCommands[vcidx];
- tableRPC.appendCommand(pcmd->name, pcmd);
- }
+ for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
+ tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
}
diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h
index 42e8021afa..a5de7e2de1 100644
--- a/src/wallet/rpcwallet.h
+++ b/src/wallet/rpcwallet.h
@@ -5,6 +5,8 @@
#ifndef BITCOIN_WALLET_RPCWALLET_H
#define BITCOIN_WALLET_RPCWALLET_H
-void walletRegisterRPCCommands();
+class CRPCTable;
+
+void RegisterWalletRPCCommands(CRPCTable &tableRPC);
#endif //BITCOIN_WALLET_RPCWALLET_H
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index ade460d6ac..1ea8d2ffe7 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -33,14 +33,14 @@
using namespace std;
-/**
- * Settings
- */
+/** Transaction fee set by the user */
CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE);
unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET;
bool bSpendZeroConfChange = DEFAULT_SPEND_ZEROCONF_CHANGE;
bool fSendFreeTransactions = DEFAULT_SEND_FREE_TRANSACTIONS;
+const char * DEFAULT_WALLET_DAT = "wallet.dat";
+
/**
* Fees smaller than this (in satoshi) are considered zero fee (for transaction creation)
* Override with -mintxfee
@@ -399,13 +399,14 @@ bool CWallet::Verify(const string& walletFile, string& warningString, string& er
CDBEnv::VerifyResult r = bitdb.Verify(walletFile, CWalletDB::Recover);
if (r == CDBEnv::RECOVER_OK)
{
- warningString += strprintf(_("Warning: wallet.dat corrupt, data salvaged!"
- " Original wallet.dat saved as wallet.{timestamp}.bak in %s; if"
- " your balance or transactions are incorrect you should"
- " restore from a backup."), GetDataDir());
+ warningString += strprintf(_("Warning: Wallet file corrupt, data salvaged!"
+ " Original %s saved as %s in %s; if"
+ " your balance or transactions are incorrect you should"
+ " restore from a backup."),
+ walletFile, "wallet.{timestamp}.bak", GetDataDir());
}
if (r == CDBEnv::RECOVER_FAIL)
- errorString += _("wallet.dat corrupt, salvage failed");
+ errorString += strprintf(_("%s corrupt, salvage failed"), walletFile);
}
return true;
@@ -846,14 +847,19 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
{
LOCK2(cs_main, cs_wallet);
- CBlockIndex* pindex;
- assert(mapBlockIndex.count(hashBlock));
- pindex = mapBlockIndex[hashBlock];
int conflictconfirms = 0;
- if (chainActive.Contains(pindex)) {
- conflictconfirms = -(chainActive.Height() - pindex->nHeight + 1);
+ if (mapBlockIndex.count(hashBlock)) {
+ CBlockIndex* pindex = mapBlockIndex[hashBlock];
+ if (chainActive.Contains(pindex)) {
+ conflictconfirms = -(chainActive.Height() - pindex->nHeight + 1);
+ }
}
- assert(conflictconfirms < 0);
+ // If number of conflict confirms cannot be determined, this means
+ // that the block is still unknown or not yet part of the main chain,
+ // for example when loading the wallet during a reindex. Do nothing in that
+ // case.
+ if (conflictconfirms >= 0)
+ return;
// Do not flush the wallet here for performance reasons
CWalletDB walletdb(strWalletFile, "r+", false);
@@ -1260,9 +1266,11 @@ bool CWalletTx::RelayWalletTransaction()
assert(pwallet->GetBroadcastTransactions());
if (!IsCoinBase())
{
- if (GetDepthInMainChain() == 0 && !isAbandoned()) {
+ if (GetDepthInMainChain() == 0 && !isAbandoned() && InMempool()) {
LogPrintf("Relaying wtx %s\n", GetHash().ToString());
- RelayTransaction((CTransaction)*this);
+ CFeeRate feeRate;
+ mempool.lookupFeeRate(GetHash(), feeRate);
+ RelayTransaction((CTransaction)*this, feeRate);
return true;
}
}
@@ -1572,7 +1580,7 @@ CAmount CWallet::GetUnconfirmedBalance() const
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
- if (!CheckFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
+ if (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0 && pcoin->InMempool())
nTotal += pcoin->GetAvailableCredit();
}
}
@@ -1617,7 +1625,7 @@ CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
- if (!CheckFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
+ if (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0 && pcoin->InMempool())
nTotal += pcoin->GetAvailableWatchOnlyCredit();
}
}
@@ -1662,11 +1670,16 @@ void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const
if (nDepth < 0)
continue;
+ // We should not consider coins which aren't at least in our mempool
+ // It's possible for these to be conflicted via ancestors which we may never be able to detect
+ if (nDepth == 0 && !pcoin->InMempool())
+ continue;
+
for (unsigned int i = 0; i < pcoin->vout.size(); i++) {
isminetype mine = IsMine(pcoin->vout[i]);
if (!(IsSpent(wtxid, i)) && mine != ISMINE_NO &&
!IsLockedCoin((*it).first, i) && (pcoin->vout[i].nValue > 0 || fIncludeZeroValue) &&
- (!coinControl || !coinControl->HasSelected() || coinControl->fAllowOtherInputs || coinControl->IsSelected((*it).first, i)))
+ (!coinControl || !coinControl->HasSelected() || coinControl->fAllowOtherInputs || coinControl->IsSelected(COutPoint((*it).first, i))))
vCoins.push_back(COutput(pcoin, i, nDepth,
((mine & ISMINE_SPENDABLE) != ISMINE_NO) ||
(coinControl && coinControl->fAllowWatchOnly && (mine & ISMINE_WATCH_SOLVABLE) != ISMINE_NO)));
@@ -1833,10 +1846,9 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int
return true;
}
-bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl) const
+bool CWallet::SelectCoins(const vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl) const
{
- vector<COutput> vCoins;
- AvailableCoins(vCoins, true, coinControl);
+ vector<COutput> vCoins(vAvailableCoins);
// coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs)
@@ -1924,16 +1936,7 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nC
// Add new txins (keeping original txin scriptSig/order)
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
{
- bool found = false;
- BOOST_FOREACH(const CTxIn& origTxIn, tx.vin)
- {
- if (txin.prevout.hash == origTxIn.prevout.hash && txin.prevout.n == origTxIn.prevout.n)
- {
- found = true;
- break;
- }
- }
- if (!found)
+ if (!coinControl.IsSelected(txin.prevout))
tx.vin.push_back(txin);
}
@@ -2002,6 +2005,9 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
{
LOCK2(cs_main, cs_wallet);
{
+ std::vector<COutput> vAvailableCoins;
+ AvailableCoins(vAvailableCoins, true, coinControl);
+
nFeeRet = 0;
// Start with no fee and loop until there is enough fee
while (true)
@@ -2051,7 +2057,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
// Choose coins to use
set<pair<const CWalletTx*,unsigned int> > setCoins;
CAmount nValueIn = 0;
- if (!SelectCoins(nValueToSelect, setCoins, nValueIn, coinControl))
+ if (!SelectCoins(vAvailableCoins, nValueToSelect, setCoins, nValueIn, coinControl))
{
strFailReason = _("Insufficient funds");
return false;
@@ -2347,6 +2353,31 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
return DB_LOAD_OK;
}
+DBErrors CWallet::ZapSelectTx(vector<uint256>& vHashIn, vector<uint256>& vHashOut)
+{
+ if (!fFileBacked)
+ return DB_LOAD_OK;
+ DBErrors nZapSelectTxRet = CWalletDB(strWalletFile,"cr+").ZapSelectTx(this, vHashIn, vHashOut);
+ if (nZapSelectTxRet == DB_NEED_REWRITE)
+ {
+ if (CDB::Rewrite(strWalletFile, "\x04pool"))
+ {
+ LOCK(cs_wallet);
+ setKeyPool.clear();
+ // Note: can't top-up keypool here, because wallet is locked.
+ // User will be prompted to unlock wallet the next operation
+ // that requires a new key.
+ }
+ }
+
+ if (nZapSelectTxRet != DB_LOAD_OK)
+ return nZapSelectTxRet;
+
+ MarkDirty();
+
+ return DB_LOAD_OK;
+
+}
DBErrors CWallet::ZapWalletTx(std::vector<CWalletTx>& vWtx)
{
@@ -2951,6 +2982,203 @@ bool CWallet::GetDestData(const CTxDestination &dest, const std::string &key, st
return false;
}
+std::string CWallet::GetWalletHelpString(bool showDebug)
+{
+ std::string strUsage = HelpMessageGroup(_("Wallet options:"));
+ strUsage += HelpMessageOpt("-disablewallet", _("Do not load the wallet and disable wallet RPC calls"));
+ strUsage += HelpMessageOpt("-keypool=<n>", strprintf(_("Set key pool size to <n> (default: %u)"), DEFAULT_KEYPOOL_SIZE));
+ strUsage += HelpMessageOpt("-fallbackfee=<amt>", strprintf(_("A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)"),
+ CURRENCY_UNIT, FormatMoney(DEFAULT_FALLBACK_FEE)));
+ strUsage += HelpMessageOpt("-mintxfee=<amt>", strprintf(_("Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)"),
+ CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MINFEE)));
+ strUsage += HelpMessageOpt("-paytxfee=<amt>", strprintf(_("Fee (in %s/kB) to add to transactions you send (default: %s)"),
+ CURRENCY_UNIT, FormatMoney(payTxFee.GetFeePerK())));
+ strUsage += HelpMessageOpt("-rescan", _("Rescan the block chain for missing wallet transactions on startup"));
+ strUsage += HelpMessageOpt("-salvagewallet", _("Attempt to recover private keys from a corrupt wallet on startup"));
+ if (showDebug)
+ strUsage += HelpMessageOpt("-sendfreetransactions", strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), DEFAULT_SEND_FREE_TRANSACTIONS));
+ strUsage += HelpMessageOpt("-spendzeroconfchange", strprintf(_("Spend unconfirmed change when sending transactions (default: %u)"), DEFAULT_SPEND_ZEROCONF_CHANGE));
+ strUsage += HelpMessageOpt("-txconfirmtarget=<n>", strprintf(_("If paytxfee is not set, include enough fee so transactions begin confirmation on average within n blocks (default: %u)"), DEFAULT_TX_CONFIRM_TARGET));
+ strUsage += HelpMessageOpt("-upgradewallet", _("Upgrade wallet to latest format on startup"));
+ strUsage += HelpMessageOpt("-wallet=<file>", _("Specify wallet file (within data directory)") + " " + strprintf(_("(default: %s)"), DEFAULT_WALLET_DAT));
+ strUsage += HelpMessageOpt("-walletbroadcast", _("Make the wallet broadcast transactions") + " " + strprintf(_("(default: %u)"), DEFAULT_WALLETBROADCAST));
+ strUsage += HelpMessageOpt("-walletnotify=<cmd>", _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)"));
+ strUsage += HelpMessageOpt("-zapwallettxes=<mode>", _("Delete all wallet transactions and only recover those parts of the blockchain through -rescan on startup") +
+ " " + _("(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)"));
+
+ if (showDebug)
+ {
+ strUsage += HelpMessageGroup(_("Wallet debugging/testing options:"));
+
+ strUsage += HelpMessageOpt("-dblogsize=<n>", strprintf("Flush wallet database activity from memory to disk log every <n> megabytes (default: %u)", DEFAULT_WALLET_DBLOGSIZE));
+ strUsage += HelpMessageOpt("-flushwallet", strprintf("Run a thread to flush wallet periodically (default: %u)", DEFAULT_FLUSHWALLET));
+ strUsage += HelpMessageOpt("-privdb", strprintf("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)", DEFAULT_WALLET_PRIVDB));
+ }
+
+ return strUsage;
+}
+
+CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWalletFile, std::string& warningString, std::string& errorString)
+{
+ // needed to restore wallet transaction meta data after -zapwallettxes
+ std::vector<CWalletTx> vWtx;
+
+ if (GetBoolArg("-zapwallettxes", false)) {
+ uiInterface.InitMessage(_("Zapping all transactions from wallet..."));
+
+ CWallet *tempWallet = new CWallet(strWalletFile);
+ DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx);
+ if (nZapWalletRet != DB_LOAD_OK) {
+ errorString = strprintf(_("Error loading %s: Wallet corrupted"), strWalletFile);
+ uiInterface.InitMessage(strprintf(_("Error loading %s: Wallet corrupted"), strWalletFile));
+ return NULL;
+ }
+
+ delete tempWallet;
+ tempWallet = NULL;
+ }
+
+ uiInterface.InitMessage(_("Loading wallet..."));
+
+ int64_t nStart = GetTimeMillis();
+ bool fFirstRun = true;
+ CWallet *walletInstance = new CWallet(strWalletFile);
+ DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
+ if (nLoadWalletRet != DB_LOAD_OK)
+ {
+ if (nLoadWalletRet == DB_CORRUPT)
+ errorString += strprintf(_("Error loading %s: Wallet corrupted"), strWalletFile) + "\n";
+ else if (nLoadWalletRet == DB_NONCRITICAL_ERROR)
+ {
+ warningString += strprintf(_("Error reading %s! All keys read correctly, but transaction data"
+ " or address book entries might be missing or incorrect."),
+ strWalletFile);
+ }
+ else if (nLoadWalletRet == DB_TOO_NEW)
+ errorString += strprintf(_("Error loading %s: Wallet requires newer version of %s"),
+ strWalletFile, _(PACKAGE_NAME)) +
+ "\n";
+ else if (nLoadWalletRet == DB_NEED_REWRITE)
+ {
+ errorString += strprintf(_("Wallet needed to be rewritten: restart %s to complete"), _(PACKAGE_NAME)) + "\n";
+ LogPrintf("%s", errorString);
+ }
+ else
+ errorString += strprintf(_("Error loading %s"), strWalletFile) + "\n";
+
+ if (!errorString.empty())
+ return NULL;
+ }
+
+ if (GetBoolArg("-upgradewallet", fFirstRun))
+ {
+ int nMaxVersion = GetArg("-upgradewallet", 0);
+ if (nMaxVersion == 0) // the -upgradewallet without argument case
+ {
+ LogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
+ nMaxVersion = CLIENT_VERSION;
+ walletInstance->SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately
+ }
+ else
+ LogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
+ if (nMaxVersion < walletInstance->GetVersion())
+ {
+ errorString += _("Cannot downgrade wallet") + "\n";
+ return NULL;
+ }
+ walletInstance->SetMaxVersion(nMaxVersion);
+ }
+
+ if (fFirstRun)
+ {
+ // Create new keyUser and set as default key
+ RandAddSeedPerfmon();
+
+ CPubKey newDefaultKey;
+ if (walletInstance->GetKeyFromPool(newDefaultKey)) {
+ walletInstance->SetDefaultKey(newDefaultKey);
+ if (!walletInstance->SetAddressBook(walletInstance->vchDefaultKey.GetID(), "", "receive"))
+ {
+ errorString += _("Cannot write default address") += "\n";
+ return NULL;
+ }
+ }
+
+ walletInstance->SetBestChain(chainActive.GetLocator());
+ }
+
+ LogPrintf(" wallet %15dms\n", GetTimeMillis() - nStart);
+
+ RegisterValidationInterface(walletInstance);
+
+ CBlockIndex *pindexRescan = chainActive.Tip();
+ if (GetBoolArg("-rescan", false))
+ pindexRescan = chainActive.Genesis();
+ else
+ {
+ CWalletDB walletdb(strWalletFile);
+ CBlockLocator locator;
+ if (walletdb.ReadBestBlock(locator))
+ pindexRescan = FindForkInGlobalIndex(chainActive, locator);
+ else
+ pindexRescan = chainActive.Genesis();
+ }
+ if (chainActive.Tip() && chainActive.Tip() != pindexRescan)
+ {
+ //We can't rescan beyond non-pruned blocks, stop and throw an error
+ //this might happen if a user uses a old wallet within a pruned node
+ // or if he ran -disablewallet for a longer time, then decided to re-enable
+ if (fPruneMode)
+ {
+ CBlockIndex *block = chainActive.Tip();
+ while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA) && block->pprev->nTx > 0 && pindexRescan != block)
+ block = block->pprev;
+
+ if (pindexRescan != block)
+ {
+ errorString = _("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)");
+ return NULL;
+ }
+ }
+
+ uiInterface.InitMessage(_("Rescanning..."));
+ LogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height() - pindexRescan->nHeight, pindexRescan->nHeight);
+ nStart = GetTimeMillis();
+ walletInstance->ScanForWalletTransactions(pindexRescan, true);
+ LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart);
+ walletInstance->SetBestChain(chainActive.GetLocator());
+ nWalletDBUpdated++;
+
+ // Restore wallet transaction metadata after -zapwallettxes=1
+ if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2")
+ {
+ CWalletDB walletdb(strWalletFile);
+
+ BOOST_FOREACH(const CWalletTx& wtxOld, vWtx)
+ {
+ uint256 hash = wtxOld.GetHash();
+ std::map<uint256, CWalletTx>::iterator mi = walletInstance->mapWallet.find(hash);
+ if (mi != walletInstance->mapWallet.end())
+ {
+ const CWalletTx* copyFrom = &wtxOld;
+ CWalletTx* copyTo = &mi->second;
+ copyTo->mapValue = copyFrom->mapValue;
+ copyTo->vOrderForm = copyFrom->vOrderForm;
+ copyTo->nTimeReceived = copyFrom->nTimeReceived;
+ copyTo->nTimeSmart = copyFrom->nTimeSmart;
+ copyTo->fFromMe = copyFrom->fFromMe;
+ copyTo->strFromAccount = copyFrom->strFromAccount;
+ copyTo->nOrderPos = copyFrom->nOrderPos;
+ copyTo->WriteToDisk(&walletdb);
+ }
+ }
+ }
+ }
+ walletInstance->SetBroadcastTransactions(GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
+
+ return walletInstance;
+}
+
CKeyPool::CKeyPool()
{
nTime = GetTime();
@@ -3028,5 +3256,5 @@ int CMerkleTx::GetBlocksToMaturity() const
bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, CAmount nAbsurdFee)
{
CValidationState state;
- return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, false, nAbsurdFee);
+ return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, NULL, false, nAbsurdFee);
}
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 990b27c7ce..5db36f52d1 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -55,6 +55,8 @@ static const unsigned int DEFAULT_TX_CONFIRM_TARGET = 2;
static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000;
static const bool DEFAULT_WALLETBROADCAST = true;
+extern const char * DEFAULT_WALLET_DAT;
+
class CBlockIndex;
class CCoinControl;
class COutput;
@@ -542,7 +544,7 @@ private:
* all coins from coinControl are selected; Never select unconfirmed coins
* if they are not ours
*/
- bool SelectCoins(const CAmount& nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl *coinControl = NULL) const;
+ bool SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl *coinControl = NULL) const;
CWalletDB *pwalletdbEncryption;
@@ -790,6 +792,7 @@ public:
DBErrors LoadWallet(bool& fFirstRunRet);
DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx);
+ DBErrors ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut);
bool SetAddressBook(const CTxDestination& address, const std::string& strName, const std::string& purpose);
@@ -869,6 +872,12 @@ public:
/* Mark a transaction (and it in-wallet descendants) as abandoned so its inputs may be respent. */
bool AbandonTransaction(const uint256& hashTx);
+
+ /* Returns the wallets help message */
+ static std::string GetWalletHelpString(bool showDebug);
+
+ /* initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */
+ static CWallet* InitLoadWallet(bool fDisableWallet, const std::string& strWalletFile, std::string& warningString, std::string& errorString);
};
/** A key allocated from the key pool. */
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index 67511976df..f2b5408e92 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -785,6 +785,45 @@ DBErrors CWalletDB::FindWalletTx(CWallet* pwallet, vector<uint256>& vTxHash, vec
return result;
}
+DBErrors CWalletDB::ZapSelectTx(CWallet* pwallet, vector<uint256>& vTxHashIn, vector<uint256>& vTxHashOut)
+{
+ // build list of wallet TXs and hashes
+ vector<uint256> vTxHash;
+ vector<CWalletTx> vWtx;
+ DBErrors err = FindWalletTx(pwallet, vTxHash, vWtx);
+ if (err != DB_LOAD_OK) {
+ return err;
+ }
+
+ std::sort(vTxHash.begin(), vTxHash.end());
+ std::sort(vTxHashIn.begin(), vTxHashIn.end());
+
+ // erase each matching wallet TX
+ bool delerror = false;
+ vector<uint256>::iterator it = vTxHashIn.begin();
+ BOOST_FOREACH (uint256 hash, vTxHash) {
+ while (it < vTxHashIn.end() && (*it) < hash) {
+ it++;
+ }
+ if (it == vTxHashIn.end()) {
+ break;
+ }
+ else if ((*it) == hash) {
+ pwallet->mapWallet.erase(hash);
+ if(!EraseTx(hash)) {
+ LogPrint("db", "Transaction was found for deletion but returned database error: %s\n", hash.GetHex());
+ delerror = true;
+ }
+ vTxHashOut.push_back(hash);
+ }
+ }
+
+ if (delerror) {
+ return DB_CORRUPT;
+ }
+ return DB_LOAD_OK;
+}
+
DBErrors CWalletDB::ZapWalletTx(CWallet* pwallet, vector<CWalletTx>& vWtx)
{
// build list of wallet TXs
@@ -847,16 +886,16 @@ void ThreadFlushWalletDB(const string& strFile)
map<string, int>::iterator mi = bitdb.mapFileUseCount.find(strFile);
if (mi != bitdb.mapFileUseCount.end())
{
- LogPrint("db", "Flushing wallet.dat\n");
+ LogPrint("db", "Flushing %s\n", strFile);
nLastFlushed = nWalletDBUpdated;
int64_t nStart = GetTimeMillis();
- // Flush wallet.dat so it's self contained
+ // Flush wallet file so it's self contained
bitdb.CloseDb(strFile);
bitdb.CheckpointLSN(strFile);
bitdb.mapFileUseCount.erase(mi++);
- LogPrint("db", "Flushed wallet.dat %dms\n", GetTimeMillis() - nStart);
+ LogPrint("db", "Flushed %s %dms\n", strFile, GetTimeMillis() - nStart);
}
}
}
@@ -879,7 +918,7 @@ bool BackupWallet(const CWallet& wallet, const string& strDest)
bitdb.CheckpointLSN(wallet.strWalletFile);
bitdb.mapFileUseCount.erase(wallet.strWalletFile);
- // Copy wallet.dat
+ // Copy wallet file
boost::filesystem::path pathSrc = GetDataDir() / wallet.strWalletFile;
boost::filesystem::path pathDest(strDest);
if (boost::filesystem::is_directory(pathDest))
@@ -891,10 +930,10 @@ bool BackupWallet(const CWallet& wallet, const string& strDest)
#else
boost::filesystem::copy_file(pathSrc, pathDest);
#endif
- LogPrintf("copied wallet.dat to %s\n", pathDest.string());
+ LogPrintf("copied %s to %s\n", wallet.strWalletFile, pathDest.string());
return true;
} catch (const boost::filesystem::filesystem_error& e) {
- LogPrintf("error copying wallet.dat to %s - %s\n", pathDest.string(), e.what());
+ LogPrintf("error copying %s to %s - %s\n", wallet.strWalletFile, pathDest.string(), e.what());
return false;
}
}
@@ -905,15 +944,15 @@ bool BackupWallet(const CWallet& wallet, const string& strDest)
}
//
-// Try to (very carefully!) recover wallet.dat if there is a problem.
+// Try to (very carefully!) recover wallet file if there is a problem.
//
bool CWalletDB::Recover(CDBEnv& dbenv, const std::string& filename, bool fOnlyKeys)
{
// Recovery procedure:
- // move wallet.dat to wallet.timestamp.bak
+ // move wallet file to wallet.timestamp.bak
// Call Salvage with fAggressive=true to
// get as much data as possible.
- // Rewrite salvaged data to wallet.dat
+ // Rewrite salvaged data to fresh wallet file
// Set -rescan so any missing transactions will be
// found.
int64_t now = GetTime();
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index 8da33dead2..fe6c366343 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -73,7 +73,7 @@ public:
}
};
-/** Access to the wallet database (wallet.dat) */
+/** Access to the wallet database */
class CWalletDB : public CDB
{
public:
@@ -130,6 +130,7 @@ public:
DBErrors LoadWallet(CWallet* pwallet);
DBErrors FindWalletTx(CWallet* pwallet, std::vector<uint256>& vTxHash, std::vector<CWalletTx>& vWtx);
DBErrors ZapWalletTx(CWallet* pwallet, std::vector<CWalletTx>& vWtx);
+ DBErrors ZapSelectTx(CWallet* pwallet, std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut);
static bool Recover(CDBEnv& dbenv, const std::string& filename, bool fOnlyKeys);
static bool Recover(CDBEnv& dbenv, const std::string& filename);
diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp
index c8adcf8462..8705532429 100644
--- a/src/zmq/zmqnotificationinterface.cpp
+++ b/src/zmq/zmqnotificationinterface.cpp
@@ -100,7 +100,6 @@ bool CZMQNotificationInterface::Initialize()
if (i!=notifiers.end())
{
- Shutdown();
return false;
}
diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp
index ddc8fe93e9..f5839620ff 100644
--- a/src/zmq/zmqpublishnotifier.cpp
+++ b/src/zmq/zmqpublishnotifier.cpp
@@ -69,6 +69,7 @@ bool CZMQAbstractPublishNotifier::Initialize(void *pcontext)
if (rc!=0)
{
zmqError("Failed to bind address");
+ zmq_close(psocket);
return false;
}