aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml3
-rw-r--r--Makefile.am12
-rw-r--r--build-aux/m4/ax_boost_base.m420
-rw-r--r--build-aux/m4/ax_boost_program_options.m47
-rw-r--r--build-aux/m4/ax_boost_system.m45
-rw-r--r--build-aux/m4/ax_check_compile_flag.m412
-rw-r--r--build-aux/m4/ax_check_link_flag.m413
-rw-r--r--build-aux/m4/ax_check_preproc_flag.m412
-rw-r--r--build-aux/m4/ax_gcc_func_attribute.m48
-rw-r--r--build-aux/m4/ax_pthread.m4537
-rw-r--r--configure.ac60
-rw-r--r--contrib/README.md13
-rwxr-xr-xcontrib/devtools/github-merge.py52
-rwxr-xr-xcontrib/devtools/security-check.py34
-rwxr-xr-xcontrib/devtools/symbol-check.py63
-rw-r--r--contrib/gitian-descriptors/gitian-linux.yml2
-rw-r--r--contrib/gitian-descriptors/gitian-osx.yml2
-rw-r--r--contrib/gitian-descriptors/gitian-win.yml2
-rw-r--r--contrib/gitian-keys/achow101-key.pgp (renamed from contrib/gitian-downloader/achow101-key.pgp)0
-rw-r--r--contrib/gitian-keys/aschildbach-key.pgp (renamed from contrib/gitian-downloader/aschildbach-key.pgp)bin1993 -> 1993 bytes
-rw-r--r--contrib/gitian-keys/bluematt-key.pgp (renamed from contrib/gitian-downloader/bluematt-key.pgp)bin10324 -> 10324 bytes
-rw-r--r--contrib/gitian-keys/btcdrak-key.pgp (renamed from contrib/gitian-downloader/btcdrak-key.pgp)0
-rw-r--r--contrib/gitian-keys/cdecker-key.pgp (renamed from contrib/gitian-downloader/cdecker-key.pgp)bin2230 -> 2230 bytes
-rw-r--r--contrib/gitian-keys/centaur1-key.pgp (renamed from contrib/gitian-downloader/centaur1-key.pgp)0
-rw-r--r--contrib/gitian-keys/cfields-key.pgp (renamed from contrib/gitian-downloader/cfields-key.pgp)0
-rw-r--r--contrib/gitian-keys/devrandom-key.pgp (renamed from contrib/gitian-downloader/devrandom-key.pgp)bin2213 -> 2213 bytes
-rw-r--r--contrib/gitian-keys/erkmos.pgp (renamed from contrib/gitian-downloader/erkmos.pgp)bin10205 -> 10205 bytes
-rw-r--r--contrib/gitian-keys/fanquake-key.pgp (renamed from contrib/gitian-downloader/fanquake-key.pgp)0
-rw-r--r--contrib/gitian-keys/gavinandresen-key.pgp (renamed from contrib/gitian-downloader/gavinandresen-key.pgp)bin1176 -> 1176 bytes
-rw-r--r--contrib/gitian-keys/jl2012-key.pgp105
-rw-r--r--contrib/gitian-keys/jonasschnelli-key.pgp (renamed from contrib/gitian-downloader/jonasschnelli-key.pgp)0
-rw-r--r--contrib/gitian-keys/laanwj-key.pgp (renamed from contrib/gitian-downloader/laanwj-key.pgp)0
-rw-r--r--contrib/gitian-keys/luke-jr-key.pgp (renamed from contrib/gitian-downloader/luke-jr-key.pgp)bin6518 -> 6518 bytes
-rw-r--r--contrib/gitian-keys/marcofalke-key.pgp69
-rw-r--r--contrib/gitian-keys/michagogo-key.pgp (renamed from contrib/gitian-downloader/michagogo-key.pgp)0
-rw-r--r--contrib/gitian-keys/petertodd-key.pgp (renamed from contrib/gitian-downloader/petertodd-key.pgp)0
-rw-r--r--contrib/gitian-keys/prab-key.pgp (renamed from contrib/gitian-downloader/prab-key.pgp)0
-rw-r--r--contrib/gitian-keys/sipa-key.pgp (renamed from contrib/gitian-downloader/sipa-key.pgp)bin137597 -> 137597 bytes
-rw-r--r--contrib/gitian-keys/tcatm-key.pgp (renamed from contrib/gitian-downloader/tcatm-key.pgp)bin1554 -> 1554 bytes
-rw-r--r--contrib/gitian-keys/wtogami-key.pgp (renamed from contrib/gitian-downloader/wtogami-key.pgp)0
-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/verify-commits/trusted-keys1
-rw-r--r--contrib/verifybinaries/README.md (renamed from contrib/verifysfbinaries/README.md)9
-rwxr-xr-xcontrib/verifybinaries/verify.sh (renamed from contrib/verifysfbinaries/verify.sh)6
-rwxr-xr-xcontrib/zmq/zmq_sub.py14
-rw-r--r--depends/Makefile24
-rw-r--r--depends/README.md2
-rwxr-xr-xdepends/config.guess90
-rwxr-xr-xdepends/config.sub12
-rw-r--r--depends/funcs.mk18
-rw-r--r--depends/packages/miniupnpc.mk4
-rw-r--r--depends/packages/native_cctools.mk4
-rw-r--r--depends/packages/qt.mk4
-rw-r--r--doc/bips.md3
-rw-r--r--doc/build-osx.md14
-rw-r--r--doc/build-unix.md41
-rw-r--r--doc/developer-notes.md6
-rw-r--r--doc/gitian-building.md34
-rw-r--r--doc/gitian-building/all_files_in_one_partition.pngbin0 -> 3350 bytes
-rw-r--r--doc/gitian-building/create_vm_file_location_size.pngbin71743 -> 111942 bytes
-rw-r--r--doc/gitian-building/select_startup_disk.pngbin130324 -> 72785 bytes
-rw-r--r--doc/release-notes.md42
-rw-r--r--doc/release-process.md294
-rw-r--r--doc/tor.md2
-rw-r--r--doc/zmq.md5
-rwxr-xr-xqa/pull-tester/rpc-tests.py140
-rwxr-xr-xqa/rpc-tests/abandonconflict.py6
-rwxr-xr-xqa/rpc-tests/bip65-cltv-p2p.py7
-rwxr-xr-xqa/rpc-tests/bip68-112-113-p2p.py539
-rwxr-xr-xqa/rpc-tests/bip68-sequence.py53
-rwxr-xr-xqa/rpc-tests/bip9-softforks.py213
-rwxr-xr-xqa/rpc-tests/bipdersig-p2p.py9
-rwxr-xr-xqa/rpc-tests/blockchain.py3
-rwxr-xr-xqa/rpc-tests/decodescript.py24
-rwxr-xr-xqa/rpc-tests/disablewallet.py14
-rwxr-xr-xqa/rpc-tests/fundrawtransaction.py125
-rwxr-xr-xqa/rpc-tests/getblocktemplate_longpoll.py22
-rwxr-xr-xqa/rpc-tests/getblocktemplate_proposals.py34
-rwxr-xr-xqa/rpc-tests/httpbasics.py41
-rwxr-xr-xqa/rpc-tests/importprunedfunds.py142
-rwxr-xr-xqa/rpc-tests/invalidblockrequest.py12
-rwxr-xr-xqa/rpc-tests/invalidtxrequest.py6
-rwxr-xr-xqa/rpc-tests/keypool.py28
-rwxr-xr-xqa/rpc-tests/listtransactions.py84
-rwxr-xr-xqa/rpc-tests/maxblocksinflight.py56
-rwxr-xr-xqa/rpc-tests/maxuploadtarget.py5
-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.py13
-rwxr-xr-xqa/rpc-tests/p2p-acceptblock.py2
-rwxr-xr-xqa/rpc-tests/p2p-feefilter.py99
-rwxr-xr-xqa/rpc-tests/p2p-fullblocktest.py36
-rwxr-xr-xqa/rpc-tests/p2p-versionbits-warning.py160
-rwxr-xr-xqa/rpc-tests/prioritise_transaction.py33
-rwxr-xr-xqa/rpc-tests/proxy_test.py80
-rwxr-xr-xqa/rpc-tests/pruning.py8
-rwxr-xr-xqa/rpc-tests/rawtransactions.py10
-rwxr-xr-xqa/rpc-tests/receivedby.py40
-rwxr-xr-xqa/rpc-tests/replace-by-fee.py61
-rwxr-xr-xqa/rpc-tests/rest.py20
-rwxr-xr-xqa/rpc-tests/smartfees.py4
-rw-r--r--qa/rpc-tests/test_framework/authproxy.py12
-rw-r--r--qa/rpc-tests/test_framework/blockstore.py7
-rw-r--r--qa/rpc-tests/test_framework/blocktools.py10
-rwxr-xr-xqa/rpc-tests/test_framework/comptool.py30
-rwxr-xr-xqa/rpc-tests/test_framework/mininode.py370
-rw-r--r--qa/rpc-tests/test_framework/netutil.py28
-rw-r--r--qa/rpc-tests/test_framework/script.py4
-rw-r--r--qa/rpc-tests/test_framework/socks5.py4
-rwxr-xr-xqa/rpc-tests/test_framework/test_framework.py7
-rw-r--r--qa/rpc-tests/test_framework/util.py122
-rwxr-xr-xqa/rpc-tests/wallet.py93
-rwxr-xr-xqa/rpc-tests/zapwallettxes.py10
-rwxr-xr-xqa/rpc-tests/zmq_test.py35
-rwxr-xr-xshare/qt/extract_strings_qt.py9
-rw-r--r--share/setup.nsi.in28
-rw-r--r--src/Makefile.am34
-rw-r--r--src/Makefile.leveldb.include81
-rw-r--r--src/Makefile.qt.include9
-rw-r--r--src/Makefile.test.include15
-rw-r--r--src/alert.cpp266
-rw-r--r--src/alert.h113
-rw-r--r--src/amount.cpp22
-rw-r--r--src/amount.h21
-rw-r--r--src/base58.cpp13
-rw-r--r--src/base58.h4
-rw-r--r--src/chain.h2
-rw-r--r--src/chainparams.cpp38
-rw-r--r--src/chainparams.h3
-rw-r--r--src/coincontrol.h5
-rw-r--r--src/coins.cpp8
-rw-r--r--src/coins.h33
-rw-r--r--src/consensus/params.h30
-rw-r--r--src/core_write.cpp4
-rw-r--r--src/crypto/ripemd160.h2
-rw-r--r--src/crypto/sha1.h2
-rw-r--r--src/crypto/sha256.h2
-rw-r--r--src/crypto/sha512.h2
-rw-r--r--src/dbwrapper.cpp55
-rw-r--r--src/dbwrapper.h72
-rw-r--r--src/init.cpp125
-rw-r--r--src/init.h2
-rw-r--r--src/key.cpp6
-rw-r--r--src/key.h21
-rw-r--r--src/keystore.cpp1
-rw-r--r--src/main.cpp535
-rw-r--r--src/main.h56
-rw-r--r--src/merkleblock.cpp14
-rw-r--r--src/merkleblock.h9
-rw-r--r--src/miner.cpp11
-rw-r--r--src/net.cpp54
-rw-r--r--src/net.h16
-rw-r--r--src/netbase.cpp48
-rw-r--r--src/netbase.h23
-rw-r--r--src/policy/fees.cpp19
-rw-r--r--src/policy/fees.h17
-rw-r--r--src/policy/policy.cpp6
-rw-r--r--src/policy/rbf.cpp15
-rw-r--r--src/policy/rbf.h8
-rw-r--r--src/prevector.h19
-rw-r--r--src/primitives/block.cpp2
-rw-r--r--src/primitives/block.h3
-rw-r--r--src/primitives/transaction.h10
-rw-r--r--src/protocol.cpp6
-rw-r--r--src/protocol.h14
-rw-r--r--src/pubkey.cpp6
-rw-r--r--src/pubkey.h30
-rw-r--r--src/qt/bitcoin.qrc1
-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.ui7
-rw-r--r--src/qt/forms/sendcoinsdialog.ui55
-rw-r--r--src/qt/guiconstants.h2
-rw-r--r--src/qt/res/icons/transaction_abandoned.pngbin0 -> 1473 bytes
-rw-r--r--src/qt/rpcconsole.cpp4
-rw-r--r--src/qt/sendcoinsdialog.cpp8
-rw-r--r--src/qt/transactiondesc.cpp5
-rw-r--r--src/qt/transactionrecord.cpp9
-rw-r--r--src/qt/transactionrecord.h5
-rw-r--r--src/qt/transactiontablemodel.cpp10
-rw-r--r--src/qt/transactionview.cpp33
-rw-r--r--src/qt/transactionview.h2
-rw-r--r--src/qt/walletmodel.cpp15
-rw-r--r--src/qt/walletmodel.h3
-rw-r--r--src/rest.cpp3
-rw-r--r--src/rpc/blockchain.cpp155
-rw-r--r--src/rpc/client.cpp6
-rw-r--r--src/rpc/mining.cpp133
-rw-r--r--src/rpc/misc.cpp18
-rw-r--r--src/rpc/net.cpp34
-rw-r--r--src/rpc/rawtransaction.cpp28
-rw-r--r--src/rpc/register.h32
-rw-r--r--src/rpc/server.cpp78
-rw-r--r--src/rpc/server.h60
-rw-r--r--src/script/interpreter.cpp12
-rw-r--r--src/script/ismine.cpp (renamed from src/wallet/wallet_ismine.cpp)2
-rw-r--r--src/script/ismine.h (renamed from src/wallet/wallet_ismine.h)6
-rw-r--r--src/script/standard.h2
-rw-r--r--src/sync.cpp55
-rw-r--r--src/sync.h33
-rw-r--r--src/test/alert_tests.cpp181
-rw-r--r--src/test/amount_tests.cpp71
-rw-r--r--src/test/bctest.py2
-rw-r--r--src/test/bip32_tests.cpp16
-rwxr-xr-xsrc/test/bitcoin-util-test.py2
-rw-r--r--src/test/bloom_tests.cpp23
-rw-r--r--src/test/coins_tests.cpp2
-rw-r--r--src/test/data/alertTests.rawbin1279 -> 0 bytes
-rw-r--r--src/test/data/script_invalid.json877
-rw-r--r--src/test/data/script_tests.json1824
-rw-r--r--src/test/data/script_valid.json911
-rw-r--r--src/test/dbwrapper_tests.cpp8
-rw-r--r--src/test/mempool_tests.cpp124
-rw-r--r--src/test/miner_tests.cpp33
-rw-r--r--src/test/multisig_tests.cpp12
-rw-r--r--src/test/pmt_tests.cpp8
-rw-r--r--src/test/prevector_tests.cpp15
-rw-r--r--src/test/rpc_tests.cpp26
-rw-r--r--src/test/script_P2SH_tests.cpp9
-rw-r--r--src/test/script_tests.cpp633
-rw-r--r--src/test/serialize_tests.cpp21
-rw-r--r--src/test/test_bitcoin.cpp33
-rw-r--r--src/test/test_bitcoin.h7
-rw-r--r--src/test/txvalidationcache_tests.cpp2
-rw-r--r--src/test/util_tests.cpp5
-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.cpp2
-rw-r--r--src/txdb.cpp82
-rw-r--r--src/txdb.h26
-rw-r--r--src/txmempool.cpp216
-rw-r--r--src/txmempool.h167
-rw-r--r--src/ui_interface.cpp24
-rw-r--r--src/ui_interface.h13
-rw-r--r--src/uint256.h8
-rw-r--r--src/util.cpp4
-rw-r--r--src/utiltime.cpp2
-rw-r--r--src/version.h5
-rw-r--r--src/versionbits.cpp133
-rw-r--r--src/versionbits.h59
-rw-r--r--src/wallet/rpcdump.cpp107
-rw-r--r--src/wallet/rpcwallet.cpp102
-rw-r--r--src/wallet/rpcwallet.h4
-rw-r--r--src/wallet/test/accounting_tests.cpp (renamed from src/test/accounting_tests.cpp)4
-rw-r--r--src/wallet/test/rpc_wallet_tests.cpp (renamed from src/test/rpc_wallet_tests.cpp)4
-rw-r--r--src/wallet/test/wallet_test_fixture.cpp28
-rw-r--r--src/wallet/test/wallet_test_fixture.h18
-rw-r--r--src/wallet/test/wallet_tests.cpp4
-rw-r--r--src/wallet/wallet.cpp247
-rw-r--r--src/wallet/wallet.h33
-rw-r--r--src/wallet/walletdb.cpp39
-rw-r--r--src/wallet/walletdb.h1
-rw-r--r--src/zmq/zmqnotificationinterface.cpp1
-rw-r--r--src/zmq/zmqpublishnotifier.cpp35
-rw-r--r--src/zmq/zmqpublishnotifier.h12
267 files changed, 9610 insertions, 5354 deletions
diff --git a/.travis.yml b/.travis.yml
index 31b3d6d96e..95ef36bf02 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -64,6 +64,7 @@ before_script:
- 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:
+ - export TRAVIS_COMMIT_LOG=`git log --format=fuller -1`
- if [ -n "$USE_SHELL" ]; then export CONFIG_SHELL="$USE_SHELL"; fi
- OUTDIR=$BASE_OUTDIR/$TRAVIS_PULL_REQUEST/$TRAVIS_JOB_NUMBER-$HOST
- BITCOIN_CONFIG_ALL="--disable-dependency-tracking --prefix=$TRAVIS_BUILD_DIR/depends/$HOST --bindir=$OUTDIR/bin --libdir=$OUTDIR/lib"
@@ -79,4 +80,6 @@ script:
- if [ "$RUN_TESTS" = "true" ]; then make check; fi
- if [ "$RUN_TESTS" = "true" ]; then qa/pull-tester/rpc-tests.py --coverage; fi
after_script:
+ - echo $TRAVIS_COMMIT_RANGE
+ - echo $TRAVIS_COMMIT_LOG
- if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then (echo "Upload goes here. Something like: scp -r $BASE_OUTDIR server" || echo "upload failed"); fi
diff --git a/Makefile.am b/Makefile.am
index d6cbd7cb12..5783c1fdd8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -10,9 +10,9 @@ pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libbitcoinconsensus.pc
endif
-BITCOIND_BIN=$(top_builddir)/src/bitcoind$(EXEEXT)
-BITCOIN_QT_BIN=$(top_builddir)/src/qt/bitcoin-qt$(EXEEXT)
-BITCOIN_CLI_BIN=$(top_builddir)/src/bitcoin-cli$(EXEEXT)
+BITCOIND_BIN=$(top_builddir)/src/$(BITCOIN_DAEMON_NAME)$(EXEEXT)
+BITCOIN_QT_BIN=$(top_builddir)/src/qt/$(BITCOIN_GUI_NAME)$(EXEEXT)
+BITCOIN_CLI_BIN=$(top_builddir)/src/$(BITCOIN_CLI_NAME)$(EXEEXT)
BITCOIN_WIN_INSTALLER=$(PACKAGE)-$(PACKAGE_VERSION)-win$(WINDOWS_BITS)-setup$(EXEEXT)
empty :=
@@ -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/build-aux/m4/ax_boost_base.m4 b/build-aux/m4/ax_boost_base.m4
index 3f24d5ddc6..45d948933d 100644
--- a/build-aux/m4/ax_boost_base.m4
+++ b/build-aux/m4/ax_boost_base.m4
@@ -33,7 +33,7 @@
# and this notice are preserved. This file is offered as-is, without any
# warranty.
-#serial 23
+#serial 26
AC_DEFUN([AX_BOOST_BASE],
[
@@ -95,8 +95,8 @@ if test "x$want_boost" = "xyes"; then
x86_64)
libsubdirs="lib64 libx32 lib lib64"
;;
- ppc64|s390x|sparc64|aarch64)
- libsubdirs="lib64 lib lib64"
+ ppc64|s390x|sparc64|aarch64|ppc64le)
+ libsubdirs="lib64 lib lib64 ppc64le"
;;
esac
@@ -170,7 +170,7 @@ if test "x$want_boost" = "xyes"; then
AC_MSG_RESULT(yes)
succeeded=yes
found_system=yes
- ],[:
+ ],[
])
AC_LANG_POP([C++])
@@ -179,6 +179,10 @@ if test "x$want_boost" = "xyes"; then
dnl if we found no boost with system layout we search for boost libraries
dnl built and installed without the --layout=system option or for a staged(not installed) version
if test "x$succeeded" != "xyes"; then
+ CPPFLAGS="$CPPFLAGS_SAVED"
+ LDFLAGS="$LDFLAGS_SAVED"
+ BOOST_CPPFLAGS=
+ BOOST_LDFLAGS=
_version=0
if test "$ac_boost_path" != ""; then
if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then
@@ -191,6 +195,12 @@ if test "x$want_boost" = "xyes"; then
VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE"
done
+ dnl if nothing found search for layout used in Windows distributions
+ if test -z "$BOOST_CPPFLAGS"; then
+ if test -d "$ac_boost_path/boost" && test -r "$ac_boost_path/boost"; then
+ BOOST_CPPFLAGS="-I$ac_boost_path"
+ fi
+ fi
fi
else
if test "$cross_compiling" != yes; then
@@ -253,7 +263,7 @@ if test "x$want_boost" = "xyes"; then
AC_MSG_RESULT(yes)
succeeded=yes
found_system=yes
- ],[:
+ ],[
])
AC_LANG_POP([C++])
fi
diff --git a/build-aux/m4/ax_boost_program_options.m4 b/build-aux/m4/ax_boost_program_options.m4
index f591441854..2bdb593716 100644
--- a/build-aux/m4/ax_boost_program_options.m4
+++ b/build-aux/m4/ax_boost_program_options.m4
@@ -29,7 +29,7 @@
# and this notice are preserved. This file is offered as-is, without any
# warranty.
-#serial 22
+#serial 24
AC_DEFUN([AX_BOOST_PROGRAM_OPTIONS],
[
@@ -63,9 +63,9 @@ AC_DEFUN([AX_BOOST_PROGRAM_OPTIONS],
AC_CACHE_CHECK([whether the Boost::Program_Options library is available],
ax_cv_boost_program_options,
[AC_LANG_PUSH(C++)
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/program_options.hpp>
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/program_options/errors.hpp>
]],
- [[boost::program_options::options_description generic("Generic options");
+ [[boost::program_options::error err("Error message");
return 0;]])],
ax_cv_boost_program_options=yes, ax_cv_boost_program_options=no)
AC_LANG_POP([C++])
@@ -74,7 +74,6 @@ AC_DEFUN([AX_BOOST_PROGRAM_OPTIONS],
AC_DEFINE(HAVE_BOOST_PROGRAM_OPTIONS,,[define if the Boost::PROGRAM_OPTIONS library is available])
BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
if test "x$ax_boost_user_program_options_lib" = "x"; then
- ax_lib=
for libextension in `ls $BOOSTLIBDIR/libboost_program_options*.so* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_program_options.*\)\.so.*$;\1;'` `ls $BOOSTLIBDIR/libboost_program_options*.dylib* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_program_options.*\)\.dylib.*$;\1;'` `ls $BOOSTLIBDIR/libboost_program_options*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_program_options.*\)\.a.*$;\1;'` ; do
ax_lib=${libextension}
AC_CHECK_LIB($ax_lib, exit,
diff --git a/build-aux/m4/ax_boost_system.m4 b/build-aux/m4/ax_boost_system.m4
index 9c78280fca..1c05450cbe 100644
--- a/build-aux/m4/ax_boost_system.m4
+++ b/build-aux/m4/ax_boost_system.m4
@@ -31,7 +31,7 @@
# and this notice are preserved. This file is offered as-is, without any
# warranty.
-#serial 17
+#serial 18
AC_DEFUN([AX_BOOST_SYSTEM],
[
@@ -68,9 +68,10 @@ AC_DEFUN([AX_BOOST_SYSTEM],
ax_cv_boost_system,
[AC_LANG_PUSH([C++])
CXXFLAGS_SAVE=$CXXFLAGS
+ CXXFLAGS=
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/system/error_code.hpp>]],
- [[boost::system::system_category]])],
+ [[boost::system::error_category *a = 0;]])],
ax_cv_boost_system=yes, ax_cv_boost_system=no)
CXXFLAGS=$CXXFLAGS_SAVE
AC_LANG_POP([C++])
diff --git a/build-aux/m4/ax_check_compile_flag.m4 b/build-aux/m4/ax_check_compile_flag.m4
index c3a8d695a1..ca3639715e 100644
--- a/build-aux/m4/ax_check_compile_flag.m4
+++ b/build-aux/m4/ax_check_compile_flag.m4
@@ -4,7 +4,7 @@
#
# SYNOPSIS
#
-# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS])
+# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
#
# DESCRIPTION
#
@@ -19,6 +19,8 @@
# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
# force the compiler to issue an error when a bad flag is given.
#
+# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
+#
# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
#
@@ -53,19 +55,19 @@
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
-#serial 2
+#serial 4
AC_DEFUN([AX_CHECK_COMPILE_FLAG],
-[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX
+[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
_AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
+ AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
[AS_VAR_SET(CACHEVAR,[yes])],
[AS_VAR_SET(CACHEVAR,[no])])
_AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
-AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes],
+AS_VAR_IF(CACHEVAR,yes,
[m4_default([$2], :)],
[m4_default([$3], :)])
AS_VAR_POPDEF([CACHEVAR])dnl
diff --git a/build-aux/m4/ax_check_link_flag.m4 b/build-aux/m4/ax_check_link_flag.m4
index e2d0d363e4..eb01a6ce13 100644
--- a/build-aux/m4/ax_check_link_flag.m4
+++ b/build-aux/m4/ax_check_link_flag.m4
@@ -4,7 +4,7 @@
#
# SYNOPSIS
#
-# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS])
+# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
#
# DESCRIPTION
#
@@ -19,6 +19,8 @@
# EXTRA-FLAGS FLAG". This can for example be used to force the linker to
# issue an error when a bad flag is given.
#
+# INPUT gives an alternative input source to AC_LINK_IFELSE.
+#
# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
# macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG.
#
@@ -53,18 +55,19 @@
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
-#serial 2
+#serial 4
AC_DEFUN([AX_CHECK_LINK_FLAG],
-[AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl
+[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
+AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl
AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [
ax_check_save_flags=$LDFLAGS
LDFLAGS="$LDFLAGS $4 $1"
- AC_LINK_IFELSE([AC_LANG_PROGRAM()],
+ AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
[AS_VAR_SET(CACHEVAR,[yes])],
[AS_VAR_SET(CACHEVAR,[no])])
LDFLAGS=$ax_check_save_flags])
-AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes],
+AS_VAR_IF(CACHEVAR,yes,
[m4_default([$2], :)],
[m4_default([$3], :)])
AS_VAR_POPDEF([CACHEVAR])dnl
diff --git a/build-aux/m4/ax_check_preproc_flag.m4 b/build-aux/m4/ax_check_preproc_flag.m4
index b1cfef6b86..ca1d5ee2b6 100644
--- a/build-aux/m4/ax_check_preproc_flag.m4
+++ b/build-aux/m4/ax_check_preproc_flag.m4
@@ -4,7 +4,7 @@
#
# SYNOPSIS
#
-# AX_CHECK_PREPROC_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS])
+# AX_CHECK_PREPROC_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
#
# DESCRIPTION
#
@@ -19,6 +19,8 @@
# "CPPFLAGS EXTRA-FLAGS FLAG". This can for example be used to force the
# preprocessor to issue an error when a bad flag is given.
#
+# INPUT gives an alternative input source to AC_PREPROC_IFELSE.
+#
# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
# macro in sync with AX_CHECK_{COMPILE,LINK}_FLAG.
#
@@ -53,19 +55,19 @@
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
-#serial 2
+#serial 4
AC_DEFUN([AX_CHECK_PREPROC_FLAG],
-[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX
+[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]cppflags_$4_$1])dnl
AC_CACHE_CHECK([whether _AC_LANG preprocessor accepts $1], CACHEVAR, [
ax_check_save_flags=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $4 $1"
- AC_PREPROC_IFELSE([AC_LANG_PROGRAM()],
+ AC_PREPROC_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
[AS_VAR_SET(CACHEVAR,[yes])],
[AS_VAR_SET(CACHEVAR,[no])])
CPPFLAGS=$ax_check_save_flags])
-AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes],
+AS_VAR_IF(CACHEVAR,yes,
[m4_default([$2], :)],
[m4_default([$3], :)])
AS_VAR_POPDEF([CACHEVAR])dnl
diff --git a/build-aux/m4/ax_gcc_func_attribute.m4 b/build-aux/m4/ax_gcc_func_attribute.m4
index 275ca63a2c..c788ca9bd4 100644
--- a/build-aux/m4/ax_gcc_func_attribute.m4
+++ b/build-aux/m4/ax_gcc_func_attribute.m4
@@ -31,6 +31,7 @@
# cold
# const
# constructor
+# constructor_priority for constructor attribute with priority
# deprecated
# destructor
# dllexport
@@ -73,7 +74,7 @@
# and this notice are preserved. This file is offered as-is, without any
# warranty.
-#serial 2
+#serial 3
AC_DEFUN([AX_GCC_FUNC_ATTRIBUTE], [
AS_VAR_PUSHDEF([ac_var], [ax_cv_have_func_attribute_$1])
@@ -103,6 +104,9 @@ AC_DEFUN([AX_GCC_FUNC_ATTRIBUTE], [
[const], [
int foo( void ) __attribute__(($1));
],
+ [constructor_priority], [
+ int foo( void ) __attribute__((__constructor__(65535/2)));
+ ],
[constructor], [
int foo( void ) __attribute__(($1));
],
@@ -180,6 +184,8 @@ AC_DEFUN([AX_GCC_FUNC_ATTRIBUTE], [
[visibility], [
int foo_def( void ) __attribute__(($1("default")));
int foo_hid( void ) __attribute__(($1("hidden")));
+ int foo_int( void ) __attribute__(($1("internal")));
+ int foo_pro( void ) __attribute__(($1("protected")));
],
[warning], [
int foo( void ) __attribute__(($1("")));
diff --git a/build-aux/m4/ax_pthread.m4 b/build-aux/m4/ax_pthread.m4
index d383ad5c6d..d218d1af73 100644
--- a/build-aux/m4/ax_pthread.m4
+++ b/build-aux/m4/ax_pthread.m4
@@ -19,10 +19,10 @@
# is necessary on AIX to use the special cc_r compiler alias.)
#
# NOTE: You are assumed to not only compile your program with these flags,
-# but also link it with them as well. e.g. you should link with
+# but also to link with them as well. For example, you might link with
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
#
-# If you are only building threads programs, you may wish to use these
+# If you are only building threaded programs, you may wish to use these
# variables in your default LIBS, CFLAGS, and CC:
#
# LIBS="$PTHREAD_LIBS $LIBS"
@@ -30,8 +30,8 @@
# CC="$PTHREAD_CC"
#
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
-# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
-# (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
+# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
+# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
#
# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
@@ -82,35 +82,40 @@
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
-#serial 21
+#serial 22
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
AC_DEFUN([AX_PTHREAD], [
AC_REQUIRE([AC_CANONICAL_HOST])
+AC_REQUIRE([AC_PROG_CC])
+AC_REQUIRE([AC_PROG_SED])
AC_LANG_PUSH([C])
ax_pthread_ok=no
# We used to check for pthread.h first, but this fails if pthread.h
-# requires special compiler flags (e.g. on True64 or Sequent).
+# requires special compiler flags (e.g. on Tru64 or Sequent).
# It gets checked for in the link test anyway.
# First of all, check if the user has set any of the PTHREAD_LIBS,
# etcetera environment variables, and if threads linking works using
# them:
-if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
- save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
- save_LIBS="$LIBS"
- LIBS="$PTHREAD_LIBS $LIBS"
- AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
- AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes])
- AC_MSG_RESULT([$ax_pthread_ok])
- if test x"$ax_pthread_ok" = xno; then
- PTHREAD_LIBS=""
- PTHREAD_CFLAGS=""
- fi
- LIBS="$save_LIBS"
- CFLAGS="$save_CFLAGS"
+if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
+ ax_pthread_save_CC="$CC"
+ ax_pthread_save_CFLAGS="$CFLAGS"
+ ax_pthread_save_LIBS="$LIBS"
+ AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
+ AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])
+ AC_MSG_RESULT([$ax_pthread_ok])
+ if test "x$ax_pthread_ok" = "xno"; then
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+ fi
+ CC="$ax_pthread_save_CC"
+ CFLAGS="$ax_pthread_save_CFLAGS"
+ LIBS="$ax_pthread_save_LIBS"
fi
# We must check for the threads library under a number of different
@@ -123,7 +128,7 @@ fi
# which indicates that we try without any flags at all, and "pthread-config"
# which is a program returning the flags for the Pth emulation library.
-ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
+ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
# The ordering *is* (sometimes) important. Some notes on the
# individual items follow:
@@ -132,186 +137,334 @@ ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mt
# none: in case threads are in libc; should be tried before -Kthread and
# other compiler flags to prevent continual compiler warnings
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
-# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
-# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
-# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
-# -pthreads: Solaris/gcc
-# -mthreads: Mingw32/gcc, Lynx/gcc
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
+# (Note: HP C rejects this with "bad form for `-t' option")
+# -pthreads: Solaris/gcc (Note: HP C also rejects)
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
-# doesn't hurt to check since this sometimes defines pthreads too;
-# also defines -D_REENTRANT)
-# ... -mt is also the pthreads flag for HP/aCC
+# doesn't hurt to check since this sometimes defines pthreads and
+# -D_REENTRANT too), HP C (must be checked before -lpthread, which
+# is present but should not be used directly; and before -mthreads,
+# because the compiler interprets this as "-mt" + "-hreads")
+# -mthreads: Mingw32/gcc, Lynx/gcc
# pthread: Linux, etcetera
# --thread-safe: KAI C++
# pthread-config: use pthread-config program (for GNU Pth library)
-case ${host_os} in
- solaris*)
+case $host_os in
+
+ freebsd*)
+
+ # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+ # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+
+ ax_pthread_flags="-kthread lthread $ax_pthread_flags"
+ ;;
+
+ hpux*)
+
+ # From the cc(1) man page: "[-mt] Sets various -D flags to enable
+ # multi-threading and also sets -lpthread."
+
+ ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
+ ;;
+
+ openedition*)
- # On Solaris (at least, for some versions), libc contains stubbed
- # (non-functional) versions of the pthreads routines, so link-based
- # tests will erroneously succeed. (We need to link with -pthreads/-mt/
- # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
- # a function called by this macro, so we could check for that, but
- # who knows whether they'll stub that too in a future libc.) So,
- # we'll just look for -pthreads and -lpthread first:
+ # IBM z/OS requires a feature-test macro to be defined in order to
+ # enable POSIX threads at all, so give the user a hint if this is
+ # not set. (We don't define these ourselves, as they can affect
+ # other portions of the system API in unpredictable ways.)
- ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
- ;;
+ AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING],
+ [
+# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
+ AX_PTHREAD_ZOS_MISSING
+# endif
+ ],
+ [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])])
+ ;;
- darwin*)
- ax_pthread_flags="-pthread $ax_pthread_flags"
- ;;
+ solaris*)
+
+ # On Solaris (at least, for some versions), libc contains stubbed
+ # (non-functional) versions of the pthreads routines, so link-based
+ # tests will erroneously succeed. (N.B.: The stubs are missing
+ # pthread_cleanup_push, or rather a function called by this macro,
+ # so we could check for that, but who knows whether they'll stub
+ # that too in a future libc.) So we'll check first for the
+ # standard Solaris way of linking pthreads (-mt -lpthread).
+
+ ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags"
+ ;;
esac
-# Clang doesn't consider unrecognized options an error unless we specify
-# -Werror. We throw in some extra Clang-specific options to ensure that
-# this doesn't happen for GCC, which also accepts -Werror.
-
-AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags])
-save_CFLAGS="$CFLAGS"
-ax_pthread_extra_flags="-Werror"
-CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument"
-AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])],
- [AC_MSG_RESULT([yes])],
- [ax_pthread_extra_flags=
- AC_MSG_RESULT([no])])
-CFLAGS="$save_CFLAGS"
-
-if test x"$ax_pthread_ok" = xno; then
-for flag in $ax_pthread_flags; do
-
- case $flag in
- none)
- AC_MSG_CHECKING([whether pthreads work without any flags])
- ;;
-
- -*)
- AC_MSG_CHECKING([whether pthreads work with $flag])
- PTHREAD_CFLAGS="$flag"
- ;;
-
- pthread-config)
- AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
- if test x"$ax_pthread_config" = xno; then continue; fi
- PTHREAD_CFLAGS="`pthread-config --cflags`"
- PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
- ;;
-
- *)
- AC_MSG_CHECKING([for the pthreads library -l$flag])
- PTHREAD_LIBS="-l$flag"
- ;;
- esac
-
- save_LIBS="$LIBS"
- save_CFLAGS="$CFLAGS"
- LIBS="$PTHREAD_LIBS $LIBS"
- CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags"
-
- # Check for various functions. We must include pthread.h,
- # since some functions may be macros. (On the Sequent, we
- # need a special flag -Kthread to make this header compile.)
- # We check for pthread_join because it is in -lpthread on IRIX
- # while pthread_create is in libc. We check for pthread_attr_init
- # due to DEC craziness with -lpthreads. We check for
- # pthread_cleanup_push because it is one of the few pthread
- # functions on Solaris that doesn't have a non-functional libc stub.
- # We try pthread_create on general principles.
- AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
- static void routine(void *a) { a = 0; }
- static void *start_routine(void *a) { return a; }],
- [pthread_t th; pthread_attr_t attr;
- pthread_create(&th, 0, start_routine, 0);
- pthread_join(th, 0);
- pthread_attr_init(&attr);
- pthread_cleanup_push(routine, 0);
- pthread_cleanup_pop(0) /* ; */])],
- [ax_pthread_ok=yes],
- [])
-
- LIBS="$save_LIBS"
- CFLAGS="$save_CFLAGS"
-
- AC_MSG_RESULT([$ax_pthread_ok])
- if test "x$ax_pthread_ok" = xyes; then
- break;
- fi
-
- PTHREAD_LIBS=""
- PTHREAD_CFLAGS=""
+# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
+
+AS_IF([test "x$GCC" = "xyes"],
+ [ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"])
+
+# The presence of a feature test macro requesting re-entrant function
+# definitions is, on some systems, a strong hint that pthreads support is
+# correctly enabled
+
+case $host_os in
+ darwin* | hpux* | linux* | osf* | solaris*)
+ ax_pthread_check_macro="_REENTRANT"
+ ;;
+
+ aix* | freebsd*)
+ ax_pthread_check_macro="_THREAD_SAFE"
+ ;;
+
+ *)
+ ax_pthread_check_macro="--"
+ ;;
+esac
+AS_IF([test "x$ax_pthread_check_macro" = "x--"],
+ [ax_pthread_check_cond=0],
+ [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"])
+
+# Are we compiling with Clang?
+
+AC_CACHE_CHECK([whether $CC is Clang],
+ [ax_cv_PTHREAD_CLANG],
+ [ax_cv_PTHREAD_CLANG=no
+ # Note that Autoconf sets GCC=yes for Clang as well as GCC
+ if test "x$GCC" = "xyes"; then
+ AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
+ [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
+# if defined(__clang__) && defined(__llvm__)
+ AX_PTHREAD_CC_IS_CLANG
+# endif
+ ],
+ [ax_cv_PTHREAD_CLANG=yes])
+ fi
+ ])
+ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
+
+ax_pthread_clang_warning=no
+
+# Clang needs special handling, because older versions handle the -pthread
+# option in a rather... idiosyncratic way
+
+if test "x$ax_pthread_clang" = "xyes"; then
+
+ # Clang takes -pthread; it has never supported any other flag
+
+ # (Note 1: This will need to be revisited if a system that Clang
+ # supports has POSIX threads in a separate library. This tends not
+ # to be the way of modern systems, but it's conceivable.)
+
+ # (Note 2: On some systems, notably Darwin, -pthread is not needed
+ # to get POSIX threads support; the API is always present and
+ # active. We could reasonably leave PTHREAD_CFLAGS empty. But
+ # -pthread does define _REENTRANT, and while the Darwin headers
+ # ignore this macro, third-party headers might not.)
+
+ PTHREAD_CFLAGS="-pthread"
+ PTHREAD_LIBS=
+
+ ax_pthread_ok=yes
+
+ # However, older versions of Clang make a point of warning the user
+ # that, in an invocation where only linking and no compilation is
+ # taking place, the -pthread option has no effect ("argument unused
+ # during compilation"). They expect -pthread to be passed in only
+ # when source code is being compiled.
+ #
+ # Problem is, this is at odds with the way Automake and most other
+ # C build frameworks function, which is that the same flags used in
+ # compilation (CFLAGS) are also used in linking. Many systems
+ # supported by AX_PTHREAD require exactly this for POSIX threads
+ # support, and in fact it is often not straightforward to specify a
+ # flag that is used only in the compilation phase and not in
+ # linking. Such a scenario is extremely rare in practice.
+ #
+ # Even though use of the -pthread flag in linking would only print
+ # a warning, this can be a nuisance for well-run software projects
+ # that build with -Werror. So if the active version of Clang has
+ # this misfeature, we search for an option to squash it.
+
+ AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread],
+ [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],
+ [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
+ # Create an alternate version of $ac_link that compiles and
+ # links in two steps (.c -> .o, .o -> exe) instead of one
+ # (.c -> exe), because the warning occurs only in the second
+ # step
+ ax_pthread_save_ac_link="$ac_link"
+ ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
+ ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"`
+ ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
+ ax_pthread_save_CFLAGS="$CFLAGS"
+ for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
+ AS_IF([test "x$ax_pthread_try" = "xunknown"], [break])
+ CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
+ ac_link="$ax_pthread_save_ac_link"
+ AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
+ [ac_link="$ax_pthread_2step_ac_link"
+ AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
+ [break])
+ ])
+ done
+ ac_link="$ax_pthread_save_ac_link"
+ CFLAGS="$ax_pthread_save_CFLAGS"
+ AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no])
+ ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
+ ])
+
+ case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
+ no | unknown) ;;
+ *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
+ esac
+
+fi # $ax_pthread_clang = yes
+
+if test "x$ax_pthread_ok" = "xno"; then
+for ax_pthread_try_flag in $ax_pthread_flags; do
+
+ case $ax_pthread_try_flag in
+ none)
+ AC_MSG_CHECKING([whether pthreads work without any flags])
+ ;;
+
+ -mt,pthread)
+ AC_MSG_CHECKING([whether pthreads work with -mt -lpthread])
+ PTHREAD_CFLAGS="-mt"
+ PTHREAD_LIBS="-lpthread"
+ ;;
+
+ -*)
+ AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
+ PTHREAD_CFLAGS="$ax_pthread_try_flag"
+ ;;
+
+ pthread-config)
+ AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
+ AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
+ PTHREAD_CFLAGS="`pthread-config --cflags`"
+ PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+ ;;
+
+ *)
+ AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
+ PTHREAD_LIBS="-l$ax_pthread_try_flag"
+ ;;
+ esac
+
+ ax_pthread_save_CFLAGS="$CFLAGS"
+ ax_pthread_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+
+ # Check for various functions. We must include pthread.h,
+ # since some functions may be macros. (On the Sequent, we
+ # need a special flag -Kthread to make this header compile.)
+ # We check for pthread_join because it is in -lpthread on IRIX
+ # while pthread_create is in libc. We check for pthread_attr_init
+ # due to DEC craziness with -lpthreads. We check for
+ # pthread_cleanup_push because it is one of the few pthread
+ # functions on Solaris that doesn't have a non-functional libc stub.
+ # We try pthread_create on general principles.
+
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
+# if $ax_pthread_check_cond
+# error "$ax_pthread_check_macro must be defined"
+# endif
+ static void routine(void *a) { a = 0; }
+ static void *start_routine(void *a) { return a; }],
+ [pthread_t th; pthread_attr_t attr;
+ pthread_create(&th, 0, start_routine, 0);
+ pthread_join(th, 0);
+ pthread_attr_init(&attr);
+ pthread_cleanup_push(routine, 0);
+ pthread_cleanup_pop(0) /* ; */])],
+ [ax_pthread_ok=yes],
+ [])
+
+ CFLAGS="$ax_pthread_save_CFLAGS"
+ LIBS="$ax_pthread_save_LIBS"
+
+ AC_MSG_RESULT([$ax_pthread_ok])
+ AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
+
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
done
fi
# Various other checks:
-if test "x$ax_pthread_ok" = xyes; then
- save_LIBS="$LIBS"
- LIBS="$PTHREAD_LIBS $LIBS"
- save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
-
- # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
- AC_MSG_CHECKING([for joinable pthread attribute])
- attr_name=unknown
- for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
- AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
- [int attr = $attr; return attr /* ; */])],
- [attr_name=$attr; break],
- [])
- done
- AC_MSG_RESULT([$attr_name])
- if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
- AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name],
- [Define to necessary symbol if this constant
- uses a non-standard name on your system.])
- fi
-
- AC_MSG_CHECKING([if more special flags are required for pthreads])
- flag=no
- case ${host_os} in
- aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
- osf* | hpux*) flag="-D_REENTRANT";;
- solaris*)
- if test "$GCC" = "yes"; then
- flag="-D_REENTRANT"
- else
- # TODO: What about Clang on Solaris?
- flag="-mt -D_REENTRANT"
- fi
- ;;
- esac
- AC_MSG_RESULT([$flag])
- if test "x$flag" != xno; then
- PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
- fi
-
- AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
- [ax_cv_PTHREAD_PRIO_INHERIT], [
- AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
- [[int i = PTHREAD_PRIO_INHERIT;]])],
- [ax_cv_PTHREAD_PRIO_INHERIT=yes],
- [ax_cv_PTHREAD_PRIO_INHERIT=no])
- ])
- AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
- [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])])
-
- LIBS="$save_LIBS"
- CFLAGS="$save_CFLAGS"
-
- # More AIX lossage: compile with *_r variant
- if test "x$GCC" != xyes; then
- case $host_os in
- aix*)
- AS_CASE(["x/$CC"],
- [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
- [#handle absolute path differently from PATH based program lookup
- AS_CASE(["x$CC"],
- [x/*],
- [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
- [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
- ;;
- esac
- fi
+if test "x$ax_pthread_ok" = "xyes"; then
+ ax_pthread_save_CFLAGS="$CFLAGS"
+ ax_pthread_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+
+ # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
+ AC_CACHE_CHECK([for joinable pthread attribute],
+ [ax_cv_PTHREAD_JOINABLE_ATTR],
+ [ax_cv_PTHREAD_JOINABLE_ATTR=unknown
+ for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
+ [int attr = $ax_pthread_attr; return attr /* ; */])],
+ [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],
+ [])
+ done
+ ])
+ AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
+ test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
+ test "x$ax_pthread_joinable_attr_defined" != "xyes"],
+ [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE],
+ [$ax_cv_PTHREAD_JOINABLE_ATTR],
+ [Define to necessary symbol if this constant
+ uses a non-standard name on your system.])
+ ax_pthread_joinable_attr_defined=yes
+ ])
+
+ AC_CACHE_CHECK([whether more special flags are required for pthreads],
+ [ax_cv_PTHREAD_SPECIAL_FLAGS],
+ [ax_cv_PTHREAD_SPECIAL_FLAGS=no
+ case $host_os in
+ solaris*)
+ ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
+ ;;
+ esac
+ ])
+ AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
+ test "x$ax_pthread_special_flags_added" != "xyes"],
+ [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
+ ax_pthread_special_flags_added=yes])
+
+ AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
+ [ax_cv_PTHREAD_PRIO_INHERIT],
+ [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
+ [[int i = PTHREAD_PRIO_INHERIT;]])],
+ [ax_cv_PTHREAD_PRIO_INHERIT=yes],
+ [ax_cv_PTHREAD_PRIO_INHERIT=no])
+ ])
+ AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
+ test "x$ax_pthread_prio_inherit_defined" != "xyes"],
+ [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])
+ ax_pthread_prio_inherit_defined=yes
+ ])
+
+ CFLAGS="$ax_pthread_save_CFLAGS"
+ LIBS="$ax_pthread_save_LIBS"
+
+ # More AIX lossage: compile with *_r variant
+ if test "x$GCC" != "xyes"; then
+ case $host_os in
+ aix*)
+ AS_CASE(["x/$CC"],
+ [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
+ [#handle absolute path differently from PATH based program lookup
+ AS_CASE(["x$CC"],
+ [x/*],
+ [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
+ [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
+ ;;
+ esac
+ fi
fi
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
@@ -321,12 +474,12 @@ AC_SUBST([PTHREAD_CFLAGS])
AC_SUBST([PTHREAD_CC])
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
-if test x"$ax_pthread_ok" = xyes; then
- ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
- :
+if test "x$ax_pthread_ok" = "xyes"; then
+ ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
+ :
else
- ax_pthread_ok=no
- $2
+ ax_pthread_ok=no
+ $2
fi
AC_LANG_POP
])dnl AX_PTHREAD
diff --git a/configure.ac b/configure.ac
index 939dfeaabf..03b9052104 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,13 +7,18 @@ define(_CLIENT_VERSION_BUILD, 0)
define(_CLIENT_VERSION_IS_RELEASE, false)
define(_COPYRIGHT_YEAR, 2016)
define(_COPYRIGHT_HOLDERS,[The %s developers])
-define(_COPYRIGHT_HOLDERS_SUBSTITUTION,[Bitcoin Core])
+define(_COPYRIGHT_HOLDERS_SUBSTITUTION,[[Bitcoin Core]])
AC_INIT([Bitcoin Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[https://github.com/bitcoin/bitcoin/issues],[bitcoin],[https://bitcoincore.org/])
AC_CONFIG_SRCDIR([src/main.cpp])
AC_CONFIG_HEADERS([src/config/bitcoin-config.h])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([build-aux/m4])
+BITCOIN_DAEMON_NAME=bitcoind
+BITCOIN_GUI_NAME=bitcoin-qt
+BITCOIN_CLI_NAME=bitcoin-cli
+BITCOIN_TX_NAME=bitcoin-tx
+
AC_CANONICAL_HOST
AH_TOP([#ifndef BITCOIN_CONFIG_H])
@@ -60,7 +65,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)
@@ -98,6 +103,11 @@ AC_ARG_ENABLE(tests,
[use_tests=$enableval],
[use_tests=yes])
+AC_ARG_ENABLE(gui-tests,
+ AS_HELP_STRING([--disable-gui-tests],[do not compile GUI tests (default is to compile if GUI and tests enabled)]),
+ [use_gui_tests=$enableval],
+ [use_gui_tests=$use_tests])
+
AC_ARG_ENABLE(bench,
AS_HELP_STRING([--disable-bench],[do not compile benchmarks (default is to compile)]),
[use_bench=$enableval],
@@ -257,7 +267,7 @@ case $host in
fi
CPPFLAGS="$CPPFLAGS -D_MT -DWIN32 -D_WINDOWS -DBOOST_THREAD_USE_LIB"
- LEVELDB_TARGET_FLAGS="TARGET_OS=OS_WINDOWS_CROSSCOMPILE"
+ LEVELDB_TARGET_FLAGS="-DOS_WINDOWS"
if test "x$CXXFLAGS_overridden" = "xno"; then
CXXFLAGS="$CXXFLAGS -w"
fi
@@ -279,7 +289,7 @@ case $host in
;;
*darwin*)
TARGET_OS=darwin
- LEVELDB_TARGET_FLAGS="TARGET_OS=Darwin"
+ LEVELDB_TARGET_FLAGS="-DOS_MACOSX"
if test x$cross_compiling != xyes; then
BUILD_OS=darwin
AC_CHECK_PROG([PORT],port, port)
@@ -344,9 +354,11 @@ case $host in
OBJCXXFLAGS="$CXXFLAGS"
;;
*linux*)
- TARGET_OS=linux
+ LEVELDB_TARGET_FLAGS="-DOS_LINUX"
;;
*)
+ OTHER_OS=`echo ${host_os} | awk '{print toupper($0)}'`
+ LEVELDB_TARGET_FLAGS="-DOS_${OTHER_OS}"
;;
esac
@@ -531,6 +543,18 @@ if test x$use_reduce_exports = xyes; then
[AC_MSG_ERROR([Cannot set default symbol visibility. Use --disable-reduce-exports.])])
fi
+dnl This can go away when we require c++11
+TEMP_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS="$CXXFLAGS -std=c++0x"
+AC_MSG_CHECKING(for c++11 atomics)
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ #include <atomic>
+ ]],[[]])],
+ [ AC_MSG_RESULT(yes); LEVELDB_ATOMIC_CPPFLAGS="-DLEVELDB_ATOMIC_PRESENT"; LEVELDB_ATOMIC_CXXFLAGS="-std=c++0x"],
+ [ AC_MSG_RESULT(no)]
+)
+CXXFLAGS="$TEMP_CXXFLAGS"
+
LEVELDB_CPPFLAGS=
LIBLEVELDB=
LIBMEMENV=
@@ -919,8 +943,8 @@ else
fi
dnl these are only used when qt is enabled
+BUILD_TEST_QT=""
if test x$bitcoin_enable_qt != xno; then
- BUILD_QT=qt
dnl enable dbus support
AC_MSG_CHECKING([whether to build GUI with support for D-Bus])
if test x$bitcoin_enable_qt_dbus != xno; then
@@ -950,9 +974,9 @@ if test x$bitcoin_enable_qt != xno; then
fi
AC_MSG_CHECKING([whether to build test_bitcoin-qt])
- if test x$use_tests$bitcoin_enable_qt_test = xyesyes; then
+ if test x$use_gui_tests$bitcoin_enable_qt_test = xyesyes; then
AC_MSG_RESULT([yes])
- BUILD_TEST_QT="test"
+ BUILD_TEST_QT="yes"
else
AC_MSG_RESULT([no])
fi
@@ -963,9 +987,10 @@ AM_CONDITIONAL([ENABLE_ZMQ], [test "x$use_zmq" = "xyes"])
AC_MSG_CHECKING([whether to build test_bitcoin])
if test x$use_tests = xyes; then
AC_MSG_RESULT([yes])
- BUILD_TEST="test"
+ BUILD_TEST="yes"
else
AC_MSG_RESULT([no])
+ BUILD_TEST=""
fi
AC_MSG_CHECKING([whether to reduce exports])
@@ -983,9 +1008,9 @@ AM_CONDITIONAL([TARGET_DARWIN], [test x$TARGET_OS = xdarwin])
AM_CONDITIONAL([BUILD_DARWIN], [test x$BUILD_OS = xdarwin])
AM_CONDITIONAL([TARGET_WINDOWS], [test x$TARGET_OS = xwindows])
AM_CONDITIONAL([ENABLE_WALLET],[test x$enable_wallet = xyes])
-AM_CONDITIONAL([ENABLE_TESTS],[test x$use_tests = xyes])
+AM_CONDITIONAL([ENABLE_TESTS],[test x$BUILD_TEST = xyes])
AM_CONDITIONAL([ENABLE_QT],[test x$bitcoin_enable_qt = xyes])
-AM_CONDITIONAL([ENABLE_QT_TESTS],[test x$use_tests$bitcoin_enable_qt_test = xyesyes])
+AM_CONDITIONAL([ENABLE_QT_TESTS],[test x$BUILD_TEST_QT = xyes])
AM_CONDITIONAL([ENABLE_BENCH],[test x$use_bench = xyes])
AM_CONDITIONAL([USE_QRCODE], [test x$use_qr = xyes])
AM_CONDITIONAL([USE_LCOV],[test x$use_lcov = xyes])
@@ -999,10 +1024,10 @@ AC_DEFINE(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR, [Minor version])
AC_DEFINE(CLIENT_VERSION_REVISION, _CLIENT_VERSION_REVISION, [Build revision])
AC_DEFINE(CLIENT_VERSION_BUILD, _CLIENT_VERSION_BUILD, [Version Build])
AC_DEFINE(CLIENT_VERSION_IS_RELEASE, _CLIENT_VERSION_IS_RELEASE, [Version is release])
-AC_DEFINE(COPYRIGHT_YEAR, _COPYRIGHT_YEAR, [Version is release])
+AC_DEFINE(COPYRIGHT_YEAR, _COPYRIGHT_YEAR, [Copyright year])
AC_DEFINE(COPYRIGHT_HOLDERS, "_COPYRIGHT_HOLDERS", [Copyright holder(s) before %s replacement])
AC_DEFINE(COPYRIGHT_HOLDERS_SUBSTITUTION, "_COPYRIGHT_HOLDERS_SUBSTITUTION", [Replacement for %s in copyright holders string])
-define(_COPYRIGHT_HOLDERS_FINAL, patsubst(_COPYRIGHT_HOLDERS, [%s], [_COPYRIGHT_HOLDERS_SUBSTITUTION]))
+define(_COPYRIGHT_HOLDERS_FINAL, [patsubst(_COPYRIGHT_HOLDERS, [%s], [_COPYRIGHT_HOLDERS_SUBSTITUTION])])
AC_DEFINE(COPYRIGHT_HOLDERS_FINAL, "_COPYRIGHT_HOLDERS_FINAL", [Copyright holder(s)])
AC_SUBST(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR)
AC_SUBST(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR)
@@ -1013,6 +1038,10 @@ AC_SUBST(COPYRIGHT_YEAR, _COPYRIGHT_YEAR)
AC_SUBST(COPYRIGHT_HOLDERS, "_COPYRIGHT_HOLDERS")
AC_SUBST(COPYRIGHT_HOLDERS_SUBSTITUTION, "_COPYRIGHT_HOLDERS_SUBSTITUTION")
AC_SUBST(COPYRIGHT_HOLDERS_FINAL, "_COPYRIGHT_HOLDERS_FINAL")
+AC_SUBST(BITCOIN_DAEMON_NAME)
+AC_SUBST(BITCOIN_GUI_NAME)
+AC_SUBST(BITCOIN_CLI_NAME)
+AC_SUBST(BITCOIN_TX_NAME)
AC_SUBST(RELDFLAGS)
AC_SUBST(HARDENED_CXXFLAGS)
@@ -1026,11 +1055,10 @@ AC_SUBST(USE_QRCODE)
AC_SUBST(BOOST_LIBS)
AC_SUBST(TESTDEFS)
AC_SUBST(LEVELDB_TARGET_FLAGS)
-AC_SUBST(BUILD_TEST)
-AC_SUBST(BUILD_QT)
-AC_SUBST(BUILD_TEST_QT)
AC_SUBST(MINIUPNPC_CPPFLAGS)
AC_SUBST(MINIUPNPC_LIBS)
+AC_SUBST(LEVELDB_ATOMIC_CPPFLAGS)
+AC_SUBST(LEVELDB_ATOMIC_CXXFLAGS)
AC_CONFIG_FILES([Makefile src/Makefile share/setup.nsi share/qt/Info.plist src/test/buildenv.py])
AC_CONFIG_FILES([qa/pull-tester/run-bitcoind-for-test.sh],[chmod +x qa/pull-tester/run-bitcoind-for-test.sh])
AC_CONFIG_FILES([qa/pull-tester/tests_config.py],[chmod +x qa/pull-tester/tests_config.py])
diff --git a/contrib/README.md b/contrib/README.md
index 5155ff0cb4..a23b197cc6 100644
--- a/contrib/README.md
+++ b/contrib/README.md
@@ -34,19 +34,22 @@ Contains files used to package bitcoind/bitcoin-qt
for Debian-based Linux systems. If you compile bitcoind/bitcoin-qt yourself, there are some useful files here.
### [Gitian-descriptors](/contrib/gitian-descriptors) ###
-Gavin's notes on getting gitian builds up and running using KVM.
+Notes on getting Gitian builds up and running using KVM.
-### [Gitian-downloader](/contrib/gitian-downloader)
-Various PGP files of core developers.
+### [Gitian-keys](/contrib/gitian-keys)
+PGP keys used for signing Bitcoin Core [Gitian release](/doc/release-process.md) results.
### [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.
-### [Verify SF Binaries](/contrib/verifysfbinaries) ###
-This script attempts to download and verify the signature file SHA256SUMS.asc from SourceForge.
+### [Verify Binaries](/contrib/verifybinaries) ###
+This script attempts to download and verify the signature file SHA256SUMS.asc from bitcoin.org.
diff --git a/contrib/devtools/github-merge.py b/contrib/devtools/github-merge.py
index c8dcaae268..f82362fe41 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,38 +43,39 @@ 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
-def retrieve_pr_title(repo,pull):
+def retrieve_pr_info(repo,pull):
'''
- Retrieve pull request title from github.
+ Retrieve pull request information 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
except Exception as e:
- print('Warning: unable to retrieve pull title from github: %s' % e)
+ print('Warning: unable to retrieve pull information 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
-def parse_arguments(branch):
+def parse_arguments():
epilog = '''
In addition, you can set the following git configuration variables:
githubmerge.repository (mandatory),
user.signingkey (mandatory),
githubmerge.host (default: git@github.com),
- githubmerge.branch (default: master),
+ githubmerge.branch (no default),
githubmerge.testcmd (default: none).
'''
parser = argparse.ArgumentParser(description='Utility to merge, sign and push github pull requests',
@@ -77,14 +83,14 @@ def parse_arguments(branch):
parser.add_argument('pull', metavar='PULL', type=int, nargs=1,
help='Pull request ID to merge')
parser.add_argument('branch', metavar='BRANCH', type=str, nargs='?',
- default=branch, help='Branch to merge against (default: '+branch+')')
+ default=None, help='Branch to merge against (default: githubmerge.branch setting, or base branch for pull, or \'master\')')
return parser.parse_args()
def main():
# Extract settings from git repo
repo = git_config_get('githubmerge.repository')
host = git_config_get('githubmerge.host','git@github.com')
- branch = git_config_get('githubmerge.branch','master')
+ opt_branch = git_config_get('githubmerge.branch',None)
testcmd = git_config_get('githubmerge.testcmd')
signingkey = git_config_get('user.signingkey')
if repo is None:
@@ -99,9 +105,20 @@ def main():
host_repo = host+":"+repo # shortcut for push/pull target
# Extract settings from command line
- args = parse_arguments(branch)
+ args = parse_arguments()
pull = str(args.pull[0])
- branch = args.branch
+
+ # Receive pull information from github
+ info = retrieve_pr_info(repo,pull)
+ if info is None:
+ exit(1)
+ title = info['title']
+ # precedence order for destination branch argument:
+ # - command line argument
+ # - githubmerge.branch setting
+ # - base branch for pull (as retrieved from github)
+ # - 'master'
+ branch = args.branch or opt_branch or info['base']['ref'] or 'master'
# Initialize source branches
head_branch = 'pull/'+pull+'/head'
@@ -141,7 +158,6 @@ def main():
try:
# Create unsigned merge commit.
- title = retrieve_pr_title(repo,pull)
if title:
firstline = 'Merge #%s: %s' % (pull,title)
else:
@@ -159,7 +175,7 @@ def main():
print("ERROR: Creating merge failed (already merged?).",file=stderr)
exit(4)
- print('%s#%s%s %s' % (ATTR_RESET+ATTR_PR,pull,ATTR_RESET,title))
+ print('%s#%s%s %s %sinto %s%s' % (ATTR_RESET+ATTR_PR,pull,ATTR_RESET,title,ATTR_RESET+ATTR_PR,branch,ATTR_RESET))
subprocess.check_call([GIT,'log','--graph','--topo-order','--pretty=format:'+COMMIT_FORMAT,base_branch+'..'+head_branch])
print()
# Run test command if configured.
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 1f2c4f9999..13941f5d55 100644
--- a/contrib/gitian-descriptors/gitian-linux.yml
+++ b/contrib/gitian-descriptors/gitian-linux.yml
@@ -26,7 +26,7 @@ files: []
script: |
WRAP_DIR=$HOME/wrapped
HOSTS="i686-pc-linux-gnu x86_64-unknown-linux-gnu"
- CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++"
+ CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports --disable-bench --disable-gui-tests LDFLAGS=-static-libstdc++"
FAKETIME_HOST_PROGS=""
FAKETIME_PROGS="date ar ranlib nm strip"
diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml
index 6f68ae08ce..c430932f9d 100644
--- a/contrib/gitian-descriptors/gitian-osx.yml
+++ b/contrib/gitian-descriptors/gitian-osx.yml
@@ -36,7 +36,7 @@ files:
script: |
WRAP_DIR=$HOME/wrapped
HOSTS="x86_64-apple-darwin11"
- CONFIGFLAGS="--enable-reduce-exports GENISOIMAGE=$WRAP_DIR/genisoimage"
+ CONFIGFLAGS="--enable-reduce-exports --disable-bench --disable-gui-tests GENISOIMAGE=$WRAP_DIR/genisoimage"
FAKETIME_HOST_PROGS=""
FAKETIME_PROGS="ar ranlib date dmg genisoimage"
diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml
index f0fbff3e10..9f7322f0b5 100644
--- a/contrib/gitian-descriptors/gitian-win.yml
+++ b/contrib/gitian-descriptors/gitian-win.yml
@@ -29,7 +29,7 @@ files: []
script: |
WRAP_DIR=$HOME/wrapped
HOSTS="x86_64-w64-mingw32 i686-w64-mingw32"
- CONFIGFLAGS="--enable-reduce-exports"
+ CONFIGFLAGS="--enable-reduce-exports --disable-gui-tests"
FAKETIME_HOST_PROGS="g++ ar ranlib nm windres strip"
FAKETIME_PROGS="date makensis zip"
diff --git a/contrib/gitian-downloader/achow101-key.pgp b/contrib/gitian-keys/achow101-key.pgp
index 030fd5cf3c..030fd5cf3c 100644
--- a/contrib/gitian-downloader/achow101-key.pgp
+++ b/contrib/gitian-keys/achow101-key.pgp
diff --git a/contrib/gitian-downloader/aschildbach-key.pgp b/contrib/gitian-keys/aschildbach-key.pgp
index df06e19fa4..df06e19fa4 100644
--- a/contrib/gitian-downloader/aschildbach-key.pgp
+++ b/contrib/gitian-keys/aschildbach-key.pgp
Binary files differ
diff --git a/contrib/gitian-downloader/bluematt-key.pgp b/contrib/gitian-keys/bluematt-key.pgp
index 2389d4657f..2389d4657f 100644
--- a/contrib/gitian-downloader/bluematt-key.pgp
+++ b/contrib/gitian-keys/bluematt-key.pgp
Binary files differ
diff --git a/contrib/gitian-downloader/btcdrak-key.pgp b/contrib/gitian-keys/btcdrak-key.pgp
index 60d76c0ec7..60d76c0ec7 100644
--- a/contrib/gitian-downloader/btcdrak-key.pgp
+++ b/contrib/gitian-keys/btcdrak-key.pgp
diff --git a/contrib/gitian-downloader/cdecker-key.pgp b/contrib/gitian-keys/cdecker-key.pgp
index 928a74b315..928a74b315 100644
--- a/contrib/gitian-downloader/cdecker-key.pgp
+++ b/contrib/gitian-keys/cdecker-key.pgp
Binary files differ
diff --git a/contrib/gitian-downloader/centaur1-key.pgp b/contrib/gitian-keys/centaur1-key.pgp
index 71a42e5148..71a42e5148 100644
--- a/contrib/gitian-downloader/centaur1-key.pgp
+++ b/contrib/gitian-keys/centaur1-key.pgp
diff --git a/contrib/gitian-downloader/cfields-key.pgp b/contrib/gitian-keys/cfields-key.pgp
index 6b0bd240ba..6b0bd240ba 100644
--- a/contrib/gitian-downloader/cfields-key.pgp
+++ b/contrib/gitian-keys/cfields-key.pgp
diff --git a/contrib/gitian-downloader/devrandom-key.pgp b/contrib/gitian-keys/devrandom-key.pgp
index 71898127ba..71898127ba 100644
--- a/contrib/gitian-downloader/devrandom-key.pgp
+++ b/contrib/gitian-keys/devrandom-key.pgp
Binary files differ
diff --git a/contrib/gitian-downloader/erkmos.pgp b/contrib/gitian-keys/erkmos.pgp
index 9d3f060627..9d3f060627 100644
--- a/contrib/gitian-downloader/erkmos.pgp
+++ b/contrib/gitian-keys/erkmos.pgp
Binary files differ
diff --git a/contrib/gitian-downloader/fanquake-key.pgp b/contrib/gitian-keys/fanquake-key.pgp
index 9c03ff4522..9c03ff4522 100644
--- a/contrib/gitian-downloader/fanquake-key.pgp
+++ b/contrib/gitian-keys/fanquake-key.pgp
diff --git a/contrib/gitian-downloader/gavinandresen-key.pgp b/contrib/gitian-keys/gavinandresen-key.pgp
index f81f44e874..f81f44e874 100644
--- a/contrib/gitian-downloader/gavinandresen-key.pgp
+++ b/contrib/gitian-keys/gavinandresen-key.pgp
Binary files differ
diff --git a/contrib/gitian-keys/jl2012-key.pgp b/contrib/gitian-keys/jl2012-key.pgp
new file mode 100644
index 0000000000..b8aad7fd88
--- /dev/null
+++ b/contrib/gitian-keys/jl2012-key.pgp
@@ -0,0 +1,105 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Comment: GPGTools - https://gpgtools.org
+
+mQINBFYhRd0BEAC+2VU+8+f9RTPLtl0C815oxaOCA9Tle13xNER8NjFrVwIuFQ64
+nO8Fbhd5KEEARuMS/lc5G6IV0QxBpDGE1sEjPQXrA6UnX8SDkNGhmoAsV07MP2Xl
+glN9qqYUEoVD7ueh7Cp3A9rFjg7wcMJCPQDP6lZY4cPgYlE1C31TCrEdAsVVTQg+
+xIYWnhB92VxOJhk0N0h6xtCQ2MOtYDjYcBndQ5iK7L5jy5LI89YVRfbKtWqWZdwR
+lgj2JCLeXKauXBI1qbedCJrz5e8nXcdqZt9TXSHo/XhNlqvsLiqBq4aXNU3xRkrv
+fcweZ9jR9DjyQzefYFGaiCk37R4qLbaqQRm0luUizkCegIuTv44e/zig0im8yPAI
+WtGnmBPSy4MpvvWiVVb+jHikdQG1T7g9kF6gEmj4kj9UseWnasiq+kkSNE67vLxb
+uZDfA3QhavRMJbCNEY49/IX6urIsiCLFbe6C7JVWvJ7d5l3MAHE8Sut+ytjX7z7O
+LFt7YD6loxGAdopEUZm50xs8PswKDajlzWGFXjDZdzQA1tb2CpHUtDkAInYDutR4
+qA29qtxaBswozzUYiDptGSkBqD1Nus7UAJYkwe2EjeszNPhmIAQXGWx2yWplPOJk
+ZWDuhQtrDXZikl70q0ekIJ7bxkpMO8xUuhsBCS3Wn6GAtySy0XTttmItfQARAQAB
+tBZqbDIwMTIgPGpsMjAxMkB4YnQuaGs+iQI3BBMBCgAhBQJWIUXdAhsBBQsJCAcD
+BRUKCQgLBRYCAwEAAh4BAheAAAoJEMUkKhqzk2UXsbIQAJnXDjhEoKSILJRrKbg+
+MXP3Rhxc/ThXu5C8yhfYqKblqCaNNfEmrlercJKJVMvjY0tVTXYo8BEJmNN7nSNI
+su8NheJ9vXacN3XrgkMPuFiUyKj9PGpSsM6Q8MjT0Bzd0pxodk+g0UEjyMktfu/3
+TqLsnoFPOtIjMOkr/uBzZn5d0AXIZQbAz4Xa2zBW+uR3OSXRRXCRJjCSWGIfDX0Y
+i/Ea+3Be+y9bMqDa3nPULEkW7+RNuyjLr6QwPZ0/BpTTDcM6Vic2daFPO5B0+o3z
+PMFmPcEd4nRHTPM9A5SaJtC8MjF/89mjhpxG3v8RqkqCdqdM2cezi/T4YD4jcynE
+F36Ya3GuuewxEZci/N5ySG5gG8Y+80Wgc1e+sNtvIffHk3Wju2kOvNcBA2TBw36V
+XCJXHROTA5+Cx4lUxOkQTJoYSVzx852WS6WHeLg1+XnDZvT7ciVIV0ExJQ9C1XOM
+wjFMRsTWl+vflxmgCeHCIari57Jw3ij7ghRCgeqLp7FIXK5qSI4Tw2eajJpoTKPs
+wlaO6kvOXtaCDH30FuVhKbPxII01Xi/A2ALtTkpA6mfnf19orQjv+HxX/iwUlpHM
+UwsuhpZSQYIxIv/BOQnXDfw4TcjnHsqXZbqNzzFEjGurMTlOUX4KeTPscdOLUpnO
+1FM4JIVybHHfhCH9Mpq+MIwCiQGBBBMBCABrBQJWpym9BYMJZgGAXhSAAAAAABUA
+QGJsb2NraGFzaEBiaXRjb2luLm9yZzAwMDAwMDAwMDAwMDAwMDAwNWJiZWZkNGM3
+Mzk5OTE0OGRmZDQ1MjA5ZjA2MTUwMTljMTNjMGVjOWUwYmQ4MzUACgkQf6sRQmfk
++gQcZAgApPqnaIIE8Q5sruzua50RFRmmBtQys8sM95ciWYE4QaTXUnlhHl4QR4z/
+TQTRSBqXpdHQ9HBWrhFb6E0ykDEVx9zdEt0fvtlhHx1ItrZetfiA4PwidnyoDKs/
+/nt01RGreKSMDGInaQVEQxvEW+A0fwvcCdE8Mh3LcIydohfqUViB0c5zb7rUmize
++2Kt4Uth9T+ooo+UE87pHSJcxlcPOv6Dc7KeoUicD8DwWdsT7oxAMk9jj/ut4UNx
+xOEp9Sa3sFN20tHMqyOZwnl22Py0y4ayJnceawpuka/bx7samg/2uUrO+dNKXObN
+trebP83+8UFHOo7VGhesuawgwNjWW7kBjQRWIUbHAQwAy6re/3ur/fgNfE9yKivp
+Bqmjq0eU5l3iT59hvKr7S+6GHUa+YvE9BBsawDSI4UILNQX0YGT1LRa20mC1okBX
+5SIEpWzoZhybTMVMwS2ZHkUyO6VBAieUVojP3XQHFcDAiBvW7RRhJ2BU+v9DGo88
+HAYqKEB85P/i/E/a1xUfTWiiIhA8Dd/Hv6pzIG5QvN8XfrMIayLwpOV1G6KvBIJb
+zyUVUvLyQySiZOyDczrAxzYq7b1qv8xwHDUzyUl6skPqbex1cFWIeiML9EY4DnZ9
+l3qb31Bhp+EHydv0esclM5XKQriSg/hsnJOLlCS45z/YhqGOCoD8QxXUJ71NhD/H
+QR/AvGyTDcPr1/U1DJ0lG778wCOEe1Nad0G/8rcpHSY66RZR/Wf318S7uJt0mUw2
+JMt1BRxfbdgJaleUAqYjNQAMDb8LfPO6jhQnmf0nN99dpdzkwV/drVRcLDEnupDr
+keBsokcuohzE0gbjUT4cNc0DuUsIELMTApG8KQCgzJy/ABEBAAGJA8QEGAEKAA8C
+GwIFAlbi67wFCQGu8u4BqcDdIAQZAQoABgUCViFGxwAKCRDunlUgNL4k0qceC/91
+2ocEDwiu9kpBGCW0HD+VSyMVjLWMiClk+jPngvNEt63ZkYqRiy7fwnPuJrLFlaL0
+E0JLIweihC5AyPSJT1Q0LnOwbqCHn1s+9RfIodG/v6M48Ez4GffOtmYwW9KqogK7
+4FwdIx/wOIYDeh4rT7LRaWBNcIXO8J1+v/83u+Vx6TWKZTiZKQMEV8VOJWfSmTCE
+6HVgUYvLCPB6DI+X4aVead1kayKOSuXlG/l94B5RHlJB/xQXZd1INyrZetTZxYzZ
+CBhIWaZ/ji5vqFot0xVNYplRkbg1Mc96X+hwee8eiB/ySSWxUV/DDkA5ZzuE8n8R
+EEjzqazjMNe50P7XKVg/eBE+TpgCDlqv69dqnOF326m6T3+FH/LDOHguQfB7pQKx
+siviqjO3molBSyMHL39XFWyteVbgbbSaTRkpX//b7dQoFMiVhigcM78qoymBi6yX
+qwpN13JoNuNJhEOwex5eEEUCVibFReUkBrYoGnWbwuOxiLORx/IbuNYOvsTGYEAJ
+EMUkKhqzk2UXWScQAIvAgEpQpzuE1CWMBWcM/n4ruUrOVTeo6dYpUGN1LI0758xm
+4VI47I8wPEy4pAbdPcqoaNnMcA/NpSYa3hV0svQDLqT96qKTrN71N1gNJa+5w+KN
+rwev8MRpjuze9b4dn3avs4L9f0fkpzjSzezKwVb7loFSZqgKAaI0aSoOUTec9+OU
+5ymgkYPEEF12ydkyMzLwyKrtEnIqgwQpjYTN/3P1x7Gkhv+E8Lz06TSga84yVy5I
+5gO1Hklc3MW0J9jPJe3uALUtEh49KxCE2rdbIX7YbkxWaHHfK98Mu998IXr/4eUe
+Zhf2CLC2cuuYbk1/rOcxPmeIJKa6S5PlWOf3Y2yLRO0VKcjD5pcGxiImoDVXC4VM
+hztCVLddjU70c1ktSIBQBu9gkpPcECrzjYtpeAavOUgmpP/zQ8X2NGp6+5n9Wwii
+tAgByNCg0s+PqcAZxup34b3ZY/t475tDlAmIOovH14Aa8g+0Ketj++9rPpmg9kGs
+sGmn4mVItClaA7L9vZQQFnSxjyfICKsSxBhqded0lsinlzBfXDEh3N6fEXh81/Gg
+zLUmTlkhcGaFXplYqrUIlkdO9PD4R2h5P6laLhK2dAf7oKavWHZQp02Yb5nVBiDc
+KiVWKBP4nuTkWZCG5R966wpR1IOQQ3LykSd5SstcZX6iTpv4NZpCxI4CXpaCuQGN
+BFYhSHABDADHaEJVygBdwU81c4YynyTOnWTZX+BR3EvRW51GcnfvjqkqgmlWNLET
+JkswQ8+s0mjKGVnz4dkdr4cUbVegj/St7wzoO+m5mYIDMJf1j83Vo6lTo9FJFzbc
+HrYC9RS7NkQmD7qzJz4KY/h0n5szFIC/JpYECBNzYrJQc8m2kZiSlyUQJve5/I5J
+iI6QnM0x4kixNe32GITmKw9s3E2iRf6yXVlsrPouNS33lPXKtvmO1ae7R+G8Ve+D
+JDv+TLxccy2iU9wuz4I3k20+rlmEwk17feDhfleh5Q+qjI4vkaNcXFa5coZE0HyW
+SwAtLPSOv2vWkuFeYncXRyzg/CvKR57i9wnqMzNTMt3bHY2HezE13bHln5B/Jqr4
+ihhFQBqPG+UZlGYRfAI60PLh2yftX5xkm/POiLgEKF76/yIZI8wcPzzurAhFaZBp
+8/MUv2ZJ/OUT4rdEVV+6XnrijNqVBU8mf8BML5CvjyhsU69yf1mvpiLQr34FNEcn
+JekDGPIk97cAEQEAAYkCJQQYAQoADwIbDAUCVuLr0AUJAa7xWwAKCRDFJCoas5Nl
+F8NMD/4hRoOKENEq940Z0iJg0TDvRvRnaIYsbneRQ3yg1DGVIQ+4RHmzQdpN9MW0
+5RTRLqJsW25ydWwh7y0O/oBRjaoDRAkMSIyOo/Fy+E9WWBmAwzeYCi91MyfetKIO
+ocrXxpXXKnotAFDOgWGF8K+LlTDH/biOrd8ftgOVJWhz3X04ma7xvT2tQTqfFdbt
+EivA+jFExq3No0Iq+Ctt/e0H2d9np62SeKBVdpbx9xAc2tPKKDSl+FyB7lj5CK5/
+FKhotl2bJhVXET48P6e+bFVwfRO7o48zuK5CJVbbdjhavQGhQoxfedW2dn9y7QoM
+qayUuVIhULE/k+y3jsJBUT7p567nSdUGbc3uKt1sfPKYTdsFbHiTRltXmsIiv4bG
+PslbXSvOQblFOXWrAE22CdKmGzhlEiFnbviZCCl0BFf4CwEVBJ3p9Lcoir1l9Aty
+HIIFI3z1mmTz4F9BMbe6saNwBzO+Kh4+US5NV/hqvyz0aOLltb6KfI8WF8kOa1Cx
+Djz/DTHnvMWO/dIOJuKsThfuxZZq3R1w3O36RB8XzDT/8NV86gfQwN07NWz1rdy4
+60fK36EjOJDqm/434/BDzWh8TqmnSamENxBTbICmWOj/25M26tA2S9zcPLJHTGMA
+3yL3QlBtjWY2uNqr51cnZHgPKxBWzaRvcrZ+lUq5EG+F4J7q5rkBjQRWIUitAQwA
+5A2AhW9DFxVsM105WEErD2NuM2rvtq7dTwArBEi2KdWkSGQvCE9xgyH8u5AEWxj8
+XXHE/rfunW0d9oF7Z9FbOuV+1HQOAj5hQQWLWHERwZ4gOAqG8ZKAbuwTlqitdiXE
+PZiJYZSq0NXtngyeTx7XqzQSatfFOIQLzIiwPQXX0Tt+JB3B2SN/D2NP7rubzfS2
+Bg0ErhV20fPDl8YloEJFfj9lpF0ZJnJ5hXYP9Fl4MoPkyBkGPrJPooZ4FqUFHDiw
+mttzP1BzFlwpAPGpI0NrkBdBlfFAtvhjreeB5Z4VYwt1xqoXgI+jYXAxoMl+rtkK
+FdWaoT7wHwqDBeBWYXoyXA2dYIY8Ux1jeDBnREck7vaXhln6zXqMAQowE+F9OQnr
+Wgf/LoOn5MYxsBDY9mPAO8urxUDE+Dq43JBXlS+jybMNZWdtkaBrIde7dw9IT8Fn
+p8pG78DmgPxmRFH9QoypTqMfB+x7ZuB0fk1ud4ut33qLo78BWZoW0H++13CbSmrZ
+ABEBAAGJAiUEGAEKAA8CGyAFAlbi690FCQGu8SoACgkQxSQqGrOTZRcNQBAAmeL1
+8Wr7vuvL5dySoYmWqHFvM8gRUwIGza5c3D29NYZJcPJRRkdGCV2IXEuUSOLtnjAN
+kTM1TVMMnetqNR8Uryr7z3XjqYLnVwGqOPnFnlkE2zS3pG8AGG6OxxBhuEMvkwcd
+1s3tWUlJYRWi1XhEjVZ5Km2pHsVxvoXeJCUVsa8nSXzqF8gOLm409NFMiKkp8QOG
+heEV4yWrHkySi1fVfOdrHfBzu2lUmHGgSbmJIpLcK+cL3TjpJ+DkSNbniI13I/Eb
+PO4Uai4a3QYz6sspZ7UzF/pjY5v6WpWXiVB5PP2Y5BrMUgWRlFxPYTc3KiIHUYVi
+IjVtSOsVaRCHL/SYRq/qHs63XxlxKIhhilbR4OO+CvJ6N/vEpSbx69SqlxgDArZy
+g3QQqerlLGpSFim9iWk3QBGWtQ96Ek6rjLLOn7b34I6bxXtfcOEo7gl0Y1TFkfOp
+nsXAcRLrrXCpAhgC/vIQRTMKEcC18kj/vY144DwefzYCBhbI/rCSohAq8a/zhq2T
+E+xlCYy931HWlUAGx/hms/0q+KQ712Zgk4XxXEx4RZiv3zl9Uph6c7SXxAMb8o2v
+PzAxd3ShNOnng9hAl8zk5O1RZPa5u51ppkO1FsJ9zjb2Kvdg4ZEBtK8jETv9ckuq
+yj9YmZZSRRQ2dujg81sLQ9CrO7WB3IGpwh+4lHQ=
+=1irw
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/contrib/gitian-downloader/jonasschnelli-key.pgp b/contrib/gitian-keys/jonasschnelli-key.pgp
index 3831eaea11..3831eaea11 100644
--- a/contrib/gitian-downloader/jonasschnelli-key.pgp
+++ b/contrib/gitian-keys/jonasschnelli-key.pgp
diff --git a/contrib/gitian-downloader/laanwj-key.pgp b/contrib/gitian-keys/laanwj-key.pgp
index 559295109d..559295109d 100644
--- a/contrib/gitian-downloader/laanwj-key.pgp
+++ b/contrib/gitian-keys/laanwj-key.pgp
diff --git a/contrib/gitian-downloader/luke-jr-key.pgp b/contrib/gitian-keys/luke-jr-key.pgp
index 4406e6d5be..4406e6d5be 100644
--- a/contrib/gitian-downloader/luke-jr-key.pgp
+++ b/contrib/gitian-keys/luke-jr-key.pgp
Binary files differ
diff --git a/contrib/gitian-keys/marcofalke-key.pgp b/contrib/gitian-keys/marcofalke-key.pgp
new file mode 100644
index 0000000000..ee626500a4
--- /dev/null
+++ b/contrib/gitian-keys/marcofalke-key.pgp
@@ -0,0 +1,69 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1
+
+mQINBFZu2toBEADGuBiRutibv2SlW/A7vBGeGA0n58coQaPkmi04QGMeGxdZyvad
+h8olkPO1q5B0/5E1olEjs1YquHTjSjerLz8nUg8K5OEu14KtCGvFbmtSFW7fOUHD
+/u+EykJrJczqcJJ31r4B51L8CdS1ODdBbinQRlTjtLq+pE/fJAjHI3iQ2E06vkpc
+BRVA628fZKHIcd6uXZBrDyAcKtqq1TITlcYoVlYbvMrov9bPz1NW3P6pgnO1S+UK
+RfkhG+N3bC8ttsTXo0aevz3klaVFEZ4Oo4N8TUcYoYDTZIfu/Gk23r0hBONI75IE
+pbF8u+r0M5mpXxCHqmrUgmU33CBTeuCZon5r0iEsweF+ldh5rhEOhXWxHcUUz62S
+64XoqzuOlorpWzIS53oyVTZcH6XszF+iLqSuMQCgOYhF/u47rt3Vh9D+TYJcnvGd
+0ozRuajLIRGCdVlKt212ER9QLxZ6BTOePbb+g99I2DOx6heSUDzwXWKTxt00Lr89
+LyBFa9kj2fI0BNuzx9XI0l+GK5M9xkNi5LwL5gaLsPCJHEEPaG2pcBIBbw6hjIka
+L1fgDWng6MQ/eml5JsyA3G3J07/xxoVPaN9vZ8LLO9BEiz7e3Oss8a3Mw+SfsMcH
+mJJIFT/CguJCxW3FeKs16XiDpO2Eg2WRoMJMB+psdfgo8e2q7dXIE6kCtwARAQAB
+tCNNYXJjbyBGYWxrZSA8ZmFsa2UubWFyY29AZ21haWwuY29tPokCOAQTAQIAIgUC
+Vm7a2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQNkiogvQxa5vgkA//
+Q200J62bnplhyuWMvKmpCNFG7lTtLHmwVtZmvBJiHsRwe42KRWKz6IaQgEHfBMCU
+tSra4i2KY47j4s/kyTgWeQooH9Zxh7c4EMeyOrxpqPmnKF/0tFnDyk9SCqbrrUQ+
+VuL9/JrZ3zB74GtRikvWXS43cuBheKPZSwdGrGWtP74Z48eKXa8mOZtDfQJACqpZ
+lF2Hv0GOFKDNfaol6BkANpeDv3orhnysY5TqE8iA4VuHAL2MDmWg68Rb9sjPoj7U
+TIYyeqiok/R56SkN+WnGGI7l4+pk8pBqhkjZUjVTEEABR81Vu+Rn8OxTqpKu6gW3
+YACXnk/kXYY4I3Ri63eK0BQEeZ6Q8nrPhqHYK7fzlbwwL4Id5bDJpBZW+a6Hvlw+
+zQXpObhMSxtDJZzEonqq5PwJLlkLPU4sbS1tuinCdAII0Qz0Tv3Nwvcrr+KWiNqr
+vf1ed7CecDcQpSqHfhhibgykLfdAJGNpGxyA4yhOUHax4TbYZctL3ZYXRWGrF//z
+Gv33w+8DMb3zM+BP2SBR5D7MFTqE2X7bTn/0pRnfYObjgU7+pT0bed4SyEY2mnqb
+ikPTKfz/g+xLL46lMaJKLgBdS14A6+k3qVUDaBNMb7crSQlutmU3fRhNYq1KW9IX
+vEI7YuEfMa6vj4rLW+68CKYBu2pNBSQZ9LHedx1UM3u5AQ0EVm7hJQEIAMTDtNiw
+0WJUO8T7G2vA4WFHbvBoGM4CH9LaOm0JpH3L0DQ+XD5EWGICwlpkoiQiRPpGSmSc
+KAbAgtfS+a91z4GSWEgL+q9HqVZO22yQSeCbtbnJs44BMJzgMcVxiFOc0JQU0KPR
+zrT2TtD/Z4ryOvI2nuepv3aRz0RSQEsBnhMx/aNIV9YbRJ0YofC8BPReK5hQ6rYT
+V2C4P0RoPCdjeGx//0Ilg+xTbPSG1urSKVUEz6UCT21MaCBsyxN5Z+Wa2K9F/894
+y+TsWMQQcUYZ57DXFHM1dOkfDYorVATNOnv3dIJEjQDU0dYEE0yNUYG5nu+UjluJ
+LG/ZTiXhkNQla+MAEQEAAYkDRAQYAQIADwUCVm7hJQIbAgUJAO1OAAEpCRA2SKiC
+9DFrm8BdIAQZAQIABgUCVm7hJQAKCRAtfyNy5Q/hN0XMB/94V+GgGRgCxvwdAT92
+RCatOJcf1YJuw1aKWjAiib0FVeChZebZYqW+jwvMkXZwxlVFhcpFlUzAqCRwcJx/
+QoalF7u2yTL6DEEGcC8bUKrhtXQch4/D28BWJAJlR/7bItdWMIuw4WV/8s97t8Ca
+Fn2Fc1T6/B20VclsxoeaAoXZUcWG9YIKRbEaogt3LxsRjgQLZiIicjRl0C5YpYDt
+JvnENKuLwSRte6gKkuUi7Xw4iIP1aEwTTdZe0km6If6pVPwCK1cU9xMpsMftT1Fl
+NdK/dJbfWoYrS24U30XvCxsFMogD5jJ+PiXUoXDBjPJmDiXrGUDR+je/RqsUKBH5
+zyKaI1oP/A5Dq/EU5ceIfMPaS8iK4DjgwKdh8zuprDQ+JSf4iD1b/HHlwcrXmGFG
+4uRO0X/V0ybIdYj4U4qXRm2FTA20x7MDEDW0i/cJQKNrVZC7HQnvrdG7ggG0KVok
+tTvsIWJTmpQ3MY47rTtWQrmRdiiSRWeTFyE4sPUy3XpuPA5ZKGF5vN7A1p1WYSZH
+gl6NBv2vp3wjwplSpYumzh0q+o7W4bhdy9+BR+K8l5a9LKyCrwL92XKLqp3iAyvq
+RdbCrTvfppYtNwJ06JBww/b+aO08vTFY08eYbMTOVxNJUtzpq+JUe9QHOzbBNCv5
+viIVqNRJEQw8ITQQ1AjgN3iWdnbVQEwYv3D6VNkpzDpZD6tzOmJwwbRc5rISCVL3
+DQQglc7BYIkcI47QHBdf979H8EvA39U4yFHW3DfApHBl/gzHcEbb5RoBYc5yb+02
+U8xGHxGJ7q4h40N+oLCc4S04gepqtCeIQ8cgCPjRdPKuP8o2O2wzDYvqr3RlzM1M
+l+GWmv+3em/RWwhWggDIf/XhYkSbC/USJuPjQEYqJRcpx+60HYV7Ro6/RryOoLUA
+0ZXu6IYs2qT+KEcLQ4D1XKNb0GFnHW+3SXqehl4qI0zdPUOLKpXhCpThhC8BlqV5
+O1aP/5jnogwcW1HF+tUc4h3nwrgvcajrikjffdBIrUidoDVEN04WuQENBFZu4oYB
+CADQwtiaFcDxMms3bNyRrfaIA5gNWEhoTRFNXMKY5SacsavamWzlfNRBIlYMl27z
+oMZK4hpxH568UKhwQyb/qLt7gI9hLBOdgRaWZuOCghNGX3MQCBodDLXTahnvUlXp
+pXnUOtuQmODPjTDIjNXjcsZUUzSJoanQ+Zt8OWPBYumrFC9Xw5fFRcrNmSbWnllx
+Nveyrm6mlOydSUXq8D1vh4vkNGtQ/0nrFuSTBGsl2vY+ClX4o8iYunaHmhEboqjp
+BMEC4WdBql6N5CI64HQ0e2iGXVSTPiMHnpqQlnaOvx3gdaYPW15hjISgjPb6ygdp
+uyGXyPRa+0X7TlTtGXLLcoB/ABEBAAGJAiUEGAECAA8FAlZu4oYCGwwFCQDtTgAA
+CgkQNkiogvQxa5sE5w//VrTdVm1ak3RCtZU1D25D6yiSMKZ05j6PDyJfZNI/QubJ
+5Qq/VKzITa4kr50LNnM/wZzQPxEM5K6HyA5Wk3tt4IXqmqyZ8VUS+55sl1b5Tg6q
+NSLc2qXmY+BeVGmQZwke4nY8wvTNI3wGDekJTPd5a1rjkw64l8n2Xy5ErVaYlhkW
+8KyD96PTKhsJgRqGmAtZjJ2i1e64oR/VYR1B9daghGzueV/uvdhD5DxH7UsKSBUZ
+vb7lCeOK9Fuvs12/ULgMmymFxSvKeD5+etGUPsNA3gRpqwNcipp0QNhiQmm8nRq9
+vH8Kv9tPmaXL2JHWJB4pMXQXX/DIww3I2gaFfHL60Dr120Ddte3uqdG9KSYQHz7s
+/bH+vFsvqr17CHflA/Ogto4rfrlL5qo3SaJVRQwI5vhA3Nx/K22WeH7l25Mu6mAw
+kQo0c76fmSvOTpvCVC8aDvhLlm1nF1ao+dq4QafnCrKU3PTn1SlkZ2hwfFzRy/Ru
+Vdep6Xd2M3tux3O82UoHLF7Z+4G+NgP69h87rMOSikszRsNiCi80xO3aT2CU8Yt/
+l3sduhFP5TqvfKjTJAK6EfUIukVC0JEL8ktpYCyxb9tN6DTPHEhCJUTXZI9Y60iT
+ZIrV7MYY51HatEEJKhpUtLeYSyutj0ubbETfrt2b3cjHNfQh+OLEVUjaQwZXKdU=
+=GC3s
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/contrib/gitian-downloader/michagogo-key.pgp b/contrib/gitian-keys/michagogo-key.pgp
index 47bc404554..47bc404554 100644
--- a/contrib/gitian-downloader/michagogo-key.pgp
+++ b/contrib/gitian-keys/michagogo-key.pgp
diff --git a/contrib/gitian-downloader/petertodd-key.pgp b/contrib/gitian-keys/petertodd-key.pgp
index 5ee82a6f7e..5ee82a6f7e 100644
--- a/contrib/gitian-downloader/petertodd-key.pgp
+++ b/contrib/gitian-keys/petertodd-key.pgp
diff --git a/contrib/gitian-downloader/prab-key.pgp b/contrib/gitian-keys/prab-key.pgp
index 0870c88b9b..0870c88b9b 100644
--- a/contrib/gitian-downloader/prab-key.pgp
+++ b/contrib/gitian-keys/prab-key.pgp
diff --git a/contrib/gitian-downloader/sipa-key.pgp b/contrib/gitian-keys/sipa-key.pgp
index a1930ddee9..a1930ddee9 100644
--- a/contrib/gitian-downloader/sipa-key.pgp
+++ b/contrib/gitian-keys/sipa-key.pgp
Binary files differ
diff --git a/contrib/gitian-downloader/tcatm-key.pgp b/contrib/gitian-keys/tcatm-key.pgp
index baaec76b8c..baaec76b8c 100644
--- a/contrib/gitian-downloader/tcatm-key.pgp
+++ b/contrib/gitian-keys/tcatm-key.pgp
Binary files differ
diff --git a/contrib/gitian-downloader/wtogami-key.pgp b/contrib/gitian-keys/wtogami-key.pgp
index e0f6c4c5fd..e0f6c4c5fd 100644
--- a/contrib/gitian-downloader/wtogami-key.pgp
+++ b/contrib/gitian-keys/wtogami-key.pgp
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/verify-commits/trusted-keys b/contrib/verify-commits/trusted-keys
index a0d0f82db3..ad1b28be0c 100644
--- a/contrib/verify-commits/trusted-keys
+++ b/contrib/verify-commits/trusted-keys
@@ -5,3 +5,4 @@ AF8BE07C7049F3A26B239D5325B3083201782B2F
81291FA67D2C379A006A053FEAB5AF94D9E9ABE7
3F1888C6DCA92A6499C4911FDBA1A67379A1A931
32EE5C4C3FA15CCADB46ABE529D4BCB6416F53EC
+FE09B823E6D83A3BC7983EAA2D7F2372E50FE137
diff --git a/contrib/verifysfbinaries/README.md b/contrib/verifybinaries/README.md
index 1db3fe52fc..8970f3daa4 100644
--- a/contrib/verifysfbinaries/README.md
+++ b/contrib/verifybinaries/README.md
@@ -1,6 +1,13 @@
-### Verify 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.
+
+Usage:
+
+```sh
+./verify.sh bitcoin-core-0.11.2
+./verify.sh bitcoin-core-0.12.0
+```
diff --git a/contrib/verifysfbinaries/verify.sh b/contrib/verifybinaries/verify.sh
index 847c507553..657c3bd33c 100755
--- a/contrib/verifysfbinaries/verify.sh
+++ b/contrib/verifybinaries/verify.sh
@@ -23,9 +23,6 @@ BASEDIR="https://bitcoin.org/bin/"
VERSIONPREFIX="bitcoin-core-"
RCVERSIONSTRING="rc"
-#this URL is used if a version number is not specified as an argument to the script
-SIGNATUREFILE="$BASEDIR""$VERSIONPREFIX""0.10.4/""$RCSUBDIR""$SIGNATUREFILENAME"
-
if [ ! -d "$WORKINGDIR" ]; then
mkdir "$WORKINGDIR"
fi
@@ -53,7 +50,8 @@ if [ -n "$1" ]; then
SIGNATUREFILE="$BASEDIR$SIGNATUREFILENAME"
else
- BASEDIR="${SIGNATUREFILE%/*}/"
+ echo "Error: need to specify a version on the command line"
+ exit 2
fi
#first we fetch the file containing the signature
diff --git a/contrib/zmq/zmq_sub.py b/contrib/zmq/zmq_sub.py
index decf29d42a..6268123dd8 100755
--- a/contrib/zmq/zmq_sub.py
+++ b/contrib/zmq/zmq_sub.py
@@ -3,6 +3,7 @@
import array
import binascii
import zmq
+import struct
port = 28332
@@ -19,18 +20,21 @@ try:
msg = zmqSubSocket.recv_multipart()
topic = str(msg[0])
body = msg[1]
-
+ sequence = "Unknown";
+ if len(msg[-1]) == 4:
+ msgSequence = struct.unpack('<I', msg[-1])[-1]
+ sequence = str(msgSequence)
if topic == "hashblock":
- print "- HASH BLOCK -"
+ print '- HASH BLOCK ('+sequence+') -'
print binascii.hexlify(body)
elif topic == "hashtx":
- print '- HASH TX -'
+ print '- HASH TX ('+sequence+') -'
print binascii.hexlify(body)
elif topic == "rawblock":
- print "- RAW BLOCK HEADER -"
+ print '- RAW BLOCK HEADER ('+sequence+') -'
print binascii.hexlify(body[:80])
elif topic == "rawtx":
- print '- RAW TX -'
+ print '- RAW TX ('+sequence+') -'
print binascii.hexlify(body)
except KeyboardInterrupt:
diff --git a/depends/Makefile b/depends/Makefile
index ef5a20e6c3..3ddfc85a45 100644
--- a/depends/Makefile
+++ b/depends/Makefile
@@ -15,6 +15,8 @@ BASEDIR = $(CURDIR)
HASH_LENGTH:=11
DOWNLOAD_CONNECT_TIMEOUT:=10
DOWNLOAD_RETRIES:=3
+HOST_ID_SALT ?= salt
+BUILD_ID_SALT ?= salt
host:=$(BUILD)
ifneq ($(HOST),)
@@ -73,6 +75,20 @@ include builders/$(build_os).mk
include builders/default.mk
include packages/packages.mk
+build_id_string:=$(BUILD_ID_SALT)
+build_id_string+=$(shell $(build_CC) --version 2>/dev/null)
+build_id_string+=$(shell $(build_AR) --version 2>/dev/null)
+build_id_string+=$(shell $(build_CXX) --version 2>/dev/null)
+build_id_string+=$(shell $(build_RANLIB) --version 2>/dev/null)
+build_id_string+=$(shell $(build_STRIP) --version 2>/dev/null)
+
+$(host_arch)_$(host_os)_id_string:=$(HOST_ID_SALT)
+$(host_arch)_$(host_os)_id_string+=$(shell $(host_CC) --version 2>/dev/null)
+$(host_arch)_$(host_os)_id_string+=$(shell $(host_AR) --version 2>/dev/null)
+$(host_arch)_$(host_os)_id_string+=$(shell $(host_CXX) --version 2>/dev/null)
+$(host_arch)_$(host_os)_id_string+=$(shell $(host_RANLIB) --version 2>/dev/null)
+$(host_arch)_$(host_os)_id_string+=$(shell $(host_STRIP) --version 2>/dev/null)
+
qt_packages_$(NO_QT) = $(qt_packages) $(qt_$(host_os)_packages)
qt_native_packages_$(NO_QT) = $(qt_native_packages)
wallet_packages_$(NO_WALLET) = $(wallet_packages)
@@ -90,7 +106,7 @@ include funcs.mk
toolchain_path=$($($(host_arch)_$(host_os)_native_toolchain)_prefixbin)
final_build_id_long+=$(shell $(build_SHA256SUM) config.site.in)
-final_build_id+=$(shell echo -n $(final_build_id_long) | $(build_SHA256SUM) | cut -c-$(HASH_LENGTH))
+final_build_id+=$(shell echo -n "$(final_build_id_long)" | $(build_SHA256SUM) | cut -c-$(HASH_LENGTH))
$(host_prefix)/.stamp_$(final_build_id): $(native_packages) $(packages)
$(AT)rm -rf $(@D)
$(AT)mkdir -p $(@D)
@@ -131,9 +147,9 @@ endef
define check_or_remove_sources
mkdir -p $($(package)_source_dir); cd $($(package)_source_dir); \
- $(build_SHA256SUM) -c $($(package)_fetched) >/dev/null 2>/dev/null || \
- ( if test -f $($(package)_all_sources); then echo "Checksum missing or mismatched for $(package) source. Forcing re-download."; fi; \
- rm -f $($(package)_all_sources) $($(1)_fetched))
+ test -f $($(package)_fetched) && ( $(build_SHA256SUM) -c $($(package)_fetched) >/dev/null 2>/dev/null || \
+ ( echo "Checksum missing or mismatched for $(package) source. Forcing re-download."; \
+ rm -f $($(package)_all_sources) $($(1)_fetched))) || true
endef
check-packages:
diff --git a/depends/README.md b/depends/README.md
index d85e652c60..271bbd80bf 100644
--- a/depends/README.md
+++ b/depends/README.md
@@ -38,6 +38,8 @@ The following can be set when running make: make FOO=bar
NO_WALLET: Don't download/build/cache libs needed to enable the wallet
NO_UPNP: Don't download/build/cache packages needed for enabling upnp
DEBUG: disable some optimizations and enable more runtime checking
+ HOST_ID_SALT: Optional salt to use when generating host package ids
+ BUILD_ID_SALT: Optional salt to use when generating build package ids
If some packages are not built, for example `make NO_WALLET=1`, the appropriate
options will be passed to bitcoin's configure. In this case, `--disable-wallet`.
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/funcs.mk b/depends/funcs.mk
index 050a9b1321..15e404e42d 100644
--- a/depends/funcs.mk
+++ b/depends/funcs.mk
@@ -19,15 +19,19 @@ define int_get_all_dependencies
$(sort $(foreach dep,$(2),$(2) $(call int_get_all_dependencies,$(1),$($(dep)_dependencies))))
endef
-define fetch_file
-(test -f $$($(1)_source_dir)/$(4) || \
- ( mkdir -p $$($(1)_download_dir) && echo Fetching $(1)... && \
- ( $(build_DOWNLOAD) "$$($(1)_download_dir)/$(4).temp" "$(2)/$(3)" || \
- $(build_DOWNLOAD) "$$($(1)_download_dir)/$(4).temp" "$(FALLBACK_DOWNLOAD_PATH)/$(3)" ) && \
+define fetch_file_inner
+ ( mkdir -p $$($(1)_download_dir) && echo Fetching $(3) from $(2) && \
+ $(build_DOWNLOAD) "$$($(1)_download_dir)/$(4).temp" "$(2)/$(3)" && \
echo "$(5) $$($(1)_download_dir)/$(4).temp" > $$($(1)_download_dir)/.$(4).hash && \
$(build_SHA256SUM) -c $$($(1)_download_dir)/.$(4).hash && \
mv $$($(1)_download_dir)/$(4).temp $$($(1)_source_dir)/$(4) && \
- rm -rf $$($(1)_download_dir) ))
+ rm -rf $$($(1)_download_dir) )
+endef
+
+define fetch_file
+ ( test -f $$($(1)_source_dir)/$(4) || \
+ ( $(call fetch_file_inner,$(1),$(2),$(3),$(4),$(5)) || \
+ $(call fetch_file_inner,$(1),$(FALLBACK_DOWNLOAD_PATH),$(3),$(4),$(5))))
endef
define int_get_build_recipe_hash
@@ -39,7 +43,7 @@ define int_get_build_id
$(eval $(1)_dependencies += $($(1)_$(host_arch)_$(host_os)_dependencies) $($(1)_$(host_os)_dependencies))
$(eval $(1)_all_dependencies:=$(call int_get_all_dependencies,$(1),$($($(1)_type)_native_toolchain) $($(1)_dependencies)))
$(foreach dep,$($(1)_all_dependencies),$(eval $(1)_build_id_deps+=$(dep)-$($(dep)_version)-$($(dep)_recipe_hash)))
-$(eval $(1)_build_id_long:=$(1)-$($(1)_version)-$($(1)_recipe_hash)-$(release_type) $($(1)_build_id_deps))
+$(eval $(1)_build_id_long:=$(1)-$($(1)_version)-$($(1)_recipe_hash)-$(release_type) $($(1)_build_id_deps) $($($(1)_type)_id_string))
$(eval $(1)_build_id:=$(shell echo -n "$($(1)_build_id_long)" | $(build_SHA256SUM) | cut -c-$(HASH_LENGTH)))
final_build_id_long+=$($(package)_build_id_long)
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/packages/native_cctools.mk b/depends/packages/native_cctools.mk
index 1c1bcf199a..b5603a8d48 100644
--- a/depends/packages/native_cctools.mk
+++ b/depends/packages/native_cctools.mk
@@ -17,6 +17,10 @@ $(call fetch_file,$(package),$($(package)_clang_download_path),$($(package)_clan
endef
define $(package)_extract_cmds
+ mkdir -p $($(package)_extract_dir) && \
+ echo "$($(package)_sha256_hash) $($(package)_source)" > $($(package)_extract_dir)/.$($(package)_file_name).hash && \
+ echo "$($(package)_clang_sha256_hash) $($(package)_source_dir)/$($(package)_clang_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \
+ $(build_SHA256SUM) -c $($(package)_extract_dir)/.$($(package)_file_name).hash && \
mkdir -p toolchain/bin toolchain/lib/clang/3.5/include && \
tar --strip-components=1 -C toolchain -xf $($(package)_source_dir)/$($(package)_clang_file_name) && \
echo "#!/bin/sh" > toolchain/bin/$(host)-dsymutil && \
diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk
index 901b761fde..77df77b73f 100644
--- a/depends/packages/qt.mk
+++ b/depends/packages/qt.mk
@@ -108,8 +108,8 @@ endef
define $(package)_extract_cmds
mkdir -p $($(package)_extract_dir) && \
echo "$($(package)_sha256_hash) $($(package)_source)" > $($(package)_extract_dir)/.$($(package)_file_name).hash && \
- echo "$($(package)_qttranslations_sha256_hash) $($(package)_source_dir)/$($(package)_qttranslations_file_name)" > $($(package)_extract_dir)/.$($(package)_file_name).hash && \
- echo "$($(package)_qttools_sha256_hash) $($(package)_source_dir)/$($(package)_qttools_file_name)" > $($(package)_extract_dir)/.$($(package)_file_name).hash && \
+ echo "$($(package)_qttranslations_sha256_hash) $($(package)_source_dir)/$($(package)_qttranslations_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \
+ echo "$($(package)_qttools_sha256_hash) $($(package)_source_dir)/$($(package)_qttools_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \
$(build_SHA256SUM) -c $($(package)_extract_dir)/.$($(package)_file_name).hash && \
mkdir qtbase && \
tar --strip-components=1 -xf $($(package)_source) -C qtbase && \
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-osx.md b/doc/build-osx.md
index c3cb1b7891..296e0aa1f0 100644
--- a/doc/build-osx.md
+++ b/doc/build-osx.md
@@ -1,6 +1,6 @@
Mac OS X Build Instructions and Notes
====================================
-This guide will show you how to build bitcoind (headless client) for OS X.
+This guide will show you how to build Bitcoin Core for OS X.
Notes
-----
@@ -114,6 +114,16 @@ you can monitor its process by looking at the debug.log file, like this:
Other commands:
-------
- ./bitcoind -daemon # to start the bitcoin daemon.
+ ./bitcoind -daemon # to start the bitcoin daemon.
./bitcoin-cli --help # for a list of command-line options.
./bitcoin-cli help # When the daemon is running, to get a list of RPC commands
+
+Using Qt official installer while building
+------------------------------------------
+
+If you prefer to use the latest Qt installed from the official binary
+installer over the brew version, you have to make several changes to
+the installed tree and its binaries (all these changes are contained
+in the brew version already). The changes needed are described in
+[#7714](https://github.com/bitcoin/bitcoin/issues/7714). We do not
+support building Bitcoin Core this way though.
diff --git a/doc/build-unix.md b/doc/build-unix.md
index 5b519b8044..dc754fc733 100644
--- a/doc/build-unix.md
+++ b/doc/build-unix.md
@@ -248,3 +248,44 @@ Additional Configure Flags
A list of additional configure flags can be displayed with:
./configure --help
+
+
+Setup and Build Example: Arch Linux
+-----------------------------------
+This example lists the steps necessary to setup and build a command line only, non-wallet distribution of the latest changes on Arch Linux:
+
+ pacman -S git base-devel boost libevent python
+ git clone https://github.com/bitcoin/bitcoin.git
+ cd bitcoin/
+ ./autogen.sh
+ ./configure --disable-wallet --without-gui --without-miniupnpc
+ make check
+
+Note:
+Enabling wallet support requires either compiling against a Berkeley DB newer than 4.8 (package `db`) using `--with-incompatible-bdb`,
+or building and depending on a local version of Berkeley DB 4.8. The readily available Arch Linux packages are currently built using
+`--with-incompatible-bdb` according to the [PKGBUILD](https://projects.archlinux.org/svntogit/community.git/tree/bitcoin/trunk/PKGBUILD).
+As mentioned above, when maintaining portability of the wallet between the standard Bitcoin Core distributions and independently built
+node software is desired, Berkeley DB 4.8 must be used.
+
+
+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.
diff --git a/doc/developer-notes.md b/doc/developer-notes.md
index 358792251b..8affb2158a 100644
--- a/doc/developer-notes.md
+++ b/doc/developer-notes.md
@@ -71,6 +71,12 @@ To describe a member or variable use:
int var; //!< Detailed description after the member
```
+or
+```cpp
+//! Description before the member
+int var;
+```
+
Also OK:
```c++
///
diff --git a/doc/gitian-building.md b/doc/gitian-building.md
index 54993d13a9..3126218518 100644
--- a/doc/gitian-building.md
+++ b/doc/gitian-building.md
@@ -47,7 +47,7 @@ You can also install Gitian on actual hardware instead of using virtualization.
Create a new VirtualBox VM
---------------------------
-In the VirtualBox GUI click "Create" and choose the following parameters in the wizard:
+In the VirtualBox GUI click "New" and choose the following parameters in the wizard:
![](gitian-building/create_new_vm.png)
@@ -74,13 +74,6 @@ In the VirtualBox GUI click "Create" and choose the following parameters in the
- File location and size: at least 40GB; as low as 20GB *may* be possible, but better to err on the safe side
- Click `Create`
-Get the [Debian 8.x net installer](http://cdimage.debian.org/debian-cd/8.3.0/amd64/iso-cd/debian-8.3.0-amd64-netinst.iso) (a more recent minor version should also work, see also [Debian Network installation](https://www.debian.org/CD/netinst/)).
-This DVD image can be validated using a SHA256 hashing tool, for example on
-Unixy OSes by entering the following in a terminal:
-
- echo "dd25bcdde3c6ea5703cc0f313cde621b13d42ff7d252e2538a11663c93bf8654 debian-8.3.0-amd64-netinst.iso" | sha256sum -c
- # (must return OK)
-
After creating the VM, we need to configure it.
- Click the `Settings` button, then go to the `Network` tab. Adapter 1 should be attached to `NAT`.
@@ -102,6 +95,13 @@ After creating the VM, we need to configure it.
- Click `Ok` twice to save.
+Get the [Debian 8.x net installer](http://cdimage.debian.org/debian-cd/8.4.0/amd64/iso-cd/debian-8.4.0-amd64-netinst.iso) (a more recent minor version should also work, see also [Debian Network installation](https://www.debian.org/CD/netinst/)).
+This DVD image can be validated using a SHA256 hashing tool, for example on
+Unixy OSes by entering the following in a terminal:
+
+ echo "7a6b418e6a4ee3ca75dda04d79ed96c9e2c33bb0c703ca7e40c6374ab4590748 debian-8.4.0-amd64-netinst.iso" | sha256sum -c
+ # (must return OK)
+
Then start the VM. On the first launch you will be asked for a CD or DVD image. Choose the downloaded iso.
![](gitian-building/select_startup_disk.png)
@@ -160,6 +160,10 @@ To select a different button, press `Tab`.
![](gitian-building/debian_install_12_choose_disk.png)
+ - Partition Disks -> *All files in one partition*
+
+![](gitian-building/all_files_in_one_partition.png)
+
- Finish partitioning and write changes to disk -> *Yes* (`Tab`, `Enter` to select the `Yes` button)
![](gitian-building/debian_install_14_finish.png)
@@ -313,7 +317,7 @@ Setting up the Gitian image
-------------------------
Gitian needs a virtual image of the operating system to build in.
-Currently this is Ubuntu Precise x86_64.
+Currently this is Ubuntu Trusty x86_64.
This image will be copied and used every time that a build is started to
make sure that the build is deterministic.
Creating the image will take a while, but only has to be done once.
@@ -363,7 +367,7 @@ Output from `gbuild` will look something like
Resolving deltas: 100% (41590/41590), done.
From https://github.com/bitcoin/bitcoin
... (new tags, new branch etc)
- --- Building for precise amd64 ---
+ --- Building for trusty amd64 ---
Stopping target if it is up
Making a new image copy
stdin: is not a tty
@@ -412,14 +416,14 @@ So, if you use LXC:
export PATH="$PATH":/path/to/gitian-builder/libexec
export USE_LXC=1
cd /path/to/gitian-builder
-./libexec/make-clean-vm --suite precise --arch amd64
+./libexec/make-clean-vm --suite trusty --arch amd64
-LXC_ARCH=amd64 LXC_SUITE=precise on-target -u root apt-get update
-LXC_ARCH=amd64 LXC_SUITE=precise on-target -u root \
+LXC_ARCH=amd64 LXC_SUITE=trusty on-target -u root apt-get update
+LXC_ARCH=amd64 LXC_SUITE=trusty on-target -u root \
-e DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends -y install \
$( sed -ne '/^packages:/,/[^-] .*/ {/^- .*/{s/"//g;s/- //;p}}' ../bitcoin/contrib/gitian-descriptors/*|sort|uniq )
-LXC_ARCH=amd64 LXC_SUITE=precise on-target -u root apt-get -q -y purge grub
-LXC_ARCH=amd64 LXC_SUITE=precise on-target -u root -e DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade
+LXC_ARCH=amd64 LXC_SUITE=trusty on-target -u root apt-get -q -y purge grub
+LXC_ARCH=amd64 LXC_SUITE=trusty on-target -u root -e DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade
```
And then set offline mode for apt-cacher-ng:
diff --git a/doc/gitian-building/all_files_in_one_partition.png b/doc/gitian-building/all_files_in_one_partition.png
new file mode 100644
index 0000000000..8cbb0d8adc
--- /dev/null
+++ b/doc/gitian-building/all_files_in_one_partition.png
Binary files differ
diff --git a/doc/gitian-building/create_vm_file_location_size.png b/doc/gitian-building/create_vm_file_location_size.png
index 14aef5abae..5f77206b6f 100644
--- a/doc/gitian-building/create_vm_file_location_size.png
+++ b/doc/gitian-building/create_vm_file_location_size.png
Binary files differ
diff --git a/doc/gitian-building/select_startup_disk.png b/doc/gitian-building/select_startup_disk.png
index 5acdc3fe10..59bc093e2c 100644
--- a/doc/gitian-building/select_startup_disk.png
+++ b/doc/gitian-building/select_startup_disk.png
Binary files differ
diff --git a/doc/release-notes.md b/doc/release-notes.md
index 707f2357f8..7a673cc350 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -1,6 +1,21 @@
(note: this is a temporary file, to be added-to by anybody, and moved to
release-notes at release time)
+Bitcoin Core version *version* is now available from:
+
+ <https://bitcoin.org/bin/bitcoin-core-*version*/>
+
+This is a new major version release, including new features, various bugfixes
+and performance improvements, as well as updated translations.
+
+Please report bugs using the issue tracker at github:
+
+ <https://github.com/bitcoin/bitcoin/issues>
+
+To receive security and update notifications, please subscribe to:
+
+ <https://bitcoincore.org/en/list/announcements/join/>
+
Notable changes
===============
@@ -21,6 +36,13 @@ 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.
+RPC low-level changes
+----------------------
+
+- `gettxoutsetinfo` UTXO hash (`hash_serialized`) has changed. There was a divergence between
+ 32-bit and 64-bit platforms, and the txids were missing in the hashed data. This has been
+ fixed, but this means that the output will be different than from previous versions.
+
0.13.0 Change log
=================
@@ -45,12 +67,32 @@ The following outputs are affected by this change:
- REST `/rest/block/` (JSON format when including extended tx details)
- `bitcoin-tx -json`
+### ZMQ
+
+Each ZMQ notification now contains an up-counting sequence number that allows
+listeners to detect lost notifications.
+The sequence number is always the last element in a multi-part ZMQ notification and
+therefore backward compatible.
+Each message type has its own counter.
+(https://github.com/bitcoin/bitcoin/pull/7762)
+
### Configuration and command-line options
### Block and transaction handling
### 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-process.md b/doc/release-process.md
index 2c83896c22..34dead86bc 100644
--- a/doc/release-process.md
+++ b/doc/release-process.md
@@ -1,181 +1,228 @@
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)
+Before every release candidate:
+
+* Update translations (ping wumpus on IRC) see [translation_process.md](https://github.com/bitcoin/bitcoin/blob/master/doc/translation_process.md#syncing-with-transifex)
+
+Before every minor and major release:
+
* Update [bips.md](bips.md) to account for changes since the last release.
-* Update hardcoded [seeds](/contrib/seeds)
+* Update version in sources (see below)
+* Write release notes (see below)
+
+Before every major release:
-* * *
+* Update hardcoded [seeds](/contrib/seeds/README.md), see [this pull request](https://github.com/bitcoin/bitcoin/pull/7415) for an example.
+
+### First time / New builders
-###First time / New builders
Check out the source code in the following directory hierarchy.
- cd /path/to/your/toplevel/build
- git clone https://github.com/bitcoin/gitian.sigs.git
- git clone https://github.com/bitcoin/bitcoin-detached-sigs.git
- git clone https://github.com/devrandom/gitian-builder.git
- git clone https://github.com/bitcoin/bitcoin.git
+ cd /path/to/your/toplevel/build
+ git clone https://github.com/bitcoin/gitian.sigs.git
+ git clone https://github.com/bitcoin/bitcoin-detached-sigs.git
+ git clone https://github.com/devrandom/gitian-builder.git
+ git clone https://github.com/bitcoin/bitcoin.git
+
+### Bitcoin maintainers/release engineers, update version in sources
+
+Update the following:
+
+- `configure.ac`:
+ - `_CLIENT_VERSION_MAJOR`
+ - `_CLIENT_VERSION_MINOR`
+ - `_CLIENT_VERSION_REVISION`
+ - Don't forget to set `_CLIENT_VERSION_IS_RELEASE` to `true`
+- `src/clientversion.h`: (this mirrors `configure.ac` - see issue #3539)
+ - `CLIENT_VERSION_MAJOR`
+ - `CLIENT_VERSION_MINOR`
+ - `CLIENT_VERSION_REVISION`
+ - Don't forget to set `CLIENT_VERSION_IS_RELEASE` to `true`
+- `doc/README.md` and `doc/README_windows.txt`
+- `doc/Doxyfile`: `PROJECT_NUMBER` contains the full version
+- `contrib/gitian-descriptors/*.yml`: usually one'd want to do this on master after branching off the release - but be sure to at least do it before a new major release
-###Bitcoin maintainers/release engineers, update (commit) version in sources
+Write release notes. git shortlog helps a lot, for example:
- pushd ./bitcoin
- contrib/verifysfbinaries/verify.sh
- configure.ac
- doc/README*
- doc/Doxyfile
- contrib/gitian-descriptors/*.yml
- src/clientversion.h (change CLIENT_VERSION_IS_RELEASE to true)
+ git shortlog --no-merges v(current version, e.g. 0.7.2)..v(new version, e.g. 0.8.0)
- # tag version in git
+(or ping @wumpus on IRC, he has specific tooling to generate the list of merged pulls
+and sort them into categories based on labels)
- git tag -s v(new version, e.g. 0.8.0)
+Generate list of authors:
- # write release notes. git shortlog helps a lot, for example:
+ git log --format='%aN' "$*" | sort -ui | sed -e 's/^/- /'
- git shortlog --no-merges v(current version, e.g. 0.7.2)..v(new version, e.g. 0.8.0)
- popd
+Tag version (or release candidate) in git
-* * *
+ git tag -s v(new version, e.g. 0.8.0)
-###Setup and perform Gitian builds
+### Setup and perform Gitian builds
- Setup Gitian descriptors:
+Setup Gitian descriptors:
- pushd ./bitcoin
- export SIGNER=(your Gitian key, ie bluematt, sipa, etc)
- export VERSION=(new version, e.g. 0.8.0)
- git fetch
- git checkout v${VERSION}
- popd
+ pushd ./bitcoin
+ export SIGNER=(your Gitian key, ie bluematt, sipa, etc)
+ export VERSION=(new version, e.g. 0.8.0)
+ git fetch
+ git checkout v${VERSION}
+ popd
- Ensure your gitian.sigs are up-to-date if you wish to gverify your builds against other Gitian signatures.
+Ensure your gitian.sigs are up-to-date if you wish to gverify your builds against other Gitian signatures.
- pushd ./gitian.sigs
- git pull
- popd
+ pushd ./gitian.sigs
+ git pull
+ popd
- Ensure gitian-builder is up-to-date to take advantage of new caching features (`e9741525c` or later is recommended).
+Ensure gitian-builder is up-to-date to take advantage of new caching features (`e9741525c` or later is recommended).
- pushd ./gitian-builder
- git pull
+ pushd ./gitian-builder
+ git pull
+ popd
-###Fetch and create inputs: (first time, or when dependency versions change)
+### Fetch and create inputs: (first time, or when dependency versions change)
- mkdir -p inputs
- wget -P inputs https://bitcoincore.org/cfields/osslsigncode-Backports-to-1.7.1.patch
- wget -P inputs http://downloads.sourceforge.net/project/osslsigncode/osslsigncode/osslsigncode-1.7.1.tar.gz
+ pushd ./gitian-builder
+ mkdir -p inputs
+ wget -P inputs https://bitcoincore.org/cfields/osslsigncode-Backports-to-1.7.1.patch
+ wget -P inputs http://downloads.sourceforge.net/project/osslsigncode/osslsigncode/osslsigncode-1.7.1.tar.gz
+ popd
- Register and download the Apple SDK: see [OS X readme](README_osx.txt) for details.
+Register and download the Apple SDK: see [OS X readme](README_osx.txt) for details.
- https://developer.apple.com/devcenter/download.action?path=/Developer_Tools/xcode_6.1.1/xcode_6.1.1.dmg
+https://developer.apple.com/devcenter/download.action?path=/Developer_Tools/xcode_6.1.1/xcode_6.1.1.dmg
- Using a Mac, create a tarball for the 10.9 SDK and copy it to the inputs directory:
+Using a Mac, create a tarball for the 10.9 SDK and copy it to the inputs directory:
- tar -C /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.9.sdk.tar.gz MacOSX10.9.sdk
+ tar -C /Volumes/Xcode/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/ -czf MacOSX10.9.sdk.tar.gz MacOSX10.9.sdk
-###Optional: Seed the Gitian sources cache and offline git repositories
+### Optional: Seed the Gitian sources cache and offline git repositories
By default, Gitian will fetch source files as needed. To cache them ahead of time:
- make -C ../bitcoin/depends download SOURCES_PATH=`pwd`/cache/common
+ pushd ./gitian-builder
+ make -C ../bitcoin/depends download SOURCES_PATH=`pwd`/cache/common
+ popd
Only missing files will be fetched, so this is safe to re-run for each build.
NOTE: Offline builds must use the --url flag to ensure Gitian fetches only from local URLs. For example:
-```
-./bin/gbuild --url bitcoin=/path/to/bitcoin,signature=/path/to/sigs {rest of arguments}
-```
+
+ pushd ./gitian-builder
+ ./bin/gbuild --url bitcoin=/path/to/bitcoin,signature=/path/to/sigs {rest of arguments}
+ popd
+
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
+ pushd ./gitian-builder
+ ./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
+ ./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
+ ./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 ../
+ popd
- Build output expected:
+Build output expected:
- 1. source tarball (bitcoin-${VERSION}.tar.gz)
- 2. linux 32-bit and 64-bit dist tarballs (bitcoin-${VERSION}-linux[32|64].tar.gz)
- 3. windows 32-bit and 64-bit unsigned installers and dist zips (bitcoin-${VERSION}-win[32|64]-setup-unsigned.exe, bitcoin-${VERSION}-win[32|64].zip)
- 4. OS X unsigned installer and dist tarball (bitcoin-${VERSION}-osx-unsigned.dmg, bitcoin-${VERSION}-osx64.tar.gz)
- 5. Gitian signatures (in gitian.sigs/${VERSION}-<linux|{win,osx}-unsigned>/(your Gitian key)/
+ 1. source tarball (`bitcoin-${VERSION}.tar.gz`)
+ 2. linux 32-bit and 64-bit dist tarballs (`bitcoin-${VERSION}-linux[32|64].tar.gz`)
+ 3. windows 32-bit and 64-bit unsigned installers and dist zips (`bitcoin-${VERSION}-win[32|64]-setup-unsigned.exe`, `bitcoin-${VERSION}-win[32|64].zip`)
+ 4. OS X unsigned installer and dist tarball (`bitcoin-${VERSION}-osx-unsigned.dmg`, `bitcoin-${VERSION}-osx64.tar.gz`)
+ 5. Gitian signatures (in `gitian.sigs/${VERSION}-<linux|{win,osx}-unsigned>/(your Gitian key)/`)
-###Verify other gitian builders signatures to your own. (Optional)
+### Verify other gitian builders signatures to your own. (Optional)
- Add other gitian builders keys to your gpg keyring
+Add other gitian builders keys to your gpg keyring
- gpg --import ../bitcoin/contrib/gitian-downloader/*.pgp
+ gpg --import bitcoin/contrib/gitian-keys/*.pgp
- Verify the signatures
+Verify the signatures
- ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-linux ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml
- ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-win-unsigned ../bitcoin/contrib/gitian-descriptors/gitian-win.yml
- ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-osx-unsigned ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml
+ pushd ./gitian-builder
+ ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-linux ../bitcoin/contrib/gitian-descriptors/gitian-linux.yml
+ ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-win-unsigned ../bitcoin/contrib/gitian-descriptors/gitian-win.yml
+ ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-osx-unsigned ../bitcoin/contrib/gitian-descriptors/gitian-osx.yml
+ popd
- popd
-
-###Next steps:
+### Next steps:
Commit your signature to gitian.sigs:
- pushd gitian.sigs
- git add ${VERSION}-linux/${SIGNER}
- git add ${VERSION}-win-unsigned/${SIGNER}
- git add ${VERSION}-osx-unsigned/${SIGNER}
- git commit -a
- git push # Assuming you can push to the gitian.sigs tree
- 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.
-
- Create (and optionally verify) the signed OS X binary:
-
- pushd ./gitian-builder
- ./bin/gbuild -i --commit signature=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml
- ./bin/gsign --signer $SIGNER --release ${VERSION}-osx-signed --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml
- ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-osx-signed ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml
- mv build/out/bitcoin-osx-signed.dmg ../bitcoin-${VERSION}-osx.dmg
- popd
-
- Create (and optionally verify) the signed Windows binaries:
-
- pushd ./gitian-builder
- ./bin/gbuild -i --commit signature=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml
- ./bin/gsign --signer $SIGNER --release ${VERSION}-win-signed --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml
- ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-win-signed ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml
- mv build/out/bitcoin-*win64-setup.exe ../bitcoin-${VERSION}-win64-setup.exe
- mv build/out/bitcoin-*win32-setup.exe ../bitcoin-${VERSION}-win32-setup.exe
- popd
+ pushd gitian.sigs
+ git add ${VERSION}-linux/${SIGNER}
+ git add ${VERSION}-win-unsigned/${SIGNER}
+ git add ${VERSION}-osx-unsigned/${SIGNER}
+ git commit -a
+ git push # Assuming you can push to the gitian.sigs tree
+ popd
-Commit your signature for the signed OS X/Windows binaries:
+Wait for Windows/OS X detached signatures:
+
+- Once the Windows/OS X builds each have 3 matching signatures, they will be signed with their respective release keys.
+- Detached signatures will then be committed to the [bitcoin-detached-sigs](https://github.com/bitcoin/bitcoin-detached-sigs) repository, which can be combined with the unsigned apps to create signed binaries.
+
+Create (and optionally verify) the signed OS X binary:
- pushd gitian.sigs
- git add ${VERSION}-osx-signed/${SIGNER}
- git add ${VERSION}-win-signed/${SIGNER}
- git commit -a
- git push # Assuming you can push to the gitian.sigs tree
- popd
+ pushd ./gitian-builder
+ ./bin/gbuild -i --commit signature=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml
+ ./bin/gsign --signer $SIGNER --release ${VERSION}-osx-signed --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml
+ ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-osx-signed ../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml
+ mv build/out/bitcoin-osx-signed.dmg ../bitcoin-${VERSION}-osx.dmg
+ popd
--------------------------------------------------------------------------
+Create (and optionally verify) the signed Windows binaries:
+
+ pushd ./gitian-builder
+ ./bin/gbuild -i --commit signature=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml
+ ./bin/gsign --signer $SIGNER --release ${VERSION}-win-signed --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml
+ ./bin/gverify -v -d ../gitian.sigs/ -r ${VERSION}-win-signed ../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml
+ mv build/out/bitcoin-*win64-setup.exe ../bitcoin-${VERSION}-win64-setup.exe
+ mv build/out/bitcoin-*win32-setup.exe ../bitcoin-${VERSION}-win32-setup.exe
+ popd
+
+Commit your signature for the signed OS X/Windows binaries:
+
+ pushd gitian.sigs
+ git add ${VERSION}-osx-signed/${SIGNER}
+ git add ${VERSION}-win-signed/${SIGNER}
+ git commit -a
+ git push # Assuming you can push to the gitian.sigs tree
+ popd
### After 3 or more people have gitian-built and their results match:
- Create `SHA256SUMS.asc` for the builds, and GPG-sign it:
+
```bash
sha256sum * > SHA256SUMS
+```
+
+The list of files should be:
+```
+bitcoin-${VERSION}-linux32.tar.gz
+bitcoin-${VERSION}-linux64.tar.gz
+bitcoin-${VERSION}-osx64.tar.gz
+bitcoin-${VERSION}-osx.dmg
+bitcoin-${VERSION}.tar.gz
+bitcoin-${VERSION}-win32-setup.exe
+bitcoin-${VERSION}-win32.zip
+bitcoin-${VERSION}-win64-setup.exe
+bitcoin-${VERSION}-win64.zip
+```
+
+- GPG-sign it, delete the unsigned file:
+```
gpg --digest-algo sha256 --clearsign SHA256SUMS # outputs SHA256SUMS.asc
rm SHA256SUMS
```
@@ -185,6 +232,15 @@ Note: check that SHA256SUMS itself doesn't end up in SHA256SUMS, which is a spur
- Upload zips and installers, as well as `SHA256SUMS.asc` from last step, to the bitcoin.org server
into `/var/www/bin/bitcoin-core-${VERSION}`
+- A `.torrent` will appear in the directory after a few minutes. Optionally help seed this torrent. To get the `magnet:` URI use:
+```bash
+transmission-show -m <torrent file>
+```
+Insert the magnet URI into the announcement sent to mailing lists. This permits
+people without access to `bitcoin.org` to download the binary distribution.
+Also put it into the `optional_magnetlink:` slot in the YAML file for
+bitcoin.org (see below for bitcoin.org update instructions).
+
- Update bitcoin.org version
- First, check to see if the Bitcoin.org maintainers have prepared a
@@ -202,16 +258,18 @@ Note: check that SHA256SUMS itself doesn't end up in SHA256SUMS, which is a spur
- Announce the release:
- - Release sticky on bitcointalk: https://bitcointalk.org/index.php?board=1.0
+ - bitcoin-dev and bitcoin-core-dev mailing list
+
+ - Bitcoin Core announcements list https://bitcoincore.org/en/list/announcements/join/
- - Bitcoin-development mailing list
+ - bitcoincore.org blog post
- Update title of #bitcoin on Freenode IRC
- - Optionally reddit /r/Bitcoin, ... but this will usually sort out itself
+ - Optionally twitter, reddit /r/Bitcoin, ... but this will usually sort out itself
-- Notify BlueMatt so that he can start building [the PPAs](https://launchpad.net/~bitcoin/+archive/ubuntu/bitcoin)
+ - 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
+ - Add release notes for the new version to the directory `doc/release-notes` in git master
-- Celebrate
+ - Celebrate
diff --git a/doc/tor.md b/doc/tor.md
index be41255449..43e922718b 100644
--- a/doc/tor.md
+++ b/doc/tor.md
@@ -3,7 +3,7 @@ TOR SUPPORT IN BITCOIN
It is possible to run Bitcoin as a Tor hidden service, and connect to such services.
-The following directions assume you have a Tor proxy running on port 9050. Many distributions default to having a SOCKS proxy listening on port 9050, but others may not. In particular, the Tor Browser Bundle defaults to listening on a random port. See [Tor Project FAQ:TBBSocksPort](https://www.torproject.org/docs/faq.html.en#TBBSocksPort) for how to properly
+The following directions assume you have a Tor proxy running on port 9050. Many distributions default to having a SOCKS proxy listening on port 9050, but others may not. In particular, the Tor Browser Bundle defaults to listening on port 9150. See [Tor Project FAQ:TBBSocksPort](https://www.torproject.org/docs/faq.html.en#TBBSocksPort) for how to properly
configure Tor.
diff --git a/doc/zmq.md b/doc/zmq.md
index 902d1124c7..8d795a388a 100644
--- a/doc/zmq.md
+++ b/doc/zmq.md
@@ -99,3 +99,8 @@ using other means such as firewalling.
Note that when the block chain tip changes, a reorganisation may occur
and just the tip will be notified. It is up to the subscriber to
retrieve the chain from the last known block to the new tip.
+
+There are several possibilities that ZMQ notification can get lost
+during transmission depending on the communication type your are
+using. Bitcoind appends an up-counting sequence number to each
+notification which allows listeners to detect lost notifications.
diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py
index 485888e9b4..c0637209e3 100755
--- a/qa/pull-tester/rpc-tests.py
+++ b/qa/pull-tester/rpc-tests.py
@@ -32,23 +32,14 @@ import re
from tests_config import *
#If imported values are not defined then set to zero (or disabled)
-if not vars().has_key('ENABLE_WALLET'):
+if 'ENABLE_WALLET' not in vars():
ENABLE_WALLET=0
-if not vars().has_key('ENABLE_BITCOIND'):
+if 'ENABLE_BITCOIND' not in vars():
ENABLE_BITCOIND=0
-if not vars().has_key('ENABLE_UTILS'):
+if 'ENABLE_UTILS' not in vars():
ENABLE_UTILS=0
-if not vars().has_key('ENABLE_ZMQ'):
+if 'ENABLE_ZMQ' not in vars():
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
@@ -76,13 +67,28 @@ if "BITCOIND" not in os.environ:
if "BITCOINCLI" not in os.environ:
os.environ["BITCOINCLI"] = buildDir + '/src/bitcoin-cli' + EXEEXT
-#Disable Windows tests by default
if EXEEXT == ".exe" and "-win" not in opts:
- print "Win tests currently disabled. Use -win option to enable"
+ # https://github.com/bitcoin/bitcoin/commit/d52802551752140cf41f0d9a225a43e84404d3e9
+ # https://github.com/bitcoin/bitcoin/pull/5677#issuecomment-136646964
+ print "Win tests currently disabled by default. Use -win option to enable"
+ sys.exit(0)
+
+if not (ENABLE_WALLET == 1 and ENABLE_UTILS == 1 and ENABLE_BITCOIND == 1):
+ print "No rpc tests to run. Wallet, utils, and bitcoind must all be enabled"
sys.exit(0)
+# python-zmq may not be installed. Handle this gracefully and with some helpful info
+if ENABLE_ZMQ:
+ try:
+ import zmq
+ except ImportError as e:
+ print("ERROR: \"import zmq\" failed. Set ENABLE_ZMQ=0 or " \
+ "to run zmq tests, see dependency info in /qa/README.md.")
+ raise e
+
#Tests
testScripts = [
+ 'bip68-112-113-p2p.py',
'wallet.py',
'listtransactions.py',
'receivedby.py',
@@ -115,8 +121,14 @@ testScripts = [
'invalidblockrequest.py',
'invalidtxrequest.py',
'abandonconflict.py',
+ 'p2p-versionbits-warning.py',
+ 'importprunedfunds.py',
]
+if ENABLE_ZMQ:
+ testScripts.append('zmq_test.py')
+
testScriptsExt = [
+ 'bip9-softforks.py',
'bip65-cltv.py',
'bip65-cltv-p2p.py',
'bip68-sequence.py',
@@ -126,7 +138,6 @@ testScriptsExt = [
'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
@@ -136,13 +147,10 @@ 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
-if ENABLE_ZMQ == 1:
- testScripts.append('zmq_test.py')
-
-
def runtests():
coverage = None
@@ -150,53 +158,49 @@ def runtests():
coverage = RPCCoverage()
print("Initializing coverage directory at %s\n" % coverage.dir)
- if(ENABLE_WALLET == 1 and ENABLE_UTILS == 1 and ENABLE_BITCOIND == 1):
- rpcTestDir = buildDir + '/qa/rpc-tests/'
- run_extended = '-extended' in opts
- cov_flag = coverage.flag if coverage else ''
- flags = " --srcdir %s/src %s %s" % (buildDir, cov_flag, passOn)
-
- #Run Tests
- for i in range(len(testScripts)):
- if (len(opts) == 0
- or (len(opts) == 1 and "-win" in opts )
- or run_extended
- or testScripts[i] in opts
- or re.sub(".py$", "", testScripts[i]) in opts ):
-
- print("Running testscript %s%s%s ..." % (bold[1], testScripts[i], bold[0]))
- time0 = time.time()
- subprocess.check_call(
- rpcTestDir + testScripts[i] + flags, shell=True)
- print("Duration: %s s\n" % (int(time.time() - time0)))
-
- # exit if help is called so we print just one set of
- # instructions
- p = re.compile(" -h| --help")
- if p.match(passOn):
- sys.exit(0)
-
- # Run Extended Tests
- for i in range(len(testScriptsExt)):
- if (run_extended or testScriptsExt[i] in opts
- or re.sub(".py$", "", testScriptsExt[i]) in opts):
-
- print(
- "Running 2nd level testscript "
- + "%s%s%s ..." % (bold[1], testScriptsExt[i], bold[0]))
- time0 = time.time()
- subprocess.check_call(
- rpcTestDir + testScriptsExt[i] + flags, shell=True)
- print("Duration: %s s\n" % (int(time.time() - time0)))
-
- if coverage:
- coverage.report_rpc_coverage()
-
- print("Cleaning up coverage data")
- coverage.cleanup()
-
- else:
- print "No rpc tests to run. Wallet, utils, and bitcoind must all be enabled"
+ rpcTestDir = buildDir + '/qa/rpc-tests/'
+ run_extended = '-extended' in opts
+ cov_flag = coverage.flag if coverage else ''
+ flags = " --srcdir %s/src %s %s" % (buildDir, cov_flag, passOn)
+
+ #Run Tests
+ for i in range(len(testScripts)):
+ if (len(opts) == 0
+ or (len(opts) == 1 and "-win" in opts )
+ or run_extended
+ or testScripts[i] in opts
+ or re.sub(".py$", "", testScripts[i]) in opts ):
+
+ print("Running testscript %s%s%s ..." % (bold[1], testScripts[i], bold[0]))
+ time0 = time.time()
+ subprocess.check_call(
+ rpcTestDir + testScripts[i] + flags, shell=True)
+ print("Duration: %s s\n" % (int(time.time() - time0)))
+
+ # exit if help is called so we print just one set of
+ # instructions
+ p = re.compile(" -h| --help")
+ if p.match(passOn):
+ sys.exit(0)
+
+ # Run Extended Tests
+ for i in range(len(testScriptsExt)):
+ if (run_extended or testScriptsExt[i] in opts
+ or re.sub(".py$", "", testScriptsExt[i]) in opts):
+
+ print(
+ "Running 2nd level testscript "
+ + "%s%s%s ..." % (bold[1], testScriptsExt[i], bold[0]))
+ time0 = time.time()
+ subprocess.check_call(
+ rpcTestDir + testScriptsExt[i] + flags, shell=True)
+ print("Duration: %s s\n" % (int(time.time() - time0)))
+
+ if coverage:
+ coverage.report_rpc_coverage()
+
+ print("Cleaning up coverage data")
+ coverage.cleanup()
class RPCCoverage(object):
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/bip65-cltv-p2p.py b/qa/rpc-tests/bip65-cltv-p2p.py
index bbd518cf5f..99d74344ae 100755
--- a/qa/rpc-tests/bip65-cltv-p2p.py
+++ b/qa/rpc-tests/bip65-cltv-p2p.py
@@ -10,8 +10,7 @@ from test_framework.mininode import CTransaction, NetworkThread
from test_framework.blocktools import create_coinbase, create_block
from test_framework.comptool import TestInstance, TestManager
from test_framework.script import CScript, OP_1NEGATE, OP_CHECKLOCKTIMEVERIFY, OP_DROP
-from binascii import unhexlify
-import cStringIO
+from io import BytesIO
import time
def cltv_invalidate(tx):
@@ -60,7 +59,7 @@ class BIP65Test(ComparisonTestFramework):
rawtx = node.createrawtransaction(inputs, outputs)
signresult = node.signrawtransaction(rawtx)
tx = CTransaction()
- f = cStringIO.StringIO(unhexlify(signresult['hex']))
+ f = BytesIO(hex_str_to_bytes(signresult['hex']))
tx.deserialize(f)
return tx
@@ -70,7 +69,7 @@ class BIP65Test(ComparisonTestFramework):
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()
+ self.last_block_time = int(time.time())
''' 98 more version 3 blocks '''
test_blocks = []
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..3bcfdabe26
--- /dev/null
+++ b/qa/rpc-tests/bip68-112-113-p2p.py
@@ -0,0 +1,539 @@
+#!/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 io import BytesIO
+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 = BytesIO(hex_str_to_bytes(rawtx))
+ tx.deserialize(f)
+ return tx
+
+ def sign_transaction(self, node, unsignedtx):
+ rawtx = ToHex(unsignedtx)
+ signresult = node.signrawtransaction(rawtx)
+ tx = CTransaction()
+ f = BytesIO(hex_str_to_bytes(signresult['hex']))
+ tx.deserialize(f)
+ return tx
+
+ def generate_blocks(self, number, version, test_blocks = []):
+ for i in xrange(number):
+ block = self.create_test_block([], version)
+ test_blocks.append([block, True])
+ self.last_block_time += 600
+ self.tip = block.sha256
+ self.tipheight += 1
+ return test_blocks
+
+ def create_test_block(self, txs, version = 536870912):
+ block = create_block(self.tip, create_coinbase(self.tipheight + 1), self.last_block_time + 600)
+ block.nVersion = version
+ block.vtx.extend(txs)
+ block.hashMerkleRoot = block.calc_merkle_root()
+ block.rehash()
+ block.solve()
+ return block
+
+ def create_bip68txs(self, bip68inputs, txversion, locktime_delta = 0):
+ txs = []
+ assert(len(bip68inputs) >= 16)
+ i = 0
+ for b31 in xrange(2):
+ b25txs = []
+ for b25 in xrange(2):
+ b22txs = []
+ for b22 in xrange(2):
+ b18txs = []
+ for b18 in xrange(2):
+ tx = self.create_transaction(self.nodes[0], bip68inputs[i], self.nodeaddress, Decimal("49.98"))
+ i += 1
+ tx.nVersion = txversion
+ tx.vin[0].nSequence = relative_locktimes[b31][b25][b22][b18] + locktime_delta
+ b18txs.append(self.sign_transaction(self.nodes[0], tx))
+ b22txs.append(b18txs)
+ b25txs.append(b22txs)
+ txs.append(b25txs)
+ return txs
+
+ def create_bip112special(self, input, txversion):
+ tx = self.create_transaction(self.nodes[0], input, self.nodeaddress, Decimal("49.98"))
+ tx.nVersion = txversion
+ signtx = self.sign_transaction(self.nodes[0], tx)
+ signtx.vin[0].scriptSig = CScript([-1, OP_NOP3, OP_DROP] + list(CScript(signtx.vin[0].scriptSig)))
+ return signtx
+
+ def create_bip112txs(self, bip112inputs, varyOP_CSV, txversion, locktime_delta = 0):
+ txs = []
+ assert(len(bip112inputs) >= 16)
+ i = 0
+ for b31 in xrange(2):
+ b25txs = []
+ for b25 in xrange(2):
+ b22txs = []
+ for b22 in xrange(2):
+ b18txs = []
+ for b18 in xrange(2):
+ tx = self.create_transaction(self.nodes[0], bip112inputs[i], self.nodeaddress, Decimal("49.98"))
+ i += 1
+ if (varyOP_CSV): # if varying OP_CSV, nSequence is fixed
+ tx.vin[0].nSequence = base_relative_locktime + locktime_delta
+ else: # vary nSequence instead, OP_CSV is fixed
+ tx.vin[0].nSequence = relative_locktimes[b31][b25][b22][b18] + locktime_delta
+ tx.nVersion = txversion
+ signtx = self.sign_transaction(self.nodes[0], tx)
+ if (varyOP_CSV):
+ signtx.vin[0].scriptSig = CScript([relative_locktimes[b31][b25][b22][b18], OP_NOP3, OP_DROP] + list(CScript(signtx.vin[0].scriptSig)))
+ else:
+ signtx.vin[0].scriptSig = CScript([base_relative_locktime, OP_NOP3, OP_DROP] + list(CScript(signtx.vin[0].scriptSig)))
+ b18txs.append(signtx)
+ b22txs.append(b18txs)
+ b25txs.append(b22txs)
+ txs.append(b25txs)
+ return txs
+
+ def get_tests(self):
+ long_past_time = int(time.time()) - 600 * 1000 # enough to build up to 1000 blocks 10 minutes apart without worrying about getting into the future
+ self.nodes[0].setmocktime(long_past_time - 100) # enough so that the generated blocks will still all be before long_past_time
+ self.coinbase_blocks = self.nodes[0].generate(1 + 16 + 2*32 + 1) # 82 blocks generated for inputs
+ self.nodes[0].setmocktime(0) # set time back to present so yielded blocks aren't in the future as we advance last_block_time
+ self.tipheight = 82 # height of the next block to build
+ self.last_block_time = long_past_time
+ self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0)
+ self.nodeaddress = self.nodes[0].getnewaddress()
+
+ assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'defined')
+ test_blocks = self.generate_blocks(61, 4)
+ yield TestInstance(test_blocks, sync_every_block=False) # 1
+ # Advanced from DEFINED to STARTED, height = 143
+ assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'started')
+
+ # Fail to achieve LOCKED_IN 100 out of 144 signal bit 0
+ # using a variety of bits to simulate multiple parallel softforks
+ test_blocks = self.generate_blocks(50, 536870913) # 0x20000001 (signalling ready)
+ test_blocks = self.generate_blocks(20, 4, test_blocks) # 0x00000004 (signalling not)
+ test_blocks = self.generate_blocks(50, 536871169, test_blocks) # 0x20000101 (signalling ready)
+ test_blocks = self.generate_blocks(24, 536936448, test_blocks) # 0x20010000 (signalling not)
+ yield TestInstance(test_blocks, sync_every_block=False) # 2
+ # Failed to advance past STARTED, height = 287
+ assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'started')
+
+ # 108 out of 144 signal bit 0 to achieve lock-in
+ # using a variety of bits to simulate multiple parallel softforks
+ test_blocks = self.generate_blocks(58, 536870913) # 0x20000001 (signalling ready)
+ test_blocks = self.generate_blocks(26, 4, test_blocks) # 0x00000004 (signalling not)
+ test_blocks = self.generate_blocks(50, 536871169, test_blocks) # 0x20000101 (signalling ready)
+ test_blocks = self.generate_blocks(10, 536936448, test_blocks) # 0x20010000 (signalling not)
+ yield TestInstance(test_blocks, sync_every_block=False) # 3
+ # Advanced from STARTED to LOCKED_IN, height = 431
+ assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'locked_in')
+
+ # 140 more version 4 blocks
+ test_blocks = self.generate_blocks(140, 4)
+ yield TestInstance(test_blocks, sync_every_block=False) # 4
+
+ ### Inputs at height = 572
+ # Put inputs for all tests in the chain at height 572 (tip now = 571) (time increases by 600s per block)
+ # Note we reuse inputs for v1 and v2 txs so must test these separately
+ # 16 normal inputs
+ bip68inputs = []
+ for i in xrange(16):
+ bip68inputs.append(self.send_generic_input_tx(self.nodes[0], self.coinbase_blocks))
+ # 2 sets of 16 inputs with 10 OP_CSV OP_DROP (actually will be prepended to spending scriptSig)
+ bip112basicinputs = []
+ for j in xrange(2):
+ inputs = []
+ for i in xrange(16):
+ inputs.append(self.send_generic_input_tx(self.nodes[0], self.coinbase_blocks))
+ bip112basicinputs.append(inputs)
+ # 2 sets of 16 varied inputs with (relative_lock_time) OP_CSV OP_DROP (actually will be prepended to spending scriptSig)
+ bip112diverseinputs = []
+ for j in xrange(2):
+ inputs = []
+ for i in xrange(16):
+ inputs.append(self.send_generic_input_tx(self.nodes[0], self.coinbase_blocks))
+ bip112diverseinputs.append(inputs)
+ # 1 special input with -1 OP_CSV OP_DROP (actually will be prepended to spending scriptSig)
+ bip112specialinput = self.send_generic_input_tx(self.nodes[0], self.coinbase_blocks)
+ # 1 normal input
+ bip113input = self.send_generic_input_tx(self.nodes[0], self.coinbase_blocks)
+
+ self.nodes[0].setmocktime(self.last_block_time + 600)
+ inputblockhash = self.nodes[0].generate(1)[0] # 1 block generated for inputs to be in chain at height 572
+ self.nodes[0].setmocktime(0)
+ self.tip = int("0x" + inputblockhash + "L", 0)
+ self.tipheight += 1
+ self.last_block_time += 600
+ assert_equal(len(self.nodes[0].getblock(inputblockhash,True)["tx"]), 82+1)
+
+ # 2 more version 4 blocks
+ test_blocks = self.generate_blocks(2, 4)
+ yield TestInstance(test_blocks, sync_every_block=False) # 5
+ # Not yet advanced to ACTIVE, height = 574 (will activate for block 576, not 575)
+ assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'locked_in')
+
+ # Test both version 1 and version 2 transactions for all tests
+ # BIP113 test transaction will be modified before each use to put in appropriate block time
+ bip113tx_v1 = self.create_transaction(self.nodes[0], bip113input, self.nodeaddress, Decimal("49.98"))
+ bip113tx_v1.vin[0].nSequence = 0xFFFFFFFE
+ bip113tx_v2 = self.create_transaction(self.nodes[0], bip113input, self.nodeaddress, Decimal("49.98"))
+ bip113tx_v2.vin[0].nSequence = 0xFFFFFFFE
+ bip113tx_v2.nVersion = 2
+
+ # For BIP68 test all 16 relative sequence locktimes
+ bip68txs_v1 = self.create_bip68txs(bip68inputs, 1)
+ bip68txs_v2 = self.create_bip68txs(bip68inputs, 2)
+
+ # For BIP112 test:
+ # 16 relative sequence locktimes of 10 against 10 OP_CSV OP_DROP inputs
+ bip112txs_vary_nSequence_v1 = self.create_bip112txs(bip112basicinputs[0], False, 1)
+ bip112txs_vary_nSequence_v2 = self.create_bip112txs(bip112basicinputs[0], False, 2)
+ # 16 relative sequence locktimes of 9 against 10 OP_CSV OP_DROP inputs
+ bip112txs_vary_nSequence_9_v1 = self.create_bip112txs(bip112basicinputs[1], False, 1, -1)
+ bip112txs_vary_nSequence_9_v2 = self.create_bip112txs(bip112basicinputs[1], False, 2, -1)
+ # sequence lock time of 10 against 16 (relative_lock_time) OP_CSV OP_DROP inputs
+ bip112txs_vary_OP_CSV_v1 = self.create_bip112txs(bip112diverseinputs[0], True, 1)
+ bip112txs_vary_OP_CSV_v2 = self.create_bip112txs(bip112diverseinputs[0], True, 2)
+ # sequence lock time of 9 against 16 (relative_lock_time) OP_CSV OP_DROP inputs
+ bip112txs_vary_OP_CSV_9_v1 = self.create_bip112txs(bip112diverseinputs[1], True, 1, -1)
+ bip112txs_vary_OP_CSV_9_v2 = self.create_bip112txs(bip112diverseinputs[1], True, 2, -1)
+ # -1 OP_CSV OP_DROP input
+ bip112tx_special_v1 = self.create_bip112special(bip112specialinput, 1)
+ bip112tx_special_v2 = self.create_bip112special(bip112specialinput, 2)
+
+
+ ### TESTING ###
+ ##################################
+ ### Before Soft Forks Activate ###
+ ##################################
+ # All txs should pass
+ ### Version 1 txs ###
+ success_txs = []
+ # add BIP113 tx and -1 CSV tx
+ bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
+ bip113signed1 = self.sign_transaction(self.nodes[0], bip113tx_v1)
+ success_txs.append(bip113signed1)
+ success_txs.append(bip112tx_special_v1)
+ # add BIP 68 txs
+ success_txs.extend(all_rlt_txs(bip68txs_v1))
+ # add BIP 112 with seq=10 txs
+ success_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_v1))
+ success_txs.extend(all_rlt_txs(bip112txs_vary_OP_CSV_v1))
+ # try BIP 112 with seq=9 txs
+ success_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_9_v1))
+ success_txs.extend(all_rlt_txs(bip112txs_vary_OP_CSV_9_v1))
+ yield TestInstance([[self.create_test_block(success_txs), True]]) # 6
+ self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
+
+ ### Version 2 txs ###
+ success_txs = []
+ # add BIP113 tx and -1 CSV tx
+ bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
+ bip113signed2 = self.sign_transaction(self.nodes[0], bip113tx_v2)
+ success_txs.append(bip113signed2)
+ success_txs.append(bip112tx_special_v2)
+ # add BIP 68 txs
+ success_txs.extend(all_rlt_txs(bip68txs_v2))
+ # add BIP 112 with seq=10 txs
+ success_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_v2))
+ success_txs.extend(all_rlt_txs(bip112txs_vary_OP_CSV_v2))
+ # try BIP 112 with seq=9 txs
+ success_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_9_v2))
+ success_txs.extend(all_rlt_txs(bip112txs_vary_OP_CSV_9_v2))
+ yield TestInstance([[self.create_test_block(success_txs), True]]) # 7
+ self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
+
+
+ # 1 more version 4 block to get us to height 575 so the fork should now be active for the next block
+ test_blocks = self.generate_blocks(1, 4)
+ yield TestInstance(test_blocks, sync_every_block=False) # 8
+ assert_equal(get_bip9_status(self.nodes[0], 'csv')['status'], 'active')
+
+
+ #################################
+ ### After Soft Forks Activate ###
+ #################################
+ ### BIP 113 ###
+ # BIP 113 tests should now fail regardless of version number if nLockTime isn't satisfied by new rules
+ bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
+ bip113signed1 = self.sign_transaction(self.nodes[0], bip113tx_v1)
+ bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 # = MTP of prior block (not <) but < time put on current block
+ bip113signed2 = self.sign_transaction(self.nodes[0], bip113tx_v2)
+ for bip113tx in [bip113signed1, bip113signed2]:
+ yield TestInstance([[self.create_test_block([bip113tx]), False]]) # 9,10
+ # BIP 113 tests should now pass if the locktime is < MTP
+ bip113tx_v1.nLockTime = self.last_block_time - 600 * 5 - 1 # < MTP of prior block
+ bip113signed1 = self.sign_transaction(self.nodes[0], bip113tx_v1)
+ bip113tx_v2.nLockTime = self.last_block_time - 600 * 5 - 1 # < MTP of prior block
+ bip113signed2 = self.sign_transaction(self.nodes[0], bip113tx_v2)
+ for bip113tx in [bip113signed1, bip113signed2]:
+ yield TestInstance([[self.create_test_block([bip113tx]), True]]) # 11,12
+ self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
+
+ # Next block height = 580 after 4 blocks of random version
+ test_blocks = self.generate_blocks(4, 1234)
+ yield TestInstance(test_blocks, sync_every_block=False) # 13
+
+ ### BIP 68 ###
+ ### Version 1 txs ###
+ # All still pass
+ success_txs = []
+ success_txs.extend(all_rlt_txs(bip68txs_v1))
+ yield TestInstance([[self.create_test_block(success_txs), True]]) # 14
+ self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
+
+ ### Version 2 txs ###
+ bip68success_txs = []
+ # All txs with SEQUENCE_LOCKTIME_DISABLE_FLAG set pass
+ for b25 in xrange(2):
+ for b22 in xrange(2):
+ for b18 in xrange(2):
+ bip68success_txs.append(bip68txs_v2[1][b25][b22][b18])
+ yield TestInstance([[self.create_test_block(bip68success_txs), True]]) # 15
+ self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
+ # All txs without flag fail as we are at delta height = 8 < 10 and delta time = 8 * 600 < 10 * 512
+ bip68timetxs = []
+ for b25 in xrange(2):
+ for b18 in xrange(2):
+ bip68timetxs.append(bip68txs_v2[0][b25][1][b18])
+ for tx in bip68timetxs:
+ yield TestInstance([[self.create_test_block([tx]), False]]) # 16 - 19
+ bip68heighttxs = []
+ for b25 in xrange(2):
+ for b18 in xrange(2):
+ bip68heighttxs.append(bip68txs_v2[0][b25][0][b18])
+ for tx in bip68heighttxs:
+ yield TestInstance([[self.create_test_block([tx]), False]]) # 20 - 23
+
+ # Advance one block to 581
+ test_blocks = self.generate_blocks(1, 1234)
+ yield TestInstance(test_blocks, sync_every_block=False) # 24
+
+ # Height txs should fail and time txs should now pass 9 * 600 > 10 * 512
+ bip68success_txs.extend(bip68timetxs)
+ yield TestInstance([[self.create_test_block(bip68success_txs), True]]) # 25
+ self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
+ for tx in bip68heighttxs:
+ yield TestInstance([[self.create_test_block([tx]), False]]) # 26 - 29
+
+ # Advance one block to 582
+ test_blocks = self.generate_blocks(1, 1234)
+ yield TestInstance(test_blocks, sync_every_block=False) # 30
+
+ # All BIP 68 txs should pass
+ bip68success_txs.extend(bip68heighttxs)
+ yield TestInstance([[self.create_test_block(bip68success_txs), True]]) # 31
+ self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
+
+
+ ### BIP 112 ###
+ ### Version 1 txs ###
+ # -1 OP_CSV tx should fail
+ yield TestInstance([[self.create_test_block([bip112tx_special_v1]), False]]) #32
+ # If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in argument to OP_CSV, version 1 txs should still pass
+ success_txs = []
+ for b25 in xrange(2):
+ for b22 in xrange(2):
+ for b18 in xrange(2):
+ success_txs.append(bip112txs_vary_OP_CSV_v1[1][b25][b22][b18])
+ success_txs.append(bip112txs_vary_OP_CSV_9_v1[1][b25][b22][b18])
+ yield TestInstance([[self.create_test_block(success_txs), True]]) # 33
+ self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
+
+ # If SEQUENCE_LOCKTIME_DISABLE_FLAG is unset in argument to OP_CSV, version 1 txs should now fail
+ fail_txs = []
+ fail_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_v1))
+ fail_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_9_v1))
+ for b25 in xrange(2):
+ for b22 in xrange(2):
+ for b18 in xrange(2):
+ fail_txs.append(bip112txs_vary_OP_CSV_v1[0][b25][b22][b18])
+ fail_txs.append(bip112txs_vary_OP_CSV_9_v1[0][b25][b22][b18])
+
+ for tx in fail_txs:
+ yield TestInstance([[self.create_test_block([tx]), False]]) # 34 - 81
+
+ ### Version 2 txs ###
+ # -1 OP_CSV tx should fail
+ yield TestInstance([[self.create_test_block([bip112tx_special_v2]), False]]) #82
+
+ # If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in argument to OP_CSV, version 2 txs should pass (all sequence locks are met)
+ success_txs = []
+ for b25 in xrange(2):
+ for b22 in xrange(2):
+ for b18 in xrange(2):
+ success_txs.append(bip112txs_vary_OP_CSV_v2[1][b25][b22][b18]) # 8/16 of vary_OP_CSV
+ success_txs.append(bip112txs_vary_OP_CSV_9_v2[1][b25][b22][b18]) # 8/16 of vary_OP_CSV_9
+
+ yield TestInstance([[self.create_test_block(success_txs), True]]) # 83
+ self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
+
+ ## SEQUENCE_LOCKTIME_DISABLE_FLAG is unset in argument to OP_CSV for all remaining txs ##
+ # All txs with nSequence 9 should fail either due to earlier mismatch or failing the CSV check
+ fail_txs = []
+ fail_txs.extend(all_rlt_txs(bip112txs_vary_nSequence_9_v2)) # 16/16 of vary_nSequence_9
+ for b25 in xrange(2):
+ for b22 in xrange(2):
+ for b18 in xrange(2):
+ fail_txs.append(bip112txs_vary_OP_CSV_9_v2[0][b25][b22][b18]) # 16/16 of vary_OP_CSV_9
+
+ for tx in fail_txs:
+ yield TestInstance([[self.create_test_block([tx]), False]]) # 84 - 107
+
+ # If SEQUENCE_LOCKTIME_DISABLE_FLAG is set in nSequence, tx should fail
+ fail_txs = []
+ for b25 in xrange(2):
+ for b22 in xrange(2):
+ for b18 in xrange(2):
+ fail_txs.append(bip112txs_vary_nSequence_v2[1][b25][b22][b18]) # 8/16 of vary_nSequence
+ for tx in fail_txs:
+ yield TestInstance([[self.create_test_block([tx]), False]]) # 108-115
+
+ # If sequencelock types mismatch, tx should fail
+ fail_txs = []
+ for b25 in xrange(2):
+ for b18 in xrange(2):
+ fail_txs.append(bip112txs_vary_nSequence_v2[0][b25][1][b18]) # 12/16 of vary_nSequence
+ fail_txs.append(bip112txs_vary_OP_CSV_v2[0][b25][1][b18]) # 12/16 of vary_OP_CSV
+ for tx in fail_txs:
+ yield TestInstance([[self.create_test_block([tx]), False]]) # 116-123
+
+ # Remaining txs should pass, just test masking works properly
+ success_txs = []
+ for b25 in xrange(2):
+ for b18 in xrange(2):
+ success_txs.append(bip112txs_vary_nSequence_v2[0][b25][0][b18]) # 16/16 of vary_nSequence
+ success_txs.append(bip112txs_vary_OP_CSV_v2[0][b25][0][b18]) # 16/16 of vary_OP_CSV
+ yield TestInstance([[self.create_test_block(success_txs), True]]) # 124
+ self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
+
+ # Additional test, of checking that comparison of two time types works properly
+ time_txs = []
+ for b25 in xrange(2):
+ for b18 in xrange(2):
+ tx = bip112txs_vary_OP_CSV_v2[0][b25][1][b18]
+ tx.vin[0].nSequence = base_relative_locktime | seq_type_flag
+ signtx = self.sign_transaction(self.nodes[0], tx)
+ time_txs.append(signtx)
+ yield TestInstance([[self.create_test_block(time_txs), True]]) # 125
+ self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
+
+ ### Missing aspects of test
+ ## Testing empty stack fails
+
+
+if __name__ == '__main__':
+ BIP68_112_113Test().main()
diff --git a/qa/rpc-tests/bip68-sequence.py b/qa/rpc-tests/bip68-sequence.py
index bd61282fa1..33e05dfc51 100755
--- a/qa/rpc-tests/bip68-sequence.py
+++ b/qa/rpc-tests/bip68-sequence.py
@@ -4,7 +4,7 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
#
-# Test BIP68 implementation (mempool only)
+# Test BIP68 implementation
#
from test_framework.test_framework import BitcoinTestFramework
@@ -13,7 +13,6 @@ from test_framework.script import *
from test_framework.mininode import *
from test_framework.blocktools import *
-COIN = 100000000
SEQUENCE_LOCKTIME_DISABLE_FLAG = (1<<31)
SEQUENCE_LOCKTIME_TYPE_FLAG = (1<<22) # this means use time (0 means height)
SEQUENCE_LOCKTIME_GRANULARITY = 9 # this is a bit-shift
@@ -27,8 +26,10 @@ class BIP68Test(BitcoinTestFramework):
def setup_network(self):
self.nodes = []
self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-blockprioritysize=0"]))
+ self.nodes.append(start_node(1, self.options.tmpdir, ["-debug", "-blockprioritysize=0", "-acceptnonstdtxn=0"]))
self.is_network_split = False
self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"]
+ connect_nodes(self.nodes[0], 1)
def run_test(self):
# Generate some coins
@@ -43,10 +44,18 @@ class BIP68Test(BitcoinTestFramework):
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"
+ print "Running test BIP68 not consensus before versionbits activation"
self.test_bip68_not_consensus()
+ print "Verifying nVersion=2 transactions aren't standard"
+ self.test_version2_relay(before_activation=True)
+
+ print "Activating BIP68 (and 112/113)"
+ self.activateCSV()
+
+ print "Verifying nVersion=2 transactions are now standard"
+ self.test_version2_relay(before_activation=False)
+
print "Passed\n"
# Test that BIP68 is not in effect if tx version is 1, or if
@@ -62,7 +71,7 @@ class BIP68Test(BitcoinTestFramework):
utxo = utxos[0]
tx1 = CTransaction()
- value = satoshi_round(utxo["amount"] - self.relayfee)*COIN
+ value = int(satoshi_round(utxo["amount"] - self.relayfee)*COIN)
# Check that the disable flag disables relative locktime.
# If sequence locks were used, this would require 1 block for the
@@ -180,8 +189,8 @@ class BIP68Test(BitcoinTestFramework):
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'])))
+ tx_size = len(ToHex(tx))//2 + 120*num_inputs + 50
+ tx.vout.append(CTxOut(int(value-self.relayfee*tx_size*COIN/1000), CScript([b'a'])))
rawtx = self.nodes[0].signrawtransaction(ToHex(tx))["hex"]
try:
@@ -334,8 +343,12 @@ class BIP68Test(BitcoinTestFramework):
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.
+ # Make sure that BIP68 isn't being used to validate blocks, prior to
+ # versionbits activation. If more blocks are mined prior to this test
+ # being run, then it's possible the test has activated the soft fork, and
+ # this test should be moved to run earlier, or deleted.
def test_bip68_not_consensus(self):
+ assert(get_bip9_status(self.nodes[0], 'csv')['status'] != 'active')
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 2)
tx1 = FromHex(CTransaction(), self.nodes[0].getrawtransaction(txid))
@@ -382,6 +395,30 @@ class BIP68Test(BitcoinTestFramework):
self.nodes[0].submitblock(ToHex(block))
assert_equal(self.nodes[0].getbestblockhash(), block.hash)
+ def activateCSV(self):
+ # activation should happen at block height 432 (3 periods)
+ min_activation_height = 432
+ height = self.nodes[0].getblockcount()
+ assert(height < 432)
+ self.nodes[0].generate(432-height)
+ assert(get_bip9_status(self.nodes[0], 'csv')['status'] == 'active')
+ sync_blocks(self.nodes)
+
+ # Use self.nodes[1] to test standardness relay policy
+ def test_version2_relay(self, before_activation):
+ inputs = [ ]
+ outputs = { self.nodes[1].getnewaddress() : 1.0 }
+ rawtx = self.nodes[1].createrawtransaction(inputs, outputs)
+ rawtxfund = self.nodes[1].fundrawtransaction(rawtx)['hex']
+ tx = FromHex(CTransaction(), rawtxfund)
+ tx.nVersion = 2
+ tx_signed = self.nodes[1].signrawtransaction(ToHex(tx))["hex"]
+ try:
+ tx_id = self.nodes[1].sendrawtransaction(tx_signed)
+ assert(before_activation == False)
+ except:
+ assert(before_activation)
+
if __name__ == '__main__':
BIP68Test().main()
diff --git a/qa/rpc-tests/bip9-softforks.py b/qa/rpc-tests/bip9-softforks.py
new file mode 100755
index 0000000000..ddca3c2e33
--- /dev/null
+++ b/qa/rpc-tests/bip9-softforks.py
@@ -0,0 +1,213 @@
+#!/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 io import BytesIO
+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 = BytesIO(hex_str_to_bytes(rawtx))
+ tx.deserialize(f)
+ tx.nVersion = 2
+ return tx
+
+ def sign_transaction(self, node, tx):
+ signresult = node.signrawtransaction(bytes_to_hex_str(tx.serialize()))
+ tx = CTransaction()
+ f = BytesIO(hex_str_to_bytes(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()
+ return info['bip9_softforks'][key]
+
+ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignature):
+ # generate some coins for later
+ self.coinbase_blocks = self.nodes[0].generate(2)
+ self.height = 3 # height of the next block to build
+ self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0)
+ self.nodeaddress = self.nodes[0].getnewaddress()
+ self.last_block_time = int(time.time())
+
+ assert_equal(self.get_bip9_status(bipName)['status'], 'defined')
+
+ # Test 1
+ # Advance from DEFINED to STARTED
+ test_blocks = self.generate_blocks(141, 4)
+ yield TestInstance(test_blocks, sync_every_block=False)
+
+ assert_equal(self.get_bip9_status(bipName)['status'], 'started')
+
+ # Test 2
+ # Fail to achieve LOCKED_IN 100 out of 144 signal bit 1
+ # using a variety of bits to simulate multiple parallel softforks
+ test_blocks = self.generate_blocks(50, activated_version) # 0x20000001 (signalling ready)
+ test_blocks = self.generate_blocks(20, 4, test_blocks) # 0x00000004 (signalling not)
+ test_blocks = self.generate_blocks(50, activated_version, test_blocks) # 0x20000101 (signalling ready)
+ test_blocks = self.generate_blocks(24, 4, test_blocks) # 0x20010000 (signalling not)
+ yield TestInstance(test_blocks, sync_every_block=False)
+
+ assert_equal(self.get_bip9_status(bipName)['status'], 'started')
+
+ # Test 3
+ # 108 out of 144 signal bit 1 to achieve LOCKED_IN
+ # using a variety of bits to simulate multiple parallel softforks
+ test_blocks = self.generate_blocks(58, activated_version) # 0x20000001 (signalling ready)
+ test_blocks = self.generate_blocks(26, 4, test_blocks) # 0x00000004 (signalling not)
+ test_blocks = self.generate_blocks(50, activated_version, test_blocks) # 0x20000101 (signalling ready)
+ test_blocks = self.generate_blocks(10, 4, test_blocks) # 0x20010000 (signalling not)
+ yield TestInstance(test_blocks, sync_every_block=False)
+
+ assert_equal(self.get_bip9_status(bipName)['status'], 'locked_in')
+
+ # Test 4
+ # 143 more version 536870913 blocks (waiting period-1)
+ test_blocks = self.generate_blocks(143, 4)
+ yield TestInstance(test_blocks, sync_every_block=False)
+
+ assert_equal(self.get_bip9_status(bipName)['status'], 'locked_in')
+
+ # Test 5
+ # Check that the new rule is enforced
+ spendtx = self.create_transaction(self.nodes[0],
+ self.coinbase_blocks[0], self.nodeaddress, 1.0)
+ invalidate(spendtx)
+ spendtx = self.sign_transaction(self.nodes[0], spendtx)
+ spendtx.rehash()
+ invalidatePostSignature(spendtx)
+ spendtx.rehash()
+ block = create_block(self.tip, create_coinbase(self.height), self.last_block_time + 1)
+ block.nVersion = activated_version
+ block.vtx.append(spendtx)
+ block.hashMerkleRoot = block.calc_merkle_root()
+ block.rehash()
+ block.solve()
+
+ self.last_block_time += 1
+ self.tip = block.sha256
+ self.height += 1
+ yield TestInstance([[block, True]])
+
+ assert_equal(self.get_bip9_status(bipName)['status'], 'active')
+
+ # Test 6
+ # Check that the new sequence lock rules are enforced
+ spendtx = self.create_transaction(self.nodes[0],
+ self.coinbase_blocks[1], self.nodeaddress, 1.0)
+ invalidate(spendtx)
+ spendtx = self.sign_transaction(self.nodes[0], spendtx)
+ spendtx.rehash()
+ invalidatePostSignature(spendtx)
+ spendtx.rehash()
+
+ block = create_block(self.tip, create_coinbase(self.height), self.last_block_time + 1)
+ block.nVersion = 5
+ block.vtx.append(spendtx)
+ block.hashMerkleRoot = block.calc_merkle_root()
+ block.rehash()
+ block.solve()
+ self.last_block_time += 1
+ yield TestInstance([[block, False]])
+
+ # Restart all
+ stop_nodes(self.nodes)
+ wait_bitcoinds()
+ shutil.rmtree(self.options.tmpdir)
+ self.setup_chain()
+ self.setup_network()
+ self.test.clear_all_connections()
+ self.test.add_all_connections(self.nodes)
+ NetworkThread().start() # Start up network handling in another thread
+
+
+ def get_tests(self):
+ for test in itertools.chain(
+ self.test_BIP('csv', 536870913, self.sequence_lock_invalidate, self.donothing),
+ self.test_BIP('csv', 536870913, self.mtp_invalidate, self.donothing),
+ self.test_BIP('csv', 536870913, self.donothing, self.csv_invalidate)
+ ):
+ yield test
+
+ def donothing(self, tx):
+ return
+
+ def csv_invalidate(self, tx):
+ '''Modify the signature in vin 0 of the tx to fail CSV
+ Prepends -1 CSV DROP in the scriptSig itself.
+ '''
+ tx.vin[0].scriptSig = CScript([OP_1NEGATE, OP_NOP3, OP_DROP] +
+ list(CScript(tx.vin[0].scriptSig)))
+
+ def sequence_lock_invalidate(self, tx):
+ '''Modify the nSequence to make it fails once sequence lock rule is activated (high timespan)
+ '''
+ tx.vin[0].nSequence = 0x00FFFFFF
+ tx.nLockTime = 0
+
+ def mtp_invalidate(self, tx):
+ '''Modify the nLockTime to make it fails once MTP rule is activated
+ '''
+ # Disable Sequence lock, Activate nLockTime
+ tx.vin[0].nSequence = 0x90FFFFFF
+ tx.nLockTime = self.last_block_time
+
+if __name__ == '__main__':
+ BIP9SoftForksTest().main()
diff --git a/qa/rpc-tests/bipdersig-p2p.py b/qa/rpc-tests/bipdersig-p2p.py
index 544e4a9670..bba86a50c4 100755
--- a/qa/rpc-tests/bipdersig-p2p.py
+++ b/qa/rpc-tests/bipdersig-p2p.py
@@ -10,8 +10,7 @@ from test_framework.mininode import CTransaction, NetworkThread
from test_framework.blocktools import create_coinbase, create_block
from test_framework.comptool import TestInstance, TestManager
from test_framework.script import CScript
-from binascii import unhexlify
-import cStringIO
+from io import BytesIO
import time
# A canonical signature consists of:
@@ -25,7 +24,7 @@ def unDERify(tx):
newscript = []
for i in scriptSig:
if (len(newscript) == 0):
- newscript.append(i[0:-1] + '\0' + i[-1])
+ newscript.append(i[0:-1] + b'\0' + i[-1:])
else:
newscript.append(i)
tx.vin[0].scriptSig = CScript(newscript)
@@ -68,7 +67,7 @@ class BIP66Test(ComparisonTestFramework):
rawtx = node.createrawtransaction(inputs, outputs)
signresult = node.signrawtransaction(rawtx)
tx = CTransaction()
- f = cStringIO.StringIO(unhexlify(signresult['hex']))
+ f = BytesIO(hex_str_to_bytes(signresult['hex']))
tx.deserialize(f)
return tx
@@ -78,7 +77,7 @@ class BIP66Test(ComparisonTestFramework):
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()
+ self.last_block_time = int(time.time())
''' 98 more version 2 blocks '''
test_blocks = []
diff --git a/qa/rpc-tests/blockchain.py b/qa/rpc-tests/blockchain.py
index 7045ae435c..8f59ee741c 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]
@@ -80,6 +82,7 @@ class BlockchainTest(BitcoinTestFramework):
assert isinstance(header['mediantime'], int)
assert isinstance(header['nonce'], int)
assert isinstance(header['version'], int)
+ assert isinstance(int(header['versionHex'], 16), int)
assert isinstance(header['difficulty'], Decimal)
if __name__ == '__main__':
diff --git a/qa/rpc-tests/decodescript.py b/qa/rpc-tests/decodescript.py
index 490808d49d..578844f2c5 100755
--- a/qa/rpc-tests/decodescript.py
+++ b/qa/rpc-tests/decodescript.py
@@ -6,8 +6,7 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
from test_framework.mininode import *
-from binascii import hexlify, unhexlify
-from cStringIO import StringIO
+from io import BytesIO
class DecodeScriptTest(BitcoinTestFramework):
"""Tests decoding scripts via RPC command "decodescript"."""
@@ -131,7 +130,7 @@ class DecodeScriptTest(BitcoinTestFramework):
assert_equal('OP_DUP OP_HASH160 dc863734a218bfe83ef770ee9d41a27f824a6e56 OP_EQUALVERIFY OP_CHECKSIG', rpc_result['vout'][0]['scriptPubKey']['asm'])
assert_equal('OP_HASH160 2a5edea39971049a540474c6a99edf0aa4074c58 OP_EQUAL', rpc_result['vout'][1]['scriptPubKey']['asm'])
txSave = CTransaction()
- txSave.deserialize(StringIO(unhexlify(tx)))
+ txSave.deserialize(BytesIO(hex_str_to_bytes(tx)))
# make sure that a specifically crafted op_return value will not pass all the IsDERSignature checks and then get decoded as a sighash type
tx = '01000000015ded05872fdbda629c7d3d02b194763ce3b9b1535ea884e3c8e765d42e316724020000006b48304502204c10d4064885c42638cbff3585915b322de33762598321145ba033fc796971e2022100bb153ad3baa8b757e30a2175bd32852d2e1cb9080f84d7e32fcdfd667934ef1b012103163c0ff73511ea1743fb5b98384a2ff09dd06949488028fd819f4d83f56264efffffffff0200000000000000000b6a0930060201000201000180380100000000001976a9141cabd296e753837c086da7a45a6c2fe0d49d7b7b88ac00000000'
@@ -147,7 +146,7 @@ class DecodeScriptTest(BitcoinTestFramework):
# some more full transaction tests of varying specific scriptSigs. used instead of
# tests in decodescript_script_sig because the decodescript RPC is specifically
# for working on scriptPubKeys (argh!).
- push_signature = hexlify(txSave.vin[0].scriptSig)[2:(0x48*2+4)]
+ push_signature = bytes_to_hex_str(txSave.vin[0].scriptSig)[2:(0x48*2+4)]
signature = push_signature[2:]
der_signature = signature[:-2]
signature_sighash_decoded = der_signature + '[ALL]'
@@ -156,25 +155,24 @@ class DecodeScriptTest(BitcoinTestFramework):
signature_2_sighash_decoded = der_signature + '[NONE|ANYONECANPAY]'
# 1) P2PK scriptSig
- txSave.vin[0].scriptSig = unhexlify(push_signature)
- rpc_result = self.nodes[0].decoderawtransaction(hexlify(txSave.serialize()))
+ txSave.vin[0].scriptSig = hex_str_to_bytes(push_signature)
+ rpc_result = self.nodes[0].decoderawtransaction(bytes_to_hex_str(txSave.serialize()))
assert_equal(signature_sighash_decoded, rpc_result['vin'][0]['scriptSig']['asm'])
# make sure that the sighash decodes come out correctly for a more complex / lesser used case.
- txSave.vin[0].scriptSig = unhexlify(push_signature_2)
- rpc_result = self.nodes[0].decoderawtransaction(hexlify(txSave.serialize()))
+ txSave.vin[0].scriptSig = hex_str_to_bytes(push_signature_2)
+ rpc_result = self.nodes[0].decoderawtransaction(bytes_to_hex_str(txSave.serialize()))
assert_equal(signature_2_sighash_decoded, rpc_result['vin'][0]['scriptSig']['asm'])
# 2) multisig scriptSig
- txSave.vin[0].scriptSig = unhexlify('00' + push_signature + push_signature_2)
- rpc_result = self.nodes[0].decoderawtransaction(hexlify(txSave.serialize()))
+ txSave.vin[0].scriptSig = hex_str_to_bytes('00' + push_signature + push_signature_2)
+ rpc_result = self.nodes[0].decoderawtransaction(bytes_to_hex_str(txSave.serialize()))
assert_equal('0 ' + signature_sighash_decoded + ' ' + signature_2_sighash_decoded, rpc_result['vin'][0]['scriptSig']['asm'])
# 3) test a scriptSig that contains more than push operations.
# in fact, it contains an OP_RETURN with data specially crafted to cause improper decode if the code does not catch it.
- txSave.vin[0].scriptSig = unhexlify('6a143011020701010101010101020601010101010101')
- rpc_result = self.nodes[0].decoderawtransaction(hexlify(txSave.serialize()))
- print(hexlify('636174'))
+ txSave.vin[0].scriptSig = hex_str_to_bytes('6a143011020701010101010101020601010101010101')
+ rpc_result = self.nodes[0].decoderawtransaction(bytes_to_hex_str(txSave.serialize()))
assert_equal('OP_RETURN 3011020701010101010101020601010101010101', rpc_result['vin'][0]['scriptSig']['asm'])
def run_test(self):
diff --git a/qa/rpc-tests/disablewallet.py b/qa/rpc-tests/disablewallet.py
index 6964348d55..cb868029fa 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 as 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 as 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..496c7fe8b0 100755
--- a/qa/rpc-tests/fundrawtransaction.py
+++ b/qa/rpc-tests/fundrawtransaction.py
@@ -48,7 +48,7 @@ class RawTransactionsTest(BitcoinTestFramework):
watchonly_address = self.nodes[0].getnewaddress()
watchonly_pubkey = self.nodes[0].validateaddress(watchonly_address)["pubkey"]
- watchonly_amount = 200
+ watchonly_amount = Decimal(200)
self.nodes[3].importpubkey(watchonly_pubkey, "", True)
watchonly_txid = self.nodes[0].sendtoaddress(watchonly_address, watchonly_amount)
self.nodes[0].sendtoaddress(self.nodes[3].getnewaddress(), watchonly_amount / 10)
@@ -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 }
@@ -148,7 +148,6 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(fee + totalOut, utx['amount']) #compare vin total and totalout+fee
-
#####################################################################
# test a fundrawtransaction with which will not get a change output #
#####################################################################
@@ -159,7 +158,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 }
@@ -178,6 +177,82 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(fee + totalOut, utx['amount']) #compare vin total and totalout+fee
+ ####################################################
+ # test a fundrawtransaction with an invalid option #
+ ####################################################
+ utx = False
+ listunspent = self.nodes[2].listunspent()
+ for aUtx in listunspent:
+ if aUtx['amount'] == 5.0:
+ utx = aUtx
+ break
+
+ assert_equal(utx!=False, True)
+
+ inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ]
+ outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) }
+ rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
+ dec_tx = self.nodes[2].decoderawtransaction(rawtx)
+ assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
+
+ try:
+ self.nodes[2].fundrawtransaction(rawtx, {'foo': 'bar'})
+ raise AssertionError("Accepted invalid option foo")
+ except JSONRPCException,e:
+ assert("Unexpected key foo" in e.error['message'])
+
+
+ ############################################################
+ # test a fundrawtransaction with an invalid change address #
+ ############################################################
+ utx = False
+ listunspent = self.nodes[2].listunspent()
+ for aUtx in listunspent:
+ if aUtx['amount'] == 5.0:
+ utx = aUtx
+ break
+
+ assert_equal(utx!=False, True)
+
+ inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ]
+ outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) }
+ rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
+ dec_tx = self.nodes[2].decoderawtransaction(rawtx)
+ assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
+
+ try:
+ self.nodes[2].fundrawtransaction(rawtx, {'changeAddress': 'foobar'})
+ raise AssertionError("Accepted invalid bitcoin address")
+ except JSONRPCException,e:
+ assert("changeAddress must be a valid bitcoin address" in e.error['message'])
+
+
+
+ ############################################################
+ # test a fundrawtransaction with a provided change address #
+ ############################################################
+ utx = False
+ listunspent = self.nodes[2].listunspent()
+ for aUtx in listunspent:
+ if aUtx['amount'] == 5.0:
+ utx = aUtx
+ break
+
+ assert_equal(utx!=False, True)
+
+ inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ]
+ outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) }
+ rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
+ dec_tx = self.nodes[2].decoderawtransaction(rawtx)
+ assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
+
+ change = self.nodes[2].getnewaddress()
+ rawtxfund = self.nodes[2].fundrawtransaction(rawtx, {'changeAddress': change, 'changePosition': 0})
+ dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
+ out = dec_tx['vout'][0];
+ assert_equal(change, out['scriptPubKey']['addresses'][0])
+
+
#########################################################################
# test a fundrawtransaction with a VIN smaller than the required amount #
@@ -189,7 +264,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 }
@@ -209,7 +284,7 @@ class RawTransactionsTest(BitcoinTestFramework):
matchingOuts = 0
for i, out in enumerate(dec_tx['vout']):
totalOut += out['value']
- if outputs.has_key(out['scriptPubKey']['addresses'][0]):
+ if out['scriptPubKey']['addresses'][0] in outputs:
matchingOuts+=1
else:
assert_equal(i, rawtxfund['changepos'])
@@ -234,7 +309,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 }
@@ -249,7 +324,7 @@ class RawTransactionsTest(BitcoinTestFramework):
matchingOuts = 0
for out in dec_tx['vout']:
totalOut += out['value']
- if outputs.has_key(out['scriptPubKey']['addresses'][0]):
+ if out['scriptPubKey']['addresses'][0] in outputs:
matchingOuts+=1
assert_equal(matchingOuts, 1)
@@ -276,7 +351,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 }
@@ -291,7 +366,7 @@ class RawTransactionsTest(BitcoinTestFramework):
matchingOuts = 0
for out in dec_tx['vout']:
totalOut += out['value']
- if outputs.has_key(out['scriptPubKey']['addresses'][0]):
+ if out['scriptPubKey']['addresses'][0] in outputs:
matchingOuts+=1
assert_equal(matchingOuts, 2)
@@ -306,14 +381,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)
- except JSONRPCException,e:
- errorString = e.error['message']
-
- assert("Insufficient" in errorString)
-
+ raise AssertionError("Spent more than available")
+ except JSONRPCException as e:
+ assert("Insufficient" in e.error['message'])
############################################################
@@ -462,12 +534,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()
@@ -488,7 +559,6 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(oldBalance+Decimal('51.10000000'), self.nodes[0].getbalance())
-
###############################################
# multiple (~19) inputs tx test | Compare fee #
###############################################
@@ -575,12 +645,12 @@ class RawTransactionsTest(BitcoinTestFramework):
outputs = {self.nodes[2].getnewaddress() : watchonly_amount / 2}
rawtx = self.nodes[3].createrawtransaction(inputs, outputs)
- result = self.nodes[3].fundrawtransaction(rawtx, True)
+ result = self.nodes[3].fundrawtransaction(rawtx, {'includeWatching': True })
res_dec = self.nodes[0].decoderawtransaction(result["hex"])
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)
###############################################################
@@ -591,6 +661,7 @@ class RawTransactionsTest(BitcoinTestFramework):
outputs = {self.nodes[2].getnewaddress() : watchonly_amount}
rawtx = self.nodes[3].createrawtransaction(inputs, outputs)
+ # Backward compatibility test (2nd param is includeWatching)
result = self.nodes[3].fundrawtransaction(rawtx, True)
res_dec = self.nodes[0].decoderawtransaction(result["hex"])
assert_equal(len(res_dec["vin"]), 2)
diff --git a/qa/rpc-tests/getblocktemplate_longpoll.py b/qa/rpc-tests/getblocktemplate_longpoll.py
index 3e85957ae2..e2a839f718 100755
--- a/qa/rpc-tests/getblocktemplate_longpoll.py
+++ b/qa/rpc-tests/getblocktemplate_longpoll.py
@@ -6,28 +6,6 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-
-def check_array_result(object_array, to_match, expected):
- """
- Pass in array of JSON objects, a dictionary with key/value pairs
- to match against, and another dictionary with expected key/value
- pairs.
- """
- num_matched = 0
- for item in object_array:
- all_match = True
- for key,value in to_match.items():
- if item[key] != value:
- all_match = False
- if not all_match:
- continue
- for key,value in expected.items():
- if item[key] != value:
- raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value)))
- num_matched = num_matched+1
- if num_matched == 0:
- raise AssertionError("No objects matched %s"%(str(to_match)))
-
import threading
class LongpollThread(threading.Thread):
diff --git a/qa/rpc-tests/getblocktemplate_proposals.py b/qa/rpc-tests/getblocktemplate_proposals.py
index f83b5f140d..be119031ba 100755
--- a/qa/rpc-tests/getblocktemplate_proposals.py
+++ b/qa/rpc-tests/getblocktemplate_proposals.py
@@ -10,28 +10,6 @@ from binascii import a2b_hex, b2a_hex
from hashlib import sha256
from struct import pack
-
-def check_array_result(object_array, to_match, expected):
- """
- Pass in array of JSON objects, a dictionary with key/value pairs
- to match against, and another dictionary with expected key/value
- pairs.
- """
- num_matched = 0
- for item in object_array:
- all_match = True
- for key,value in to_match.items():
- if item[key] != value:
- all_match = False
- if not all_match:
- continue
- for key,value in expected.items():
- if item[key] != value:
- raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value)))
- num_matched = num_matched+1
- if num_matched == 0:
- raise AssertionError("No objects matched %s"%(str(to_match)))
-
def b2x(b):
return b2a_hex(b).decode('ascii')
@@ -120,10 +98,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)
@@ -133,7 +108,7 @@ class GetBlockTemplateProposalTest(BitcoinTestFramework):
# Test 5: Add an invalid tx to the end (non-duplicate)
txlist.append(bytearray(txlist[0]))
- txlist[-1][4+1] = b'\xff'
+ txlist[-1][4+1] = 0xff
assert_template(node, tmpl, txlist, 'bad-txns-inputs-missingorspent')
txlist.pop()
@@ -144,10 +119,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..cf37976a4e 100755
--- a/qa/rpc-tests/httpbasics.py
+++ b/qa/rpc-tests/httpbasics.py
@@ -9,7 +9,6 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-import base64
try:
import http.client as httplib
@@ -31,71 +30,71 @@ class HTTPBasicsTest (BitcoinTestFramework):
#################################################
url = urlparse.urlparse(self.nodes[0].url)
authpair = url.username + ':' + url.password
- headers = {"Authorization": "Basic " + base64.b64encode(authpair)}
+ headers = {"Authorization": "Basic " + str_to_b64str(authpair)}
conn = httplib.HTTPConnection(url.hostname, url.port)
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(b'"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!
+ out1 = conn.getresponse().read()
+ assert(b'"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
- headers = {"Authorization": "Basic " + base64.b64encode(authpair), "Connection": "keep-alive"}
+ headers = {"Authorization": "Basic " + str_to_b64str(authpair), "Connection": "keep-alive"}
conn = httplib.HTTPConnection(url.hostname, url.port)
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(b'"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!
+ out1 = conn.getresponse().read()
+ assert(b'"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"
- headers = {"Authorization": "Basic " + base64.b64encode(authpair), "Connection":"close"}
+ headers = {"Authorization": "Basic " + str_to_b64str(authpair), "Connection":"close"}
conn = httplib.HTTPConnection(url.hostname, url.port)
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(b'"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)
authpair = urlNode1.username + ':' + urlNode1.password
- headers = {"Authorization": "Basic " + base64.b64encode(authpair)}
+ headers = {"Authorization": "Basic " + str_to_b64str(authpair)}
conn = httplib.HTTPConnection(urlNode1.hostname, urlNode1.port)
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
out1 = conn.getresponse().read()
- assert_equal('"error":null' in out1, True)
+ assert(b'"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)
authpair = urlNode2.username + ':' + urlNode2.password
- headers = {"Authorization": "Basic " + base64.b64encode(authpair)}
+ headers = {"Authorization": "Basic " + str_to_b64str(authpair)}
conn = httplib.HTTPConnection(urlNode2.hostname, urlNode2.port)
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(b'"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..a9324196ee
--- /dev/null
+++ b/qa/rpc-tests/importprunedfunds.py
@@ -0,0 +1,142 @@
+#!/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 as e:
+ assert('No addresses' in e.error['message'])
+ else:
+ assert(False)
+
+
+ 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 as e:
+ assert('does not exist' in e.error['message'])
+ else:
+ assert(False)
+
+
+ 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..de6be8d5b5 100755
--- a/qa/rpc-tests/invalidblockrequest.py
+++ b/qa/rpc-tests/invalidblockrequest.py
@@ -77,9 +77,9 @@ class InvalidBlockRequestTest(ComparisonTestFramework):
block2 = create_block(self.tip, create_coinbase(height), self.block_time)
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)
+ # b'0x51' is OP_TRUE
+ tx1 = create_transaction(self.block1.vtx[0], 0, b'\x51', 50 * COIN)
+ tx2 = create_transaction(tx1, 0, b'\x51', 50 * COIN)
block2.vtx.extend([tx1, tx2])
block2.hashMerkleRoot = block2.calc_merkle_root()
@@ -95,7 +95,7 @@ class InvalidBlockRequestTest(ComparisonTestFramework):
assert(block2_orig.vtx != block2.vtx)
self.tip = block2.sha256
- yield TestInstance([[block2, RejectResult(16,'bad-txns-duplicate')], [block2_orig, True]])
+ yield TestInstance([[block2, RejectResult(16, b'bad-txns-duplicate')], [block2_orig, True]])
height += 1
'''
@@ -103,14 +103,14 @@ 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()
block3.rehash()
block3.solve()
- yield TestInstance([[block3, RejectResult(16,'bad-cb-amount')]])
+ yield TestInstance([[block3, RejectResult(16, b'bad-cb-amount')]])
if __name__ == '__main__':
diff --git a/qa/rpc-tests/invalidtxrequest.py b/qa/rpc-tests/invalidtxrequest.py
index c2fe4f1dff..7b8199bab0 100755
--- a/qa/rpc-tests/invalidtxrequest.py
+++ b/qa/rpc-tests/invalidtxrequest.py
@@ -61,10 +61,10 @@ class InvalidTxRequestTest(ComparisonTestFramework):
height += 1
yield test
- # chr(100) is OP_NOTIF
+ # b'\x64' 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)
- yield TestInstance([[tx1, RejectResult(16, 'mandatory-script-verify-flag-failed')]])
+ tx1 = create_transaction(self.block1.vtx[0], 0, b'\x64', 50 * COIN - 12000)
+ yield TestInstance([[tx1, RejectResult(16, b'mandatory-script-verify-flag-failed')]])
# TODO: test further transactions...
diff --git a/qa/rpc-tests/keypool.py b/qa/rpc-tests/keypool.py
index 95d0d6832a..b86c085e00 100755
--- a/qa/rpc-tests/keypool.py
+++ b/qa/rpc-tests/keypool.py
@@ -10,28 +10,6 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-
-def check_array_result(object_array, to_match, expected):
- """
- Pass in array of JSON objects, a dictionary with key/value pairs
- to match against, and another dictionary with expected key/value
- pairs.
- """
- num_matched = 0
- for item in object_array:
- all_match = True
- for key,value in to_match.items():
- if item[key] != value:
- all_match = False
- if not all_match:
- continue
- for key,value in expected.items():
- if item[key] != value:
- raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value)))
- num_matched = num_matched+1
- if num_matched == 0:
- raise AssertionError("No objects matched %s"%(str(to_match)))
-
class KeyPoolTest(BitcoinTestFramework):
def run_test(self):
@@ -46,7 +24,7 @@ class KeyPoolTest(BitcoinTestFramework):
try:
addr = nodes[0].getnewaddress()
raise AssertionError('Keypool should be exhausted after one address')
- except JSONRPCException,e:
+ except JSONRPCException as e:
assert(e.error['code']==-12)
# put three new keys in the keypool
@@ -66,7 +44,7 @@ class KeyPoolTest(BitcoinTestFramework):
try:
addr = nodes[0].getrawchangeaddress()
raise AssertionError('Keypool should be exhausted after three addresses')
- except JSONRPCException,e:
+ except JSONRPCException as e:
assert(e.error['code']==-12)
# refill keypool with three new addresses
@@ -84,7 +62,7 @@ class KeyPoolTest(BitcoinTestFramework):
try:
nodes[0].generate(1)
raise AssertionError('Keypool should be exhausted after three addesses')
- except JSONRPCException,e:
+ except JSONRPCException as e:
assert(e.error['code']==-12)
def setup_chain(self):
diff --git a/qa/rpc-tests/listtransactions.py b/qa/rpc-tests/listtransactions.py
index 45ede8f040..4e5809f4a7 100755
--- a/qa/rpc-tests/listtransactions.py
+++ b/qa/rpc-tests/listtransactions.py
@@ -7,37 +7,15 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-from test_framework.mininode import CTransaction
-import cStringIO
-import binascii
+from test_framework.mininode import CTransaction, COIN
+from io import BytesIO
def txFromHex(hexstring):
tx = CTransaction()
- f = cStringIO.StringIO(binascii.unhexlify(hexstring))
+ f = BytesIO(hex_str_to_bytes(hexstring))
tx.deserialize(f)
return tx
-def check_array_result(object_array, to_match, expected):
- """
- Pass in array of JSON objects, a dictionary with key/value pairs
- to match against, and another dictionary with expected key/value
- pairs.
- """
- num_matched = 0
- for item in object_array:
- all_match = True
- for key,value in to_match.items():
- if item[key] != value:
- all_match = False
- if not all_match:
- continue
- for key,value in expected.items():
- if item[key] != value:
- raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value)))
- num_matched = num_matched+1
- if num_matched == 0:
- raise AssertionError("No objects matched %s"%(str(to_match)))
-
class ListTransactionsTest(BitcoinTestFramework):
def setup_nodes(self):
@@ -49,28 +27,28 @@ class ListTransactionsTest(BitcoinTestFramework):
# Simple send, 0 to 1:
txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
self.sync_all()
- check_array_result(self.nodes[0].listtransactions(),
+ assert_array_result(self.nodes[0].listtransactions(),
{"txid":txid},
{"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":0})
- check_array_result(self.nodes[1].listtransactions(),
+ assert_array_result(self.nodes[1].listtransactions(),
{"txid":txid},
{"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":0})
# mine a block, confirmations should change:
self.nodes[0].generate(1)
self.sync_all()
- check_array_result(self.nodes[0].listtransactions(),
+ assert_array_result(self.nodes[0].listtransactions(),
{"txid":txid},
{"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":1})
- check_array_result(self.nodes[1].listtransactions(),
+ assert_array_result(self.nodes[1].listtransactions(),
{"txid":txid},
{"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":1})
# send-to-self:
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.2)
- check_array_result(self.nodes[0].listtransactions(),
+ assert_array_result(self.nodes[0].listtransactions(),
{"txid":txid, "category":"send"},
{"amount":Decimal("-0.2")})
- check_array_result(self.nodes[0].listtransactions(),
+ assert_array_result(self.nodes[0].listtransactions(),
{"txid":txid, "category":"receive"},
{"amount":Decimal("0.2")})
@@ -81,28 +59,28 @@ class ListTransactionsTest(BitcoinTestFramework):
self.nodes[1].getaccountaddress("toself") : 0.44 }
txid = self.nodes[1].sendmany("", send_to)
self.sync_all()
- check_array_result(self.nodes[1].listtransactions(),
+ assert_array_result(self.nodes[1].listtransactions(),
{"category":"send","amount":Decimal("-0.11")},
{"txid":txid} )
- check_array_result(self.nodes[0].listtransactions(),
+ assert_array_result(self.nodes[0].listtransactions(),
{"category":"receive","amount":Decimal("0.11")},
{"txid":txid} )
- check_array_result(self.nodes[1].listtransactions(),
+ assert_array_result(self.nodes[1].listtransactions(),
{"category":"send","amount":Decimal("-0.22")},
{"txid":txid} )
- check_array_result(self.nodes[1].listtransactions(),
+ assert_array_result(self.nodes[1].listtransactions(),
{"category":"receive","amount":Decimal("0.22")},
{"txid":txid} )
- check_array_result(self.nodes[1].listtransactions(),
+ assert_array_result(self.nodes[1].listtransactions(),
{"category":"send","amount":Decimal("-0.33")},
{"txid":txid} )
- check_array_result(self.nodes[0].listtransactions(),
+ assert_array_result(self.nodes[0].listtransactions(),
{"category":"receive","amount":Decimal("0.33")},
{"txid":txid, "account" : "from1"} )
- check_array_result(self.nodes[1].listtransactions(),
+ assert_array_result(self.nodes[1].listtransactions(),
{"category":"send","amount":Decimal("-0.44")},
{"txid":txid, "account" : ""} )
- check_array_result(self.nodes[1].listtransactions(),
+ assert_array_result(self.nodes[1].listtransactions(),
{"category":"receive","amount":Decimal("0.44")},
{"txid":txid, "account" : "toself"} )
@@ -112,7 +90,7 @@ class ListTransactionsTest(BitcoinTestFramework):
self.nodes[1].generate(1)
self.sync_all()
assert(len(self.nodes[0].listtransactions("watchonly", 100, 0, False)) == 0)
- check_array_result(self.nodes[0].listtransactions("watchonly", 100, 0, True),
+ assert_array_result(self.nodes[0].listtransactions("watchonly", 100, 0, True),
{"category":"receive","amount":Decimal("0.1")},
{"txid":txid, "account" : "watchonly"} )
@@ -140,9 +118,9 @@ class ListTransactionsTest(BitcoinTestFramework):
# 1. Chain a few transactions that don't opt-in.
txid_1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1)
assert(not is_opt_in(self.nodes[0], txid_1))
- check_array_result(self.nodes[0].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"})
+ assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"})
sync_mempools(self.nodes)
- check_array_result(self.nodes[1].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"})
+ assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"})
# Tx2 will build off txid_1, still not opting in to RBF.
utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_1)
@@ -156,9 +134,9 @@ class ListTransactionsTest(BitcoinTestFramework):
# ...and check the result
assert(not is_opt_in(self.nodes[1], txid_2))
- check_array_result(self.nodes[1].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"})
+ assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"})
sync_mempools(self.nodes)
- check_array_result(self.nodes[0].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"})
+ assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"})
# Tx3 will opt-in to RBF
utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[0], txid_2)
@@ -167,14 +145,14 @@ class ListTransactionsTest(BitcoinTestFramework):
tx3 = self.nodes[0].createrawtransaction(inputs, outputs)
tx3_modified = txFromHex(tx3)
tx3_modified.vin[0].nSequence = 0
- tx3 = binascii.hexlify(tx3_modified.serialize()).decode('utf-8')
+ tx3 = bytes_to_hex_str(tx3_modified.serialize())
tx3_signed = self.nodes[0].signrawtransaction(tx3)['hex']
txid_3 = self.nodes[0].sendrawtransaction(tx3_signed)
assert(is_opt_in(self.nodes[0], txid_3))
- check_array_result(self.nodes[0].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"})
+ assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"})
sync_mempools(self.nodes)
- check_array_result(self.nodes[1].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"})
+ assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"})
# Tx4 will chain off tx3. Doesn't signal itself, but depends on one
# that does.
@@ -186,21 +164,21 @@ class ListTransactionsTest(BitcoinTestFramework):
txid_4 = self.nodes[1].sendrawtransaction(tx4_signed)
assert(not is_opt_in(self.nodes[1], txid_4))
- check_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"})
+ assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"})
sync_mempools(self.nodes)
- check_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"})
+ assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"})
# Replace tx3, and check that tx4 becomes unknown
tx3_b = tx3_modified
- tx3_b.vout[0].nValue -= 0.004*100000000 # bump the fee
- tx3_b = binascii.hexlify(tx3_b.serialize()).decode('utf-8')
+ tx3_b.vout[0].nValue -= int(Decimal("0.004") * COIN) # bump the fee
+ tx3_b = bytes_to_hex_str(tx3_b.serialize())
tx3_b_signed = self.nodes[0].signrawtransaction(tx3_b)['hex']
txid_3b = self.nodes[0].sendrawtransaction(tx3_b_signed, True)
assert(is_opt_in(self.nodes[0], txid_3b))
- check_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"})
+ assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"})
sync_mempools(self.nodes)
- check_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"})
+ assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"})
# Check gettransaction as well:
for n in self.nodes[0:2]:
diff --git a/qa/rpc-tests/maxblocksinflight.py b/qa/rpc-tests/maxblocksinflight.py
index 0313bce736..ad633f661d 100755
--- a/qa/rpc-tests/maxblocksinflight.py
+++ b/qa/rpc-tests/maxblocksinflight.py
@@ -41,40 +41,36 @@ class TestManager(NodeConnCB):
self.disconnectOkay = False
def run(self):
- try:
- fail = False
- self.connection.rpc.generate(1) # Leave IBD
-
- numBlocksToGenerate = [ 8, 16, 128, 1024 ]
- for count in range(len(numBlocksToGenerate)):
- current_invs = []
- for i in range(numBlocksToGenerate[count]):
- current_invs.append(CInv(2, random.randrange(0, 1<<256)))
- if len(current_invs) >= 50000:
- self.connection.send_message(msg_inv(current_invs))
- current_invs = []
- if len(current_invs) > 0:
+ self.connection.rpc.generate(1) # Leave IBD
+
+ numBlocksToGenerate = [8, 16, 128, 1024]
+ for count in range(len(numBlocksToGenerate)):
+ current_invs = []
+ for i in range(numBlocksToGenerate[count]):
+ current_invs.append(CInv(2, random.randrange(0, 1 << 256)))
+ if len(current_invs) >= 50000:
self.connection.send_message(msg_inv(current_invs))
-
- # Wait and see how many blocks were requested
- time.sleep(2)
-
- total_requests = 0
- with mininode_lock:
- for key in self.blockReqCounts:
- total_requests += self.blockReqCounts[key]
- if self.blockReqCounts[key] > 1:
- raise AssertionError("Error, test failed: block %064x requested more than once" % key)
- if total_requests > MAX_REQUESTS:
- raise AssertionError("Error, too many blocks (%d) requested" % total_requests)
- print "Round %d: success (total requests: %d)" % (count, total_requests)
- except AssertionError as e:
- print "TEST FAILED: ", e.args
+ current_invs = []
+ if len(current_invs) > 0:
+ self.connection.send_message(msg_inv(current_invs))
+
+ # Wait and see how many blocks were requested
+ time.sleep(2)
+
+ total_requests = 0
+ with mininode_lock:
+ for key in self.blockReqCounts:
+ total_requests += self.blockReqCounts[key]
+ if self.blockReqCounts[key] > 1:
+ raise AssertionError("Error, test failed: block %064x requested more than once" % key)
+ if total_requests > MAX_REQUESTS:
+ raise AssertionError("Error, too many blocks (%d) requested" % total_requests)
+ print "Round %d: success (total requests: %d)" % (count, total_requests)
self.disconnectOkay = True
self.connection.disconnect_node()
-
+
class MaxBlocksInFlightTest(BitcoinTestFramework):
def add_options(self, parser):
parser.add_option("--testbinary", dest="testbinary",
@@ -86,7 +82,7 @@ class MaxBlocksInFlightTest(BitcoinTestFramework):
initialize_chain_clean(self.options.tmpdir, 1)
def setup_network(self):
- self.nodes = start_nodes(1, self.options.tmpdir,
+ self.nodes = start_nodes(1, self.options.tmpdir,
extra_args=[['-debug', '-whitelist=127.0.0.1']],
binary=[self.options.testbinary])
diff --git a/qa/rpc-tests/maxuploadtarget.py b/qa/rpc-tests/maxuploadtarget.py
index 4d6b343f77..be45fecb5b 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,9 +175,9 @@ 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
+ success_count = max_bytes_available // old_block_size
# 144MB will be reserved for relaying new blocks, so expect this to
# succeed for ~70 tries.
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 2452b77319..afb18cf3da 100755
--- a/qa/rpc-tests/multi_rpc.py
+++ b/qa/rpc-tests/multi_rpc.py
@@ -53,7 +53,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
password2 = "8/F3uMDw4KSEbw96U3CA1C4X05dkHDN2BPFjTgZW4KI="
authpairnew = "rt:"+password
- headers = {"Authorization": "Basic " + base64.b64encode(authpair)}
+ headers = {"Authorization": "Basic " + str_to_b64str(authpair)}
conn = httplib.HTTPConnection(url.hostname, url.port)
conn.connect()
@@ -63,7 +63,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
conn.close()
#Use new authpair to confirm both work
- headers = {"Authorization": "Basic " + base64.b64encode(authpairnew)}
+ headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)}
conn = httplib.HTTPConnection(url.hostname, url.port)
conn.connect()
@@ -74,7 +74,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
#Wrong login name with rt's password
authpairnew = "rtwrong:"+password
- headers = {"Authorization": "Basic " + base64.b64encode(authpairnew)}
+ headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)}
conn = httplib.HTTPConnection(url.hostname, url.port)
conn.connect()
@@ -85,7 +85,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
#Wrong password for rt
authpairnew = "rt:"+password+"wrong"
- headers = {"Authorization": "Basic " + base64.b64encode(authpairnew)}
+ headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)}
conn = httplib.HTTPConnection(url.hostname, url.port)
conn.connect()
@@ -96,7 +96,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
#Correct for rt2
authpairnew = "rt2:"+password2
- headers = {"Authorization": "Basic " + base64.b64encode(authpairnew)}
+ headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)}
conn = httplib.HTTPConnection(url.hostname, url.port)
conn.connect()
@@ -107,7 +107,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
#Wrong password for rt2
authpairnew = "rt2:"+password2+"wrong"
- headers = {"Authorization": "Basic " + base64.b64encode(authpairnew)}
+ headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)}
conn = httplib.HTTPConnection(url.hostname, url.port)
conn.connect()
@@ -117,6 +117,5 @@ class HTTPBasicsTest (BitcoinTestFramework):
conn.close()
-
if __name__ == '__main__':
HTTPBasicsTest ().main ()
diff --git a/qa/rpc-tests/p2p-acceptblock.py b/qa/rpc-tests/p2p-acceptblock.py
index bf355780c1..e429fcc5fe 100755
--- a/qa/rpc-tests/p2p-acceptblock.py
+++ b/qa/rpc-tests/p2p-acceptblock.py
@@ -150,7 +150,7 @@ class AcceptBlockTest(BitcoinTestFramework):
# 2. Send one block that builds on each tip.
# This should be accepted.
blocks_h2 = [] # the height 2 blocks on each node's chain
- block_time = time.time() + 1
+ block_time = int(time.time()) + 1
for i in xrange(2):
blocks_h2.append(create_block(tips[i], create_coinbase(2), block_time))
blocks_h2[i].solve()
diff --git a/qa/rpc-tests/p2p-feefilter.py b/qa/rpc-tests/p2p-feefilter.py
new file mode 100755
index 0000000000..281b6ca37a
--- /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')
+
+# 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-fullblocktest.py b/qa/rpc-tests/p2p-fullblocktest.py
index b1e8ca53ee..ae82d9dca9 100755
--- a/qa/rpc-tests/p2p-fullblocktest.py
+++ b/qa/rpc-tests/p2p-fullblocktest.py
@@ -33,7 +33,7 @@ class FullBlockTest(ComparisonTestFramework):
self.num_nodes = 1
self.block_heights = {}
self.coinbase_key = CECKey()
- self.coinbase_key.set_secretbytes(bytes("horsebattery"))
+ self.coinbase_key.set_secretbytes(b"horsebattery")
self.coinbase_pubkey = self.coinbase_key.get_pubkey()
self.block_time = int(time.time())+1
self.tip = None
@@ -70,7 +70,7 @@ class FullBlockTest(ComparisonTestFramework):
block = create_block(base_block_hash, coinbase, self.block_time)
if (spend != None):
tx = CTransaction()
- tx.vin.append(CTxIn(COutPoint(spend.tx.sha256, spend.n), "", 0xffffffff)) # no signature yet
+ tx.vin.append(CTxIn(COutPoint(spend.tx.sha256, spend.n), b"", 0xffffffff)) # no signature yet
# This copies the java comparison tool testing behavior: the first
# txout has a garbage scriptPubKey, "to make sure we're not
# pre-verifying too much" (?)
@@ -80,7 +80,7 @@ class FullBlockTest(ComparisonTestFramework):
else:
tx.vout.append(CTxOut(1, script))
# Now sign it if necessary
- scriptSig = ""
+ scriptSig = b""
scriptPubKey = bytearray(spend.tx.vout[spend.n].scriptPubKey)
if (scriptPubKey[0] == OP_TRUE): # looks like an anyone-can-spend
scriptSig = CScript([OP_TRUE])
@@ -225,7 +225,7 @@ class FullBlockTest(ComparisonTestFramework):
# \-> b3 (1) -> b4 (2)
tip(6)
block(9, spend=out4, additional_coinbase_value=1)
- yield rejected(RejectResult(16, 'bad-cb-amount'))
+ yield rejected(RejectResult(16, b'bad-cb-amount'))
# Create a fork that ends in a block with too much fee (the one that causes the reorg)
@@ -237,7 +237,7 @@ class FullBlockTest(ComparisonTestFramework):
yield rejected()
block(11, spend=out4, additional_coinbase_value=1)
- yield rejected(RejectResult(16, 'bad-cb-amount'))
+ yield rejected(RejectResult(16, b'bad-cb-amount'))
# Try again, but with a valid fork first
@@ -269,7 +269,7 @@ class FullBlockTest(ComparisonTestFramework):
# \-> b3 (1) -> b4 (2)
# Test that a block with a lot of checksigs is okay
- lots_of_checksigs = CScript([OP_CHECKSIG] * (1000000 / 50 - 1))
+ lots_of_checksigs = CScript([OP_CHECKSIG] * (1000000 // 50 - 1))
tip(13)
block(15, spend=out5, script=lots_of_checksigs)
yield accepted()
@@ -277,9 +277,9 @@ class FullBlockTest(ComparisonTestFramework):
# Test that a block with too many checksigs is rejected
out6 = get_spendable_output()
- too_many_checksigs = CScript([OP_CHECKSIG] * (1000000 / 50))
+ too_many_checksigs = CScript([OP_CHECKSIG] * (1000000 // 50))
block(16, spend=out6, script=too_many_checksigs)
- yield rejected(RejectResult(16, 'bad-blk-sigops'))
+ yield rejected(RejectResult(16, b'bad-blk-sigops'))
# Attempt to spend a transaction created on a different fork
@@ -288,7 +288,7 @@ class FullBlockTest(ComparisonTestFramework):
# \-> b3 (1) -> b4 (2)
tip(15)
block(17, spend=txout_b3)
- yield rejected(RejectResult(16, 'bad-txns-inputs-missingorspent'))
+ yield rejected(RejectResult(16, b'bad-txns-inputs-missingorspent'))
# Attempt to spend a transaction created on a different fork (on a fork this time)
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
@@ -309,7 +309,7 @@ class FullBlockTest(ComparisonTestFramework):
tip(15)
out7 = get_spendable_output()
block(20, spend=out7)
- yield rejected(RejectResult(16, 'bad-txns-premature-spend-of-coinbase'))
+ yield rejected(RejectResult(16, b'bad-txns-premature-spend-of-coinbase'))
# Attempt to spend a coinbase at depth too low (on a fork this time)
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
@@ -333,7 +333,7 @@ class FullBlockTest(ComparisonTestFramework):
old_hash = b23.sha256
tx = CTransaction()
script_length = MAX_BLOCK_SIZE - len(b23.serialize()) - 69
- script_output = CScript([chr(0)*script_length])
+ script_output = CScript([b'\x00' * script_length])
tx.vout.append(CTxOut(0, script_output))
tx.vin.append(CTxIn(COutPoint(b23.vtx[1].sha256, 1)))
b23 = update_block(23, [tx])
@@ -345,11 +345,11 @@ class FullBlockTest(ComparisonTestFramework):
tip(15)
b24 = block(24, spend=out6)
script_length = MAX_BLOCK_SIZE - len(b24.serialize()) - 69
- script_output = CScript([chr(0)*(script_length+1)])
+ script_output = CScript([b'\x00' * (script_length+1)])
tx.vout = [CTxOut(0, script_output)]
b24 = update_block(24, [tx])
assert_equal(len(b24.serialize()), MAX_BLOCK_SIZE+1)
- yield rejected(RejectResult(16, 'bad-blk-length'))
+ yield rejected(RejectResult(16, b'bad-blk-length'))
b25 = block(25, spend=out7)
yield rejected()
@@ -361,12 +361,12 @@ class FullBlockTest(ComparisonTestFramework):
# \-> b3 (1) -> b4 (2)
tip(15)
b26 = block(26, spend=out6)
- b26.vtx[0].vin[0].scriptSig = chr(0)
+ b26.vtx[0].vin[0].scriptSig = b'\x00'
b26.vtx[0].rehash()
# update_block causes the merkle root to get updated, even with no new
# transactions, and updates the required state.
b26 = update_block(26, [])
- yield rejected(RejectResult(16, 'bad-cb-length'))
+ yield rejected(RejectResult(16, b'bad-cb-length'))
# Extend the b26 chain to make sure bitcoind isn't accepting b26
b27 = block(27, spend=out7)
@@ -375,10 +375,10 @@ class FullBlockTest(ComparisonTestFramework):
# Now try a too-large-coinbase script
tip(15)
b28 = block(28, spend=out6)
- b28.vtx[0].vin[0].scriptSig = chr(0)*101
+ b28.vtx[0].vin[0].scriptSig = b'\x00' * 101
b28.vtx[0].rehash()
b28 = update_block(28, [])
- yield rejected(RejectResult(16, 'bad-cb-length'))
+ yield rejected(RejectResult(16, b'bad-cb-length'))
# Extend the b28 chain to make sure bitcoind isn't accepted b28
b29 = block(29, spend=out7)
@@ -390,7 +390,7 @@ class FullBlockTest(ComparisonTestFramework):
# b30 has a max-sized coinbase scriptSig.
tip(23)
b30 = block(30)
- b30.vtx[0].vin[0].scriptSig = chr(0)*100
+ b30.vtx[0].vin[0].scriptSig = b'\x00' * 100
b30.vtx[0].rehash()
b30 = update_block(30, [])
yield accepted()
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/proxy_test.py b/qa/rpc-tests/proxy_test.py
index 7f77e664d2..91c871ddc9 100755
--- a/qa/rpc-tests/proxy_test.py
+++ b/qa/rpc-tests/proxy_test.py
@@ -7,6 +7,7 @@ import socket
from test_framework.socks5 import Socks5Configuration, Socks5Command, Socks5Server, AddressType
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
+from test_framework.netutil import test_ipv6_local
'''
Test plan:
- Start bitcoind's with different proxy configurations
@@ -34,6 +35,7 @@ addnode connect to generic DNS name
class ProxyTest(BitcoinTestFramework):
def __init__(self):
+ self.have_ipv6 = test_ipv6_local()
# Create two proxies on different ports
# ... one unauthenticated
self.conf1 = Socks5Configuration()
@@ -45,29 +47,36 @@ class ProxyTest(BitcoinTestFramework):
self.conf2.addr = ('127.0.0.1', 14000 + (os.getpid() % 1000))
self.conf2.unauth = True
self.conf2.auth = True
- # ... one on IPv6 with similar configuration
- self.conf3 = Socks5Configuration()
- self.conf3.af = socket.AF_INET6
- self.conf3.addr = ('::1', 15000 + (os.getpid() % 1000))
- self.conf3.unauth = True
- self.conf3.auth = True
+ if self.have_ipv6:
+ # ... one on IPv6 with similar configuration
+ self.conf3 = Socks5Configuration()
+ self.conf3.af = socket.AF_INET6
+ self.conf3.addr = ('::1', 15000 + (os.getpid() % 1000))
+ self.conf3.unauth = True
+ self.conf3.auth = True
+ else:
+ print "Warning: testing without local IPv6 support"
self.serv1 = Socks5Server(self.conf1)
self.serv1.start()
self.serv2 = Socks5Server(self.conf2)
self.serv2.start()
- self.serv3 = Socks5Server(self.conf3)
- self.serv3.start()
+ if self.have_ipv6:
+ self.serv3 = Socks5Server(self.conf3)
+ self.serv3.start()
def setup_nodes(self):
# Note: proxies are not used to connect to local nodes
# this is because the proxy to use is based on CService.GetNetwork(), which return NET_UNROUTABLE for localhost
- return start_nodes(4, self.options.tmpdir, extra_args=[
+ args = [
['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf1.addr),'-proxyrandomize=1'],
['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf1.addr),'-onion=%s:%i' % (self.conf2.addr),'-proxyrandomize=0'],
['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf2.addr),'-proxyrandomize=1'],
- ['-listen', '-debug=net', '-debug=proxy', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0', '-noonion']
- ])
+ []
+ ]
+ if self.have_ipv6:
+ args[3] = ['-listen', '-debug=net', '-debug=proxy', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0', '-noonion']
+ return start_nodes(4, self.options.tmpdir, extra_args=args)
def node_test(self, node, proxies, auth, test_onion=True):
rv = []
@@ -77,25 +86,26 @@ class ProxyTest(BitcoinTestFramework):
assert(isinstance(cmd, Socks5Command))
# Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
- assert_equal(cmd.addr, "15.61.23.23")
+ assert_equal(cmd.addr, b"15.61.23.23")
assert_equal(cmd.port, 1234)
if not auth:
assert_equal(cmd.username, None)
assert_equal(cmd.password, None)
rv.append(cmd)
- # Test: outgoing IPv6 connection through node
- node.addnode("[1233:3432:2434:2343:3234:2345:6546:4534]:5443", "onetry")
- cmd = proxies[1].queue.get()
- assert(isinstance(cmd, Socks5Command))
- # Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6
- assert_equal(cmd.atyp, AddressType.DOMAINNAME)
- assert_equal(cmd.addr, "1233:3432:2434:2343:3234:2345:6546:4534")
- assert_equal(cmd.port, 5443)
- if not auth:
- assert_equal(cmd.username, None)
- assert_equal(cmd.password, None)
- rv.append(cmd)
+ if self.have_ipv6:
+ # Test: outgoing IPv6 connection through node
+ node.addnode("[1233:3432:2434:2343:3234:2345:6546:4534]:5443", "onetry")
+ cmd = proxies[1].queue.get()
+ assert(isinstance(cmd, Socks5Command))
+ # Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6
+ assert_equal(cmd.atyp, AddressType.DOMAINNAME)
+ assert_equal(cmd.addr, b"1233:3432:2434:2343:3234:2345:6546:4534")
+ assert_equal(cmd.port, 5443)
+ if not auth:
+ assert_equal(cmd.username, None)
+ assert_equal(cmd.password, None)
+ rv.append(cmd)
if test_onion:
# Test: outgoing onion connection through node
@@ -103,7 +113,7 @@ class ProxyTest(BitcoinTestFramework):
cmd = proxies[2].queue.get()
assert(isinstance(cmd, Socks5Command))
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
- assert_equal(cmd.addr, "bitcoinostk4e4re.onion")
+ assert_equal(cmd.addr, b"bitcoinostk4e4re.onion")
assert_equal(cmd.port, 8333)
if not auth:
assert_equal(cmd.username, None)
@@ -115,7 +125,7 @@ class ProxyTest(BitcoinTestFramework):
cmd = proxies[3].queue.get()
assert(isinstance(cmd, Socks5Command))
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
- assert_equal(cmd.addr, "node.noumenon")
+ assert_equal(cmd.addr, b"node.noumenon")
assert_equal(cmd.port, 8333)
if not auth:
assert_equal(cmd.username, None)
@@ -135,10 +145,11 @@ class ProxyTest(BitcoinTestFramework):
rv = self.node_test(self.nodes[2], [self.serv2, self.serv2, self.serv2, self.serv2], True)
# Check that credentials as used for -proxyrandomize connections are unique
credentials = set((x.username,x.password) for x in rv)
- assert_equal(len(credentials), 4)
+ assert_equal(len(credentials), len(rv))
- # proxy on IPv6 localhost
- self.node_test(self.nodes[3], [self.serv3, self.serv3, self.serv3, self.serv3], False, False)
+ if self.have_ipv6:
+ # proxy on IPv6 localhost
+ self.node_test(self.nodes[3], [self.serv3, self.serv3, self.serv3, self.serv3], False, False)
def networks_dict(d):
r = {}
@@ -167,11 +178,12 @@ class ProxyTest(BitcoinTestFramework):
assert_equal(n2[net]['proxy_randomize_credentials'], True)
assert_equal(n2['onion']['reachable'], True)
- n3 = networks_dict(self.nodes[3].getnetworkinfo())
- for net in ['ipv4','ipv6']:
- assert_equal(n3[net]['proxy'], '[%s]:%i' % (self.conf3.addr))
- assert_equal(n3[net]['proxy_randomize_credentials'], False)
- assert_equal(n3['onion']['reachable'], False)
+ if self.have_ipv6:
+ n3 = networks_dict(self.nodes[3].getnetworkinfo())
+ for net in ['ipv4','ipv6']:
+ assert_equal(n3[net]['proxy'], '[%s]:%i' % (self.conf3.addr))
+ assert_equal(n3[net]['proxy_randomize_credentials'], False)
+ assert_equal(n3['onion']['reachable'], False)
if __name__ == '__main__':
ProxyTest().main()
diff --git a/qa/rpc-tests/pruning.py b/qa/rpc-tests/pruning.py
index b0f4b88aee..eccd157e5c 100755
--- a/qa/rpc-tests/pruning.py
+++ b/qa/rpc-tests/pruning.py
@@ -15,7 +15,7 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
def calc_usage(blockdir):
- return sum(os.path.getsize(blockdir+f) for f in os.listdir(blockdir) if os.path.isfile(blockdir+f))/(1024*1024)
+ return sum(os.path.getsize(blockdir+f) for f in os.listdir(blockdir) if os.path.isfile(blockdir+f)) / (1024. * 1024.)
class PruneTest(BitcoinTestFramework):
@@ -56,7 +56,7 @@ class PruneTest(BitcoinTestFramework):
self.nodes[1].generate(200)
sync_blocks(self.nodes[0:2])
self.nodes[0].generate(150)
- # Then mine enough full blocks to create more than 550MB of data
+ # Then mine enough full blocks to create more than 550MiB of data
for i in xrange(645):
self.mine_full_block(self.nodes[0], self.address[0])
@@ -66,7 +66,7 @@ class PruneTest(BitcoinTestFramework):
if not os.path.isfile(self.prunedir+"blk00000.dat"):
raise AssertionError("blk00000.dat is missing, pruning too early")
print "Success"
- print "Though we're already using more than 550MB, current usage:", calc_usage(self.prunedir)
+ print "Though we're already using more than 550MiB, current usage:", calc_usage(self.prunedir)
print "Mining 25 more blocks should cause the first block file to be pruned"
# Pruning doesn't run until we're allocating another chunk, 20 full blocks past the height cutoff will ensure this
for i in xrange(25):
@@ -311,7 +311,7 @@ class PruneTest(BitcoinTestFramework):
# \ \
# ++...++(1044) ..
#
- # N0 ********************(1032) @@...@@@(1552)
+ # N0 ********************(1032) @@...@@@(1552)
# \
# *...**(1320)
diff --git a/qa/rpc-tests/rawtransactions.py b/qa/rpc-tests/rawtransactions.py
index dd9e5e28a5..e38ef6c8b1 100755
--- a/qa/rpc-tests/rawtransactions.py
+++ b/qa/rpc-tests/rawtransactions.py
@@ -56,13 +56,13 @@ class RawTransactionsTest(BitcoinTestFramework):
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
rawtx = self.nodes[2].signrawtransaction(rawtx)
- errorString = ""
try:
rawtx = self.nodes[2].sendrawtransaction(rawtx['hex'])
- except JSONRPCException,e:
- errorString = e.error['message']
+ except JSONRPCException as e:
+ assert("Missing inputs" in e.error['message'])
+ else:
+ assert(False)
- assert("Missing inputs" in errorString)
#########################
# RAW TX MULTISIG TESTS #
@@ -88,8 +88,6 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_equal(self.nodes[2].getbalance(), bal+Decimal('1.20000000')) #node2 has both keys of the 2of2 ms addr., tx should affect the balance
-
-
# 2of3 test from different nodes
bal = self.nodes[2].getbalance()
addr1 = self.nodes[1].getnewaddress()
diff --git a/qa/rpc-tests/receivedby.py b/qa/rpc-tests/receivedby.py
index 606426b394..7d8231f5e4 100755
--- a/qa/rpc-tests/receivedby.py
+++ b/qa/rpc-tests/receivedby.py
@@ -25,32 +25,6 @@ def get_sub_array_from_array(object_array, to_match):
return item
return []
-def check_array_result(object_array, to_match, expected, should_not_find = False):
- """
- Pass in array of JSON objects, a dictionary with key/value pairs
- to match against, and another dictionary with expected key/value
- pairs.
- If the should_not_find flag is true, to_match should not be found in object_array
- """
- if should_not_find == True:
- expected = { }
- num_matched = 0
- for item in object_array:
- all_match = True
- for key,value in to_match.items():
- if item[key] != value:
- all_match = False
- if not all_match:
- continue
- for key,value in expected.items():
- if item[key] != value:
- raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value)))
- num_matched = num_matched+1
- if num_matched == 0 and should_not_find != True:
- raise AssertionError("No objects matched %s"%(str(to_match)))
- if num_matched > 0 and should_not_find == True:
- raise AssertionError("Objects was matched %s"%(str(to_match)))
-
class ReceivedByTest(BitcoinTestFramework):
def setup_nodes(self):
@@ -68,26 +42,26 @@ class ReceivedByTest(BitcoinTestFramework):
self.sync_all()
#Check not listed in listreceivedbyaddress because has 0 confirmations
- check_array_result(self.nodes[1].listreceivedbyaddress(),
+ assert_array_result(self.nodes[1].listreceivedbyaddress(),
{"address":addr},
{ },
True)
#Bury Tx under 10 block so it will be returned by listreceivedbyaddress
self.nodes[1].generate(10)
self.sync_all()
- check_array_result(self.nodes[1].listreceivedbyaddress(),
+ assert_array_result(self.nodes[1].listreceivedbyaddress(),
{"address":addr},
{"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]})
#With min confidence < 10
- check_array_result(self.nodes[1].listreceivedbyaddress(5),
+ assert_array_result(self.nodes[1].listreceivedbyaddress(5),
{"address":addr},
{"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]})
#With min confidence > 10, should not find Tx
- check_array_result(self.nodes[1].listreceivedbyaddress(11),{"address":addr},{ },True)
+ assert_array_result(self.nodes[1].listreceivedbyaddress(11),{"address":addr},{ },True)
#Empty Tx
addr = self.nodes[1].getnewaddress()
- check_array_result(self.nodes[1].listreceivedbyaddress(0,True),
+ assert_array_result(self.nodes[1].listreceivedbyaddress(0,True),
{"address":addr},
{"address":addr, "account":"", "amount":0, "confirmations":0, "txids":[]})
@@ -131,7 +105,7 @@ class ReceivedByTest(BitcoinTestFramework):
self.sync_all()
# listreceivedbyaccount should return received_by_account_json because of 0 confirmations
- check_array_result(self.nodes[1].listreceivedbyaccount(),
+ assert_array_result(self.nodes[1].listreceivedbyaccount(),
{"account":account},
received_by_account_json)
@@ -143,7 +117,7 @@ class ReceivedByTest(BitcoinTestFramework):
self.nodes[1].generate(10)
self.sync_all()
# listreceivedbyaccount should return updated account balance
- check_array_result(self.nodes[1].listreceivedbyaccount(),
+ assert_array_result(self.nodes[1].listreceivedbyaccount(),
{"account":account},
{"account":received_by_account_json["account"], "amount":(received_by_account_json["amount"] + Decimal("0.1"))})
diff --git a/qa/rpc-tests/replace-by-fee.py b/qa/rpc-tests/replace-by-fee.py
index ba1956853a..4c8ef6de26 100755
--- a/qa/rpc-tests/replace-by-fee.py
+++ b/qa/rpc-tests/replace-by-fee.py
@@ -11,16 +11,11 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
from test_framework.script import *
from test_framework.mininode import *
-import binascii
-COIN = 100000000
MAX_REPLACEMENT_LIMIT = 100
-def satoshi_round(amount):
- return Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN)
-
def txToHex(tx):
- return binascii.hexlify(tx.serialize()).decode('utf-8')
+ return bytes_to_hex_str(tx.serialize())
def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])):
"""Create a txout with a given amount and scriptPubKey
@@ -54,9 +49,7 @@ def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])):
tx2.vout = [CTxOut(amount, scriptPubKey)]
tx2.rehash()
- binascii.hexlify(tx2.serialize()).decode('utf-8')
-
- signed_tx = node.signrawtransaction(binascii.hexlify(tx2.serialize()).decode('utf-8'))
+ signed_tx = node.signrawtransaction(txToHex(tx2))
txid = node.sendrawtransaction(signed_tx['hex'], True)
@@ -120,7 +113,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
def test_simple_doublespend(self):
"""Simple doublespend"""
- tx0_outpoint = make_utxo(self.nodes[0], 1.1*COIN)
+ tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
tx1a = CTransaction()
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
@@ -144,7 +137,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Extra 0.1 BTC fee
tx1b = CTransaction()
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- tx1b.vout = [CTxOut(0.9*COIN, CScript([b'b']))]
+ tx1b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))]
tx1b_hex = txToHex(tx1b)
tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
@@ -236,7 +229,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
_total_txs=_total_txs):
yield x
- fee = 0.0001*COIN
+ fee = int(0.0001*COIN)
n = MAX_REPLACEMENT_LIMIT
tree_txs = list(branch(tx0_outpoint, initial_nValue, n, fee=fee))
assert_equal(len(tree_txs), n)
@@ -269,7 +262,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Try again, but with more total transactions than the "max txs
# double-spent at once" anti-DoS limit.
for n in (MAX_REPLACEMENT_LIMIT+1, MAX_REPLACEMENT_LIMIT*2):
- fee = 0.0001*COIN
+ fee = int(0.0001*COIN)
tx0_outpoint = make_utxo(self.nodes[0], initial_nValue)
tree_txs = list(branch(tx0_outpoint, initial_nValue, n, fee=fee))
assert_equal(len(tree_txs), n)
@@ -292,7 +285,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
def test_replacement_feeperkb(self):
"""Replacement requires fee-per-KB to be higher"""
- tx0_outpoint = make_utxo(self.nodes[0], 1.1*COIN)
+ tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
tx1a = CTransaction()
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
@@ -304,7 +297,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# rejected.
tx1b = CTransaction()
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- tx1b.vout = [CTxOut(0.001*COIN, CScript([b'a'*999000]))]
+ tx1b.vout = [CTxOut(int(0.001*COIN), CScript([b'a'*999000]))]
tx1b_hex = txToHex(tx1b)
try:
@@ -316,12 +309,12 @@ class ReplaceByFeeTest(BitcoinTestFramework):
def test_spends_of_conflicting_outputs(self):
"""Replacements that spend conflicting tx outputs are rejected"""
- utxo1 = make_utxo(self.nodes[0], 1.2*COIN)
- utxo2 = make_utxo(self.nodes[0], 3.0*COIN)
+ utxo1 = make_utxo(self.nodes[0], int(1.2*COIN))
+ utxo2 = make_utxo(self.nodes[0], 3*COIN)
tx1a = CTransaction()
tx1a.vin = [CTxIn(utxo1, nSequence=0)]
- tx1a.vout = [CTxOut(1.1*COIN, CScript([b'a']))]
+ tx1a.vout = [CTxOut(int(1.1*COIN), CScript([b'a']))]
tx1a_hex = txToHex(tx1a)
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
@@ -344,7 +337,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Spend tx1a's output to test the indirect case.
tx1b = CTransaction()
tx1b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)]
- tx1b.vout = [CTxOut(1.0*COIN, CScript([b'a']))]
+ tx1b.vout = [CTxOut(1*COIN, CScript([b'a']))]
tx1b_hex = txToHex(tx1b)
tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
tx1b_txid = int(tx1b_txid, 16)
@@ -364,12 +357,12 @@ class ReplaceByFeeTest(BitcoinTestFramework):
def test_new_unconfirmed_inputs(self):
"""Replacements that add new unconfirmed inputs are rejected"""
- confirmed_utxo = make_utxo(self.nodes[0], 1.1*COIN)
- unconfirmed_utxo = make_utxo(self.nodes[0], 0.1*COIN, False)
+ confirmed_utxo = make_utxo(self.nodes[0], int(1.1*COIN))
+ unconfirmed_utxo = make_utxo(self.nodes[0], int(0.1*COIN), False)
tx1 = CTransaction()
tx1.vin = [CTxIn(confirmed_utxo)]
- tx1.vout = [CTxOut(1.0*COIN, CScript([b'a']))]
+ tx1.vout = [CTxOut(1*COIN, CScript([b'a']))]
tx1_hex = txToHex(tx1)
tx1_txid = self.nodes[0].sendrawtransaction(tx1_hex, True)
@@ -393,7 +386,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Start by creating a single transaction with many outputs
initial_nValue = 10*COIN
utxo = make_utxo(self.nodes[0], initial_nValue)
- fee = 0.0001*COIN
+ fee = int(0.0001*COIN)
split_value = int((initial_nValue-fee)/(MAX_REPLACEMENT_LIMIT+1))
actual_fee = initial_nValue - split_value*(MAX_REPLACEMENT_LIMIT+1)
@@ -446,7 +439,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
def test_opt_in(self):
""" Replacing should only work if orig tx opted in """
- tx0_outpoint = make_utxo(self.nodes[0], 1.1*COIN)
+ tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
# Create a non-opting in transaction
tx1a = CTransaction()
@@ -458,7 +451,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Shouldn't be able to double-spend
tx1b = CTransaction()
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- tx1b.vout = [CTxOut(0.9*COIN, CScript([b'b']))]
+ tx1b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))]
tx1b_hex = txToHex(tx1b)
try:
@@ -469,7 +462,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
print tx1b_txid
assert(False)
- tx1_outpoint = make_utxo(self.nodes[0], 1.1*COIN)
+ tx1_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
# Create a different non-opting in transaction
tx2a = CTransaction()
@@ -481,7 +474,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Still shouldn't be able to double-spend
tx2b = CTransaction()
tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)]
- tx2b.vout = [CTxOut(0.9*COIN, CScript([b'b']))]
+ tx2b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))]
tx2b_hex = txToHex(tx2b)
try:
@@ -501,19 +494,19 @@ class ReplaceByFeeTest(BitcoinTestFramework):
tx3a = CTransaction()
tx3a.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0xffffffff),
CTxIn(COutPoint(tx2a_txid, 0), nSequence=0xfffffffd)]
- tx3a.vout = [CTxOut(0.9*COIN, CScript([b'c'])), CTxOut(0.9*COIN, CScript([b'd']))]
+ tx3a.vout = [CTxOut(int(0.9*COIN), CScript([b'c'])), CTxOut(int(0.9*COIN), CScript([b'd']))]
tx3a_hex = txToHex(tx3a)
self.nodes[0].sendrawtransaction(tx3a_hex, True)
tx3b = CTransaction()
tx3b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)]
- tx3b.vout = [CTxOut(0.5*COIN, CScript([b'e']))]
+ tx3b.vout = [CTxOut(int(0.5*COIN), CScript([b'e']))]
tx3b_hex = txToHex(tx3b)
tx3c = CTransaction()
tx3c.vin = [CTxIn(COutPoint(tx2a_txid, 0), nSequence=0)]
- tx3c.vout = [CTxOut(0.5*COIN, CScript([b'f']))]
+ tx3c.vout = [CTxOut(int(0.5*COIN), CScript([b'f']))]
tx3c_hex = txToHex(tx3c)
self.nodes[0].sendrawtransaction(tx3b_hex, True)
@@ -526,7 +519,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# correctly used by replacement logic
# 1. Check that feeperkb uses modified fees
- tx0_outpoint = make_utxo(self.nodes[0], 1.1*COIN)
+ tx0_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
tx1a = CTransaction()
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
@@ -537,7 +530,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Higher fee, but the actual fee per KB is much lower.
tx1b = CTransaction()
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- tx1b.vout = [CTxOut(0.001*COIN, CScript([b'a'*740000]))]
+ tx1b.vout = [CTxOut(int(0.001*COIN), CScript([b'a'*740000]))]
tx1b_hex = txToHex(tx1b)
# Verify tx1b cannot replace tx1a.
@@ -557,7 +550,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
assert(tx1b_txid in self.nodes[0].getrawmempool())
# 2. Check that absolute fee checks use modified fee.
- tx1_outpoint = make_utxo(self.nodes[0], 1.1*COIN)
+ tx1_outpoint = make_utxo(self.nodes[0], int(1.1*COIN))
tx2a = CTransaction()
tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0)]
@@ -568,7 +561,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Lower fee, but we'll prioritise it
tx2b = CTransaction()
tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)]
- tx2b.vout = [CTxOut(1.01*COIN, CScript([b'a']))]
+ tx2b.vout = [CTxOut(int(1.01*COIN), CScript([b'a']))]
tx2b.rehash()
tx2b_hex = txToHex(tx2b)
diff --git a/qa/rpc-tests/rest.py b/qa/rpc-tests/rest.py
index 8c83536501..359f9239fb 100755
--- a/qa/rpc-tests/rest.py
+++ b/qa/rpc-tests/rest.py
@@ -11,8 +11,9 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
from struct import *
+from io import BytesIO
+from codecs import encode
import binascii
-import StringIO
try:
import http.client as httplib
@@ -38,7 +39,7 @@ def http_get_call(host, port, path, response_object = 0):
if response_object:
return conn.getresponse()
- return conn.getresponse().read()
+ return conn.getresponse().read().decode('utf-8')
#allows simple http post calls with a request body
def http_post_call(host, port, path, requestdata = '', response_object = 0):
@@ -140,13 +141,13 @@ class RESTTest (BitcoinTestFramework):
bb_hash = self.nodes[0].getbestblockhash()
binaryRequest = b'\x01\x02'
- binaryRequest += binascii.unhexlify(txid)
+ binaryRequest += hex_str_to_bytes(txid)
binaryRequest += pack("i", n)
- binaryRequest += binascii.unhexlify(vintx)
+ binaryRequest += hex_str_to_bytes(vintx)
binaryRequest += pack("i", 0)
bin_response = http_post_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'bin', binaryRequest)
- output = StringIO.StringIO()
+ output = BytesIO()
output.write(bin_response)
output.seek(0)
chainHeight = unpack("i", output.read(4))[0]
@@ -233,7 +234,7 @@ class RESTTest (BitcoinTestFramework):
assert_equal(response_hex.status, 200)
assert_greater_than(int(response_hex.getheader('content-length')), 160)
response_hex_str = response_hex.read()
- assert_equal(response_str.encode("hex")[0:160], response_hex_str[0:160])
+ assert_equal(encode(response_str, "hex_codec")[0:160], response_hex_str[0:160])
# compare with hex block header
response_header_hex = http_get_call(url.hostname, url.port, '/rest/headers/1/'+bb_hash+self.FORMAT_SEPARATOR+"hex", True)
@@ -241,7 +242,7 @@ class RESTTest (BitcoinTestFramework):
assert_greater_than(int(response_header_hex.getheader('content-length')), 160)
response_header_hex_str = response_header_hex.read()
assert_equal(response_hex_str[0:160], response_header_hex_str[0:160])
- assert_equal(response_header_str.encode("hex")[0:160], response_header_hex_str[0:160])
+ assert_equal(encode(response_header_str, "hex_codec")[0:160], response_header_hex_str[0:160])
# check json format
block_json_string = http_get_call(url.hostname, url.port, '/rest/block/'+bb_hash+self.FORMAT_SEPARATOR+'json')
@@ -251,7 +252,7 @@ class RESTTest (BitcoinTestFramework):
# compare with json block header
response_header_json = http_get_call(url.hostname, url.port, '/rest/headers/1/'+bb_hash+self.FORMAT_SEPARATOR+"json", True)
assert_equal(response_header_json.status, 200)
- response_header_json_str = response_header_json.read()
+ response_header_json_str = response_header_json.read().decode('utf-8')
json_obj = json.loads(response_header_json_str, parse_float=Decimal)
assert_equal(len(json_obj), 1) #ensure that there is one header in the json response
assert_equal(json_obj[0]['hash'], bb_hash) #request/response hash should be the same
@@ -275,7 +276,7 @@ class RESTTest (BitcoinTestFramework):
self.sync_all()
response_header_json = http_get_call(url.hostname, url.port, '/rest/headers/5/'+bb_hash+self.FORMAT_SEPARATOR+"json", True)
assert_equal(response_header_json.status, 200)
- response_header_json_str = response_header_json.read()
+ response_header_json_str = response_header_json.read().decode('utf-8')
json_obj = json.loads(response_header_json_str)
assert_equal(len(json_obj), 5) #now we should have 5 header objects
@@ -291,7 +292,6 @@ class RESTTest (BitcoinTestFramework):
assert_greater_than(int(response.getheader('content-length')), 10)
-
# check block tx details
# let's make 3 tx and mine them on node 1
txs = []
diff --git a/qa/rpc-tests/smartfees.py b/qa/rpc-tests/smartfees.py
index b209ae0c16..2c064ad8a0 100755
--- a/qa/rpc-tests/smartfees.py
+++ b/qa/rpc-tests/smartfees.py
@@ -105,7 +105,7 @@ def check_estimates(node, fees_seen, max_invalid, print_estimates = True):
print([str(all_estimates[e-1]) for e in [1,2,3,6,15,25]])
delta = 1.0e-6 # account for rounding error
last_e = max(fees_seen)
- for e in filter(lambda x: x >= 0, all_estimates):
+ for e in [x for x in all_estimates if x >= 0]:
# Estimates should be within the bounds of what transactions fees actually were:
if float(e)+delta < min(fees_seen) or float(e)-delta > max(fees_seen):
raise AssertionError("Estimated fee (%f) out of range (%f,%f)"
@@ -219,7 +219,7 @@ class EstimateFeeTest(BitcoinTestFramework):
from_index = random.randint(1,2)
(txhex, fee) = small_txpuzzle_randfee(self.nodes[from_index], self.confutxo,
self.memutxo, Decimal("0.005"), min_fee, min_fee)
- tx_kbytes = (len(txhex)/2)/1000.0
+ tx_kbytes = (len(txhex) // 2) / 1000.0
self.fees_per_kb.append(float(fee)/tx_kbytes)
sync_mempools(self.nodes[0:3],.1)
mined = mining_node.getblock(mining_node.generate(1)[0],True)["tx"]
diff --git a/qa/rpc-tests/test_framework/authproxy.py b/qa/rpc-tests/test_framework/authproxy.py
index fba469a0dd..e5f7ab3656 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('__'):
@@ -155,6 +154,11 @@ class AuthServiceProxy(object):
raise JSONRPCException({
'code': -342, 'message': 'missing HTTP response from server'})
+ content_type = http_response.getheader('Content-Type')
+ if content_type != 'application/json':
+ raise JSONRPCException({
+ 'code': -342, 'message': 'non-JSON HTTP response with \'%i %s\' from server' % (http_response.status, http_response.reason)})
+
responsedata = http_response.read().decode('utf8')
response = json.loads(responsedata, parse_float=decimal.Decimal)
if "error" in response and response["error"] is None:
diff --git a/qa/rpc-tests/test_framework/blockstore.py b/qa/rpc-tests/test_framework/blockstore.py
index b9775b477c..73d9ffbb2f 100644
--- a/qa/rpc-tests/test_framework/blockstore.py
+++ b/qa/rpc-tests/test_framework/blockstore.py
@@ -3,8 +3,9 @@
# and for constructing a getheaders message
#
-from mininode import *
+from .mininode import *
import dbm
+from io import BytesIO
class BlockStore(object):
def __init__(self, datadir):
@@ -21,7 +22,7 @@ class BlockStore(object):
serialized_block = self.blockDB[repr(blockhash)]
except KeyError:
return None
- f = cStringIO.StringIO(serialized_block)
+ f = BytesIO(serialized_block)
ret = CBlock()
ret.deserialize(f)
ret.calc_sha256()
@@ -115,7 +116,7 @@ class TxStore(object):
serialized_tx = self.txDB[repr(txhash)]
except KeyError:
return None
- f = cStringIO.StringIO(serialized_tx)
+ f = BytesIO(serialized_tx)
ret = CTransaction()
ret.deserialize(f)
ret.calc_sha256()
diff --git a/qa/rpc-tests/test_framework/blocktools.py b/qa/rpc-tests/test_framework/blocktools.py
index 7eea41b75c..384f40e62d 100644
--- a/qa/rpc-tests/test_framework/blocktools.py
+++ b/qa/rpc-tests/test_framework/blocktools.py
@@ -4,8 +4,8 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
#
-from mininode import *
-from script import CScript, OP_TRUE, OP_CHECKSIG
+from .mininode import *
+from .script import CScript, OP_TRUE, OP_CHECKSIG
# Create a block (with regtest difficulty)
def create_block(hashprev, coinbase, nTime=None):
@@ -29,7 +29,7 @@ def serialize_script_num(value):
neg = value < 0
absvalue = -value if neg else value
while (absvalue):
- r.append(chr(absvalue & 0xff))
+ r.append(int(absvalue & 0xff))
absvalue >>= 8
if r[-1] & 0x80:
r.append(0x80 if neg else 0)
@@ -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):
@@ -62,6 +62,6 @@ def create_transaction(prevtx, n, sig, value):
tx = CTransaction()
assert(n < len(prevtx.vout))
tx.vin.append(CTxIn(COutPoint(prevtx.sha256, n), sig, 0xffffffff))
- tx.vout.append(CTxOut(value, ""))
+ tx.vout.append(CTxOut(value, b""))
tx.calc_sha256()
return tx
diff --git a/qa/rpc-tests/test_framework/comptool.py b/qa/rpc-tests/test_framework/comptool.py
index a4cd4d0a89..17626cf8da 100755
--- a/qa/rpc-tests/test_framework/comptool.py
+++ b/qa/rpc-tests/test_framework/comptool.py
@@ -4,9 +4,9 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
#
-from mininode import *
-from blockstore import BlockStore, TxStore
-from util import p2p_port
+from .mininode import *
+from .blockstore import BlockStore, TxStore
+from .util import p2p_port
'''
This is a tool for comparing two or more bitcoinds to each other
@@ -27,25 +27,11 @@ 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.
'''
- def __init__(self, code, reason=''):
+ def __init__(self, code, reason=b''):
self.code = code
self.reason = reason
def match(self, other):
@@ -111,9 +97,9 @@ class TestNode(NodeConnCB):
raise AssertionError("Got pong for unknown ping [%s]" % repr(message))
def on_reject(self, conn, message):
- if message.message == 'tx':
+ if message.message == b'tx':
self.tx_reject_map[message.data] = RejectResult(message.code, message.reason)
- if message.message == 'block':
+ if message.message == b'block':
self.block_reject_map[message.data] = RejectResult(message.code, message.reason)
def send_inv(self, obj):
@@ -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 81bb439cea..af33564114 100755
--- a/qa/rpc-tests/test_framework/mininode.py
+++ b/qa/rpc-tests/test_framework/mininode.py
@@ -20,11 +20,12 @@
import struct
import socket
import asyncore
-import binascii
import time
import sys
import random
-import cStringIO
+from binascii import hexlify, unhexlify
+from io import BytesIO
+from codecs import encode
import hashlib
from threading import RLock
from threading import Thread
@@ -33,11 +34,13 @@ import copy
BIP0031_VERSION = 60000
MY_VERSION = 60001 # past bip-31 for ping/pong
-MY_SUBVERSION = "/python-mininode-tester:0.0.1/"
+MY_SUBVERSION = b"/python-mininode-tester:0.0.2/"
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)
@@ -73,12 +76,12 @@ def deser_string(f):
def ser_string(s):
if len(s) < 253:
- return chr(len(s)) + s
+ return struct.pack("B", len(s)) + s
elif len(s) < 0x10000:
- return chr(253) + struct.pack("<H", len(s)) + s
+ return struct.pack("<BH", 253, len(s)) + s
elif len(s) < 0x100000000L:
- return chr(254) + struct.pack("<I", len(s)) + s
- return chr(255) + struct.pack("<Q", len(s)) + s
+ return struct.pack("<BI", 254, len(s)) + s
+ return struct.pack("<BQ", 255, len(s)) + s
def deser_uint256(f):
@@ -128,15 +131,15 @@ def deser_vector(f, c):
def ser_vector(l):
- r = ""
+ r = b""
if len(l) < 253:
- r = chr(len(l))
+ r = struct.pack("B", len(l))
elif len(l) < 0x10000:
- r = chr(253) + struct.pack("<H", len(l))
+ r = struct.pack("<BH", 253, len(l))
elif len(l) < 0x100000000L:
- r = chr(254) + struct.pack("<I", len(l))
+ r = struct.pack("<BI", 254, len(l))
else:
- r = chr(255) + struct.pack("<Q", len(l))
+ r = struct.pack("<BQ", 255, len(l))
for i in l:
r += i.serialize()
return r
@@ -158,15 +161,15 @@ def deser_uint256_vector(f):
def ser_uint256_vector(l):
- r = ""
+ r = b""
if len(l) < 253:
- r = chr(len(l))
+ r = struct.pack("B", len(l))
elif len(l) < 0x10000:
- r = chr(253) + struct.pack("<H", len(l))
+ r = struct.pack("<BH", 253, len(l))
elif len(l) < 0x100000000L:
- r = chr(254) + struct.pack("<I", len(l))
+ r = struct.pack("<BI", 254, len(l))
else:
- r = chr(255) + struct.pack("<Q", len(l))
+ r = struct.pack("<BQ", 255, len(l))
for i in l:
r += ser_uint256(i)
return r
@@ -190,13 +193,13 @@ def deser_string_vector(f):
def ser_string_vector(l):
r = ""
if len(l) < 253:
- r = chr(len(l))
+ r = struct.pack("B", len(l))
elif len(l) < 0x10000:
- r = chr(253) + struct.pack("<H", len(l))
+ r = struct.pack("<BH", 253, len(l))
elif len(l) < 0x100000000L:
- r = chr(254) + struct.pack("<I", len(l))
+ r = struct.pack("<BI", 254, len(l))
else:
- r = chr(255) + struct.pack("<Q", len(l))
+ r = struct.pack("<BQ", 255, len(l))
for sv in l:
r += ser_string(sv)
return r
@@ -218,34 +221,34 @@ def deser_int_vector(f):
def ser_int_vector(l):
- r = ""
+ r = b""
if len(l) < 253:
- r = chr(len(l))
+ r = struct.pack("B", len(l))
elif len(l) < 0x10000:
- r = chr(253) + struct.pack("<H", len(l))
+ r = struct.pack("<BH", 253, len(l))
elif len(l) < 0x100000000L:
- r = chr(254) + struct.pack("<I", len(l))
+ r = struct.pack("<BI", 254, len(l))
else:
- r = chr(255) + struct.pack("<Q", len(l))
+ r = struct.pack("<BQ", 255, len(l))
for i in 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)))
+ obj.deserialize(BytesIO(unhexlify(hex_string.encode('ascii'))))
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')
+ return hexlify(obj.serialize()).decode('ascii')
# Objects that map to bitcoind objects, which can be serialized/deserialized
class CAddress(object):
def __init__(self):
self.nServices = 1
- self.pchReserved = "\x00" * 10 + "\xff" * 2
+ self.pchReserved = b"\x00" * 10 + b"\xff" * 2
self.ip = "0.0.0.0"
self.port = 0
@@ -256,7 +259,7 @@ class CAddress(object):
self.port = struct.unpack(">H", f.read(2))[0]
def serialize(self):
- r = ""
+ r = b""
r += struct.pack("<Q", self.nServices)
r += self.pchReserved
r += socket.inet_aton(self.ip)
@@ -283,7 +286,7 @@ class CInv(object):
self.hash = deser_uint256(f)
def serialize(self):
- r = ""
+ r = b""
r += struct.pack("<i", self.type)
r += ser_uint256(self.hash)
return r
@@ -303,7 +306,7 @@ class CBlockLocator(object):
self.vHave = deser_uint256_vector(f)
def serialize(self):
- r = ""
+ r = b""
r += struct.pack("<i", self.nVersion)
r += ser_uint256_vector(self.vHave)
return r
@@ -323,7 +326,7 @@ class COutPoint(object):
self.n = struct.unpack("<I", f.read(4))[0]
def serialize(self):
- r = ""
+ r = b""
r += ser_uint256(self.hash)
r += struct.pack("<I", self.n)
return r
@@ -333,7 +336,7 @@ class COutPoint(object):
class CTxIn(object):
- def __init__(self, outpoint=None, scriptSig="", nSequence=0):
+ def __init__(self, outpoint=None, scriptSig=b"", nSequence=0):
if outpoint is None:
self.prevout = COutPoint()
else:
@@ -348,7 +351,7 @@ class CTxIn(object):
self.nSequence = struct.unpack("<I", f.read(4))[0]
def serialize(self):
- r = ""
+ r = b""
r += self.prevout.serialize()
r += ser_string(self.scriptSig)
r += struct.pack("<I", self.nSequence)
@@ -356,12 +359,12 @@ class CTxIn(object):
def __repr__(self):
return "CTxIn(prevout=%s scriptSig=%s nSequence=%i)" \
- % (repr(self.prevout), binascii.hexlify(self.scriptSig),
+ % (repr(self.prevout), hexlify(self.scriptSig),
self.nSequence)
class CTxOut(object):
- def __init__(self, nValue=0, scriptPubKey=""):
+ def __init__(self, nValue=0, scriptPubKey=b""):
self.nValue = nValue
self.scriptPubKey = scriptPubKey
@@ -370,15 +373,15 @@ class CTxOut(object):
self.scriptPubKey = deser_string(f)
def serialize(self):
- r = ""
+ r = b""
r += struct.pack("<q", self.nValue)
r += ser_string(self.scriptPubKey)
return r
def __repr__(self):
return "CTxOut(nValue=%i.%08i scriptPubKey=%s)" \
- % (self.nValue // 100000000, self.nValue % 100000000,
- binascii.hexlify(self.scriptPubKey))
+ % (self.nValue // COIN, self.nValue % COIN,
+ hexlify(self.scriptPubKey))
class CTransaction(object):
@@ -407,7 +410,7 @@ class CTransaction(object):
self.hash = None
def serialize(self):
- r = ""
+ r = b""
r += struct.pack("<i", self.nVersion)
r += ser_vector(self.vin)
r += ser_vector(self.vout)
@@ -421,12 +424,12 @@ class CTransaction(object):
def calc_sha256(self):
if self.sha256 is None:
self.sha256 = uint256_from_str(hash256(self.serialize()))
- self.hash = hash256(self.serialize())[::-1].encode('hex_codec')
+ self.hash = encode(hash256(self.serialize())[::-1], 'hex_codec').decode('ascii')
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
@@ -471,7 +474,7 @@ class CBlockHeader(object):
self.hash = None
def serialize(self):
- r = ""
+ r = b""
r += struct.pack("<i", self.nVersion)
r += ser_uint256(self.hashPrevBlock)
r += ser_uint256(self.hashMerkleRoot)
@@ -482,7 +485,7 @@ class CBlockHeader(object):
def calc_sha256(self):
if self.sha256 is None:
- r = ""
+ r = b""
r += struct.pack("<i", self.nVersion)
r += ser_uint256(self.hashPrevBlock)
r += ser_uint256(self.hashMerkleRoot)
@@ -490,7 +493,7 @@ class CBlockHeader(object):
r += struct.pack("<I", self.nBits)
r += struct.pack("<I", self.nNonce)
self.sha256 = uint256_from_str(hash256(r))
- self.hash = hash256(r)[::-1].encode('hex_codec')
+ self.hash = encode(hash256(r)[::-1], 'hex_codec').decode('ascii')
def rehash(self):
self.sha256 = None
@@ -513,7 +516,7 @@ class CBlock(CBlockHeader):
self.vtx = deser_vector(f, CTransaction)
def serialize(self):
- r = ""
+ r = b""
r += super(CBlock, self).serialize()
r += ser_vector(self.vtx)
return r
@@ -568,9 +571,9 @@ class CUnsignedAlert(object):
self.nMaxVer = 0
self.setSubVer = []
self.nPriority = 0
- self.strComment = ""
- self.strStatusBar = ""
- self.strReserved = ""
+ self.strComment = b""
+ self.strStatusBar = b""
+ self.strReserved = b""
def deserialize(self, f):
self.nVersion = struct.unpack("<i", f.read(4))[0]
@@ -588,7 +591,7 @@ class CUnsignedAlert(object):
self.strReserved = deser_string(f)
def serialize(self):
- r = ""
+ r = b""
r += struct.pack("<i", self.nVersion)
r += struct.pack("<q", self.nRelayUntil)
r += struct.pack("<q", self.nExpiration)
@@ -613,8 +616,8 @@ class CUnsignedAlert(object):
class CAlert(object):
def __init__(self):
- self.vchMsg = ""
- self.vchSig = ""
+ self.vchMsg = b""
+ self.vchSig = b""
def deserialize(self, f):
self.vchMsg = deser_string(f)
@@ -633,12 +636,12 @@ class CAlert(object):
# Objects that correspond to messages on the wire
class msg_version(object):
- command = "version"
+ command = b"version"
def __init__(self):
self.nVersion = MY_VERSION
self.nServices = 1
- self.nTime = time.time()
+ self.nTime = int(time.time())
self.addrTo = CAddress()
self.addrFrom = CAddress()
self.nNonce = random.getrandbits(64)
@@ -669,7 +672,7 @@ class msg_version(object):
self.nStartingHeight = None
def serialize(self):
- r = ""
+ r = b""
r += struct.pack("<i", self.nVersion)
r += struct.pack("<Q", self.nServices)
r += struct.pack("<q", self.nTime)
@@ -688,7 +691,7 @@ class msg_version(object):
class msg_verack(object):
- command = "verack"
+ command = b"verack"
def __init__(self):
pass
@@ -697,14 +700,14 @@ class msg_verack(object):
pass
def serialize(self):
- return ""
+ return b""
def __repr__(self):
return "msg_verack()"
class msg_addr(object):
- command = "addr"
+ command = b"addr"
def __init__(self):
self.addrs = []
@@ -720,7 +723,7 @@ class msg_addr(object):
class msg_alert(object):
- command = "alert"
+ command = b"alert"
def __init__(self):
self.alert = CAlert()
@@ -730,7 +733,7 @@ class msg_alert(object):
self.alert.deserialize(f)
def serialize(self):
- r = ""
+ r = b""
r += self.alert.serialize()
return r
@@ -739,7 +742,7 @@ class msg_alert(object):
class msg_inv(object):
- command = "inv"
+ command = b"inv"
def __init__(self, inv=None):
if inv is None:
@@ -758,7 +761,7 @@ class msg_inv(object):
class msg_getdata(object):
- command = "getdata"
+ command = b"getdata"
def __init__(self, inv=None):
self.inv = inv if inv != None else []
@@ -774,7 +777,7 @@ class msg_getdata(object):
class msg_getblocks(object):
- command = "getblocks"
+ command = b"getblocks"
def __init__(self):
self.locator = CBlockLocator()
@@ -786,7 +789,7 @@ class msg_getblocks(object):
self.hashstop = deser_uint256(f)
def serialize(self):
- r = ""
+ r = b""
r += self.locator.serialize()
r += ser_uint256(self.hashstop)
return r
@@ -797,7 +800,7 @@ class msg_getblocks(object):
class msg_tx(object):
- command = "tx"
+ command = b"tx"
def __init__(self, tx=CTransaction()):
self.tx = tx
@@ -813,7 +816,7 @@ class msg_tx(object):
class msg_block(object):
- command = "block"
+ command = b"block"
def __init__(self, block=None):
if block is None:
@@ -832,7 +835,7 @@ class msg_block(object):
class msg_getaddr(object):
- command = "getaddr"
+ command = b"getaddr"
def __init__(self):
pass
@@ -841,14 +844,14 @@ class msg_getaddr(object):
pass
def serialize(self):
- return ""
+ return b""
def __repr__(self):
return "msg_getaddr()"
class msg_ping_prebip31(object):
- command = "ping"
+ command = b"ping"
def __init__(self):
pass
@@ -857,14 +860,14 @@ class msg_ping_prebip31(object):
pass
def serialize(self):
- return ""
+ return b""
def __repr__(self):
return "msg_ping() (pre-bip31)"
class msg_ping(object):
- command = "ping"
+ command = b"ping"
def __init__(self, nonce=0L):
self.nonce = nonce
@@ -873,7 +876,7 @@ class msg_ping(object):
self.nonce = struct.unpack("<Q", f.read(8))[0]
def serialize(self):
- r = ""
+ r = b""
r += struct.pack("<Q", self.nonce)
return r
@@ -882,16 +885,16 @@ class msg_ping(object):
class msg_pong(object):
- command = "pong"
+ command = b"pong"
- def __init__(self, nonce=0L):
+ def __init__(self, nonce=0):
self.nonce = nonce
def deserialize(self, f):
self.nonce = struct.unpack("<Q", f.read(8))[0]
def serialize(self):
- r = ""
+ r = b""
r += struct.pack("<Q", self.nonce)
return r
@@ -900,7 +903,7 @@ class msg_pong(object):
class msg_mempool(object):
- command = "mempool"
+ command = b"mempool"
def __init__(self):
pass
@@ -909,13 +912,13 @@ class msg_mempool(object):
pass
def serialize(self):
- return ""
+ return b""
def __repr__(self):
return "msg_mempool()"
class msg_sendheaders(object):
- command = "sendheaders"
+ command = b"sendheaders"
def __init__(self):
pass
@@ -924,7 +927,7 @@ class msg_sendheaders(object):
pass
def serialize(self):
- return ""
+ return b""
def __repr__(self):
return "msg_sendheaders()"
@@ -934,7 +937,7 @@ class msg_sendheaders(object):
# vector of hashes
# hash_stop (hash of last desired block header, 0 to get as many as possible)
class msg_getheaders(object):
- command = "getheaders"
+ command = b"getheaders"
def __init__(self):
self.locator = CBlockLocator()
@@ -946,7 +949,7 @@ class msg_getheaders(object):
self.hashstop = deser_uint256(f)
def serialize(self):
- r = ""
+ r = b""
r += self.locator.serialize()
r += ser_uint256(self.hashstop)
return r
@@ -959,7 +962,7 @@ class msg_getheaders(object):
# headers message has
# <count> <vector of block headers>
class msg_headers(object):
- command = "headers"
+ command = b"headers"
def __init__(self):
self.headers = []
@@ -979,11 +982,12 @@ class msg_headers(object):
class msg_reject(object):
- command = "reject"
+ command = b"reject"
+ REJECT_MALFORMED = 1
def __init__(self):
- self.message = ""
- self.code = ""
+ self.message = b""
+ self.code = 0
self.reason = ""
self.data = 0L
@@ -991,14 +995,16 @@ class msg_reject(object):
self.message = deser_string(f)
self.code = struct.unpack("<B", f.read(1))[0]
self.reason = deser_string(f)
- if (self.message == "block" or self.message == "tx"):
+ if (self.code != self.REJECT_MALFORMED and
+ (self.message == b"block" or self.message == b"tx")):
self.data = deser_uint256(f)
def serialize(self):
r = ser_string(self.message)
r += struct.pack("<B", self.code)
r += ser_string(self.reason)
- if (self.message == "block" or self.message == "tx"):
+ if (self.code != self.REJECT_MALFORMED and
+ (self.message == b"block" or self.message == b"tx")):
r += ser_uint256(self.data)
return r
@@ -1006,6 +1012,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 = b"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 = b""
+ 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
@@ -1082,33 +1119,61 @@ 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
class NodeConn(asyncore.dispatcher):
messagemap = {
- "version": msg_version,
- "verack": msg_verack,
- "addr": msg_addr,
- "alert": msg_alert,
- "inv": msg_inv,
- "getdata": msg_getdata,
- "getblocks": msg_getblocks,
- "tx": msg_tx,
- "block": msg_block,
- "getaddr": msg_getaddr,
- "ping": msg_ping,
- "pong": msg_pong,
- "headers": msg_headers,
- "getheaders": msg_getheaders,
- "reject": msg_reject,
- "mempool": msg_mempool
+ b"version": msg_version,
+ b"verack": msg_verack,
+ b"addr": msg_addr,
+ b"alert": msg_alert,
+ b"inv": msg_inv,
+ b"getdata": msg_getdata,
+ b"getblocks": msg_getblocks,
+ b"tx": msg_tx,
+ b"block": msg_block,
+ b"getaddr": msg_getaddr,
+ b"ping": msg_ping,
+ b"pong": msg_pong,
+ b"headers": msg_headers,
+ b"getheaders": msg_getheaders,
+ b"reject": msg_reject,
+ b"mempool": msg_mempool,
+ b"feefilter": msg_feefilter
}
MAGIC_BYTES = {
- "mainnet": "\xf9\xbe\xb4\xd9", # mainnet
- "testnet3": "\x0b\x11\x09\x07", # testnet3
- "regtest": "\xfa\xbf\xb5\xda" # regtest
+ "mainnet": b"\xf9\xbe\xb4\xd9", # mainnet
+ "testnet3": b"\x0b\x11\x09\x07", # testnet3
+ "regtest": b"\xfa\xbf\xb5\xda" # regtest
}
def __init__(self, dstaddr, dstport, rpc, callback, net="regtest", services=1):
@@ -1117,8 +1182,8 @@ class NodeConn(asyncore.dispatcher):
self.dstaddr = dstaddr
self.dstport = dstport
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
- self.sendbuf = ""
- self.recvbuf = ""
+ self.sendbuf = b""
+ self.recvbuf = b""
self.ver_send = 209
self.ver_recv = 209
self.last_sent = 0
@@ -1155,8 +1220,8 @@ class NodeConn(asyncore.dispatcher):
self.show_debug_msg("MiniNode: Closing Connection to %s:%d... "
% (self.dstaddr, self.dstport))
self.state = "closed"
- self.recvbuf = ""
- self.sendbuf = ""
+ self.recvbuf = b""
+ self.sendbuf = b""
try:
self.close()
except:
@@ -1190,43 +1255,46 @@ class NodeConn(asyncore.dispatcher):
self.sendbuf = self.sendbuf[sent:]
def got_data(self):
- while True:
- if len(self.recvbuf) < 4:
- return
- if self.recvbuf[:4] != self.MAGIC_BYTES[self.network]:
- raise ValueError("got garbage %s" % repr(self.recvbuf))
- if self.ver_recv < 209:
- if len(self.recvbuf) < 4 + 12 + 4:
- return
- command = self.recvbuf[4:4+12].split("\x00", 1)[0]
- msglen = struct.unpack("<i", self.recvbuf[4+12:4+12+4])[0]
- checksum = None
- if len(self.recvbuf) < 4 + 12 + 4 + msglen:
- return
- msg = self.recvbuf[4+12+4:4+12+4+msglen]
- self.recvbuf = self.recvbuf[4+12+4+msglen:]
- else:
- if len(self.recvbuf) < 4 + 12 + 4 + 4:
- return
- command = self.recvbuf[4:4+12].split("\x00", 1)[0]
- msglen = struct.unpack("<i", self.recvbuf[4+12:4+12+4])[0]
- checksum = self.recvbuf[4+12+4:4+12+4+4]
- if len(self.recvbuf) < 4 + 12 + 4 + 4 + msglen:
+ try:
+ while True:
+ if len(self.recvbuf) < 4:
return
- msg = self.recvbuf[4+12+4+4:4+12+4+4+msglen]
- th = sha256(msg)
- h = sha256(th)
- if checksum != h[:4]:
- raise ValueError("got bad checksum " + repr(self.recvbuf))
- self.recvbuf = self.recvbuf[4+12+4+4+msglen:]
- if command in self.messagemap:
- f = cStringIO.StringIO(msg)
- t = self.messagemap[command]()
- t.deserialize(f)
- self.got_message(t)
- else:
- self.show_debug_msg("Unknown command: '" + command + "' " +
- repr(msg))
+ if self.recvbuf[:4] != self.MAGIC_BYTES[self.network]:
+ raise ValueError("got garbage %s" % repr(self.recvbuf))
+ if self.ver_recv < 209:
+ if len(self.recvbuf) < 4 + 12 + 4:
+ return
+ command = self.recvbuf[4:4+12].split(b"\x00", 1)[0]
+ msglen = struct.unpack("<i", self.recvbuf[4+12:4+12+4])[0]
+ checksum = None
+ if len(self.recvbuf) < 4 + 12 + 4 + msglen:
+ return
+ msg = self.recvbuf[4+12+4:4+12+4+msglen]
+ self.recvbuf = self.recvbuf[4+12+4+msglen:]
+ else:
+ if len(self.recvbuf) < 4 + 12 + 4 + 4:
+ return
+ command = self.recvbuf[4:4+12].split(b"\x00", 1)[0]
+ msglen = struct.unpack("<i", self.recvbuf[4+12:4+12+4])[0]
+ checksum = self.recvbuf[4+12+4:4+12+4+4]
+ if len(self.recvbuf) < 4 + 12 + 4 + 4 + msglen:
+ return
+ msg = self.recvbuf[4+12+4+4:4+12+4+4+msglen]
+ th = sha256(msg)
+ h = sha256(th)
+ if checksum != h[:4]:
+ raise ValueError("got bad checksum " + repr(self.recvbuf))
+ self.recvbuf = self.recvbuf[4+12+4+4+msglen:]
+ if command in self.messagemap:
+ f = BytesIO(msg)
+ t = self.messagemap[command]()
+ t.deserialize(f)
+ self.got_message(t)
+ else:
+ self.show_debug_msg("Unknown command: '" + command + "' " +
+ repr(msg))
+ except Exception as e:
+ print 'got_data:', repr(e)
def send_message(self, message, pushbuf=False):
if self.state != "connected" and not pushbuf:
@@ -1236,7 +1304,7 @@ class NodeConn(asyncore.dispatcher):
data = message.serialize()
tmsg = self.MAGIC_BYTES[self.network]
tmsg += command
- tmsg += "\x00" * (12 - len(command))
+ tmsg += b"\x00" * (12 - len(command))
tmsg += struct.pack("<I", len(data))
if self.ver_send >= 209:
th = sha256(data)
@@ -1248,11 +1316,11 @@ class NodeConn(asyncore.dispatcher):
self.last_sent = time.time()
def got_message(self, message):
- if message.command == "version":
+ if message.command == b"version":
if message.nVersion <= BIP0031_VERSION:
- self.messagemap['ping'] = msg_ping_prebip31
+ self.messagemap[b'ping'] = msg_ping_prebip31
if self.last_sent + 30 * 60 < time.time():
- self.send_message(self.messagemap['ping']())
+ self.send_message(self.messagemap[b'ping']())
self.show_debug_msg("Recv %s" % repr(message))
self.cb.deliver(self, message)
diff --git a/qa/rpc-tests/test_framework/netutil.py b/qa/rpc-tests/test_framework/netutil.py
index 50daa87937..52a7ab7489 100644
--- a/qa/rpc-tests/test_framework/netutil.py
+++ b/qa/rpc-tests/test_framework/netutil.py
@@ -4,13 +4,14 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
# Linux network utilities
+
import sys
import socket
import fcntl
import struct
import array
import os
-import binascii
+from binascii import unhexlify, hexlify
# Roughly based on http://voorloopnul.com/blog/a-python-netstat-in-less-than-100-lines-of-code/ by Ricardo Pascal
STATE_ESTABLISHED = '01'
@@ -43,9 +44,9 @@ def _remove_empty(array):
def _convert_ip_port(array):
host,port = array.split(':')
# convert host from mangled-per-four-bytes form as used by kernel
- host = binascii.unhexlify(host)
+ host = unhexlify(host)
host_out = ''
- for x in range(0, len(host)/4):
+ for x in range(0, len(host) // 4):
(val,) = struct.unpack('=I', host[x*4:(x+1)*4])
host_out += '%08x' % val
@@ -94,7 +95,7 @@ def all_interfaces():
max_possible = 8 # initial value
while True:
bytes = max_possible * struct_size
- names = array.array('B', '\0' * bytes)
+ names = array.array('B', b'\0' * bytes)
outbytes = struct.unpack('iL', fcntl.ioctl(
s.fileno(),
0x8912, # SIOCGIFCONF
@@ -105,7 +106,7 @@ def all_interfaces():
else:
break
namestr = names.tostring()
- return [(namestr[i:i+16].split('\0', 1)[0],
+ return [(namestr[i:i+16].split(b'\0', 1)[0],
socket.inet_ntoa(namestr[i+20:i+24]))
for i in range(0, outbytes, struct_size)]
@@ -136,4 +137,19 @@ def addr_to_hex(addr):
addr = sub[0] + ([0] * nullbytes) + sub[1]
else:
raise ValueError('Could not parse address %s' % addr)
- return binascii.hexlify(bytearray(addr))
+ return hexlify(bytearray(addr)).decode('ascii')
+
+def test_ipv6_local():
+ '''
+ Check for (local) IPv6 support.
+ '''
+ import socket
+ # By using SOCK_DGRAM this will not actually make a connection, but it will
+ # fail if there is no route to IPv6 localhost.
+ have_ipv6 = True
+ try:
+ s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
+ s.connect(('::1', 0))
+ except socket.error:
+ have_ipv6 = False
+ return have_ipv6
diff --git a/qa/rpc-tests/test_framework/script.py b/qa/rpc-tests/test_framework/script.py
index bf5e25fb27..5fb5758f81 100644
--- a/qa/rpc-tests/test_framework/script.py
+++ b/qa/rpc-tests/test_framework/script.py
@@ -629,7 +629,7 @@ class CScriptNum(object):
neg = obj.value < 0
absvalue = -obj.value if neg else obj.value
while (absvalue):
- r.append(chr(absvalue & 0xff))
+ r.append(absvalue & 0xff)
absvalue >>= 8
if r[-1] & 0x80:
r.append(0x80 if neg else 0)
@@ -777,7 +777,7 @@ class CScript(bytes):
# need to change
def _repr(o):
if isinstance(o, bytes):
- return "x('%s')" % hexlify(o).decode('utf8')
+ return b"x('%s')" % hexlify(o).decode('ascii')
else:
return repr(o)
diff --git a/qa/rpc-tests/test_framework/socks5.py b/qa/rpc-tests/test_framework/socks5.py
index 1dbfb98d5d..f725d97701 100644
--- a/qa/rpc-tests/test_framework/socks5.py
+++ b/qa/rpc-tests/test_framework/socks5.py
@@ -102,7 +102,7 @@ class Socks5Connection(object):
addr = recvall(self.conn, 4)
elif atyp == AddressType.DOMAINNAME:
n = recvall(self.conn, 1)[0]
- addr = str(recvall(self.conn, n))
+ addr = recvall(self.conn, n)
elif atyp == AddressType.IPV6:
addr = recvall(self.conn, 16)
else:
@@ -117,7 +117,7 @@ class Socks5Connection(object):
self.serv.queue.put(cmdin)
print('Proxy: ', cmdin)
# Fall through to disconnect
- except Exception,e:
+ except Exception as e:
traceback.print_exc(file=sys.stderr)
self.serv.queue.put(e)
finally:
diff --git a/qa/rpc-tests/test_framework/test_framework.py b/qa/rpc-tests/test_framework/test_framework.py
index 584f318d0b..3b08cd1384 100755
--- a/qa/rpc-tests/test_framework/test_framework.py
+++ b/qa/rpc-tests/test_framework/test_framework.py
@@ -26,7 +26,7 @@ from .util import (
check_json_precision,
initialize_chain_clean,
)
-from authproxy import AuthServiceProxy, JSONRPCException
+from .authproxy import AuthServiceProxy, JSONRPCException
class BitcoinTestFramework(object):
@@ -140,7 +140,10 @@ class BitcoinTestFramework(object):
print("JSONRPC error: "+e.error['message'])
traceback.print_tb(sys.exc_info()[2])
except AssertionError as e:
- print("Assertion failed: "+e.message)
+ print("Assertion failed: "+ str(e))
+ traceback.print_tb(sys.exc_info()[2])
+ except KeyError as e:
+ print("key not found: "+ str(e))
traceback.print_tb(sys.exc_info()[2])
except Exception as e:
print("Unexpected exception caught during testing: "+str(e))
diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py
index 8c472a518d..27891f7f4c 100644
--- a/qa/rpc-tests/test_framework/util.py
+++ b/qa/rpc-tests/test_framework/util.py
@@ -1,6 +1,8 @@
# 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.
+
+
#
# Helpful routines for regression testing
#
@@ -9,6 +11,8 @@
import os
import sys
+from binascii import hexlify, unhexlify
+from base64 import b64encode
from decimal import Decimal, ROUND_DOWN
import json
import random
@@ -16,6 +20,7 @@ import shutil
import subprocess
import time
import re
+import errno
from . import coverage
from .authproxy import AuthServiceProxy, JSONRPCException
@@ -90,6 +95,15 @@ def check_json_precision():
def count_bytes(hex_string):
return len(bytearray.fromhex(hex_string))
+def bytes_to_hex_str(byte_str):
+ return hexlify(byte_str).decode('ascii')
+
+def hex_str_to_bytes(hex_str):
+ return unhexlify(hex_str.encode('ascii'))
+
+def str_to_b64str(string):
+ return b64encode(string.encode('utf-8')).decode('ascii')
+
def sync_blocks(rpc_connections, wait=1):
"""
Wait until everybody has the same block count
@@ -130,11 +144,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 +183,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 +191,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 +274,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 +293,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)
@@ -445,9 +478,40 @@ def assert_is_hash_string(string, length=64):
raise AssertionError(
"String %r contains invalid characters for a hash." % string)
+def assert_array_result(object_array, to_match, expected, should_not_find = False):
+ """
+ Pass in array of JSON objects, a dictionary with key/value pairs
+ to match against, and another dictionary with expected key/value
+ pairs.
+ If the should_not_find flag is true, to_match should not be found
+ in object_array
+ """
+ if should_not_find == True:
+ expected = { }
+ num_matched = 0
+ for item in object_array:
+ all_match = True
+ for key,value in to_match.items():
+ if item[key] != value:
+ all_match = False
+ if not all_match:
+ continue
+ elif should_not_find == True:
+ num_matched = num_matched+1
+ for key,value in expected.items():
+ if item[key] != value:
+ raise AssertionError("%s : expected %s=%s"%(str(item), str(key), str(value)))
+ num_matched = num_matched+1
+ if num_matched == 0 and should_not_find != True:
+ raise AssertionError("No objects matched %s"%(str(to_match)))
+ if num_matched > 0 and should_not_find == True:
+ raise AssertionError("Objects were found %s"%(str(to_match)))
+
def satoshi_round(amount):
- return Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN)
+ 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 +539,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 +559,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 = []
@@ -511,3 +587,7 @@ def create_lots_of_big_transactions(node, txouts, utxos, fee):
txid = node.sendrawtransaction(signresult["hex"], True)
txids.append(txid)
return txids
+
+def get_bip9_status(node, key):
+ info = node.getblockchaininfo()
+ return info['bip9_softforks'][key]
diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py
index 6cd879e4a0..555f836482 100755
--- a/qa/rpc-tests/wallet.py
+++ b/qa/rpc-tests/wallet.py
@@ -32,6 +32,12 @@ class WalletTest (BitcoinTestFramework):
self.sync_all()
def run_test (self):
+
+ # Check that there's no UTXO on none of the nodes
+ assert_equal(len(self.nodes[0].listunspent()), 0)
+ assert_equal(len(self.nodes[1].listunspent()), 0)
+ assert_equal(len(self.nodes[2].listunspent()), 0)
+
print "Mining blocks..."
self.nodes[0].generate(1)
@@ -48,6 +54,11 @@ class WalletTest (BitcoinTestFramework):
assert_equal(self.nodes[1].getbalance(), 50)
assert_equal(self.nodes[2].getbalance(), 0)
+ # Check that only first and second nodes have UTXOs
+ assert_equal(len(self.nodes[0].listunspent()), 1)
+ assert_equal(len(self.nodes[1].listunspent()), 1)
+ assert_equal(len(self.nodes[2].listunspent()), 0)
+
# Send 21 BTC from 0 to 2 using sendtoaddress call.
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11)
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10)
@@ -59,6 +70,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 +168,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
@@ -232,28 +256,62 @@ class WalletTest (BitcoinTestFramework):
txObj = self.nodes[0].gettransaction(txId)
assert_equal(txObj['amount'], Decimal('-0.0001'))
- #this should fail
- errorString = ""
try:
txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "1f-4")
- except JSONRPCException,e:
- errorString = e.error['message']
+ except JSONRPCException as e:
+ assert("Invalid amount" in e.error['message'])
+ else:
+ raise AssertionError("Must not parse invalid amounts")
- assert_equal("Invalid amount" in errorString, True)
- errorString = ""
try:
- self.nodes[0].generate("2") #use a string to as block amount parameter must fail because it's not interpreted as amount
- except JSONRPCException,e:
- errorString = e.error['message']
+ self.nodes[0].generate("2")
+ raise AssertionError("Must not accept strings as numeric")
+ except JSONRPCException as e:
+ assert("not an integer" in e.error['message'])
+
+ # Import address and private key to check correct behavior of spendable unspents
+ # 1. Send some coins to generate new UTXO
+ address_to_import = self.nodes[2].getnewaddress()
+ txid = self.nodes[0].sendtoaddress(address_to_import, 1)
+ self.nodes[0].generate(1)
+ self.sync_all()
+
+ # 2. Import address from node2 to node1
+ self.nodes[1].importaddress(address_to_import)
- assert_equal("not an integer" in errorString, True)
+ # 3. Validate that the imported address is watch-only on node1
+ assert(self.nodes[1].validateaddress(address_to_import)["iswatchonly"])
+
+ # 4. Check that the unspents after import are not spendable
+ assert_array_result(self.nodes[1].listunspent(),
+ {"address": address_to_import},
+ {"spendable": False})
+
+ # 5. Import private key of the previously imported address on node1
+ priv_key = self.nodes[2].dumpprivkey(address_to_import)
+ self.nodes[1].importprivkey(priv_key)
+
+ # 6. Check that the unspents are now spendable on node1
+ assert_array_result(self.nodes[1].listunspent(),
+ {"address": address_to_import},
+ {"spendable": True})
+
+ # 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
+ self.nodes[1].gettransaction(cbTxId)
#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 +325,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/qa/rpc-tests/zmq_test.py b/qa/rpc-tests/zmq_test.py
index 88532541ab..97850bea3c 100755
--- a/qa/rpc-tests/zmq_test.py
+++ b/qa/rpc-tests/zmq_test.py
@@ -11,6 +11,7 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
import zmq
import binascii
+import struct
try:
import http.client as httplib
@@ -28,8 +29,8 @@ class ZMQTest (BitcoinTestFramework):
def setup_nodes(self):
self.zmqContext = zmq.Context()
self.zmqSubSocket = self.zmqContext.socket(zmq.SUB)
- self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, "hashblock")
- self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, "hashtx")
+ self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashblock")
+ self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashtx")
self.zmqSubSocket.connect("tcp://127.0.0.1:%i" % self.port)
return start_nodes(4, self.options.tmpdir, extra_args=[
['-zmqpubhashtx=tcp://127.0.0.1:'+str(self.port), '-zmqpubhashblock=tcp://127.0.0.1:'+str(self.port)],
@@ -46,13 +47,19 @@ class ZMQTest (BitcoinTestFramework):
print "listen..."
msg = self.zmqSubSocket.recv_multipart()
- topic = str(msg[0])
+ topic = msg[0]
+ assert_equal(topic, b"hashtx")
body = msg[1]
+ nseq = msg[2]
+ msgSequence = struct.unpack('<I', msg[-1])[-1]
+ assert_equal(msgSequence, 0) #must be sequence 0 on hashtx
msg = self.zmqSubSocket.recv_multipart()
- topic = str(msg[0])
+ topic = msg[0]
body = msg[1]
- blkhash = binascii.hexlify(body)
+ msgSequence = struct.unpack('<I', msg[-1])[-1]
+ assert_equal(msgSequence, 0) #must be sequence 0 on hashblock
+ blkhash = bytes_to_hex_str(body)
assert_equal(genhashes[0], blkhash) #blockhash from generate must be equal to the hash received over zmq
@@ -61,12 +68,16 @@ class ZMQTest (BitcoinTestFramework):
self.sync_all()
zmqHashes = []
+ blockcount = 0
for x in range(0,n*2):
msg = self.zmqSubSocket.recv_multipart()
- topic = str(msg[0])
+ topic = msg[0]
body = msg[1]
- if topic == "hashblock":
- zmqHashes.append(binascii.hexlify(body))
+ if topic == b"hashblock":
+ zmqHashes.append(bytes_to_hex_str(body))
+ msgSequence = struct.unpack('<I', msg[-1])[-1]
+ assert_equal(msgSequence, blockcount+1)
+ blockcount += 1
for x in range(0,n):
assert_equal(genhashes[x], zmqHashes[x]) #blockhash from generate must be equal to the hash received over zmq
@@ -77,11 +88,13 @@ class ZMQTest (BitcoinTestFramework):
# now we should receive a zmq msg because the tx was broadcast
msg = self.zmqSubSocket.recv_multipart()
- topic = str(msg[0])
+ topic = msg[0]
body = msg[1]
hashZMQ = ""
- if topic == "hashtx":
- hashZMQ = binascii.hexlify(body)
+ if topic == b"hashtx":
+ hashZMQ = bytes_to_hex_str(body)
+ msgSequence = struct.unpack('<I', msg[-1])[-1]
+ assert_equal(msgSequence, blockcount+1)
assert_equal(hashRPC, hashZMQ) #blockhash from generate must be equal to the hash received over zmq
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/setup.nsi.in b/share/setup.nsi.in
index e553a5ae88..c062f96a30 100644
--- a/share/setup.nsi.in
+++ b/share/setup.nsi.in
@@ -20,7 +20,7 @@ SetCompressor /SOLID lzma
!define MUI_STARTMENUPAGE_REGISTRY_KEY ${REGKEY}
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME StartMenuGroup
!define MUI_STARTMENUPAGE_DEFAULTFOLDER "@PACKAGE_NAME@"
-!define MUI_FINISHPAGE_RUN $INSTDIR\bitcoin-qt.exe
+!define MUI_FINISHPAGE_RUN $INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@
!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "@abs_top_srcdir@/share/pixmaps/nsis-wizard.bmp"
!define MUI_UNFINISHPAGE_NOAUTOCLOSE
@@ -48,7 +48,7 @@ Var StartMenuGroup
!insertmacro MUI_LANGUAGE English
# Installer attributes
-OutFile @abs_top_srcdir@/bitcoin-${VERSION}-win@WINDOWS_BITS@-setup.exe
+OutFile @abs_top_srcdir@/@PACKAGE_TARNAME@-${VERSION}-win@WINDOWS_BITS@-setup.exe
!if "@WINDOWS_BITS@" == "64"
InstallDir $PROGRAMFILES64\Bitcoin
!else
@@ -73,20 +73,16 @@ ShowUninstDetails show
Section -Main SEC0000
SetOutPath $INSTDIR
SetOverwrite on
- File @abs_top_srcdir@/release/bitcoin-qt.exe
+ File @abs_top_srcdir@/release/@BITCOIN_GUI_NAME@@EXEEXT@
File /oname=COPYING.txt @abs_top_srcdir@/COPYING
File /oname=readme.txt @abs_top_srcdir@/doc/README_windows.txt
SetOutPath $INSTDIR\daemon
- File @abs_top_srcdir@/release/bitcoind.exe
- File @abs_top_srcdir@/release/bitcoin-cli.exe
+ File @abs_top_srcdir@/release/@BITCOIN_DAEMON_NAME@@EXEEXT@
+ File @abs_top_srcdir@/release/@BITCOIN_CLI_NAME@@EXEEXT@
SetOutPath $INSTDIR\doc
File /r @abs_top_srcdir@/doc\*.*
SetOutPath $INSTDIR
WriteRegStr HKCU "${REGKEY}\Components" Main 1
-
- # Remove old wxwidgets-based-bitcoin executable and locales:
- Delete /REBOOTOK $INSTDIR\bitcoin.exe
- RMDir /r /REBOOTOK $INSTDIR\locale
SectionEnd
Section -post SEC0001
@@ -95,7 +91,7 @@ Section -post SEC0001
WriteUninstaller $INSTDIR\uninstall.exe
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
CreateDirectory $SMPROGRAMS\$StartMenuGroup
- CreateShortcut "$SMPROGRAMS\$StartMenuGroup\$(^Name).lnk" $INSTDIR\bitcoin-qt.exe
+ CreateShortcut "$SMPROGRAMS\$StartMenuGroup\$(^Name).lnk" $INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@
CreateShortcut "$SMPROGRAMS\$StartMenuGroup\Uninstall $(^Name).lnk" $INSTDIR\uninstall.exe
!insertmacro MUI_STARTMENU_WRITE_END
WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" DisplayName "$(^Name)"
@@ -106,10 +102,10 @@ Section -post SEC0001
WriteRegStr HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" UninstallString $INSTDIR\uninstall.exe
WriteRegDWORD HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoModify 1
WriteRegDWORD HKCU "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(^Name)" NoRepair 1
- WriteRegStr HKCR "bitcoin" "URL Protocol" ""
- WriteRegStr HKCR "bitcoin" "" "URL:Bitcoin"
- WriteRegStr HKCR "bitcoin\DefaultIcon" "" $INSTDIR\bitcoin-qt.exe
- WriteRegStr HKCR "bitcoin\shell\open\command" "" '"$INSTDIR\bitcoin-qt.exe" "%1"'
+ WriteRegStr HKCR "@PACKAGE_TARNAME@" "URL Protocol" ""
+ WriteRegStr HKCR "@PACKAGE_TARNAME@" "" "URL:Bitcoin"
+ WriteRegStr HKCR "@PACKAGE_TARNAME@\DefaultIcon" "" $INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@
+ WriteRegStr HKCR "@PACKAGE_TARNAME@\shell\open\command" "" '"$INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@" "%1"'
SectionEnd
# Macro for selecting uninstaller sections
@@ -127,7 +123,7 @@ done${UNSECTION_ID}:
# Uninstaller sections
Section /o -un.Main UNSEC0000
- Delete /REBOOTOK $INSTDIR\bitcoin-qt.exe
+ Delete /REBOOTOK $INSTDIR\@BITCOIN_GUI_NAME@@EXEEXT@
Delete /REBOOTOK $INSTDIR\COPYING.txt
Delete /REBOOTOK $INSTDIR\readme.txt
RMDir /r /REBOOTOK $INSTDIR\daemon
@@ -147,7 +143,7 @@ Section -un.post UNSEC0001
DeleteRegValue HKCU "${REGKEY}" Path
DeleteRegKey /IfEmpty HKCU "${REGKEY}\Components"
DeleteRegKey /IfEmpty HKCU "${REGKEY}"
- DeleteRegKey HKCR "bitcoin"
+ DeleteRegKey HKCR "@PACKAGE_TARNAME@"
RmDir /REBOOTOK $SMPROGRAMS\$StartMenuGroup
RmDir /REBOOTOK $INSTDIR
Push $R0
diff --git a/src/Makefile.am b/src/Makefile.am
index fa7a78f330..3c056386fa 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,6 +3,7 @@ DIST_SUBDIRS = secp256k1 univalue
AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(HARDENED_LDFLAGS)
AM_CXXFLAGS = $(HARDENED_CXXFLAGS)
AM_CPPFLAGS = $(HARDENED_CPPFLAGS)
+EXTRA_LIBRARIES =
if EMBEDDED_UNIVALUE
LIBUNIVALUE = univalue/libunivalue.la
@@ -13,21 +14,6 @@ else
LIBUNIVALUE = $(UNIVALUE_LIBS)
endif
-if EMBEDDED_LEVELDB
-LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/include
-LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/helpers/memenv
-LIBLEVELDB += $(builddir)/leveldb/libleveldb.a
-LIBMEMENV += $(builddir)/leveldb/libmemenv.a
-
-# NOTE: This dependency is not strictly necessary, but without it make may try to build both in parallel, which breaks the LevelDB build system in a race
-$(LIBLEVELDB): $(LIBMEMENV)
-
-$(LIBLEVELDB) $(LIBMEMENV):
- @echo "Building LevelDB ..." && $(MAKE) -C $(@D) $(@F) CXX="$(CXX)" \
- CC="$(CC)" PLATFORM=$(TARGET_OS) AR="$(AR)" $(LEVELDB_TARGET_FLAGS) \
- OPT="$(AM_CXXFLAGS) $(PIE_FLAGS) $(CXXFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -D__STDC_LIMIT_MACROS"
-endif
-
BITCOIN_CONFIG_INCLUDES=-I$(builddir)/config
BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS)
@@ -49,7 +35,7 @@ $(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*)
# Make is not made aware of per-object dependencies to avoid limiting building parallelization
# But to build the less dependent modules first, we manually select their order here:
-EXTRA_LIBRARIES = \
+EXTRA_LIBRARIES += \
crypto/libbitcoin_crypto.a \
libbitcoin_util.a \
libbitcoin_common.a \
@@ -87,7 +73,6 @@ endif
# bitcoin core #
BITCOIN_CORE_H = \
addrman.h \
- alert.h \
base58.h \
bloom.h \
chain.h \
@@ -131,10 +116,12 @@ BITCOIN_CORE_H = \
rpc/client.h \
rpc/protocol.h \
rpc/server.h \
+ rpc/register.h \
scheduler.h \
script/sigcache.h \
script/sign.h \
script/standard.h \
+ script/ismine.h \
streams.h \
support/allocators/secure.h \
support/allocators/zeroafterfree.h \
@@ -152,11 +139,11 @@ BITCOIN_CORE_H = \
utilmoneystr.h \
utiltime.h \
validationinterface.h \
+ versionbits.h \
wallet/crypter.h \
wallet/db.h \
wallet/rpcwallet.h \
wallet/wallet.h \
- wallet/wallet_ismine.h \
wallet/walletdb.h \
zmq/zmqabstractnotifier.h \
zmq/zmqconfig.h\
@@ -175,7 +162,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 \
@@ -199,11 +185,14 @@ libbitcoin_server_a_SOURCES = \
rpc/rawtransaction.cpp \
rpc/server.cpp \
script/sigcache.cpp \
+ script/ismine.cpp \
timedata.cpp \
torcontrol.cpp \
txdb.cpp \
txmempool.cpp \
+ ui_interface.cpp \
validationinterface.cpp \
+ versionbits.cpp \
$(BITCOIN_CORE_H)
if ENABLE_ZMQ
@@ -228,7 +217,6 @@ libbitcoin_wallet_a_SOURCES = \
wallet/rpcdump.cpp \
wallet/rpcwallet.cpp \
wallet/wallet.cpp \
- wallet/wallet_ismine.cpp \
wallet/walletdb.cpp \
policy/rbf.cpp \
$(BITCOIN_CORE_H)
@@ -478,7 +466,11 @@ endif
%.pb.cc %.pb.h: %.proto
@test -f $(PROTOC)
- $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(abspath $(<D) $<)
+ $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$(<D) $<
+
+if EMBEDDED_LEVELDB
+include Makefile.leveldb.include
+endif
if ENABLE_TESTS
include Makefile.test.include
diff --git a/src/Makefile.leveldb.include b/src/Makefile.leveldb.include
new file mode 100644
index 0000000000..36a6bc4095
--- /dev/null
+++ b/src/Makefile.leveldb.include
@@ -0,0 +1,81 @@
+LIBLEVELDB_INT = leveldb/libleveldb.a
+LIBMEMENV_INT = leveldb/libmemenv.a
+
+EXTRA_LIBRARIES += $(LIBLEVELDB_INT)
+EXTRA_LIBRARIES += $(LIBMEMENV_INT)
+
+LIBLEVELDB += $(LIBLEVELDB_INT)
+LIBMEMENV += $(LIBMEMENV_INT)
+
+LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/include
+LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/helpers/memenv
+
+LEVELDB_CPPFLAGS_INT =
+LEVELDB_CPPFLAGS_INT += -I$(srcdir)/leveldb
+LEVELDB_CPPFLAGS_INT += $(LEVELDB_TARGET_FLAGS)
+LEVELDB_CPPFLAGS_INT += $(LEVELDB_ATOMIC_CPPFLAGS)
+LEVELDB_CPPFLAGS_INT += -D__STDC_LIMIT_MACROS
+
+if TARGET_WINDOWS
+LEVELDB_CPPFLAGS_INT += -DLEVELDB_PLATFORM_WINDOWS -DWINVER=0x0500 -D__USE_MINGW_ANSI_STDIO=1
+else
+LEVELDB_CPPFLAGS_INT += -DLEVELDB_PLATFORM_POSIX
+endif
+
+LEVELDB_CXXFLAGS_INT =
+LEVELDB_CXXFLAGS_INT += $(LEVELDB_ATOMIC_CXXFLAGS)
+
+leveldb_libleveldb_a_CPPFLAGS = $(AM_CPPFLAGS) $(LEVELDB_CPPFLAGS_INT) $(LEVELDB_CPPFLAGS)
+leveldb_libleveldb_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) $(LEVELDB_CXXFLAGS_INT)
+
+leveldb_libleveldb_a_SOURCES=
+leveldb_libleveldb_a_SOURCES += leveldb/db/builder.cc
+leveldb_libleveldb_a_SOURCES += leveldb/db/c.cc
+leveldb_libleveldb_a_SOURCES += leveldb/db/dbformat.cc
+leveldb_libleveldb_a_SOURCES += leveldb/db/db_impl.cc
+leveldb_libleveldb_a_SOURCES += leveldb/db/db_iter.cc
+leveldb_libleveldb_a_SOURCES += leveldb/db/dumpfile.cc
+leveldb_libleveldb_a_SOURCES += leveldb/db/filename.cc
+leveldb_libleveldb_a_SOURCES += leveldb/db/log_reader.cc
+leveldb_libleveldb_a_SOURCES += leveldb/db/log_writer.cc
+leveldb_libleveldb_a_SOURCES += leveldb/db/memtable.cc
+leveldb_libleveldb_a_SOURCES += leveldb/db/repair.cc
+leveldb_libleveldb_a_SOURCES += leveldb/db/table_cache.cc
+leveldb_libleveldb_a_SOURCES += leveldb/db/version_edit.cc
+leveldb_libleveldb_a_SOURCES += leveldb/db/version_set.cc
+leveldb_libleveldb_a_SOURCES += leveldb/db/write_batch.cc
+leveldb_libleveldb_a_SOURCES += leveldb/table/block_builder.cc
+leveldb_libleveldb_a_SOURCES += leveldb/table/block.cc
+leveldb_libleveldb_a_SOURCES += leveldb/table/filter_block.cc
+leveldb_libleveldb_a_SOURCES += leveldb/table/format.cc
+leveldb_libleveldb_a_SOURCES += leveldb/table/iterator.cc
+leveldb_libleveldb_a_SOURCES += leveldb/table/merger.cc
+leveldb_libleveldb_a_SOURCES += leveldb/table/table_builder.cc
+leveldb_libleveldb_a_SOURCES += leveldb/table/table.cc
+leveldb_libleveldb_a_SOURCES += leveldb/table/two_level_iterator.cc
+leveldb_libleveldb_a_SOURCES += leveldb/util/arena.cc
+leveldb_libleveldb_a_SOURCES += leveldb/util/bloom.cc
+leveldb_libleveldb_a_SOURCES += leveldb/util/cache.cc
+leveldb_libleveldb_a_SOURCES += leveldb/util/coding.cc
+leveldb_libleveldb_a_SOURCES += leveldb/util/comparator.cc
+leveldb_libleveldb_a_SOURCES += leveldb/util/crc32c.cc
+leveldb_libleveldb_a_SOURCES += leveldb/util/env.cc
+leveldb_libleveldb_a_SOURCES += leveldb/util/env_posix.cc
+leveldb_libleveldb_a_SOURCES += leveldb/util/env_win.cc
+leveldb_libleveldb_a_SOURCES += leveldb/util/filter_policy.cc
+leveldb_libleveldb_a_SOURCES += leveldb/util/hash.cc
+leveldb_libleveldb_a_SOURCES += leveldb/util/histogram.cc
+leveldb_libleveldb_a_SOURCES += leveldb/util/logging.cc
+leveldb_libleveldb_a_SOURCES += leveldb/util/options.cc
+leveldb_libleveldb_a_SOURCES += leveldb/util/status.cc
+
+if TARGET_WINDOWS
+leveldb_libleveldb_a_SOURCES += leveldb/util/env_win.cc
+leveldb_libleveldb_a_SOURCES += leveldb/port/port_win.cc
+else
+leveldb_libleveldb_a_SOURCES += leveldb/port/port_posix.cc
+endif
+
+leveldb_libmemenv_a_CPPFLAGS = $(leveldb_libleveldb_a_CPPFLAGS)
+leveldb_libmemenv_a_CXXFLAGS = $(leveldb_libleveldb_a_CXXFLAGS)
+leveldb_libmemenv_a_SOURCES = leveldb/helpers/memenv/memenv.cc
diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index ca4e1e70d0..3b39919441 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -268,7 +268,8 @@ RES_ICONS = \
qt/res/icons/tx_output.png \
qt/res/icons/tx_mined.png \
qt/res/icons/warning.png \
- qt/res/icons/verify.png
+ qt/res/icons/verify.png \
+ qt/res/icons/transaction_abandoned.png
BITCOIN_QT_CPP = \
qt/bantablemodel.cpp \
@@ -391,7 +392,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"
@@ -423,11 +424,11 @@ ui_%.h: %.ui
$(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(UIC) -o $@ $< || (echo "Error creating $@"; false)
%.moc: %.cpp
- $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(MOC) $(QT_INCLUDES) $(MOC_DEFS) $< | \
+ $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(MOC) $(DEFAULT_INCLUDES) $(QT_INCLUDES) $(MOC_DEFS) $< | \
$(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@
moc_%.cpp: %.h
- $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(MOC) $(QT_INCLUDES) $(MOC_DEFS) $< | \
+ $(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(MOC) $(DEFAULT_INCLUDES) $(QT_INCLUDES) $(MOC_DEFS) $< | \
$(SED) -e '/^\*\*.*Created:/d' -e '/^\*\*.*by:/d' > $@
%.qm: %.ts
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 0c4e47a147..08e2f6af4d 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -20,16 +20,15 @@ EXTRA_DIST += \
test/data/txcreatesign.hex
JSON_TEST_FILES = \
- test/data/script_valid.json \
+ test/data/script_tests.json \
test/data/base58_keys_valid.json \
test/data/base58_encode_decode.json \
test/data/base58_keys_invalid.json \
- test/data/script_invalid.json \
test/data/tx_invalid.json \
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,6 +37,7 @@ 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 \
@@ -83,15 +83,18 @@ BITCOIN_TESTS =\
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
if ENABLE_WALLET
BITCOIN_TESTS += \
- test/accounting_tests.cpp \
+ wallet/test/wallet_test_fixture.cpp \
+ wallet/test/wallet_test_fixture.h \
+ wallet/test/accounting_tests.cpp \
wallet/test/wallet_tests.cpp \
- test/rpc_wallet_tests.cpp
+ wallet/test/rpc_wallet_tests.cpp
endif
test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES)
@@ -128,7 +131,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..7b8618de33 100644
--- a/src/amount.cpp
+++ b/src/amount.cpp
@@ -9,20 +9,30 @@
const std::string CURRENCY_UNIT = "BTC";
-CFeeRate::CFeeRate(const CAmount& nFeePaid, size_t nSize)
+CFeeRate::CFeeRate(const CAmount& nFeePaid, size_t nBytes_)
{
+ assert(nBytes_ <= uint64_t(std::numeric_limits<int64_t>::max()));
+ int64_t nSize = int64_t(nBytes_);
+
if (nSize > 0)
- nSatoshisPerK = nFeePaid*1000/nSize;
+ nSatoshisPerK = nFeePaid * 1000 / nSize;
else
nSatoshisPerK = 0;
}
-CAmount CFeeRate::GetFee(size_t nSize) const
+CAmount CFeeRate::GetFee(size_t nBytes_) const
{
- CAmount nFee = nSatoshisPerK*nSize / 1000;
+ assert(nBytes_ <= uint64_t(std::numeric_limits<int64_t>::max()));
+ int64_t nSize = int64_t(nBytes_);
+
+ CAmount nFee = nSatoshisPerK * nSize / 1000;
- if (nFee == 0 && nSatoshisPerK > 0)
- nFee = nSatoshisPerK;
+ if (nFee == 0 && nSize != 0) {
+ if (nSatoshisPerK > 0)
+ nFee = CAmount(1);
+ if (nSatoshisPerK < 0)
+ nFee = CAmount(-1);
+ }
return nFee;
}
diff --git a/src/amount.h b/src/amount.h
index a48b17d514..5e52f37f23 100644
--- a/src/amount.h
+++ b/src/amount.h
@@ -11,6 +11,7 @@
#include <stdlib.h>
#include <string>
+/** Amount in satoshis (Can be negative) */
typedef int64_t CAmount;
static const CAmount COIN = 100000000;
@@ -30,22 +31,28 @@ extern const std::string CURRENCY_UNIT;
static const CAmount MAX_MONEY = 21000000 * COIN;
inline bool MoneyRange(const CAmount& nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
-/** Type-safe wrapper class for fee rates
- * (how much to pay based on transaction size)
+/**
+ * Fee rate in satoshis per kilobyte: CAmount / kB
*/
class CFeeRate
{
private:
CAmount nSatoshisPerK; // unit is satoshis-per-1,000-bytes
public:
+ /** Fee rate of 0 satoshis per kB */
CFeeRate() : nSatoshisPerK(0) { }
explicit CFeeRate(const CAmount& _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) { }
- CFeeRate(const CAmount& nFeePaid, size_t nSize);
+ /** Constructor for a fee rate in satoshis per kB. The size in bytes must not exceed (2^63 - 1)*/
+ CFeeRate(const CAmount& nFeePaid, size_t nBytes);
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 nBytes) 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..d1d60a6f1d 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.
@@ -172,7 +177,7 @@ bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes)
vchData.resize(vchTemp.size() - nVersionBytes);
if (!vchData.empty())
memcpy(&vchData[0], &vchTemp[nVersionBytes], vchData.size());
- memory_cleanse(&vchTemp[0], vchData.size());
+ memory_cleanse(&vchTemp[0], vchTemp.size());
return true;
}
diff --git a/src/base58.h b/src/base58.h
index a3980118aa..cccebc9e0e 100644
--- a/src/base58.h
+++ b/src/base58.h
@@ -164,7 +164,7 @@ public:
CBitcoinExtKeyBase() {}
};
-typedef CBitcoinExtKeyBase<CExtKey, 74, CChainParams::EXT_SECRET_KEY> CBitcoinExtKey;
-typedef CBitcoinExtKeyBase<CExtPubKey, 74, CChainParams::EXT_PUBLIC_KEY> CBitcoinExtPubKey;
+typedef CBitcoinExtKeyBase<CExtKey, BIP32_EXTKEY_SIZE, CChainParams::EXT_SECRET_KEY> CBitcoinExtKey;
+typedef CBitcoinExtKeyBase<CExtPubKey, BIP32_EXTKEY_SIZE, CChainParams::EXT_PUBLIC_KEY> CBitcoinExtPubKey;
#endif // BITCOIN_BASE58_H
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..5c7d190125 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;
@@ -238,8 +266,8 @@ public:
assert(consensus.hashGenesisBlock == uint256S("0x0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206"));
assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
- vFixedSeeds.clear(); //! Regtest mode doesn't have any fixed seeds.
- vSeeds.clear(); //! Regtest mode doesn't have any DNS seeds.
+ vFixedSeeds.clear(); //!< Regtest mode doesn't have any fixed seeds.
+ vSeeds.clear(); //!< Regtest mode doesn't have any DNS seeds.
fMiningRequiresPeers = false;
fDefaultConsistencyChecks = true;
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/coins.cpp b/src/coins.cpp
index 877fb8b26c..1c329740b4 100644
--- a/src/coins.cpp
+++ b/src/coins.cpp
@@ -45,7 +45,7 @@ bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) const { return fal
bool CCoinsView::HaveCoins(const uint256 &txid) const { return false; }
uint256 CCoinsView::GetBestBlock() const { return uint256(); }
bool CCoinsView::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return false; }
-bool CCoinsView::GetStats(CCoinsStats &stats) const { return false; }
+CCoinsViewCursor *CCoinsView::Cursor() const { return 0; }
CCoinsViewBacked::CCoinsViewBacked(CCoinsView *viewIn) : base(viewIn) { }
@@ -54,7 +54,7 @@ bool CCoinsViewBacked::HaveCoins(const uint256 &txid) const { return base->HaveC
uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); }
void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); }
-bool CCoinsViewBacked::GetStats(CCoinsStats &stats) const { return base->GetStats(stats); }
+CCoinsViewCursor *CCoinsViewBacked::Cursor() const { return base->Cursor(); }
CCoinsKeyHasher::CCoinsKeyHasher() : salt(GetRandHash()) {}
@@ -300,3 +300,7 @@ CCoinsModifier::~CCoinsModifier()
cache.cachedCoinsUsage += it->second.coins.DynamicMemoryUsage();
}
}
+
+CCoinsViewCursor::~CCoinsViewCursor()
+{
+}
diff --git a/src/coins.h b/src/coins.h
index d297cae1aa..d72f885473 100644
--- a/src/coins.h
+++ b/src/coins.h
@@ -297,19 +297,26 @@ struct CCoinsCacheEntry
typedef boost::unordered_map<uint256, CCoinsCacheEntry, CCoinsKeyHasher> CCoinsMap;
-struct CCoinsStats
+/** Cursor for iterating over CoinsView state */
+class CCoinsViewCursor
{
- int nHeight;
- uint256 hashBlock;
- uint64_t nTransactions;
- uint64_t nTransactionOutputs;
- uint64_t nSerializedSize;
- uint256 hashSerialized;
- CAmount nTotalAmount;
+public:
+ CCoinsViewCursor(const uint256 &hashBlockIn): hashBlock(hashBlockIn) {}
+ virtual ~CCoinsViewCursor();
- CCoinsStats() : nHeight(0), nTransactions(0), nTransactionOutputs(0), nSerializedSize(0), nTotalAmount(0) {}
-};
+ virtual bool GetKey(uint256 &key) const = 0;
+ virtual bool GetValue(CCoins &coins) const = 0;
+ /* Don't care about GetKeySize here */
+ virtual unsigned int GetValueSize() const = 0;
+ virtual bool Valid() const = 0;
+ virtual void Next() = 0;
+
+ //! Get best block at the time this cursor was created
+ const uint256 &GetBestBlock() const { return hashBlock; }
+private:
+ uint256 hashBlock;
+};
/** Abstract view on the open txout dataset. */
class CCoinsView
@@ -329,8 +336,8 @@ public:
//! The passed mapCoins can be modified.
virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock);
- //! Calculate statistics about the unspent transaction output set
- virtual bool GetStats(CCoinsStats &stats) const;
+ //! Get a cursor to iterate over the whole state
+ virtual CCoinsViewCursor *Cursor() const;
//! As we use CCoinsViews polymorphically, have a virtual destructor
virtual ~CCoinsView() {}
@@ -350,7 +357,7 @@ public:
uint256 GetBestBlock() const;
void SetBackend(CCoinsView &viewIn);
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock);
- bool GetStats(CCoinsStats &stats) const;
+ CCoinsViewCursor *Cursor() const;
};
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/core_write.cpp b/src/core_write.cpp
index b660e86c30..6f9e2266a3 100644
--- a/src/core_write.cpp
+++ b/src/core_write.cpp
@@ -35,7 +35,7 @@ string FormatScript(const CScript& script)
} else if ((op >= OP_1 && op <= OP_16) || op == OP_1NEGATE) {
ret += strprintf("%i ", op - OP_1NEGATE - 1);
continue;
- } else if (op >= OP_NOP && op <= OP_CHECKMULTISIGVERIFY) {
+ } else if (op >= OP_NOP && op <= OP_NOP10) {
string str(GetOpName(op));
if (str.substr(0, 3) == string("OP_")) {
ret += str.substr(3, string::npos) + " ";
@@ -45,7 +45,7 @@ string FormatScript(const CScript& script)
if (vch.size() > 0) {
ret += strprintf("0x%x 0x%x ", HexStr(it2, it - vch.size()), HexStr(it - vch.size(), it));
} else {
- ret += strprintf("0x%x", HexStr(it2, it));
+ ret += strprintf("0x%x ", HexStr(it2, it));
}
continue;
}
diff --git a/src/crypto/ripemd160.h b/src/crypto/ripemd160.h
index 687204fdae..bd41f02508 100644
--- a/src/crypto/ripemd160.h
+++ b/src/crypto/ripemd160.h
@@ -14,7 +14,7 @@ class CRIPEMD160
private:
uint32_t s[5];
unsigned char buf[64];
- size_t bytes;
+ uint64_t bytes;
public:
static const size_t OUTPUT_SIZE = 20;
diff --git a/src/crypto/sha1.h b/src/crypto/sha1.h
index 7b2a21bc6c..8fb20810be 100644
--- a/src/crypto/sha1.h
+++ b/src/crypto/sha1.h
@@ -14,7 +14,7 @@ class CSHA1
private:
uint32_t s[5];
unsigned char buf[64];
- size_t bytes;
+ uint64_t bytes;
public:
static const size_t OUTPUT_SIZE = 20;
diff --git a/src/crypto/sha256.h b/src/crypto/sha256.h
index 85cf33739a..5b15b6a233 100644
--- a/src/crypto/sha256.h
+++ b/src/crypto/sha256.h
@@ -14,7 +14,7 @@ class CSHA256
private:
uint32_t s[8];
unsigned char buf[64];
- size_t bytes;
+ uint64_t bytes;
public:
static const size_t OUTPUT_SIZE = 32;
diff --git a/src/crypto/sha512.h b/src/crypto/sha512.h
index f1f17caf90..614681fae2 100644
--- a/src/crypto/sha512.h
+++ b/src/crypto/sha512.h
@@ -14,7 +14,7 @@ class CSHA512
private:
uint64_t s[8];
unsigned char buf[128];
- size_t bytes;
+ uint64_t bytes;
public:
static const size_t OUTPUT_SIZE = 64;
diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp
index 1907e2fa78..09c68fbe55 100644
--- a/src/dbwrapper.cpp
+++ b/src/dbwrapper.cpp
@@ -15,20 +15,6 @@
#include <memenv.h>
#include <stdint.h>
-void HandleError(const leveldb::Status& status) throw(dbwrapper_error)
-{
- if (status.ok())
- return;
- LogPrintf("%s\n", status.ToString());
- if (status.IsCorruption())
- throw dbwrapper_error("Database corrupted");
- if (status.IsIOError())
- throw dbwrapper_error("Database I/O error");
- if (status.IsNotFound())
- throw dbwrapper_error("Database entry missing");
- throw dbwrapper_error("Unknown database error");
-}
-
static leveldb::Options GetOptions(size_t nCacheSize)
{
leveldb::Options options;
@@ -61,13 +47,13 @@ CDBWrapper::CDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, b
if (fWipe) {
LogPrintf("Wiping LevelDB in %s\n", path.string());
leveldb::Status result = leveldb::DestroyDB(path.string(), options);
- HandleError(result);
+ dbwrapper_private::HandleError(result);
}
TryCreateDirectory(path);
LogPrintf("Opening LevelDB in %s\n", path.string());
}
leveldb::Status status = leveldb::DB::Open(options, path.string(), &pdb);
- HandleError(status);
+ dbwrapper_private::HandleError(status);
LogPrintf("Opened LevelDB successfully\n");
// The base-case obfuscation key, which is a noop.
@@ -84,10 +70,10 @@ CDBWrapper::CDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, b
Write(OBFUSCATE_KEY_KEY, new_key);
obfuscate_key = new_key;
- LogPrintf("Wrote new obfuscate key for %s: %s\n", path.string(), GetObfuscateKeyHex());
+ LogPrintf("Wrote new obfuscate key for %s: %s\n", path.string(), HexStr(obfuscate_key));
}
- LogPrintf("Using obfuscation key for %s: %s\n", path.string(), GetObfuscateKeyHex());
+ LogPrintf("Using obfuscation key for %s: %s\n", path.string(), HexStr(obfuscate_key));
}
CDBWrapper::~CDBWrapper()
@@ -102,10 +88,10 @@ CDBWrapper::~CDBWrapper()
options.env = NULL;
}
-bool CDBWrapper::WriteBatch(CDBBatch& batch, bool fSync) throw(dbwrapper_error)
+bool CDBWrapper::WriteBatch(CDBBatch& batch, bool fSync)
{
leveldb::Status status = pdb->Write(fSync ? syncoptions : writeoptions, &batch.batch);
- HandleError(status);
+ dbwrapper_private::HandleError(status);
return true;
}
@@ -136,17 +122,30 @@ bool CDBWrapper::IsEmpty()
return !(it->Valid());
}
-const std::vector<unsigned char>& CDBWrapper::GetObfuscateKey() const
+CDBIterator::~CDBIterator() { delete piter; }
+bool CDBIterator::Valid() { return piter->Valid(); }
+void CDBIterator::SeekToFirst() { piter->SeekToFirst(); }
+void CDBIterator::Next() { piter->Next(); }
+
+namespace dbwrapper_private {
+
+void HandleError(const leveldb::Status& status)
{
- return obfuscate_key;
+ if (status.ok())
+ return;
+ LogPrintf("%s\n", status.ToString());
+ if (status.IsCorruption())
+ throw dbwrapper_error("Database corrupted");
+ if (status.IsIOError())
+ throw dbwrapper_error("Database I/O error");
+ if (status.IsNotFound())
+ throw dbwrapper_error("Database entry missing");
+ throw dbwrapper_error("Unknown database error");
}
-std::string CDBWrapper::GetObfuscateKeyHex() const
+const std::vector<unsigned char>& GetObfuscateKey(const CDBWrapper &w)
{
- return HexStr(obfuscate_key);
+ return w.obfuscate_key;
}
-CDBIterator::~CDBIterator() { delete piter; }
-bool CDBIterator::Valid() { return piter->Valid(); }
-void CDBIterator::SeekToFirst() { piter->SeekToFirst(); }
-void CDBIterator::Next() { piter->Next(); }
+};
diff --git a/src/dbwrapper.h b/src/dbwrapper.h
index 5e7313f7eb..a0779d3ab9 100644
--- a/src/dbwrapper.h
+++ b/src/dbwrapper.h
@@ -23,7 +23,23 @@ public:
dbwrapper_error(const std::string& msg) : std::runtime_error(msg) {}
};
-void HandleError(const leveldb::Status& status) throw(dbwrapper_error);
+class CDBWrapper;
+
+/** These should be considered an implementation detail of the specific database.
+ */
+namespace dbwrapper_private {
+
+/** Handle database error by throwing dbwrapper_error exception.
+ */
+void HandleError(const leveldb::Status& status);
+
+/** Work around circular dependency, as well as for testing in dbwrapper_tests.
+ * Database obfuscation should be considered an implementation detail of the
+ * specific database.
+ */
+const std::vector<unsigned char>& GetObfuscateKey(const CDBWrapper &w);
+
+};
/** Batch of changes queued to be written to a CDBWrapper */
class CDBBatch
@@ -31,14 +47,14 @@ class CDBBatch
friend class CDBWrapper;
private:
+ const CDBWrapper &parent;
leveldb::WriteBatch batch;
- const std::vector<unsigned char> *obfuscate_key;
public:
/**
- * @param[in] obfuscate_key If passed, XOR data with this key.
+ * @param[in] parent CDBWrapper that this batch is to be submitted to
*/
- CDBBatch(const std::vector<unsigned char> *obfuscate_key) : obfuscate_key(obfuscate_key) { };
+ CDBBatch(const CDBWrapper &parent) : parent(parent) { };
template <typename K, typename V>
void Write(const K& key, const V& value)
@@ -51,7 +67,7 @@ public:
CDataStream ssValue(SER_DISK, CLIENT_VERSION);
ssValue.reserve(ssValue.GetSerializeSize(value));
ssValue << value;
- ssValue.Xor(*obfuscate_key);
+ ssValue.Xor(dbwrapper_private::GetObfuscateKey(parent));
leveldb::Slice slValue(&ssValue[0], ssValue.size());
batch.Put(slKey, slValue);
@@ -72,17 +88,17 @@ public:
class CDBIterator
{
private:
+ const CDBWrapper &parent;
leveldb::Iterator *piter;
- const std::vector<unsigned char> *obfuscate_key;
public:
/**
+ * @param[in] parent Parent CDBWrapper instance.
* @param[in] piterIn The original leveldb iterator.
- * @param[in] obfuscate_key If passed, XOR data with this key.
*/
- CDBIterator(leveldb::Iterator *piterIn, const std::vector<unsigned char>* obfuscate_key) :
- piter(piterIn), obfuscate_key(obfuscate_key) { };
+ CDBIterator(const CDBWrapper &parent, leveldb::Iterator *piterIn) :
+ parent(parent), piter(piterIn) { };
~CDBIterator();
bool Valid();
@@ -118,7 +134,7 @@ public:
leveldb::Slice slValue = piter->value();
try {
CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
- ssValue.Xor(*obfuscate_key);
+ ssValue.Xor(dbwrapper_private::GetObfuscateKey(parent));
ssValue >> value;
} catch (const std::exception&) {
return false;
@@ -134,6 +150,7 @@ public:
class CDBWrapper
{
+ friend const std::vector<unsigned char>& dbwrapper_private::GetObfuscateKey(const CDBWrapper &w);
private:
//! custom environment this database is using (may be NULL in case of default environment)
leveldb::Env* penv;
@@ -180,7 +197,7 @@ public:
~CDBWrapper();
template <typename K, typename V>
- bool Read(const K& key, V& value) const throw(dbwrapper_error)
+ bool Read(const K& key, V& value) const
{
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(ssKey.GetSerializeSize(key));
@@ -193,7 +210,7 @@ public:
if (status.IsNotFound())
return false;
LogPrintf("LevelDB read failure: %s\n", status.ToString());
- HandleError(status);
+ dbwrapper_private::HandleError(status);
}
try {
CDataStream ssValue(strValue.data(), strValue.data() + strValue.size(), SER_DISK, CLIENT_VERSION);
@@ -206,15 +223,15 @@ public:
}
template <typename K, typename V>
- bool Write(const K& key, const V& value, bool fSync = false) throw(dbwrapper_error)
+ bool Write(const K& key, const V& value, bool fSync = false)
{
- CDBBatch batch(&obfuscate_key);
+ CDBBatch batch(*this);
batch.Write(key, value);
return WriteBatch(batch, fSync);
}
template <typename K>
- bool Exists(const K& key) const throw(dbwrapper_error)
+ bool Exists(const K& key) const
{
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(ssKey.GetSerializeSize(key));
@@ -227,20 +244,20 @@ public:
if (status.IsNotFound())
return false;
LogPrintf("LevelDB read failure: %s\n", status.ToString());
- HandleError(status);
+ dbwrapper_private::HandleError(status);
}
return true;
}
template <typename K>
- bool Erase(const K& key, bool fSync = false) throw(dbwrapper_error)
+ bool Erase(const K& key, bool fSync = false)
{
- CDBBatch batch(&obfuscate_key);
+ CDBBatch batch(*this);
batch.Erase(key);
return WriteBatch(batch, fSync);
}
- bool WriteBatch(CDBBatch& batch, bool fSync = false) throw(dbwrapper_error);
+ bool WriteBatch(CDBBatch& batch, bool fSync = false);
// not available for LevelDB; provide for compatibility with BDB
bool Flush()
@@ -248,32 +265,21 @@ public:
return true;
}
- bool Sync() throw(dbwrapper_error)
+ bool Sync()
{
- CDBBatch batch(&obfuscate_key);
+ CDBBatch batch(*this);
return WriteBatch(batch, true);
}
CDBIterator *NewIterator()
{
- return new CDBIterator(pdb->NewIterator(iteroptions), &obfuscate_key);
+ return new CDBIterator(*this, pdb->NewIterator(iteroptions));
}
/**
* Return true if the database managed by this class contains no entries.
*/
bool IsEmpty();
-
- /**
- * Accessor for obfuscate_key.
- */
- const std::vector<unsigned char>& GetObfuscateKey() const;
-
- /**
- * Return the obfuscate_key as a hex-formatted string.
- */
- std::string GetObfuscateKeyHex() const;
-
};
#endif // BITCOIN_DBWRAPPER_H
diff --git a/src/init.cpp b/src/init.cpp
index 637b69ab05..b06f448a00 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"
@@ -63,9 +65,6 @@
using namespace std;
-#ifdef ENABLE_WALLET
-CWallet* pwalletMain = NULL;
-#endif
bool fFeeEstimatesInitialized = false;
static const bool DEFAULT_PROXYRANDOMIZE = true;
static const bool DEFAULT_REST_ENABLE = false;
@@ -95,7 +94,6 @@ enum BindFlags {
};
static const char* FEE_ESTIMATES_FILENAME="fee_estimates.dat";
-CClientUIInterface uiInterface; // Declared but not defined in ui_interface.h
//////////////////////////////////////////////////////////////////////////////
//
@@ -267,18 +265,6 @@ void HandleSIGHUP(int)
fReopenDebugLog = true;
}
-bool static InitError(const std::string &str)
-{
- uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_ERROR);
- return false;
-}
-
-bool static InitWarning(const std::string &str)
-{
- uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_WARNING);
- return true;
-}
-
bool static Bind(const CService &addr, unsigned int flags) {
if (!(flags & BF_EXPLICIT) && IsLimited(addr))
return false;
@@ -315,7 +301,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 +316,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 +351,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)"), DEFAULT_PEERBLOOMFILTERS));
- if (showDebug)
- strUsage += HelpMessageOpt("-enforcenodebloom", strprintf("Enforce minimum protocol version to limit use of bloom filters (default: %u)", DEFAULT_ENFORCENODEBLOOM));
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));
@@ -466,7 +451,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"));
@@ -744,11 +729,6 @@ static std::string ResolveErrMsg(const char * const optname, const std::string&
return strprintf(_("Cannot resolve -%s address: '%s'"), optname, strBind);
}
-static std::string AmountErrMsg(const char * const optname, const std::string& strValue)
-{
- return strprintf(_("Invalid amount for -%s=<amount>: '%s'"), optname, strValue);
-}
-
void InitLogging()
{
fPrintToConsole = GetBoolArg("-printtoconsole", false);
@@ -915,10 +895,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);
@@ -946,64 +927,14 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
nBytesPerSigOp = GetArg("-bytespersigop", nBytesPerSigOp);
#ifdef ENABLE_WALLET
- if (mapArgs.count("-mintxfee"))
- {
- CAmount n = 0;
- if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0)
- CWallet::minTxFee = CFeeRate(n);
- else
- return InitError(AmountErrMsg("mintxfee", mapArgs["-mintxfee"]));
- }
- if (mapArgs.count("-fallbackfee"))
- {
- CAmount nFeePerK = 0;
- if (!ParseMoney(mapArgs["-fallbackfee"], nFeePerK))
- return InitError(strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'"), mapArgs["-fallbackfee"]));
- if (nFeePerK > HIGH_TX_FEE_PER_KB)
- InitWarning(_("-fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available."));
- CWallet::fallbackFee = CFeeRate(nFeePerK);
- }
- if (mapArgs.count("-paytxfee"))
- {
- CAmount nFeePerK = 0;
- if (!ParseMoney(mapArgs["-paytxfee"], nFeePerK))
- return InitError(AmountErrMsg("paytxfee", mapArgs["-paytxfee"]));
- if (nFeePerK > HIGH_TX_FEE_PER_KB)
- InitWarning(_("-paytxfee is set very high! This is the transaction fee you will pay if you send a transaction."));
- payTxFee = CFeeRate(nFeePerK, 1000);
- if (payTxFee < ::minRelayTxFee)
- {
- return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
- mapArgs["-paytxfee"], ::minRelayTxFee.ToString()));
- }
- }
- if (mapArgs.count("-maxtxfee"))
- {
- CAmount nMaxFee = 0;
- if (!ParseMoney(mapArgs["-maxtxfee"], nMaxFee))
- return InitError(AmountErrMsg("maxtxfee", mapArgs["-maxtxfee"]));
- if (nMaxFee > HIGH_MAX_TX_FEE)
- InitWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
- maxTxFee = nMaxFee;
- if (CFeeRate(maxTxFee, 1000) < ::minRelayTxFee)
- {
- return InitError(strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
- mapArgs["-maxtxfee"], ::minRelayTxFee.ToString()));
- }
- }
- nTxConfirmTarget = GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET);
- bSpendZeroConfChange = GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
- fSendFreeTransactions = GetBoolArg("-sendfreetransactions", DEFAULT_SEND_FREE_TRANSACTIONS);
-
- std::string strWalletFile = GetArg("-wallet", DEFAULT_WALLET_DAT);
+ if (!CWallet::ParameterInteraction())
+ return false;
#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
@@ -1032,11 +963,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
return InitError(strprintf(_("Initialization sanity check failed. %s is shutting down."), _(PACKAGE_NAME)));
std::string strDataDir = GetDataDir().string();
-#ifdef ENABLE_WALLET
- // Wallet file must be a plain filename without a directory
- if (strWalletFile != boost::filesystem::basename(strWalletFile) + boost::filesystem::extension(strWalletFile))
- return InitError(strprintf(_("Wallet %s resides outside data directory %s"), strWalletFile, strDataDir));
-#endif
+
// Make sure only a single Bitcoin process is using the data directory.
boost::filesystem::path pathLockFile = GetDataDir() / ".lock";
FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist.
@@ -1097,20 +1024,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
// ********************************************************* Step 5: verify wallet database integrity
#ifdef ENABLE_WALLET
if (!fDisableWallet) {
- LogPrintf("Using wallet %s\n", strWalletFile);
- uiInterface.InitMessage(_("Verifying wallet..."));
-
- std::string warningString;
- std::string errorString;
-
- if (!CWallet::Verify(strWalletFile, warningString, errorString))
+ if (!CWallet::Verify())
return false;
-
- if (!warningString.empty())
- InitWarning(warningString);
- if (!errorString.empty())
- return InitError(errorString);
-
} // (!fDisableWallet)
#endif // ENABLE_WALLET
// ********************************************************* Step 6: network initialization
@@ -1223,10 +1138,11 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (mapArgs.count("-externalip")) {
BOOST_FOREACH(const std::string& strAddr, mapMultiArgs["-externalip"]) {
- CService addrLocal(strAddr, GetListenPort(), fNameLookup);
- if (!addrLocal.IsValid())
+ CService addrLocal;
+ if (Lookup(strAddr.c_str(), addrLocal, GetListenPort(), fNameLookup) && addrLocal.IsValid())
+ AddLocal(addrLocal, LOCAL_MANUAL);
+ else
return InitError(ResolveErrMsg("externalip", strAddr));
- AddLocal(CService(strAddr, GetListenPort(), fNameLookup), LOCAL_MANUAL);
}
}
@@ -1421,16 +1337,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
pwalletMain = NULL;
LogPrintf("Wallet disabled!\n");
} else {
- std::string warningString;
- std::string errorString;
- pwalletMain = CWallet::InitLoadWallet(fDisableWallet, strWalletFile, warningString, errorString);
- if (!warningString.empty())
- InitWarning(warningString);
- if (!errorString.empty())
- {
- LogPrintf("%s", errorString);
- return InitError(errorString);
- }
+ CWallet::InitLoadWallet();
if (!pwalletMain)
return false;
}
diff --git a/src/init.h b/src/init.h
index af1b94b72a..63e07ccb3c 100644
--- a/src/init.h
+++ b/src/init.h
@@ -16,8 +16,6 @@ namespace boost
class thread_group;
} // namespace boost
-extern CWallet* pwalletMain;
-
void StartShutdown();
bool ShutdownRequested();
/** Interrupt threads */
diff --git a/src/key.cpp b/src/key.cpp
index 28ba5144e4..6a3d9aa140 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -275,7 +275,7 @@ CExtPubKey CExtKey::Neuter() const {
return ret;
}
-void CExtKey::Encode(unsigned char code[74]) const {
+void CExtKey::Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const {
code[0] = nDepth;
memcpy(code+1, vchFingerprint, 4);
code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF;
@@ -286,12 +286,12 @@ void CExtKey::Encode(unsigned char code[74]) const {
memcpy(code+42, key.begin(), 32);
}
-void CExtKey::Decode(const unsigned char code[74]) {
+void CExtKey::Decode(const unsigned char code[BIP32_EXTKEY_SIZE]) {
nDepth = code[0];
memcpy(vchFingerprint, code+1, 4);
nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8];
memcpy(chaincode.begin(), code+9, 32);
- key.Set(code+42, code+74, true);
+ key.Set(code+42, code+BIP32_EXTKEY_SIZE, true);
}
bool ECC_InitSanityCheck() {
diff --git a/src/key.h b/src/key.h
index 6c820d49cd..b4f48d59f5 100644
--- a/src/key.h
+++ b/src/key.h
@@ -164,11 +164,28 @@ struct CExtKey {
a.chaincode == b.chaincode && a.key == b.key;
}
- void Encode(unsigned char code[74]) const;
- void Decode(const unsigned char code[74]);
+ void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
+ void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
bool Derive(CExtKey& out, unsigned int nChild) const;
CExtPubKey Neuter() const;
void SetMaster(const unsigned char* seed, unsigned int nSeedLen);
+ template <typename Stream>
+ void Serialize(Stream& s, int nType, int nVersion) const
+ {
+ unsigned int len = BIP32_EXTKEY_SIZE;
+ ::WriteCompactSize(s, len);
+ unsigned char code[BIP32_EXTKEY_SIZE];
+ Encode(code);
+ s.write((const char *)&code[0], len);
+ }
+ template <typename Stream>
+ void Unserialize(Stream& s, int nType, int nVersion)
+ {
+ unsigned int len = ::ReadCompactSize(s);
+ unsigned char code[BIP32_EXTKEY_SIZE];
+ s.read((char *)&code[0], len);
+ Decode(code);
+ }
};
/** Initialize the elliptic curve support. May not be called twice without calling ECC_Stop first. */
diff --git a/src/keystore.cpp b/src/keystore.cpp
index cc8a573367..d568a74350 100644
--- a/src/keystore.cpp
+++ b/src/keystore.cpp
@@ -19,6 +19,7 @@ bool CBasicKeyStore::GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) con
{
CKey key;
if (!GetKey(address, key)) {
+ LOCK(cs_KeyStore);
WatchKeyMap::const_iterator it = mapWatchKeys.find(address);
if (it != mapWatchKeys.end()) {
vchPubKeyOut = it->second;
diff --git a/src/main.cpp b/src/main.cpp
index 027a36394c..f6a89fa2e6 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;
@@ -192,16 +194,11 @@ namespace {
/** Blocks that are in flight, and that are in the queue to be downloaded. Protected by cs_main. */
struct QueuedBlock {
uint256 hash;
- CBlockIndex *pindex; //! Optional.
- int64_t nTime; //! Time of "getdata" request in microseconds.
- bool fValidatedHeaders; //! Whether this block has validated headers at the time of request.
- int64_t nTimeDisconnect; //! The timeout for this block request (for disconnecting a slow peer)
+ CBlockIndex* pindex; //!< Optional.
+ bool fValidatedHeaders; //!< Whether this block has validated headers at the time of request.
};
map<uint256, pair<NodeId, list<QueuedBlock>::iterator> > mapBlocksInFlight;
- /** Number of blocks in flight with validated headers. */
- int nQueuedValidatedHeaders = 0;
-
/** Number of preferable block download peers. */
int nPreferredDownload = 0;
@@ -210,6 +207,9 @@ namespace {
/** Dirty block file entries. */
set<int> setDirtyFileInfo;
+
+ /** Number of peers from which we're downloading blocks. */
+ int nPeersWithValidatedDownloads = 0;
} // anon namespace
//////////////////////////////////////////////////////////////////////////////
@@ -257,6 +257,8 @@ struct CNodeState {
//! Since when we're stalling block download progress (in microseconds), or 0.
int64_t nStallingSince;
list<QueuedBlock> vBlocksInFlight;
+ //! When the first entry in vBlocksInFlight started downloading. Don't care when vBlocksInFlight is empty.
+ int64_t nDownloadingSince;
int nBlocksInFlight;
int nBlocksInFlightValidHeaders;
//! Whether we consider this a preferred download peer.
@@ -274,6 +276,7 @@ struct CNodeState {
pindexBestHeaderSent = NULL;
fSyncStarted = false;
nStallingSince = 0;
+ nDownloadingSince = 0;
nBlocksInFlight = 0;
nBlocksInFlightValidHeaders = 0;
fPreferredDownload = false;
@@ -308,12 +311,6 @@ void UpdatePreferredDownload(CNode* node, CNodeState* state)
nPreferredDownload += state->fPreferredDownload;
}
-// Returns time at which to timeout block request (nTime in microseconds)
-int64_t GetBlockTimeout(int64_t nTime, int nValidatedQueuedBefore, const Consensus::Params &consensusParams)
-{
- return nTime + 500000 * consensusParams.nPowTargetSpacing * (4 + nValidatedQueuedBefore);
-}
-
void InitializeNode(NodeId nodeid, const CNode *pnode) {
LOCK(cs_main);
CNodeState &state = mapNodeState.insert(std::make_pair(nodeid, CNodeState())).first->second;
@@ -333,13 +330,21 @@ void FinalizeNode(NodeId nodeid) {
}
BOOST_FOREACH(const QueuedBlock& entry, state->vBlocksInFlight) {
- nQueuedValidatedHeaders -= entry.fValidatedHeaders;
mapBlocksInFlight.erase(entry.hash);
}
EraseOrphansFor(nodeid);
nPreferredDownload -= state->fPreferredDownload;
+ nPeersWithValidatedDownloads -= (state->nBlocksInFlightValidHeaders != 0);
+ assert(nPeersWithValidatedDownloads >= 0);
mapNodeState.erase(nodeid);
+
+ if (mapNodeState.empty()) {
+ // Do a consistency check after the last peer is removed.
+ assert(mapBlocksInFlight.empty());
+ assert(nPreferredDownload == 0);
+ assert(nPeersWithValidatedDownloads == 0);
+ }
}
// Requires cs_main.
@@ -348,8 +353,15 @@ bool MarkBlockAsReceived(const uint256& hash) {
map<uint256, pair<NodeId, list<QueuedBlock>::iterator> >::iterator itInFlight = mapBlocksInFlight.find(hash);
if (itInFlight != mapBlocksInFlight.end()) {
CNodeState *state = State(itInFlight->second.first);
- nQueuedValidatedHeaders -= itInFlight->second.second->fValidatedHeaders;
state->nBlocksInFlightValidHeaders -= itInFlight->second.second->fValidatedHeaders;
+ if (state->nBlocksInFlightValidHeaders == 0 && itInFlight->second.second->fValidatedHeaders) {
+ // Last validated block on the queue was received.
+ nPeersWithValidatedDownloads--;
+ }
+ if (state->vBlocksInFlight.begin() == itInFlight->second.second) {
+ // First block on the queue was received, update the start download time for the next one
+ state->nDownloadingSince = std::max(state->nDownloadingSince, GetTimeMicros());
+ }
state->vBlocksInFlight.erase(itInFlight->second.second);
state->nBlocksInFlight--;
state->nStallingSince = 0;
@@ -367,12 +379,17 @@ void MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const Consensus::Pa
// Make sure it's not listed somewhere already.
MarkBlockAsReceived(hash);
- int64_t nNow = GetTimeMicros();
- QueuedBlock newentry = {hash, pindex, nNow, pindex != NULL, GetBlockTimeout(nNow, nQueuedValidatedHeaders, consensusParams)};
- nQueuedValidatedHeaders += newentry.fValidatedHeaders;
+ QueuedBlock newentry = {hash, pindex, pindex != NULL};
list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(), newentry);
state->nBlocksInFlight++;
state->nBlocksInFlightValidHeaders += newentry.fValidatedHeaders;
+ if (state->nBlocksInFlight == 1) {
+ // We're starting a block download (batch) from this peer.
+ state->nDownloadingSince = GetTimeMicros();
+ }
+ if (state->nBlocksInFlightValidHeaders == 1 && pindex != NULL) {
+ nPeersWithValidatedDownloads++;
+ }
mapBlocksInFlight[hash] = std::make_pair(nodeid, it);
}
@@ -794,7 +811,25 @@ bool SequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeig
return EvaluateSequenceLocks(block, CalculateSequenceLocks(tx, flags, prevHeights, block));
}
-bool CheckSequenceLocks(const CTransaction &tx, int flags)
+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);
@@ -810,25 +845,57 @@ bool CheckSequenceLocks(const CTransaction &tx, int flags)
// *next* block, we need to use one more than chainActive.Height()
index.nHeight = tip->nHeight + 1;
- // 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__);
+ 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;
+ }
}
- 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);
}
}
-
- std::pair<int, int64_t> lockPair = CalculateSequenceLocks(tx, flags, &prevheights, index);
return EvaluateSequenceLocks(index, lockPair);
}
@@ -938,7 +1005,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();
@@ -958,6 +1025,14 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
if (fRequireStandard && !IsStandardTx(tx, reason))
return state.DoS(0, false, REJECT_NONSTANDARD, reason);
+ // Don't relay version 2 transactions until CSV is active, and we can be
+ // sure that such transactions will be mined (unless we're on
+ // -testnet/-regtest).
+ const CChainParams& chainparams = Params();
+ if (fRequireStandard && tx.nVersion >= 2 && VersionBitsTipState(chainparams.GetConsensus(), Consensus::DEPLOYMENT_CSV) != THRESHOLD_ACTIVE) {
+ return state.DoS(0, false, REJECT_NONSTANDARD, "premature-version2-tx");
+ }
+
// Only accept nLockTime-using 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.
@@ -1017,6 +1092,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
CCoinsViewCache view(&dummy);
CAmount nValueIn = 0;
+ LockPoints lp;
{
LOCK(pool.cs);
CCoinsViewMemPool viewMemPool(pcoinsTip, pool);
@@ -1060,7 +1136,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
// 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))
+ if (!CheckSequenceLocks(tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp))
return state.DoS(0, false, REJECT_NONSTANDARD, "non-BIP68-final");
}
@@ -1092,8 +1168,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
@@ -1194,20 +1273,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, false,
- REJECT_NONSTANDARD, "too many potential replacements", false,
- strprintf("too many potential replacements: rejecting replacement %s; cannot replace tx %s with untracked descendants",
- hash.ToString(),
- mi->GetTx().GetHash().ToString()));
- }
-
// Don't allow the replacement to reduce the feerate of the
// mempool.
//
@@ -1337,7 +1402,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());
@@ -1356,10 +1421,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);
@@ -1528,6 +1593,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);
@@ -1547,7 +1632,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)
{
@@ -2078,11 +2163,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;
@@ -2091,9 +2221,9 @@ static int64_t nTimeIndex = 0;
static int64_t nTimeCallbacks = 0;
static int64_t nTimeTotal = 0;
-bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck)
+bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex,
+ CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck)
{
- const CChainParams& chainparams = Params();
AssertLockHeld(cs_main);
int64_t nTimeStart = GetTimeMicros();
@@ -2179,6 +2309,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);
@@ -2187,7 +2324,6 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
CCheckQueueControl<CScriptCheck> control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : NULL);
std::vector<int> prevheights;
- int nLockTimeFlags = 0;
CAmount nFees = 0;
int nInputs = 0;
unsigned int nSigOps = 0;
@@ -2434,16 +2570,15 @@ void PruneAndFlush() {
}
/** Update chainActive and related internal data structures. */
-void static UpdateTip(CBlockIndex *pindexNew) {
- const CChainParams& chainParams = Params();
+void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) {
chainActive.SetTip(pindexNew);
// New best block
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());
@@ -2452,36 +2587,54 @@ 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;
+ }
}
}
}
/** Disconnect chainActive's tip. You probably want to call mempool.removeForReorg and manually re-limit mempool size after this, with cs_main held. */
-bool static DisconnectTip(CValidationState& state, const Consensus::Params& consensusParams)
+bool static DisconnectTip(CValidationState& state, const CChainParams& chainparams)
{
CBlockIndex *pindexDelete = chainActive.Tip();
assert(pindexDelete);
// Read block from disk.
CBlock block;
- if (!ReadBlockFromDisk(block, pindexDelete, consensusParams))
+ if (!ReadBlockFromDisk(block, pindexDelete, chainparams.GetConsensus()))
return AbortNode(state, "Failed to read block");
// Apply the block atomically to the chain state.
int64_t nStart = GetTimeMicros();
@@ -2501,8 +2654,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());
}
@@ -2514,7 +2667,7 @@ bool static DisconnectTip(CValidationState& state, const Consensus::Params& cons
// block that were added back and cleans up the mempool state.
mempool.UpdateTransactionsFromBlock(vHashUpdate);
// Update chainActive and related variables.
- UpdateTip(pindexDelete->pprev);
+ UpdateTip(pindexDelete->pprev, chainparams);
// Let wallets know transactions went from 1-confirmed to
// 0-confirmed or conflicted:
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
@@ -2550,7 +2703,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams,
LogPrint("bench", " - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * 0.001, nTimeReadFromDisk * 0.000001);
{
CCoinsViewCache view(pcoinsTip);
- bool rv = ConnectBlock(*pblock, state, pindexNew, view);
+ bool rv = ConnectBlock(*pblock, state, pindexNew, view, chainparams);
GetMainSignals().BlockChecked(*pblock, state);
if (!rv) {
if (state.IsInvalid())
@@ -2573,7 +2726,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams,
list<CTransaction> txConflicted;
mempool.removeForBlock(pblock->vtx, pindexNew->nHeight, txConflicted, !IsInitialBlockDownload());
// Update chainActive & related variables.
- UpdateTip(pindexNew);
+ UpdateTip(pindexNew, chainparams);
// Tell wallet about transactions that went from mempool
// to conflicted:
BOOST_FOREACH(const CTransaction &tx, txConflicted) {
@@ -2674,7 +2827,7 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c
// Disconnect active blocks which are no longer in the best chain.
bool fBlocksDisconnected = false;
while (chainActive.Tip() && chainActive.Tip() != pindexFork) {
- if (!DisconnectTip(state, chainparams.GetConsensus()))
+ if (!DisconnectTip(state, chainparams))
return false;
fBlocksDisconnected = true;
}
@@ -2746,6 +2899,8 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
CBlockIndex *pindexMostWork = NULL;
do {
boost::this_thread::interruption_point();
+ if (ShutdownRequested())
+ break;
CBlockIndex *pindexNewTip = NULL;
const CBlockIndex *pindexFork;
@@ -2817,7 +2972,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
return true;
}
-bool InvalidateBlock(CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex *pindex)
+bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex)
{
AssertLockHeld(cs_main);
@@ -2833,7 +2988,7 @@ bool InvalidateBlock(CValidationState& state, const Consensus::Params& consensus
setBlockIndexCandidates.erase(pindexWalk);
// ActivateBestChain considers blocks already in chainActive
// unconditionally valid already, so force disconnect away from it.
- if (!DisconnectTip(state, consensusParams)) {
+ if (!DisconnectTip(state, chainparams)) {
mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS);
return false;
}
@@ -3159,8 +3314,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;
}
@@ -3170,12 +3325,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");
}
@@ -3362,7 +3523,7 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams,
return error("%s: Consensus::CheckBlock: %s", __func__, FormatStateMessage(state));
if (!ContextualCheckBlock(block, state, pindexPrev))
return error("%s: Consensus::ContextualCheckBlock: %s", __func__, FormatStateMessage(state));
- if (!ConnectBlock(block, state, &indexDummy, viewNew, true))
+ if (!ConnectBlock(block, state, &indexDummy, viewNew, chainparams, true))
return false;
assert(state.IsValid());
@@ -3730,7 +3891,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
CBlock block;
if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus()))
return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
- if (!ConnectBlock(block, state, pindex, coins))
+ if (!ConnectBlock(block, state, pindex, coins, chainparams))
return error("VerifyDB(): *** found unconnectable block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
}
}
@@ -3757,12 +3918,15 @@ void UnloadBlockIndex()
nBlockSequenceId = 1;
mapBlockSource.clear();
mapBlocksInFlight.clear();
- nQueuedValidatedHeaders = 0;
nPreferredDownload = 0;
setDirtyBlockIndex.clear();
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;
@@ -4108,14 +4272,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;
@@ -4131,37 +4289,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")
@@ -4202,10 +4343,12 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
recentRejects->reset();
}
+ // Use pcoinsTip->HaveCoinsInCache as a quick approximation to exclude
+ // requesting or processing some txs which have already been included in a block
return recentRejects->contains(inv.hash) ||
mempool.exists(inv.hash) ||
mapOrphanTransactions.count(inv.hash) ||
- pcoinsTip->HaveCoins(inv.hash);
+ pcoinsTip->HaveCoinsInCache(inv.hash);
}
case MSG_BLOCK:
return mapBlockIndex.count(inv.hash);
@@ -4314,7 +4457,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
bool pushed = false;
{
LOCK(cs_mapRelay);
- map<CInv, CDataStream>::iterator mi = mapRelay.find(inv);
+ map<uint256, CTransaction>::iterator mi = mapRelay.find(inv.hash);
if (mi != mapRelay.end()) {
pfrom->PushMessage(inv.GetCommand(), (*mi).second);
pushed = true;
@@ -4323,10 +4466,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
if (!pushed && inv.type == MSG_TX) {
CTransaction tx;
if (mempool.lookup(inv.hash, tx)) {
- CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
- ss.reserve(1000);
- ss << tx;
- pfrom->PushMessage(NetMsgType::TX, ss);
+ pfrom->PushMessage(NetMsgType::TX, tx);
pushed = true;
}
}
@@ -4357,9 +4497,8 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
}
}
-bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived)
+bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams)
{
- const CChainParams& chainparams = Params();
RandAddSeedPerfmon();
LogPrint("net", "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id);
if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
@@ -4377,7 +4516,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", DEFAULT_ENFORCENODEBLOOM)) {
+ } else {
pfrom->fDisconnect = true;
return false;
}
@@ -4483,13 +4622,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;
@@ -4821,12 +4953,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
CValidationState state;
pfrom->setAskFor.erase(inv.hash);
- mapAlreadyAskedFor.erase(inv);
+ mapAlreadyAskedFor.erase(inv.hash);
- 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",
@@ -4857,10 +4989,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);
}
@@ -4913,7 +5045,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));
}
@@ -5079,6 +5211,14 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
return true;
}
+ // Only send one GetAddr response per connection to reduce resource waste
+ // and discourage addr stamping of INV announcements.
+ if (pfrom->fSentAddr) {
+ LogPrint("net", "Ignoring repeated \"getaddr\". peer=%d\n", pfrom->id);
+ return true;
+ }
+ pfrom->fSentAddr = true;
+
pfrom->vAddrToSend.clear();
vector<CAddress> vAddr = addrman.GetAddr();
BOOST_FOREACH(const CAddress &addr, vAddr)
@@ -5107,6 +5247,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);
@@ -5197,37 +5344,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;
@@ -5300,8 +5416,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);
}
@@ -5389,7 +5516,7 @@ bool ProcessMessages(CNode* pfrom)
bool fRet = false;
try
{
- fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime);
+ fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime, chainparams);
boost::this_thread::interruption_point();
}
catch (const std::ios_base::failure& e)
@@ -5590,7 +5717,21 @@ bool SendMessages(CNode* pto)
fRevertToInv = true;
break;
}
- assert(pBestIndex == NULL || pindex->pprev == pBestIndex);
+ if (pBestIndex != NULL && pindex->pprev != pBestIndex) {
+ // This means that the list of blocks to announce don't
+ // connect to each other.
+ // This shouldn't really be possible to hit during
+ // regular operation (because reorgs should take us to
+ // a chain that has some block not on the prior chain,
+ // which should be caught by the prior check), but one
+ // way this could happen is by using invalidateblock /
+ // reconsiderblock repeatedly on the tip, causing it to
+ // be added multiple times to vBlockHashesToAnnounce.
+ // Robustly deal with this rare situation by reverting
+ // to an inv.
+ fRevertToInv = true;
+ break;
+ }
pBestIndex = pindex;
if (fFoundStartingHeader) {
// add this to the headers message
@@ -5713,24 +5854,15 @@ bool SendMessages(CNode* pto)
LogPrintf("Peer=%d is stalling block download, disconnecting\n", pto->id);
pto->fDisconnect = true;
}
- // In case there is a block that has been in flight from this peer for (2 + 0.5 * N) times the block interval
- // (with N the number of validated blocks that were in flight at the time it was requested), disconnect due to
- // timeout. We compensate for in-flight blocks to prevent killing off peers due to our own downstream link
+ // In case there is a block that has been in flight from this peer for 2 + 0.5 * N times the block interval
+ // (with N the number of peers from which we're downloading validated blocks), disconnect due to timeout.
+ // We compensate for other peers to prevent killing off peers due to our own downstream link
// being saturated. We only count validated in-flight blocks so peers can't advertise non-existing block hashes
// to unreasonably increase our timeout.
- // We also compare the block download timeout originally calculated against the time at which we'd disconnect
- // if we assumed the block were being requested now (ignoring blocks we've requested from this peer, since we're
- // only looking at this peer's oldest request). This way a large queue in the past doesn't result in a
- // permanently large window for this block to be delivered (ie if the number of blocks in flight is decreasing
- // more quickly than once every 5 minutes, then we'll shorten the download window for this block).
if (!pto->fDisconnect && state.vBlocksInFlight.size() > 0) {
QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
- int64_t nTimeoutIfRequestedNow = GetBlockTimeout(nNow, nQueuedValidatedHeaders - state.nBlocksInFlightValidHeaders, consensusParams);
- if (queuedBlock.nTimeDisconnect > nTimeoutIfRequestedNow) {
- LogPrint("net", "Reducing block download timeout for peer=%d block=%s, orig=%d new=%d\n", pto->id, queuedBlock.hash.ToString(), queuedBlock.nTimeDisconnect, nTimeoutIfRequestedNow);
- queuedBlock.nTimeDisconnect = nTimeoutIfRequestedNow;
- }
- if (queuedBlock.nTimeDisconnect < nNow) {
+ int nOtherPeersWithValidatedDownloads = nPeersWithValidatedDownloads - (state.nBlocksInFlightValidHeaders > 0);
+ if (nNow > state.nDownloadingSince + consensusParams.nPowTargetSpacing * (BLOCK_DOWNLOAD_TIMEOUT_BASE + BLOCK_DOWNLOAD_TIMEOUT_PER_PEER * nOtherPeersWithValidatedDownloads)) {
LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", queuedBlock.hash.ToString(), pto->id);
pto->fDisconnect = true;
}
@@ -5783,6 +5915,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;
}
@@ -5791,7 +5946,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 5ba2be251c..2c9635bcf2 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,14 @@ 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;
+/** Block download timeout base, expressed in millionths of the block interval (i.e. 10 min) */
+static const int64_t BLOCK_DOWNLOAD_TIMEOUT_BASE = 1000000;
+/** Additional block download timeout per parallel downloading peer (i.e. 5 min) */
+static const int64_t BLOCK_DOWNLOAD_TIMEOUT_PER_PEER = 500000;
static const unsigned int DEFAULT_LIMITFREERELAY = 15;
static const bool DEFAULT_RELAYPRIORITY = true;
@@ -117,12 +125,13 @@ 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;
-static const bool DEFAULT_ENFORCENODEBLOOM = false;
struct BlockHasher
{
@@ -153,7 +162,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;
@@ -284,11 +292,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;
@@ -369,6 +380,11 @@ 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.
*/
@@ -378,10 +394,14 @@ bool SequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeig
* 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);
+bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp = NULL, bool useExistingLockPoints = false);
/**
* Closure representing one script verification
@@ -438,7 +458,8 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn
/** Apply the effects of this block (with given index) on the UTXO set represented by coins.
* Validity checks that depend on the UTXO set are also done; ConnectBlock()
* can fail if those validity checks fail (among other reasons). */
-bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false);
+bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins,
+ const CChainParams& chainparams, bool fJustCheck = false);
/** Undo the effects of this block (with given index) on the UTXO set represented by coins.
* In case pfClean is provided, operation will try to be tolerant about errors, and *pfClean
@@ -453,13 +474,13 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams,
class CBlockFileInfo
{
public:
- unsigned int nBlocks; //! number of blocks stored in file
- unsigned int nSize; //! number of used bytes of block file
- unsigned int nUndoSize; //! number of used bytes in the undo file
- unsigned int nHeightFirst; //! lowest height of block in file
- unsigned int nHeightLast; //! highest height of block in file
- uint64_t nTimeFirst; //! earliest time of block in file
- uint64_t nTimeLast; //! latest time of block in file
+ unsigned int nBlocks; //!< number of blocks stored in file
+ unsigned int nSize; //!< number of used bytes of block file
+ unsigned int nUndoSize; //!< number of used bytes in the undo file
+ unsigned int nHeightFirst; //!< lowest height of block in file
+ unsigned int nHeightLast; //!< highest height of block in file
+ uint64_t nTimeFirst; //!< earliest time of block in file
+ uint64_t nTimeLast; //!< latest time of block in file
ADD_SERIALIZE_METHODS;
@@ -516,7 +537,7 @@ public:
CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator);
/** Mark a block as invalid. */
-bool InvalidateBlock(CValidationState& state, const Consensus::Params& consensusParams, CBlockIndex *pindex);
+bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex);
/** Remove invalidity status from a block and its descendants. */
bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex);
@@ -537,6 +558,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 ec87e84ca7..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();
diff --git a/src/net.cpp b/src/net.cpp
index b589692d1b..7dec8fc1cf 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -90,10 +90,10 @@ std::string strSubVersion;
vector<CNode*> vNodes;
CCriticalSection cs_vNodes;
-map<CInv, CDataStream> mapRelay;
-deque<pair<int64_t, CInv> > vRelayExpiration;
+map<uint256, CTransaction> mapRelay;
+deque<pair<int64_t, uint256> > vRelayExpiration;
CCriticalSection cs_mapRelay;
-limitedmap<CInv, int64_t> mapAlreadyAskedFor(MAX_INV_SZ);
+limitedmap<uint256, int64_t> mapAlreadyAskedFor(MAX_INV_SZ);
static deque<string> vOneShots;
CCriticalSection cs_vOneShots;
@@ -1443,7 +1443,7 @@ void ThreadDNSAddressSeed()
} else {
vector<CNetAddr> vIPs;
vector<CAddress> vAdd;
- if (LookupHost(seed.host.c_str(), vIPs))
+ if (LookupHost(seed.host.c_str(), vIPs, 0, true))
{
BOOST_FOREACH(const CNetAddr& ip, vIPs)
{
@@ -1454,7 +1454,15 @@ void ThreadDNSAddressSeed()
found++;
}
}
- addrman.Add(vAdd, CNetAddr(seed.name, true));
+ // TODO: The seed name resolve may fail, yielding an IP of [::], which results in
+ // addrman assigning the same source to results from different seeds.
+ // This should switch to a hard-coded stable dummy IP for each seed name, so that the
+ // resolve is not required at all.
+ if (!vIPs.empty()) {
+ CService seedSource;
+ Lookup(seed.name.c_str(), seedSource, 0, true);
+ addrman.Add(vAdd, seedSource);
+ }
}
}
@@ -1884,7 +1892,7 @@ void static Discover(boost::thread_group& threadGroup)
if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
{
vector<CNetAddr> vaddr;
- if (LookupHost(pszHostName, vaddr))
+ if (LookupHost(pszHostName, vaddr, 0, true))
{
BOOST_FOREACH (const CNetAddr &addr, vaddr)
{
@@ -2053,20 +2061,7 @@ public:
instance_of_cnetcleanup;
-
-
-
-
-
-void RelayTransaction(const CTransaction& tx)
-{
- CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
- ss.reserve(10000);
- ss << tx;
- RelayTransaction(tx, ss);
-}
-
-void RelayTransaction(const CTransaction& tx, const CDataStream& ss)
+void RelayTransaction(const CTransaction& tx, CFeeRate feerate)
{
CInv inv(MSG_TX, tx.GetHash());
{
@@ -2078,15 +2073,19 @@ void RelayTransaction(const CTransaction& tx, const CDataStream& ss)
vRelayExpiration.pop_front();
}
- // Save original serialized message so newer versions are preserved
- mapRelay.insert(std::make_pair(inv, ss));
- vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
+ mapRelay.insert(std::make_pair(inv.hash, tx));
+ vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv.hash));
}
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
{
if(!pnode->fRelayTxes)
continue;
+ {
+ LOCK(pnode->cs_feeFilter);
+ if (feerate.GetFeePerK() < pnode->minFeeFilter)
+ continue;
+ }
LOCK(pnode->cs_filter);
if (pnode->pfilter)
{
@@ -2384,12 +2383,17 @@ CNode::CNode(SOCKET hSocketIn, const CAddress& addrIn, const std::string& addrNa
nNextAddrSend = 0;
nNextInvSend = 0;
fRelayTxes = false;
+ fSentAddr = false;
pfilter = new CBloomFilter();
nPingNonceSent = 0;
nPingUsecStart = 0;
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;
@@ -2432,7 +2436,7 @@ void CNode::AskFor(const CInv& inv)
// We're using mapAskFor as a priority queue,
// the key is the earliest time the request can be sent
int64_t nRequestTime;
- limitedmap<CInv, int64_t>::const_iterator it = mapAlreadyAskedFor.find(inv);
+ limitedmap<uint256, int64_t>::const_iterator it = mapAlreadyAskedFor.find(inv.hash);
if (it != mapAlreadyAskedFor.end())
nRequestTime = it->second;
else
@@ -2451,7 +2455,7 @@ void CNode::AskFor(const CInv& inv)
if (it != mapAlreadyAskedFor.end())
mapAlreadyAskedFor.update(it, nRequestTime);
else
- mapAlreadyAskedFor.insert(std::make_pair(inv, nRequestTime));
+ mapAlreadyAskedFor.insert(std::make_pair(inv.hash, nRequestTime));
mapAskFor.insert(std::make_pair(nRequestTime, inv));
}
diff --git a/src/net.h b/src/net.h
index ec296e2aba..bf367684f6 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"
@@ -160,10 +161,10 @@ extern int nMaxConnections;
extern std::vector<CNode*> vNodes;
extern CCriticalSection cs_vNodes;
-extern std::map<CInv, CDataStream> mapRelay;
-extern std::deque<std::pair<int64_t, CInv> > vRelayExpiration;
+extern std::map<uint256, CTransaction> mapRelay;
+extern std::deque<std::pair<int64_t, uint256> > vRelayExpiration;
extern CCriticalSection cs_mapRelay;
-extern limitedmap<CInv, int64_t> mapAlreadyAskedFor;
+extern limitedmap<uint256, int64_t> mapAlreadyAskedFor;
extern std::vector<std::string> vAddedNodes;
extern CCriticalSection cs_vAddedNodes;
@@ -357,6 +358,7 @@ public:
// b) the peer may tell us in its version message that we should not relay tx invs
// unless it loads a bloom filter.
bool fRelayTxes;
+ bool fSentAddr;
CSemaphoreGrant grantOutbound;
CCriticalSection cs_filter;
CBloomFilter* pfilter;
@@ -415,6 +417,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();
@@ -766,8 +773,7 @@ public:
class CTransaction;
-void RelayTransaction(const CTransaction& tx);
-void RelayTransaction(const CTransaction& tx, const CDataStream& ss);
+void RelayTransaction(const CTransaction& tx, CFeeRate feerate);
/** Access to the (IP) address database (peers.dat) */
class CAddrDB
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 7f79dd02c6..b44a8b16e2 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -170,7 +170,8 @@ bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsign
if (aiTrav->ai_family == AF_INET6)
{
assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6));
- vIP.push_back(CNetAddr(((struct sockaddr_in6*)(aiTrav->ai_addr))->sin6_addr));
+ struct sockaddr_in6* s6 = (struct sockaddr_in6*) aiTrav->ai_addr;
+ vIP.push_back(CNetAddr(s6->sin6_addr, s6->sin6_scope_id));
}
aiTrav = aiTrav->ai_next;
@@ -613,10 +614,12 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest
proxyType nameProxy;
GetNameProxy(nameProxy);
- CService addrResolved(CNetAddr(strDest, fNameLookup && !HaveNameProxy()), port);
- if (addrResolved.IsValid()) {
- addr = addrResolved;
- return ConnectSocket(addr, hSocketRet, nTimeout);
+ CService addrResolved;
+ if (Lookup(strDest.c_str(), addrResolved, port, fNameLookup && !HaveNameProxy())) {
+ if (addrResolved.IsValid()) {
+ addr = addrResolved;
+ return ConnectSocket(addr, hSocketRet, nTimeout);
+ }
}
addr = CService("0.0.0.0:0");
@@ -629,6 +632,7 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest
void CNetAddr::Init()
{
memset(ip, 0, sizeof(ip));
+ scopeId = 0;
}
void CNetAddr::SetIP(const CNetAddr& ipIn)
@@ -678,24 +682,25 @@ CNetAddr::CNetAddr(const struct in_addr& ipv4Addr)
SetRaw(NET_IPV4, (const uint8_t*)&ipv4Addr);
}
-CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr)
+CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr, const uint32_t scope)
{
SetRaw(NET_IPV6, (const uint8_t*)&ipv6Addr);
+ scopeId = scope;
}
-CNetAddr::CNetAddr(const char *pszIp, bool fAllowLookup)
+CNetAddr::CNetAddr(const char *pszIp)
{
Init();
std::vector<CNetAddr> vIP;
- if (LookupHost(pszIp, vIP, 1, fAllowLookup))
+ if (LookupHost(pszIp, vIP, 1, false))
*this = vIP[0];
}
-CNetAddr::CNetAddr(const std::string &strIp, bool fAllowLookup)
+CNetAddr::CNetAddr(const std::string &strIp)
{
Init();
std::vector<CNetAddr> vIP;
- if (LookupHost(strIp.c_str(), vIP, 1, fAllowLookup))
+ if (LookupHost(strIp.c_str(), vIP, 1, false))
*this = vIP[0];
}
@@ -1099,7 +1104,7 @@ CService::CService(const struct sockaddr_in& addr) : CNetAddr(addr.sin_addr), po
assert(addr.sin_family == AF_INET);
}
-CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr), port(ntohs(addr.sin6_port))
+CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr, addr.sin6_scope_id), port(ntohs(addr.sin6_port))
{
assert(addr.sin6_family == AF_INET6);
}
@@ -1118,35 +1123,35 @@ bool CService::SetSockAddr(const struct sockaddr *paddr)
}
}
-CService::CService(const char *pszIpPort, bool fAllowLookup)
+CService::CService(const char *pszIpPort)
{
Init();
CService ip;
- if (Lookup(pszIpPort, ip, 0, fAllowLookup))
+ if (Lookup(pszIpPort, ip, 0, false))
*this = ip;
}
-CService::CService(const char *pszIpPort, int portDefault, bool fAllowLookup)
+CService::CService(const char *pszIpPort, int portDefault)
{
Init();
CService ip;
- if (Lookup(pszIpPort, ip, portDefault, fAllowLookup))
+ if (Lookup(pszIpPort, ip, portDefault, false))
*this = ip;
}
-CService::CService(const std::string &strIpPort, bool fAllowLookup)
+CService::CService(const std::string &strIpPort)
{
Init();
CService ip;
- if (Lookup(strIpPort.c_str(), ip, 0, fAllowLookup))
+ if (Lookup(strIpPort.c_str(), ip, 0, false))
*this = ip;
}
-CService::CService(const std::string &strIpPort, int portDefault, bool fAllowLookup)
+CService::CService(const std::string &strIpPort, int portDefault)
{
Init();
CService ip;
- if (Lookup(strIpPort.c_str(), ip, portDefault, fAllowLookup))
+ if (Lookup(strIpPort.c_str(), ip, portDefault, false))
*this = ip;
}
@@ -1192,6 +1197,7 @@ bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const
memset(paddrin6, 0, *addrlen);
if (!GetIn6Addr(&paddrin6->sin6_addr))
return false;
+ paddrin6->sin6_scope_id = scopeId;
paddrin6->sin6_family = AF_INET6;
paddrin6->sin6_port = htons(port);
return true;
@@ -1239,7 +1245,7 @@ CSubNet::CSubNet():
memset(netmask, 0, sizeof(netmask));
}
-CSubNet::CSubNet(const std::string &strSubnet, bool fAllowLookup)
+CSubNet::CSubNet(const std::string &strSubnet)
{
size_t slash = strSubnet.find_last_of('/');
std::vector<CNetAddr> vIP;
@@ -1249,7 +1255,7 @@ CSubNet::CSubNet(const std::string &strSubnet, bool fAllowLookup)
memset(netmask, 255, sizeof(netmask));
std::string strAddress = strSubnet.substr(0, slash);
- if (LookupHost(strAddress.c_str(), vIP, 1, fAllowLookup))
+ if (LookupHost(strAddress.c_str(), vIP, 1, false))
{
network = vIP[0];
if (slash != strSubnet.npos)
diff --git a/src/netbase.h b/src/netbase.h
index 1db66ac27f..65187a17cf 100644
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -44,12 +44,13 @@ class CNetAddr
{
protected:
unsigned char ip[16]; // in network byte order
+ uint32_t scopeId; // for scoped/link-local ipv6 addresses
public:
CNetAddr();
CNetAddr(const struct in_addr& ipv4Addr);
- explicit CNetAddr(const char *pszIp, bool fAllowLookup = false);
- explicit CNetAddr(const std::string &strIp, bool fAllowLookup = false);
+ explicit CNetAddr(const char *pszIp);
+ explicit CNetAddr(const std::string &strIp);
void Init();
void SetIP(const CNetAddr& ip);
@@ -89,7 +90,7 @@ class CNetAddr
std::vector<unsigned char> GetGroup() const;
int GetReachabilityFrom(const CNetAddr *paddrPartner = NULL) const;
- CNetAddr(const struct in6_addr& pipv6Addr);
+ CNetAddr(const struct in6_addr& pipv6Addr, const uint32_t scope = 0);
bool GetIn6Addr(struct in6_addr* pipv6Addr) const;
friend bool operator==(const CNetAddr& a, const CNetAddr& b);
@@ -118,7 +119,7 @@ class CSubNet
public:
CSubNet();
- explicit CSubNet(const std::string &strSubnet, bool fAllowLookup = false);
+ explicit CSubNet(const std::string &strSubnet);
//constructor for single ip subnet (<ipv4>/32 or <ipv6>/128)
explicit CSubNet(const CNetAddr &addr);
@@ -153,10 +154,10 @@ class CService : public CNetAddr
CService(const CNetAddr& ip, unsigned short port);
CService(const struct in_addr& ipv4Addr, unsigned short port);
CService(const struct sockaddr_in& addr);
- explicit CService(const char *pszIpPort, int portDefault, bool fAllowLookup = false);
- explicit CService(const char *pszIpPort, bool fAllowLookup = false);
- explicit CService(const std::string& strIpPort, int portDefault, bool fAllowLookup = false);
- explicit CService(const std::string& strIpPort, bool fAllowLookup = false);
+ explicit CService(const char *pszIpPort, int portDefault);
+ explicit CService(const char *pszIpPort);
+ explicit CService(const std::string& strIpPort, int portDefault);
+ explicit CService(const std::string& strIpPort);
void Init();
void SetPort(unsigned short portIn);
unsigned short GetPort() const;
@@ -205,9 +206,9 @@ bool GetProxy(enum Network net, proxyType &proxyInfoOut);
bool IsProxy(const CNetAddr &addr);
bool SetNameProxy(const proxyType &addrProxy);
bool HaveNameProxy();
-bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions = 0, bool fAllowLookup = true);
-bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true);
-bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault = 0, bool fAllowLookup = true, unsigned int nMaxSolutions = 0);
+bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup);
+bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup);
+bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions);
bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0);
bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed = 0);
bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed = 0);
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..463f62f710 100644
--- a/src/policy/fees.h
+++ b/src/policy/fees.h
@@ -265,8 +265,8 @@ public:
void Read(CAutoFile& filein);
private:
- CFeeRate minTrackedFee; //! Passed to constructor to avoid dependency on main
- double minTrackedPriority; //! Set to AllowFreeThreshold
+ CFeeRate minTrackedFee; //!< Passed to constructor to avoid dependency on main
+ double minTrackedPriority; //!< Set to AllowFreeThreshold
unsigned int nBestSeenHeight;
struct TxStatsInfo
{
@@ -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..d1a15451dc 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;
}
@@ -73,12 +73,12 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason)
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
// Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed
- // keys. (remember the 520 byte limit on redeemScript size) That works
+ // keys (remember the 520 byte limit on redeemScript size). That works
// out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)+3=1627
// bytes of scriptSig, which we round off to 1650 bytes for some minor
// future-proofing. That's also enough to spend a 20-of-20
// CHECKMULTISIG scriptPubKey, though such a scriptPubKey is not
- // considered standard)
+ // considered standard.
if (txin.scriptSig.size() > 1650) {
reason = "scriptsig-size";
return false;
diff --git a/src/policy/rbf.cpp b/src/policy/rbf.cpp
index 98b1a1ba4c..133cff611d 100644
--- a/src/policy/rbf.cpp
+++ b/src/policy/rbf.cpp
@@ -14,33 +14,34 @@ bool SignalsOptInRBF(const CTransaction &tx)
return false;
}
-bool IsRBFOptIn(const CTxMemPoolEntry &entry, CTxMemPool &pool)
+RBFTransactionState IsRBFOptIn(const CTransaction &tx, CTxMemPool &pool)
{
AssertLockHeld(pool.cs);
CTxMemPool::setEntries setAncestors;
// First check the transaction itself.
- if (SignalsOptInRBF(entry.GetTx())) {
- return true;
+ if (SignalsOptInRBF(tx)) {
+ return RBF_TRANSACTIONSTATE_REPLACEABLE_BIP125;
}
// If this transaction is not in our mempool, then we can't be sure
// we will know about all its inputs.
- if (!pool.exists(entry.GetTx().GetHash())) {
- throw std::runtime_error("Cannot determine RBF opt-in signal for non-mempool transaction\n");
+ if (!pool.exists(tx.GetHash())) {
+ return RBF_TRANSACTIONSTATE_UNKNOWN;
}
// If all the inputs have nSequence >= maxint-1, it still might be
// signaled for RBF if any unconfirmed parents have signaled.
uint64_t noLimit = std::numeric_limits<uint64_t>::max();
std::string dummy;
+ CTxMemPoolEntry entry = *pool.mapTx.find(tx.GetHash());
pool.CalculateMemPoolAncestors(entry, setAncestors, noLimit, noLimit, noLimit, noLimit, dummy, false);
BOOST_FOREACH(CTxMemPool::txiter it, setAncestors) {
if (SignalsOptInRBF(it->GetTx())) {
- return true;
+ return RBF_TRANSACTIONSTATE_REPLACEABLE_BIP125;
}
}
- return false;
+ return RBF_TRANSACTIONSTATE_FINAL;
}
diff --git a/src/policy/rbf.h b/src/policy/rbf.h
index 925ce0d9bd..5a711dba07 100644
--- a/src/policy/rbf.h
+++ b/src/policy/rbf.h
@@ -7,6 +7,12 @@
#include "txmempool.h"
+enum RBFTransactionState {
+ RBF_TRANSACTIONSTATE_UNKNOWN,
+ RBF_TRANSACTIONSTATE_REPLACEABLE_BIP125,
+ RBF_TRANSACTIONSTATE_FINAL
+};
+
// Check whether the sequence numbers on this transaction are signaling
// opt-in to replace-by-fee, according to BIP 125
bool SignalsOptInRBF(const CTransaction &tx);
@@ -15,6 +21,6 @@ bool SignalsOptInRBF(const CTransaction &tx);
// according to BIP 125
// This involves checking sequence numbers of the transaction, as well
// as the sequence numbers of all in-mempool ancestors.
-bool IsRBFOptIn(const CTxMemPoolEntry &entry, CTxMemPool &pool);
+RBFTransactionState IsRBFOptIn(const CTransaction &tx, CTxMemPool &pool);
#endif // BITCOIN_POLICY_RBF_H
diff --git a/src/prevector.h b/src/prevector.h
index 1da459bcfe..a0e1e140b4 100644
--- a/src/prevector.h
+++ b/src/prevector.h
@@ -298,9 +298,8 @@ public:
}
void resize(size_type new_size) {
- while (size() > new_size) {
- item_ptr(size() - 1)->~T();
- _size--;
+ if (size() > new_size) {
+ erase(item_ptr(new_size), end());
}
if (new_size > capacity()) {
change_capacity(new_size);
@@ -368,10 +367,7 @@ public:
}
iterator erase(iterator pos) {
- (*pos).~T();
- memmove(&(*pos), &(*pos) + 1, ((char*)&(*end())) - ((char*)(1 + &(*pos))));
- _size--;
- return pos;
+ return erase(pos, pos + 1);
}
iterator erase(iterator first, iterator last) {
@@ -396,7 +392,7 @@ public:
}
void pop_back() {
- _size--;
+ erase(end() - 1, end());
}
T& front() {
@@ -416,12 +412,7 @@ public:
}
void swap(prevector<N, T, Size, Diff>& other) {
- if (_size & other._size & 1) {
- std::swap(_union.capacity, other._union.capacity);
- std::swap(_union.indirect, other._union.indirect);
- } else {
- std::swap(_union, other._union);
- }
+ std::swap(_union, other._union);
std::swap(_size, other._size);
}
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.h b/src/primitives/transaction.h
index 07ae39e0b4..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)
@@ -206,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/pubkey.cpp b/src/pubkey.cpp
index db06a89285..be4ee27cd4 100644
--- a/src/pubkey.cpp
+++ b/src/pubkey.cpp
@@ -246,7 +246,7 @@ bool CPubKey::Derive(CPubKey& pubkeyChild, ChainCode &ccChild, unsigned int nChi
return true;
}
-void CExtPubKey::Encode(unsigned char code[74]) const {
+void CExtPubKey::Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const {
code[0] = nDepth;
memcpy(code+1, vchFingerprint, 4);
code[5] = (nChild >> 24) & 0xFF; code[6] = (nChild >> 16) & 0xFF;
@@ -256,12 +256,12 @@ void CExtPubKey::Encode(unsigned char code[74]) const {
memcpy(code+41, pubkey.begin(), 33);
}
-void CExtPubKey::Decode(const unsigned char code[74]) {
+void CExtPubKey::Decode(const unsigned char code[BIP32_EXTKEY_SIZE]) {
nDepth = code[0];
memcpy(vchFingerprint, code+1, 4);
nChild = (code[5] << 24) | (code[6] << 16) | (code[7] << 8) | code[8];
memcpy(chaincode.begin(), code+9, 32);
- pubkey.Set(code+41, code+74);
+ pubkey.Set(code+41, code+BIP32_EXTKEY_SIZE);
}
bool CExtPubKey::Derive(CExtPubKey &out, unsigned int nChild) const {
diff --git a/src/pubkey.h b/src/pubkey.h
index e1a17b6582..db5444ea9d 100644
--- a/src/pubkey.h
+++ b/src/pubkey.h
@@ -23,6 +23,8 @@
* script supports up to 75 for single byte push
*/
+const unsigned int BIP32_EXTKEY_SIZE = 74;
+
/** A reference to a CKey: the Hash160 of its serialized public key */
class CKeyID : public uint160
{
@@ -205,9 +207,33 @@ struct CExtPubKey {
a.chaincode == b.chaincode && a.pubkey == b.pubkey;
}
- void Encode(unsigned char code[74]) const;
- void Decode(const unsigned char code[74]);
+ void Encode(unsigned char code[BIP32_EXTKEY_SIZE]) const;
+ void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
bool Derive(CExtPubKey& out, unsigned int nChild) const;
+
+ unsigned int GetSerializeSize(int nType, int nVersion) const
+ {
+ return BIP32_EXTKEY_SIZE+1; //add one byte for the size (compact int)
+ }
+ template <typename Stream>
+ void Serialize(Stream& s, int nType, int nVersion) const
+ {
+ unsigned int len = BIP32_EXTKEY_SIZE;
+ ::WriteCompactSize(s, len);
+ unsigned char code[BIP32_EXTKEY_SIZE];
+ Encode(code);
+ s.write((const char *)&code[0], len);
+ }
+ template <typename Stream>
+ void Unserialize(Stream& s, int nType, int nVersion)
+ {
+ unsigned int len = ::ReadCompactSize(s);
+ unsigned char code[BIP32_EXTKEY_SIZE];
+ if (len != BIP32_EXTKEY_SIZE)
+ throw std::runtime_error("Invalid extended key size\n");
+ s.read((char *)&code[0], len);
+ Decode(code);
+ }
};
/** Users of this module must hold an ECCVerifyHandle. The constructor and
diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc
index dcd3b4ae2c..24b0bae3ec 100644
--- a/src/qt/bitcoin.qrc
+++ b/src/qt/bitcoin.qrc
@@ -49,6 +49,7 @@
<file alias="fontbigger">res/icons/fontbigger.png</file>
<file alias="fontsmaller">res/icons/fontsmaller.png</file>
<file alias="prompticon">res/icons/chevron.png</file>
+ <file alias="transaction_abandoned">res/icons/transaction_abandoned.png</file>
</qresource>
<qresource prefix="/movies">
<file alias="spinner-000">res/movies/spinner-000.png</file>
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 a5ac0a7d26..c17efcf1b3 100644
--- a/src/qt/forms/debugwindow.ui
+++ b/src/qt/forms/debugwindow.ui
@@ -141,12 +141,12 @@
<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="5" column="1" colspan="2">
- <widget class="QLabel" name="buildDate">
+ <widget class="QLabel" name="dataDir">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
@@ -156,6 +156,9 @@
<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>
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/guiconstants.h b/src/qt/guiconstants.h
index 5ceffcd70a..4b2c10dd48 100644
--- a/src/qt/guiconstants.h
+++ b/src/qt/guiconstants.h
@@ -29,6 +29,8 @@ static const bool DEFAULT_SPLASHSCREEN = true;
#define COLOR_TX_STATUS_OPENUNTILDATE QColor(64, 64, 255)
/* Transaction list -- TX status decoration - offline */
#define COLOR_TX_STATUS_OFFLINE QColor(192, 192, 192)
+/* Transaction list -- TX status decoration - danger, tx needs attention */
+#define COLOR_TX_STATUS_DANGER QColor(200, 100, 100)
/* Transaction list -- TX status decoration - default color */
#define COLOR_BLACK QColor(0, 0, 0)
diff --git a/src/qt/res/icons/transaction_abandoned.png b/src/qt/res/icons/transaction_abandoned.png
new file mode 100644
index 0000000000..8ca6445c20
--- /dev/null
+++ b/src/qt/res/icons/transaction_abandoned.png
Binary files differ
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index e8ee3042db..d8647d902a 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -444,7 +444,7 @@ 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()));
@@ -459,6 +459,8 @@ void RPCConsole::setClientModel(ClientModel *model)
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);
}
}
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..bae0cbd1c8 100644
--- a/src/qt/transactiondesc.cpp
+++ b/src/qt/transactiondesc.cpp
@@ -39,7 +39,7 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
else if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
return tr("%1/offline").arg(nDepth);
else if (nDepth == 0)
- return tr("0/unconfirmed, %1").arg((wtx.InMempool() ? tr("in memory pool") : tr("not in memory pool")));
+ return tr("0/unconfirmed, %1").arg((wtx.InMempool() ? tr("in memory pool") : tr("not in memory pool"))) + (wtx.isAbandoned() ? ", "+tr("abandoned") : "");
else if (nDepth < 6)
return tr("%1/unconfirmed").arg(nDepth);
else
@@ -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..4fe47181f6 100644
--- a/src/qt/transactionrecord.cpp
+++ b/src/qt/transactionrecord.cpp
@@ -239,6 +239,8 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
else if (status.depth == 0)
{
status.status = TransactionStatus::Unconfirmed;
+ if (wtx.isAbandoned())
+ status.status = TransactionStatus::Abandoned;
}
else if (status.depth < RecommendedNumConfirmations)
{
@@ -260,11 +262,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..8c754c3aad 100644
--- a/src/qt/transactionrecord.h
+++ b/src/qt/transactionrecord.h
@@ -33,6 +33,7 @@ public:
Unconfirmed, /**< Not yet mined into a block **/
Confirming, /**< Confirmed, but waiting for the recommended number of confirmations **/
Conflicted, /**< Conflicts with other transaction or mempool **/
+ Abandoned, /**< Abandoned from the wallet **/
/// Generated (mined) transactions
Immature, /**< Mined but waiting for maturity */
MaturesWarning, /**< Transaction will likely not mature because no nodes have confirmed */
@@ -128,8 +129,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 d2a52b3022..b29ecf8348 100644
--- a/src/qt/transactiontablemodel.cpp
+++ b/src/qt/transactiontablemodel.cpp
@@ -312,6 +312,9 @@ QString TransactionTableModel::formatTxStatus(const TransactionRecord *wtx) cons
case TransactionStatus::Unconfirmed:
status = tr("Unconfirmed");
break;
+ case TransactionStatus::Abandoned:
+ status = tr("Abandoned");
+ break;
case TransactionStatus::Confirming:
status = tr("Confirming (%1 of %2 recommended confirmations)").arg(wtx->status.depth).arg(TransactionRecord::RecommendedNumConfirmations);
break;
@@ -468,6 +471,8 @@ QVariant TransactionTableModel::txStatusDecoration(const TransactionRecord *wtx)
return COLOR_TX_STATUS_OFFLINE;
case TransactionStatus::Unconfirmed:
return QIcon(":/icons/transaction_0");
+ case TransactionStatus::Abandoned:
+ return QIcon(":/icons/transaction_abandoned");
case TransactionStatus::Confirming:
switch(wtx->status.depth)
{
@@ -573,6 +578,11 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
case Qt::TextAlignmentRole:
return column_alignments[index.column()];
case Qt::ForegroundRole:
+ // Use the "danger" color for abandoned transactions
+ if(rec->status.status == TransactionStatus::Abandoned)
+ {
+ return COLOR_TX_STATUS_DANGER;
+ }
// Non-confirmed (but not immature) as transactions are grey
if(!rec->status.countsForBalance && rec->status.status != TransactionStatus::Immature)
{
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index a4d4c7a35f..a352228c36 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -37,7 +37,7 @@
TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *parent) :
QWidget(parent), model(0), transactionProxyModel(0),
- transactionView(0)
+ transactionView(0), abandonAction(0)
{
// Build filter row
setContentsMargins(0,0,0,0);
@@ -137,6 +137,7 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa
transactionView = view;
// Actions
+ abandonAction = new QAction(tr("Abandon transaction"), this);
QAction *copyAddressAction = new QAction(tr("Copy address"), this);
QAction *copyLabelAction = new QAction(tr("Copy label"), this);
QAction *copyAmountAction = new QAction(tr("Copy amount"), this);
@@ -153,8 +154,10 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa
contextMenu->addAction(copyTxIDAction);
contextMenu->addAction(copyTxHexAction);
contextMenu->addAction(copyTxPlainText);
- contextMenu->addAction(editLabelAction);
contextMenu->addAction(showDetailsAction);
+ contextMenu->addSeparator();
+ contextMenu->addAction(abandonAction);
+ contextMenu->addAction(editLabelAction);
mapperThirdPartyTxUrls = new QSignalMapper(this);
@@ -170,6 +173,7 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa
connect(view, SIGNAL(doubleClicked(QModelIndex)), this, SIGNAL(doubleClicked(QModelIndex)));
connect(view, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint)));
+ connect(abandonAction, SIGNAL(triggered()), this, SLOT(abandonTx()));
connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(copyAddress()));
connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel()));
connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount()));
@@ -360,12 +364,37 @@ void TransactionView::exportClicked()
void TransactionView::contextualMenu(const QPoint &point)
{
QModelIndex index = transactionView->indexAt(point);
+ QModelIndexList selection = transactionView->selectionModel()->selectedRows(0);
+
+ // check if transaction can be abandoned, disable context menu action in case it doesn't
+ uint256 hash;
+ hash.SetHex(selection.at(0).data(TransactionTableModel::TxHashRole).toString().toStdString());
+ abandonAction->setEnabled(model->transactionCanBeAbandoned(hash));
+
if(index.isValid())
{
contextMenu->exec(QCursor::pos());
}
}
+void TransactionView::abandonTx()
+{
+ if(!transactionView || !transactionView->selectionModel())
+ return;
+ QModelIndexList selection = transactionView->selectionModel()->selectedRows(0);
+
+ // get the hash from the TxHashRole (QVariant / QString)
+ uint256 hash;
+ QString hashQStr = selection.at(0).data(TransactionTableModel::TxHashRole).toString();
+ hash.SetHex(hashQStr.toStdString());
+
+ // Abandon the wallet transaction over the walletModel
+ model->abandonTransaction(hash);
+
+ // Update the table
+ model->getTransactionTableModel()->updateTransaction(hashQStr, CT_UPDATED, false);
+}
+
void TransactionView::copyAddress()
{
GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::AddressRole);
diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h
index 2cfbd471b0..e9b9d5b6bc 100644
--- a/src/qt/transactionview.h
+++ b/src/qt/transactionview.h
@@ -75,6 +75,7 @@ private:
QFrame *dateRangeWidget;
QDateTimeEdit *dateFrom;
QDateTimeEdit *dateTo;
+ QAction *abandonAction;
QWidget *createDateRangeWidget();
@@ -97,6 +98,7 @@ private Q_SLOTS:
void copyTxPlainText();
void openThirdPartyTxUrl(QString url);
void updateWatchOnlyColumn(bool fHaveWatchOnly);
+ void abandonTx();
Q_SIGNALS:
void doubleClicked(const QModelIndex&);
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index a5b43270f3..a0d0e70442 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -668,3 +668,18 @@ bool WalletModel::saveReceiveRequest(const std::string &sAddress, const int64_t
else
return wallet->AddDestData(dest, key, sRequest);
}
+
+bool WalletModel::transactionCanBeAbandoned(uint256 hash) const
+{
+ LOCK2(cs_main, wallet->cs_wallet);
+ const CWalletTx *wtx = wallet->GetWalletTx(hash);
+ if (!wtx || wtx->isAbandoned() || wtx->GetDepthInMainChain() > 0 || wtx->InMempool())
+ return false;
+ return true;
+}
+
+bool WalletModel::abandonTransaction(uint256 hash) const
+{
+ LOCK2(cs_main, wallet->cs_wallet);
+ return wallet->AbandonTransaction(hash);
+}
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index 7a47eda86f..e5470bf618 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -200,6 +200,9 @@ public:
void loadReceiveRequests(std::vector<std::string>& vReceiveRequests);
bool saveReceiveRequest(const std::string &sAddress, const int64_t nId, const std::string &sRequest);
+ bool transactionCanBeAbandoned(uint256 hash) const;
+ bool abandonTransaction(uint256 hash) const;
+
private:
CWallet *wallet;
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 da57973dae..6960415e2e 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -18,11 +18,14 @@
#include "txmempool.h"
#include "util.h"
#include "utilstrencodings.h"
+#include "hash.h"
#include <stdint.h>
#include <univalue.h>
+#include <boost/thread/thread.hpp> // boost::thread::interrupt
+
using namespace std;
extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry);
@@ -70,6 +73,7 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex)
result.push_back(Pair("confirmations", confirmations));
result.push_back(Pair("height", blockindex->nHeight));
result.push_back(Pair("version", blockindex->nVersion));
+ result.push_back(Pair("versionHex", strprintf("%08x", blockindex->nVersion)));
result.push_back(Pair("merkleroot", blockindex->hashMerkleRoot.GetHex()));
result.push_back(Pair("time", (int64_t)blockindex->nTime));
result.push_back(Pair("mediantime", (int64_t)blockindex->GetMedianTimePast()));
@@ -98,6 +102,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx
result.push_back(Pair("size", (int)::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION)));
result.push_back(Pair("height", blockindex->nHeight));
result.push_back(Pair("version", block.nVersion));
+ result.push_back(Pair("versionHex", strprintf("%08x", block.nVersion)));
result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
UniValue txs(UniValue::VARR);
BOOST_FOREACH(const CTransaction&tx, block.vtx)
@@ -316,6 +321,7 @@ UniValue getblockheader(const UniValue& params, bool fHelp)
" \"confirmations\" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain\n"
" \"height\" : n, (numeric) The block height or index\n"
" \"version\" : n, (numeric) The block version\n"
+ " \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n"
" \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
" \"time\" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT)\n"
" \"mediantime\" : ttt, (numeric) The median block time in seconds since epoch (Jan 1 1970 GMT)\n"
@@ -375,6 +381,7 @@ UniValue getblock(const UniValue& params, bool fHelp)
" \"size\" : n, (numeric) The block size\n"
" \"height\" : n, (numeric) The block height or index\n"
" \"version\" : n, (numeric) The block version\n"
+ " \"versionHex\" : \"00000000\", (string) The block version formatted in hexadecimal\n"
" \"merkleroot\" : \"xxxx\", (string) The merkle root\n"
" \"tx\" : [ (array of string) The transaction ids\n"
" \"transactionid\" (string) The transaction id\n"
@@ -428,6 +435,60 @@ UniValue getblock(const UniValue& params, bool fHelp)
return blockToJSON(block, pblockindex);
}
+struct CCoinsStats
+{
+ int nHeight;
+ uint256 hashBlock;
+ uint64_t nTransactions;
+ uint64_t nTransactionOutputs;
+ uint64_t nSerializedSize;
+ uint256 hashSerialized;
+ CAmount nTotalAmount;
+
+ CCoinsStats() : nHeight(0), nTransactions(0), nTransactionOutputs(0), nSerializedSize(0), nTotalAmount(0) {}
+};
+
+//! Calculate statistics about the unspent transaction output set
+static bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats)
+{
+ boost::scoped_ptr<CCoinsViewCursor> pcursor(view->Cursor());
+
+ CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
+ stats.hashBlock = pcursor->GetBestBlock();
+ {
+ LOCK(cs_main);
+ stats.nHeight = mapBlockIndex.find(stats.hashBlock)->second->nHeight;
+ }
+ ss << stats.hashBlock;
+ CAmount nTotalAmount = 0;
+ while (pcursor->Valid()) {
+ boost::this_thread::interruption_point();
+ uint256 key;
+ CCoins coins;
+ if (pcursor->GetKey(key) && pcursor->GetValue(coins)) {
+ stats.nTransactions++;
+ ss << key;
+ for (unsigned int i=0; i<coins.vout.size(); i++) {
+ const CTxOut &out = coins.vout[i];
+ if (!out.IsNull()) {
+ stats.nTransactionOutputs++;
+ ss << VARINT(i+1);
+ ss << out;
+ nTotalAmount += out.nValue;
+ }
+ }
+ stats.nSerializedSize += 32 + pcursor->GetValueSize();
+ ss << VARINT(0);
+ } else {
+ return error("%s: unable to read value", __func__);
+ }
+ pcursor->Next();
+ }
+ stats.hashSerialized = ss.GetHash();
+ stats.nTotalAmount = nTotalAmount;
+ return true;
+}
+
UniValue gettxoutsetinfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
@@ -454,7 +515,7 @@ UniValue gettxoutsetinfo(const UniValue& params, bool fHelp)
CCoinsStats stats;
FlushStateToDisk();
- if (pcoinsTip->GetStats(stats)) {
+ if (GetUTXOStats(pcoinsTip, stats)) {
ret.push_back(Pair("height", (int64_t)stats.nHeight));
ret.push_back(Pair("bestblock", stats.hashBlock.GetHex()));
ret.push_back(Pair("transactions", (int64_t)stats.nTransactions));
@@ -604,6 +665,26 @@ static UniValue SoftForkDesc(const std::string &name, int version, CBlockIndex*
return rv;
}
+static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Consensus::DeploymentPos id)
+{
+ UniValue rv(UniValue::VOBJ);
+ const ThresholdState thresholdState = VersionBitsTipState(consensusParams, id);
+ switch (thresholdState) {
+ 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;
+ }
+ if (THRESHOLD_STARTED == thresholdState)
+ {
+ rv.push_back(Pair("bit", consensusParams.vDeployments[id].bit));
+ }
+ rv.push_back(Pair("startTime", consensusParams.vDeployments[id].nStartTime));
+ rv.push_back(Pair("timeout", consensusParams.vDeployments[id].nTimeout));
+ return rv;
+}
+
UniValue getblockchaininfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
@@ -634,7 +715,15 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp)
" },\n"
" \"reject\": { ... } (object) progress toward rejecting pre-softfork blocks (same fields as \"enforce\")\n"
" }, ...\n"
- " ]\n"
+ " ],\n"
+ " \"bip9_softforks\": { (object) status of BIP9 softforks in progress\n"
+ " \"xxxx\" : { (string) name of the softfork\n"
+ " \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"lockedin\", \"active\", \"failed\"\n"
+ " \"bit\": xx, (numeric) the bit, 0-28, in the block version field used to signal this soft fork\n"
+ " \"startTime\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n"
+ " \"timeout\": xx (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n"
+ " }\n"
+ " }\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("getblockchaininfo", "")
@@ -657,10 +746,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::VOBJ);
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(Pair("csv", BIP9SoftForkDesc(consensusParams, Consensus::DEPLOYMENT_CSV)));
obj.push_back(Pair("softforks", softforks));
+ obj.push_back(Pair("bip9_softforks", bip9_softforks));
if (fPruneMode)
{
@@ -723,17 +815,30 @@ UniValue getchaintips(const UniValue& params, bool fHelp)
LOCK(cs_main);
- /* Build up a list of chain tips. We start with the list of all
- known blocks, and successively remove blocks that appear as pprev
- of another block. */
+ /*
+ * Idea: the set of chain tips is chainActive.tip, plus orphan blocks which do not have another orphan building off of them.
+ * Algorithm:
+ * - Make one pass through mapBlockIndex, picking out the orphan blocks, and also storing a set of the orphan block's pprev pointers.
+ * - Iterate through the orphan blocks. If the block isn't pointed to by another orphan, it is a chain tip.
+ * - add chainActive.Tip()
+ */
std::set<const CBlockIndex*, CompareBlocksByHeight> setTips;
+ std::set<const CBlockIndex*> setOrphans;
+ std::set<const CBlockIndex*> setPrevs;
+
BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
- setTips.insert(item.second);
- BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex)
{
- const CBlockIndex* pprev = item.second->pprev;
- if (pprev)
- setTips.erase(pprev);
+ if (!chainActive.Contains(item.second)) {
+ setOrphans.insert(item.second);
+ setPrevs.insert(item.second->pprev);
+ }
+ }
+
+ for (std::set<const CBlockIndex*>::iterator it = setOrphans.begin(); it != setOrphans.end(); ++it)
+ {
+ if (setPrevs.erase(*it) == 0) {
+ setTips.insert(*it);
+ }
}
// Always report the currently active tip.
@@ -837,7 +942,7 @@ UniValue invalidateblock(const UniValue& params, bool fHelp)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
CBlockIndex* pblockindex = mapBlockIndex[hash];
- InvalidateBlock(state, Params().GetConsensus(), pblockindex);
+ InvalidateBlock(state, Params(), pblockindex);
}
if (state.IsValid()) {
@@ -889,3 +994,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 45fb6c1642..c89af6bfa7 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -18,8 +18,8 @@ using namespace std;
class CRPCConvertParam
{
public:
- std::string methodName; //! method whose params want conversion
- int paramIdx; //! 0-based idx of param to convert
+ std::string methodName; //!< method whose params want conversion
+ int paramIdx; //!< 0-based idx of param to convert
};
static const CRPCConvertParam vRPCConvertParams[] =
@@ -29,6 +29,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "getaddednodeinfo", 0 },
{ "generate", 0 },
{ "generate", 1 },
+ { "generatetoaddress", 0 },
+ { "generatetoaddress", 2 },
{ "getnetworkhashps", 0 },
{ "getnetworkhashps", 1 },
{ "sendtoaddress", 1 },
diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp
index c33082fca0..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"
@@ -93,42 +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 generate(const UniValue& params, bool fHelp)
+UniValue generateBlocks(boost::shared_ptr<CReserveScript> coinbaseScript, int nGenerate, uint64_t nMaxTries, bool keepScript)
{
- if (fHelp || params.size() < 1 || params.size() > 2)
- throw runtime_error(
- "generate numblocks ( maxtries )\n"
- "\nMine up to numblocks blocks immediately (before the RPC call returns)\n"
- "\nArguments:\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"
- "\nGenerate 11 blocks\n"
- + HelpExampleCli("generate", "11")
- );
-
static const int nInnerLoopCount = 0x10000;
int nHeightStart = 0;
int nHeightEnd = 0;
int nHeight = 0;
- int nGenerate = params[0].get_int();
- uint64_t nMaxTries = 1000000;
- if (params.size() > 1) {
- nMaxTries = params[1].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);
@@ -164,12 +135,84 @@ 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 generate(const UniValue& params, bool fHelp)
+{
+ if (fHelp || params.size() < 1 || params.size() > 2)
+ throw runtime_error(
+ "generate numblocks ( maxtries )\n"
+ "\nMine up to numblocks blocks immediately (before the RPC call returns)\n"
+ "\nArguments:\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"
+ "\nGenerate 11 blocks\n"
+ + HelpExampleCli("generate", "11")
+ );
+
+ int nGenerate = params[0].get_int();
+ uint64_t nMaxTries = 1000000;
+ if (params.size() > 1) {
+ nMaxTries = params[1].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)");
+
+ 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();
+ }
+
+ 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 generateBlocks(coinbaseScript, nGenerate, nMaxTries, false);
+}
+
UniValue getmininginfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
@@ -738,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..ce14d034ce 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -97,9 +97,9 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp)
" \"bytesrecv\": n, (numeric) The total bytes received\n"
" \"conntime\": ttt, (numeric) The connection time in seconds since epoch (Jan 1 1970 GMT)\n"
" \"timeoffset\": ttt, (numeric) The time offset in seconds\n"
- " \"pingtime\": n, (numeric) ping time\n"
- " \"minping\": n, (numeric) minimum observed ping time\n"
- " \"pingwait\": n, (numeric) ping wait\n"
+ " \"pingtime\": n, (numeric) ping time (if available)\n"
+ " \"minping\": n, (numeric) minimum observed ping time (if any at all)\n"
+ " \"pingwait\": n, (numeric) ping wait (if non-zero)\n"
" \"version\": v, (numeric) The peer version, such as 7001\n"
" \"subver\": \"/Satoshi:0.8.5/\", (string) The string version\n"
" \"inbound\": true|false, (boolean) Inbound (true) or Outbound (false)\n"
@@ -150,8 +150,10 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp)
obj.push_back(Pair("bytesrecv", stats.nRecvBytes));
obj.push_back(Pair("conntime", stats.nTimeConnected));
obj.push_back(Pair("timeoffset", stats.nTimeOffset));
- obj.push_back(Pair("pingtime", stats.dPingTime));
- obj.push_back(Pair("minping", stats.dPingMin));
+ if (stats.dPingTime > 0.0)
+ obj.push_back(Pair("pingtime", stats.dPingTime));
+ if (stats.dPingMin < std::numeric_limits<int64_t>::max()/1e6)
+ obj.push_back(Pair("minping", stats.dPingMin));
if (stats.dPingWait > 0.0)
obj.push_back(Pair("pingwait", stats.dPingWait));
obj.push_back(Pair("version", stats.nVersion));
@@ -626,3 +628,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 33fa1437e2..d06a9142b6 100644
--- a/src/rpc/server.cpp
+++ b/src/rpc/server.cpp
@@ -89,7 +89,8 @@ void RPCTypeCheck(const UniValue& params,
void RPCTypeCheckObj(const UniValue& o,
const map<string, UniValue::VType>& typesExpected,
- bool fAllowNull)
+ bool fAllowNull,
+ bool fStrict)
{
BOOST_FOREACH(const PAIRTYPE(string, UniValue::VType)& t, typesExpected)
{
@@ -104,6 +105,18 @@ void RPCTypeCheckObj(const UniValue& o,
throw JSONRPCError(RPC_TYPE_ERROR, err);
}
}
+
+ if (fStrict)
+ {
+ BOOST_FOREACH(const string& k, o.getKeys())
+ {
+ if (typesExpected.count(k) == 0)
+ {
+ string err = strprintf("Unexpected key %s", k);
+ throw JSONRPCError(RPC_TYPE_ERROR, err);
+ }
+ }
+ }
}
CAmount AmountFromValue(const UniValue& value)
@@ -256,71 +269,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", "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()
diff --git a/src/rpc/server.h b/src/rpc/server.h
index 38cb32e7f2..b471336617 100644
--- a/src/rpc/server.h
+++ b/src/rpc/server.h
@@ -70,7 +70,7 @@ void RPCTypeCheck(const UniValue& params,
Use like: RPCTypeCheckObj(object, boost::assign::map_list_of("name", str_type)("value", int_type));
*/
void RPCTypeCheckObj(const UniValue& o,
- const std::map<std::string, UniValue::VType>& typesExpected, bool fAllowNull=false);
+ const std::map<std::string, UniValue::VType>& typesExpected, bool fAllowNull=false, bool fStrict=false);
/** Opaque base class for timers returned by NewTimerFunc.
* This provides no methods at the moment, but makes sure that delete
@@ -181,64 +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 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 149a4f0156..9c47f7c6c9 100644
--- a/src/script/interpreter.cpp
+++ b/src/script/interpreter.cpp
@@ -1015,12 +1015,12 @@ namespace {
*/
class CTransactionSignatureSerializer {
private:
- const CTransaction &txTo; //! reference to the spending transaction (the one being serialized)
- const CScript &scriptCode; //! output script being consumed
- const unsigned int nIn; //! input index of txTo being signed
- const bool fAnyoneCanPay; //! whether the hashtype has the SIGHASH_ANYONECANPAY flag set
- const bool fHashSingle; //! whether the hashtype is SIGHASH_SINGLE
- const bool fHashNone; //! whether the hashtype is SIGHASH_NONE
+ const CTransaction& txTo; //!< reference to the spending transaction (the one being serialized)
+ const CScript& scriptCode; //!< output script being consumed
+ const unsigned int nIn; //!< input index of txTo being signed
+ const bool fAnyoneCanPay; //!< whether the hashtype has the SIGHASH_ANYONECANPAY flag set
+ const bool fHashSingle; //!< whether the hashtype is SIGHASH_SINGLE
+ const bool fHashNone; //!< whether the hashtype is SIGHASH_NONE
public:
CTransactionSignatureSerializer(const CTransaction &txToIn, const CScript &scriptCodeIn, unsigned int nInIn, int nHashTypeIn) :
diff --git a/src/wallet/wallet_ismine.cpp b/src/script/ismine.cpp
index ebda5cc53d..535c56b57a 100644
--- a/src/wallet/wallet_ismine.cpp
+++ b/src/script/ismine.cpp
@@ -3,7 +3,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "wallet_ismine.h"
+#include "ismine.h"
#include "key.h"
#include "keystore.h"
diff --git a/src/wallet/wallet_ismine.h b/src/script/ismine.h
index 51afd1b140..4b7db8802b 100644
--- a/src/wallet/wallet_ismine.h
+++ b/src/script/ismine.h
@@ -3,8 +3,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_WALLET_WALLET_ISMINE_H
-#define BITCOIN_WALLET_WALLET_ISMINE_H
+#ifndef BITCOIN_SCRIPT_ISMINE_H
+#define BITCOIN_SCRIPT_ISMINE_H
#include "script/standard.h"
@@ -31,4 +31,4 @@ typedef uint8_t isminefilter;
isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest);
-#endif // BITCOIN_WALLET_WALLET_ISMINE_H
+#endif // BITCOIN_SCRIPT_ISMINE_H
diff --git a/src/script/standard.h b/src/script/standard.h
index 64bf010ec1..f348da8e19 100644
--- a/src/script/standard.h
+++ b/src/script/standard.h
@@ -27,7 +27,7 @@ public:
CScriptID(const uint160& in) : uint160(in) {}
};
-static const unsigned int MAX_OP_RETURN_RELAY = 83; //! bytes (+1 for OP_RETURN, +2 for the pushdata opcodes)
+static const unsigned int MAX_OP_RETURN_RELAY = 83; //!< bytes (+1 for OP_RETURN, +2 for the pushdata opcodes)
extern bool fAcceptDatacarrier;
extern unsigned nMaxDatacarrierBytes;
diff --git a/src/sync.cpp b/src/sync.cpp
index 8df8ae43f4..641ed2c8ca 100644
--- a/src/sync.cpp
+++ b/src/sync.cpp
@@ -56,11 +56,24 @@ private:
};
typedef std::vector<std::pair<void*, CLockLocation> > LockStack;
+typedef std::map<std::pair<void*, void*>, LockStack> LockOrders;
+typedef std::set<std::pair<void*, void*> > InvLockOrders;
-static boost::mutex dd_mutex;
-static std::map<std::pair<void*, void*>, LockStack> lockorders;
-static boost::thread_specific_ptr<LockStack> lockstack;
+struct LockData {
+ // Very ugly hack: as the global constructs and destructors run single
+ // threaded, we use this boolean to know whether LockData still exists,
+ // as DeleteLock can get called by global CCriticalSection destructors
+ // after LockData disappears.
+ bool available;
+ LockData() : available(true) {}
+ ~LockData() { available = false; }
+ LockOrders lockorders;
+ InvLockOrders invlockorders;
+ boost::mutex dd_mutex;
+} static lockdata;
+
+boost::thread_specific_ptr<LockStack> lockstack;
static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2)
{
@@ -117,7 +130,7 @@ static void push_lock(void* c, const CLockLocation& locklocation, bool fTry)
if (lockstack.get() == NULL)
lockstack.reset(new LockStack);
- dd_mutex.lock();
+ boost::unique_lock<boost::mutex> lock(lockdata.dd_mutex);
(*lockstack).push_back(std::make_pair(c, locklocation));
@@ -127,23 +140,21 @@ static void push_lock(void* c, const CLockLocation& locklocation, bool fTry)
break;
std::pair<void*, void*> p1 = std::make_pair(i.first, c);
- if (lockorders.count(p1))
+ if (lockdata.lockorders.count(p1))
continue;
- lockorders[p1] = (*lockstack);
+ lockdata.lockorders[p1] = (*lockstack);
std::pair<void*, void*> p2 = std::make_pair(c, i.first);
- if (lockorders.count(p2))
- potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]);
+ lockdata.invlockorders.insert(p2);
+ if (lockdata.lockorders.count(p2))
+ potential_deadlock_detected(p1, lockdata.lockorders[p2], lockdata.lockorders[p1]);
}
}
- dd_mutex.unlock();
}
static void pop_lock()
{
- dd_mutex.lock();
(*lockstack).pop_back();
- dd_mutex.unlock();
}
void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry)
@@ -173,4 +184,26 @@ void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine,
abort();
}
+void DeleteLock(void* cs)
+{
+ if (!lockdata.available) {
+ // We're already shutting down.
+ return;
+ }
+ boost::unique_lock<boost::mutex> lock(lockdata.dd_mutex);
+ std::pair<void*, void*> item = std::make_pair(cs, (void*)0);
+ LockOrders::iterator it = lockdata.lockorders.lower_bound(item);
+ while (it != lockdata.lockorders.end() && it->first.first == cs) {
+ std::pair<void*, void*> invitem = std::make_pair(it->first.second, it->first.first);
+ lockdata.invlockorders.erase(invitem);
+ lockdata.lockorders.erase(it++);
+ }
+ InvLockOrders::iterator invit = lockdata.invlockorders.lower_bound(item);
+ while (invit != lockdata.invlockorders.end() && invit->first == cs) {
+ std::pair<void*, void*> invinvitem = std::make_pair(invit->second, invit->first);
+ lockdata.lockorders.erase(invinvitem);
+ lockdata.invlockorders.erase(invit++);
+ }
+}
+
#endif /* DEBUG_LOCKORDER */
diff --git a/src/sync.h b/src/sync.h
index 34dd8c228e..0c58fb6b4e 100644
--- a/src/sync.h
+++ b/src/sync.h
@@ -71,30 +71,39 @@ public:
}
};
-/**
- * Wrapped boost mutex: supports recursive locking, but no waiting
- * TODO: We should move away from using the recursive lock by default.
- */
-typedef AnnotatedMixin<boost::recursive_mutex> CCriticalSection;
-
-/** Wrapped boost mutex: supports waiting but not recursive locking */
-typedef AnnotatedMixin<boost::mutex> CWaitableCriticalSection;
-
-/** Just a typedef for boost::condition_variable, can be wrapped later if desired */
-typedef boost::condition_variable CConditionVariable;
-
#ifdef DEBUG_LOCKORDER
void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
void LeaveCritical();
std::string LocksHeld();
void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs);
+void DeleteLock(void* cs);
#else
void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
void static inline LeaveCritical() {}
void static inline AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) {}
+void static inline DeleteLock(void* cs) {}
#endif
#define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
+/**
+ * Wrapped boost mutex: supports recursive locking, but no waiting
+ * TODO: We should move away from using the recursive lock by default.
+ */
+class CCriticalSection : public AnnotatedMixin<boost::recursive_mutex>
+{
+public:
+ ~CCriticalSection() {
+ DeleteLock((void*)this);
+ }
+};
+
+typedef CCriticalSection CDynamicCriticalSection;
+/** Wrapped boost mutex: supports waiting but not recursive locking */
+typedef AnnotatedMixin<boost::mutex> CWaitableCriticalSection;
+
+/** Just a typedef for boost::condition_variable, can be wrapped later if desired */
+typedef boost::condition_variable CConditionVariable;
+
#ifdef DEBUG_LOCKCONTENTION
void PrintLockContention(const char* pszName, const char* pszFile, int nLine);
#endif
diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp
index 87d35be412..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 "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..fd6f88b366
--- /dev/null
+++ b/src/test/amount_tests.cpp
@@ -0,0 +1,71 @@
+// 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(-1000);
+ // Must always just return -1 * 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);
+
+ 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);
+
+ // Check full constructor
+ // default value
+ BOOST_CHECK(CFeeRate(CAmount(-1), 1000) == CFeeRate(-1));
+ BOOST_CHECK(CFeeRate(CAmount(0), 1000) == CFeeRate(0));
+ BOOST_CHECK(CFeeRate(CAmount(1), 1000) == CFeeRate(1));
+ // lost precision (can only resolve satoshis per kB)
+ BOOST_CHECK(CFeeRate(CAmount(1), 1001) == CFeeRate(0));
+ BOOST_CHECK(CFeeRate(CAmount(2), 1001) == CFeeRate(1));
+ // some more integer checks
+ BOOST_CHECK(CFeeRate(CAmount(26), 789) == CFeeRate(32));
+ BOOST_CHECK(CFeeRate(CAmount(27), 789) == CFeeRate(34));
+ // Maximum size in bytes, should not crash
+ CFeeRate(MAX_MONEY, std::numeric_limits<size_t>::max() >> 1).GetFeePerK();
+}
+
+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/bip32_tests.cpp b/src/test/bip32_tests.cpp
index ce29e692db..7f1c2a32dd 100644
--- a/src/test/bip32_tests.cpp
+++ b/src/test/bip32_tests.cpp
@@ -117,6 +117,22 @@ void RunTest(const TestVector &test) {
}
key = keyNew;
pubkey = pubkeyNew;
+
+ CDataStream ssPub(SER_DISK, CLIENT_VERSION);
+ ssPub << pubkeyNew;
+ BOOST_CHECK(ssPub.size() == 75);
+
+ CDataStream ssPriv(SER_DISK, CLIENT_VERSION);
+ ssPriv << keyNew;
+ BOOST_CHECK(ssPriv.size() == 75);
+
+ CExtPubKey pubCheck;
+ CExtKey privCheck;
+ ssPub >> pubCheck;
+ ssPriv >> privCheck;
+
+ BOOST_CHECK(pubCheck == pubkeyNew);
+ BOOST_CHECK(privCheck == keyNew);
}
}
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/coins_tests.cpp b/src/test/coins_tests.cpp
index 3fe536f91a..48e3c8ed8e 100644
--- a/src/test/coins_tests.cpp
+++ b/src/test/coins_tests.cpp
@@ -61,8 +61,6 @@ public:
hashBestBlock_ = hashBlock;
return true;
}
-
- bool GetStats(CCoinsStats& stats) const { return false; }
};
class CCoinsViewCacheTest : public CCoinsViewCache
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
deleted file mode 100644
index 9e91132984..0000000000
--- a/src/test/data/script_invalid.json
+++ /dev/null
@@ -1,877 +0,0 @@
-[
-["Format is: [scriptSig, scriptPubKey, flags, ... comments]"],
-["It is evaluated as if there was a crediting coinbase transaction with two 0"],
-["pushes as scriptSig, and one output of 0 satoshi and given scriptPubKey,"],
-["followed by a spending transaction which spends this output as only input (and"],
-["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", "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", "", "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", "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",
-"PUSH_SIZE"],
-["0",
-"IF 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' ENDIF 1",
-"P2SH,STRICTENC",
-">520 byte push in non-executed IF branch",
-"PUSH_SIZE"],
-["1",
-"0x61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161",
-"P2SH,STRICTENC",
-">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",
-"OP_COUNT"],
-["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
-"1 2 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
-"P2SH,STRICTENC",
-">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",
-"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",
-"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", "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",
-"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",
-"",
-"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",
-"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",
-"",
-"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", "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()", "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", "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", "EVAL_FALSE"],
-
-["MINIMALDATA enforcement for PUSHDATAs"],
-
-["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",
- "MINIMALDATA"],
-
-["0x4d 0xFF00 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA",
- "PUSHDATA2 of 255 bytes minimally represented by PUSHDATA1",
- "MINIMALDATA"],
-
-["0x4e 0x00010000 0x11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA",
- "PUSHDATA4 of 256 bytes minimally represented by PUSHDATA2",
- "MINIMALDATA"],
-
-["MINIMALDATA enforcement for numeric arguments"],
-
-["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", "", "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"],
-["pubkeys/signatures so they fail due to the STRICTENC rules on validly encoded"],
-["signatures and pubkeys."],
-[
- "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.",
- "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.",
- "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", "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",
- "EVAL_FALSE"
-],
-[
- "0x47 0x3044022034bb0494b50b8ef130e2185bb220265b9284ef5b4b8a8da4d8415df489c83b5102206259a26d9cc0a125ac26af6153b17c02956855ebe1467412f066e402f5f05d1201 0x21 0x03363d90d446b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640",
- "DUP HASH160 0x14 0xc0834c0c158f53be706d234c38fd52de7eece656 EQUALVERIFY CHECKSIG",
- "",
- "P2PKH, bad pubkey",
- "EQUALVERIFY"
-],
-[
- "0x47 0x304402204710a85181663b32d25c70ec2bbd14adff5ddfff6cb50d09e155ef5f541fc86c0220056b0cc949be9386ecc5f6c2ac0493269031dbb185781db90171b54ac127790201",
- "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
- "",
- "P2PK anyonecanpay marked with normal hashtype",
- "EVAL_FALSE"
-],
-[
- "0x47 0x3044022003fef42ed6c7be8917441218f525a60e2431be978e28b7aca4d7a532cc413ae8022067a1f82c74e8d69291b90d148778405c6257bbcfc2353cc38a3e1f22bf44254601 0x23 0x210279be667ef9dcbbac54a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac",
- "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL",
- "P2SH",
- "P2SH(P2PK), bad redeemscript",
- "EVAL_FALSE"
-],
-[
- "0x47 0x304402204e2eb034be7b089534ac9e798cf6a2c79f38bcb34d1b179efd6f2de0841735db022071461beb056b5a7be1819da6a3e3ce3662831ecc298419ca101eb6887b5dd6a401 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac",
- "HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL",
- "P2SH",
- "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",
- "EVAL_FALSE"
-],
-[
- "0 0x47 0x304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001 0 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae",
- "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL",
- "P2SH",
- "P2SH(2-of-3), 1 sig",
- "EVAL_FALSE"
-],
-[
- "0x47 0x304402200060558477337b9022e70534f1fea71a318caf836812465a2509931c5e7c4987022078ec32bd50ac9e03a349ba953dfd9fe1c8d2dd8bdb1d38ddca844d3d5c78c11801",
- "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
- "DERSIG",
- "P2PK with too much R padding",
- "SIG_DER"
-],
-[
- "0x48 0x304502202de8c03fc525285c9c535631019a5f2af7c6454fa9eb392a3756a4917c420edd02210046130bf2baf7cfc065067c8b9e33a066d9c15edcea9feb0ca2d233e3597925b401",
- "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
- "DERSIG",
- "P2PK with too much S padding",
- "SIG_DER"
-],
-[
- "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201",
- "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
- "DERSIG",
- "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",
- "SIG_DER"
-],
-[
- "0x47 0x30440220005ece1335e7f657a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601",
- "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
- "",
- "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",
- "SIG_DER"
-],
-[
- "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201",
- "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
- "DERSIG",
- "BIP66 example 1, with DERSIG",
- "SIG_DER"
-],
-[
- "0x47 0x304402208e43c0b91f7c1e5bc58e41c8185f8a6086e111b0090187968a86f2822462d3c902200a58f4076b1133b18ff1dc83ee51676e44c60cc608d9534e0df5ace0424fc0be01",
- "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
- "",
- "BIP66 example 2, without DERSIG",
- "EVAL_FALSE"
-],
-[
- "0x47 0x304402208e43c0b91f7c1e5bc58e41c8185f8a6086e111b0090187968a86f2822462d3c902200a58f4076b1133b18ff1dc83ee51676e44c60cc608d9534e0df5ace0424fc0be01",
- "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
- "DERSIG",
- "BIP66 example 2, with DERSIG",
- "SIG_DER"
-],
-[
- "0",
- "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
- "",
- "BIP66 example 3, without DERSIG",
- "EVAL_FALSE"
-],
-[
- "0",
- "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
- "DERSIG",
- "BIP66 example 3, with DERSIG",
- "EVAL_FALSE"
-],
-[
- "1",
- "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
- "",
- "BIP66 example 5, without DERSIG",
- "EVAL_FALSE"
-],
-[
- "1",
- "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
- "DERSIG",
- "BIP66 example 5, with DERSIG",
- "SIG_DER"
-],
-[
- "1",
- "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
- "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",
- "SIG_DER"
-],
-[
- "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0x47 0x3044022079ea80afd538d9ada421b5101febeb6bc874e01dde5bca108c1d0479aec339a4022004576db8f66130d1df686ccf00935703689d69cf539438da1edab208b0d63c4801",
- "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
- "",
- "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",
- "SIG_DER"
-],
-[
- "0 0 0x47 0x3044022081aa9d436f2154e8b6d600516db03d78de71df685b585a9807ead4210bd883490220534bb6bdf318a419ac0749660b60e78d17d515558ef369bf872eff405b676b2e01",
- "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
- "",
- "BIP66 example 9, without DERSIG",
- "EVAL_FALSE"
-],
-[
- "0 0 0x47 0x3044022081aa9d436f2154e8b6d600516db03d78de71df685b585a9807ead4210bd883490220534bb6bdf318a419ac0749660b60e78d17d515558ef369bf872eff405b676b2e01",
- "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
- "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",
- "SIG_DER"
-],
-[
- "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0",
- "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
- "",
- "BIP66 example 11, without DERSIG",
- "EVAL_FALSE"
-],
-[
- "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0",
- "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
- "DERSIG",
- "BIP66 example 11, with DERSIG",
- "EVAL_FALSE"
-],
-[
- "0x48 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb12510101",
- "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
- "DERSIG",
- "P2PK with multi-byte hashtype, with DERSIG",
- "SIG_DER"
-],
-[
- "0x48 0x304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef001",
- "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
- "LOW_S",
- "P2PK with high S",
- "SIG_HIGH_S"
-],
-[
- "0x47 0x3044022057292e2d4dfe775becdd0a9e6547997c728cdf35390f6a017da56d654d374e4902206b643be2fc53763b4e284845bfea2c597d2dc7759941dce937636c9d341b71ed01",
- "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
- "STRICTENC",
- "P2PK with hybrid pubkey",
- "PUBKEYTYPE"
-],
-[
- "0x47 0x30440220035d554e3153c14950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101",
- "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
- "",
- "P2PK NOT with hybrid pubkey but no STRICTENC",
- "EVAL_FALSE"
-],
-[
- "0x47 0x30440220035d554e3153c14950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101",
- "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
- "STRICTENC",
- "P2PK NOT with hybrid pubkey",
- "PUBKEYTYPE"
-],
-[
- "0x47 0x30440220035d554e3153c04950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101",
- "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
- "STRICTENC",
- "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",
- "PUBKEYTYPE"
-],
-[
- "0x47 0x304402206177d513ec2cda444c021a1f4f656fc4c72ba108ae063e157eb86dc3575784940220666fc66702815d0e5413bb9b1df22aed44f5f1efb8b99d41dd5dc9a5be6d205205",
- "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
- "STRICTENC",
- "P2PK with undefined hashtype",
- "SIG_HASHTYPE"
-],
-[
- "0x47 0x304402207409b5b320296e5e2136a7b281a7f803028ca4ca44e2b83eebd46932677725de02202d4eea1c8d3c98e6f42614f54764e6e5e6542e213eb4d079737e9a8b6e9812ec05",
- "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT",
- "STRICTENC",
- "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",
- "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",
- "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",
- "SIG_PUSHONLY"
-],
-[
- "0x47 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb125101 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac",
- "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
- "",
- "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",
- "EVAL_FALSE"
-],
-[
- "11 0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001",
- "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
- "CLEANSTACK,P2SH",
- "P2PK with unnecessary input",
- "CLEANSTACK"
-],
-[
- "11 0x47 0x304402202f7505132be14872581f35d74b759212d9da40482653f1ffa3116c3294a4a51702206adbf347a2240ca41c66522b1a22a41693610b76a8e7770645dc721d1635854f01 0x43 0x410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
- "HASH160 0x14 0x31edc23bdafda4639e669f89ad6b2318dd79d032 EQUAL",
- "CLEANSTACK,P2SH",
- "P2SH with unnecessary input",
- "CLEANSTACK"
-],
-
-["The End"]
-]
diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json
new file mode 100644
index 0000000000..e69cc9e413
--- /dev/null
+++ b/src/test/data/script_tests.json
@@ -0,0 +1,1824 @@
+[
+["Format is: [scriptSig, scriptPubKey, flags, expected_scripterror, ... comments]"],
+["It is evaluated as if there was a crediting coinbase transaction with two 0"],
+["pushes as scriptSig, and one output of 0 satoshi and given scriptPubKey,"],
+["followed by a spending transaction which spends this output as only input (and"],
+["correct prevout hash), using the given scriptSig. All nLockTimes are 0, all"],
+["nSequences are max."],
+
+["", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "Test the test: we should have an empty stack after scriptSig evaluation"],
+[" ", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "and multiple spaces should not change that."],
+[" ", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+[" ", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["1 2", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK", "Similarly whitespace around and between symbols"],
+["1 2", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK"],
+[" 1 2", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK"],
+["1 2 ", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK"],
+[" 1 2 ", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK"],
+
+["1", "", "P2SH,STRICTENC", "OK"],
+["0x02 0x01 0x00", "", "P2SH,STRICTENC", "OK", "all bytes are significant, not only the last one"],
+["0x09 0x00000000 0x00000000 0x10", "", "P2SH,STRICTENC", "OK", "equals zero when cast to Int64"],
+
+["0x01 0x0b", "11 EQUAL", "P2SH,STRICTENC", "OK", "push 1 byte"],
+["0x02 0x417a", "'Az' EQUAL", "P2SH,STRICTENC", "OK"],
+["0x4b 0x417a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a",
+ "'Azzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' EQUAL", "P2SH,STRICTENC", "OK", "push 75 bytes"],
+
+["0x4c 0x01 0x07","7 EQUAL", "P2SH,STRICTENC", "OK", "0x4c is OP_PUSHDATA1"],
+["0x4d 0x0100 0x08","8 EQUAL", "P2SH,STRICTENC", "OK", "0x4d is OP_PUSHDATA2"],
+["0x4e 0x01000000 0x09","9 EQUAL", "P2SH,STRICTENC", "OK", "0x4e is OP_PUSHDATA4"],
+
+["0x4c 0x00","0 EQUAL", "P2SH,STRICTENC", "OK"],
+["0x4d 0x0000","0 EQUAL", "P2SH,STRICTENC", "OK"],
+["0x4e 0x00000000","0 EQUAL", "P2SH,STRICTENC", "OK"],
+["0x4f 1000 ADD","999 EQUAL", "P2SH,STRICTENC", "OK"],
+["0", "IF 0x50 ENDIF 1", "P2SH,STRICTENC", "OK", "0x50 is reserved (ok if not executed)"],
+["0x51", "0x5f ADD 0x60 EQUAL", "P2SH,STRICTENC", "OK", "0x51 through 0x60 push 1 through 16 onto stack"],
+["1","NOP", "P2SH,STRICTENC", "OK"],
+["0", "IF VER ELSE 1 ENDIF", "P2SH,STRICTENC", "OK", "VER non-functional (ok if not executed)"],
+["0", "IF RESERVED RESERVED1 RESERVED2 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK", "RESERVED ok in un-executed IF"],
+
+["1", "DUP IF ENDIF", "P2SH,STRICTENC", "OK"],
+["1", "IF 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["1", "DUP IF ELSE ENDIF", "P2SH,STRICTENC", "OK"],
+["1", "IF 1 ELSE ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+
+["1 1", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "OK"],
+["1 0", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "OK"],
+["1 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "OK"],
+["0 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "OK"],
+
+["1 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "OK"],
+["1 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "OK"],
+["1 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "OK"],
+["0 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "OK"],
+
+["0", "IF 0 ELSE 1 ELSE 0 ENDIF", "P2SH,STRICTENC", "OK", "Multiple ELSE's are valid and executed inverts on each ELSE encountered"],
+["1", "IF 1 ELSE 0 ELSE ENDIF", "P2SH,STRICTENC", "OK"],
+["1", "IF ELSE 0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["1", "IF 1 ELSE 0 ELSE 1 ENDIF ADD 2 EQUAL", "P2SH,STRICTENC", "OK"],
+["'' 1", "IF SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ENDIF 0x14 0x68ca4fec736264c13b859bac43d5173df6871682 EQUAL", "P2SH,STRICTENC", "OK"],
+
+["1", "NOTIF 0 ELSE 1 ELSE 0 ENDIF", "P2SH,STRICTENC", "OK", "Multiple ELSE's are valid and execution inverts on each ELSE encountered"],
+["0", "NOTIF 1 ELSE 0 ELSE ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "NOTIF ELSE 0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "NOTIF 1 ELSE 0 ELSE 1 ENDIF ADD 2 EQUAL", "P2SH,STRICTENC", "OK"],
+["'' 0", "NOTIF SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ENDIF 0x14 0x68ca4fec736264c13b859bac43d5173df6871682 EQUAL", "P2SH,STRICTENC", "OK"],
+
+["0", "IF 1 IF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 1 IF 1 ELSE RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL", "P2SH,STRICTENC", "OK", "Nested ELSE ELSE"],
+["1", "NOTIF 0 NOTIF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 0 NOTIF 1 ELSE RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL", "P2SH,STRICTENC", "OK"],
+
+["0", "IF RETURN ENDIF 1", "P2SH,STRICTENC", "OK", "RETURN only works if executed"],
+
+["1 1", "VERIFY", "P2SH,STRICTENC", "OK"],
+["1 0x05 0x01 0x00 0x00 0x00 0x00", "VERIFY", "P2SH,STRICTENC", "OK", "values >4 bytes can be cast to boolean"],
+["1 0x01 0x80", "IF 0 ENDIF", "P2SH,STRICTENC", "OK", "negative 0 is false"],
+
+["10 0 11 TOALTSTACK DROP FROMALTSTACK", "ADD 21 EQUAL", "P2SH,STRICTENC", "OK"],
+["'gavin_was_here' TOALTSTACK 11 FROMALTSTACK", "'gavin_was_here' EQUALVERIFY 11 EQUAL", "P2SH,STRICTENC", "OK"],
+
+["0 IFDUP", "DEPTH 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["1 IFDUP", "DEPTH 2 EQUALVERIFY 1 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK"],
+["0x05 0x0100000000 IFDUP", "DEPTH 2 EQUALVERIFY 0x05 0x0100000000 EQUAL", "P2SH,STRICTENC", "OK", "IFDUP dups non ints"],
+["0 DROP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["0", "DUP 1 ADD 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["0 1", "NIP", "P2SH,STRICTENC", "OK"],
+["1 0", "OVER DEPTH 3 EQUALVERIFY", "P2SH,STRICTENC", "OK"],
+["22 21 20", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "OK"],
+["22 21 20", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "OK"],
+["22 21 20", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "OK"],
+["22 21 20", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "OK"],
+["22 21 20", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "OK"],
+["22 21 20", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "OK"],
+["22 21 20", "ROT 22 EQUAL", "P2SH,STRICTENC", "OK"],
+["22 21 20", "ROT DROP 20 EQUAL", "P2SH,STRICTENC", "OK"],
+["22 21 20", "ROT DROP DROP 21 EQUAL", "P2SH,STRICTENC", "OK"],
+["22 21 20", "ROT ROT 21 EQUAL", "P2SH,STRICTENC", "OK"],
+["22 21 20", "ROT ROT ROT 20 EQUAL", "P2SH,STRICTENC", "OK"],
+["25 24 23 22 21 20", "2ROT 24 EQUAL", "P2SH,STRICTENC", "OK"],
+["25 24 23 22 21 20", "2ROT DROP 25 EQUAL", "P2SH,STRICTENC", "OK"],
+["25 24 23 22 21 20", "2ROT 2DROP 20 EQUAL", "P2SH,STRICTENC", "OK"],
+["25 24 23 22 21 20", "2ROT 2DROP DROP 21 EQUAL", "P2SH,STRICTENC", "OK"],
+["25 24 23 22 21 20", "2ROT 2DROP 2DROP 22 EQUAL", "P2SH,STRICTENC", "OK"],
+["25 24 23 22 21 20", "2ROT 2DROP 2DROP DROP 23 EQUAL", "P2SH,STRICTENC", "OK"],
+["25 24 23 22 21 20", "2ROT 2ROT 22 EQUAL", "P2SH,STRICTENC", "OK"],
+["25 24 23 22 21 20", "2ROT 2ROT 2ROT 20 EQUAL", "P2SH,STRICTENC", "OK"],
+["1 0", "SWAP 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["0 1", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP", "P2SH,STRICTENC", "OK"],
+["13 14", "2DUP ROT EQUALVERIFY EQUAL", "P2SH,STRICTENC", "OK"],
+["-1 0 1 2", "3DUP DEPTH 7 EQUALVERIFY ADD ADD 3 EQUALVERIFY 2DROP 0 EQUALVERIFY", "P2SH,STRICTENC", "OK"],
+["1 2 3 5", "2OVER ADD ADD 8 EQUALVERIFY ADD ADD 6 EQUAL", "P2SH,STRICTENC", "OK"],
+["1 3 5 7", "2SWAP ADD 4 EQUALVERIFY ADD 12 EQUAL", "P2SH,STRICTENC", "OK"],
+["0", "SIZE 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["1", "SIZE 1 EQUAL", "P2SH,STRICTENC", "OK"],
+["127", "SIZE 1 EQUAL", "P2SH,STRICTENC", "OK"],
+["128", "SIZE 2 EQUAL", "P2SH,STRICTENC", "OK"],
+["32767", "SIZE 2 EQUAL", "P2SH,STRICTENC", "OK"],
+["32768", "SIZE 3 EQUAL", "P2SH,STRICTENC", "OK"],
+["8388607", "SIZE 3 EQUAL", "P2SH,STRICTENC", "OK"],
+["8388608", "SIZE 4 EQUAL", "P2SH,STRICTENC", "OK"],
+["2147483647", "SIZE 4 EQUAL", "P2SH,STRICTENC", "OK"],
+["2147483648", "SIZE 5 EQUAL", "P2SH,STRICTENC", "OK"],
+["549755813887", "SIZE 5 EQUAL", "P2SH,STRICTENC", "OK"],
+["549755813888", "SIZE 6 EQUAL", "P2SH,STRICTENC", "OK"],
+["9223372036854775807", "SIZE 8 EQUAL", "P2SH,STRICTENC", "OK"],
+["-1", "SIZE 1 EQUAL", "P2SH,STRICTENC", "OK"],
+["-127", "SIZE 1 EQUAL", "P2SH,STRICTENC", "OK"],
+["-128", "SIZE 2 EQUAL", "P2SH,STRICTENC", "OK"],
+["-32767", "SIZE 2 EQUAL", "P2SH,STRICTENC", "OK"],
+["-32768", "SIZE 3 EQUAL", "P2SH,STRICTENC", "OK"],
+["-8388607", "SIZE 3 EQUAL", "P2SH,STRICTENC", "OK"],
+["-8388608", "SIZE 4 EQUAL", "P2SH,STRICTENC", "OK"],
+["-2147483647", "SIZE 4 EQUAL", "P2SH,STRICTENC", "OK"],
+["-2147483648", "SIZE 5 EQUAL", "P2SH,STRICTENC", "OK"],
+["-549755813887", "SIZE 5 EQUAL", "P2SH,STRICTENC", "OK"],
+["-549755813888", "SIZE 6 EQUAL", "P2SH,STRICTENC", "OK"],
+["-9223372036854775807", "SIZE 8 EQUAL", "P2SH,STRICTENC", "OK"],
+["'abcdefghijklmnopqrstuvwxyz'", "SIZE 26 EQUAL", "P2SH,STRICTENC", "OK"],
+
+["42", "SIZE 1 EQUALVERIFY 42 EQUAL", "P2SH,STRICTENC", "OK", "SIZE does not consume argument"],
+
+["2 -2 ADD", "0 EQUAL", "P2SH,STRICTENC", "OK"],
+["2147483647 -2147483647 ADD", "0 EQUAL", "P2SH,STRICTENC", "OK"],
+["-1 -1 ADD", "-2 EQUAL", "P2SH,STRICTENC", "OK"],
+
+["0 0","EQUAL", "P2SH,STRICTENC", "OK"],
+["1 1 ADD", "2 EQUAL", "P2SH,STRICTENC", "OK"],
+["1 1ADD", "2 EQUAL", "P2SH,STRICTENC", "OK"],
+["111 1SUB", "110 EQUAL", "P2SH,STRICTENC", "OK"],
+["111 1 ADD 12 SUB", "100 EQUAL", "P2SH,STRICTENC", "OK"],
+["0 ABS", "0 EQUAL", "P2SH,STRICTENC", "OK"],
+["16 ABS", "16 EQUAL", "P2SH,STRICTENC", "OK"],
+["-16 ABS", "-16 NEGATE EQUAL", "P2SH,STRICTENC", "OK"],
+["0 NOT", "NOP", "P2SH,STRICTENC", "OK"],
+["1 NOT", "0 EQUAL", "P2SH,STRICTENC", "OK"],
+["11 NOT", "0 EQUAL", "P2SH,STRICTENC", "OK"],
+["0 0NOTEQUAL", "0 EQUAL", "P2SH,STRICTENC", "OK"],
+["1 0NOTEQUAL", "1 EQUAL", "P2SH,STRICTENC", "OK"],
+["111 0NOTEQUAL", "1 EQUAL", "P2SH,STRICTENC", "OK"],
+["-111 0NOTEQUAL", "1 EQUAL", "P2SH,STRICTENC", "OK"],
+["1 1 BOOLAND", "NOP", "P2SH,STRICTENC", "OK"],
+["1 0 BOOLAND", "NOT", "P2SH,STRICTENC", "OK"],
+["0 1 BOOLAND", "NOT", "P2SH,STRICTENC", "OK"],
+["0 0 BOOLAND", "NOT", "P2SH,STRICTENC", "OK"],
+["16 17 BOOLAND", "NOP", "P2SH,STRICTENC", "OK"],
+["1 1 BOOLOR", "NOP", "P2SH,STRICTENC", "OK"],
+["1 0 BOOLOR", "NOP", "P2SH,STRICTENC", "OK"],
+["0 1 BOOLOR", "NOP", "P2SH,STRICTENC", "OK"],
+["0 0 BOOLOR", "NOT", "P2SH,STRICTENC", "OK"],
+["16 17 BOOLOR", "NOP", "P2SH,STRICTENC", "OK"],
+["11 10 1 ADD", "NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["11 10 1 ADD", "NUMEQUALVERIFY 1", "P2SH,STRICTENC", "OK"],
+["11 10 1 ADD", "NUMNOTEQUAL NOT", "P2SH,STRICTENC", "OK"],
+["111 10 1 ADD", "NUMNOTEQUAL", "P2SH,STRICTENC", "OK"],
+["11 10", "LESSTHAN NOT", "P2SH,STRICTENC", "OK"],
+["4 4", "LESSTHAN NOT", "P2SH,STRICTENC", "OK"],
+["10 11", "LESSTHAN", "P2SH,STRICTENC", "OK"],
+["-11 11", "LESSTHAN", "P2SH,STRICTENC", "OK"],
+["-11 -10", "LESSTHAN", "P2SH,STRICTENC", "OK"],
+["11 10", "GREATERTHAN", "P2SH,STRICTENC", "OK"],
+["4 4", "GREATERTHAN NOT", "P2SH,STRICTENC", "OK"],
+["10 11", "GREATERTHAN NOT", "P2SH,STRICTENC", "OK"],
+["-11 11", "GREATERTHAN NOT", "P2SH,STRICTENC", "OK"],
+["-11 -10", "GREATERTHAN NOT", "P2SH,STRICTENC", "OK"],
+["11 10", "LESSTHANOREQUAL NOT", "P2SH,STRICTENC", "OK"],
+["4 4", "LESSTHANOREQUAL", "P2SH,STRICTENC", "OK"],
+["10 11", "LESSTHANOREQUAL", "P2SH,STRICTENC", "OK"],
+["-11 11", "LESSTHANOREQUAL", "P2SH,STRICTENC", "OK"],
+["-11 -10", "LESSTHANOREQUAL", "P2SH,STRICTENC", "OK"],
+["11 10", "GREATERTHANOREQUAL", "P2SH,STRICTENC", "OK"],
+["4 4", "GREATERTHANOREQUAL", "P2SH,STRICTENC", "OK"],
+["10 11", "GREATERTHANOREQUAL NOT", "P2SH,STRICTENC", "OK"],
+["-11 11", "GREATERTHANOREQUAL NOT", "P2SH,STRICTENC", "OK"],
+["-11 -10", "GREATERTHANOREQUAL NOT", "P2SH,STRICTENC", "OK"],
+["1 0 MIN", "0 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["0 1 MIN", "0 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["-1 0 MIN", "-1 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["0 -2147483647 MIN", "-2147483647 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["2147483647 0 MAX", "2147483647 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["0 100 MAX", "100 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["-100 0 MAX", "0 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["0 -2147483647 MAX", "0 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["0 0 1", "WITHIN", "P2SH,STRICTENC", "OK"],
+["1 0 1", "WITHIN NOT", "P2SH,STRICTENC", "OK"],
+["0 -2147483647 2147483647", "WITHIN", "P2SH,STRICTENC", "OK"],
+["-1 -100 100", "WITHIN", "P2SH,STRICTENC", "OK"],
+["11 -100 100", "WITHIN", "P2SH,STRICTENC", "OK"],
+["-2147483647 -100 100", "WITHIN NOT", "P2SH,STRICTENC", "OK"],
+["2147483647 -100 100", "WITHIN NOT", "P2SH,STRICTENC", "OK"],
+
+["2147483647 2147483647 SUB", "0 EQUAL", "P2SH,STRICTENC", "OK"],
+["2147483647 DUP ADD", "4294967294 EQUAL", "P2SH,STRICTENC", "OK", ">32 bit EQUAL is valid"],
+["2147483647 NEGATE DUP ADD", "-4294967294 EQUAL", "P2SH,STRICTENC", "OK"],
+
+["''", "RIPEMD160 0x14 0x9c1185a5c5e9fc54612808977ee8f548b2258d31 EQUAL", "P2SH,STRICTENC", "OK"],
+["'a'", "RIPEMD160 0x14 0x0bdc9d2d256b3ee9daae347be6f4dc835a467ffe EQUAL", "P2SH,STRICTENC", "OK"],
+["'abcdefghijklmnopqrstuvwxyz'", "RIPEMD160 0x14 0xf71c27109c692c1b56bbdceb5b9d2865b3708dbc EQUAL", "P2SH,STRICTENC", "OK"],
+["''", "SHA1 0x14 0xda39a3ee5e6b4b0d3255bfef95601890afd80709 EQUAL", "P2SH,STRICTENC", "OK"],
+["'a'", "SHA1 0x14 0x86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 EQUAL", "P2SH,STRICTENC", "OK"],
+["'abcdefghijklmnopqrstuvwxyz'", "SHA1 0x14 0x32d10c7b8cf96570ca04ce37f2a19d84240d3a89 EQUAL", "P2SH,STRICTENC", "OK"],
+["''", "SHA256 0x20 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 EQUAL", "P2SH,STRICTENC", "OK"],
+["'a'", "SHA256 0x20 0xca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb EQUAL", "P2SH,STRICTENC", "OK"],
+["'abcdefghijklmnopqrstuvwxyz'", "SHA256 0x20 0x71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73 EQUAL", "P2SH,STRICTENC", "OK"],
+["''", "DUP HASH160 SWAP SHA256 RIPEMD160 EQUAL", "P2SH,STRICTENC", "OK"],
+["''", "DUP HASH256 SWAP SHA256 SHA256 EQUAL", "P2SH,STRICTENC", "OK"],
+["''", "NOP HASH160 0x14 0xb472a266d0bd89c13706a4132ccfb16f7c3b9fcb EQUAL", "P2SH,STRICTENC", "OK"],
+["'a'", "HASH160 NOP 0x14 0x994355199e516ff76c4fa4aab39337b9d84cf12b EQUAL", "P2SH,STRICTENC", "OK"],
+["'abcdefghijklmnopqrstuvwxyz'", "HASH160 0x4c 0x14 0xc286a1af0947f58d1ad787385b1c2c4a976f9e71 EQUAL", "P2SH,STRICTENC", "OK"],
+["''", "HASH256 0x20 0x5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456 EQUAL", "P2SH,STRICTENC", "OK"],
+["'a'", "HASH256 0x20 0xbf5d3affb73efd2ec6c36ad3112dd933efed63c4e1cbffcfa88e2759c144f2d8 EQUAL", "P2SH,STRICTENC", "OK"],
+["'abcdefghijklmnopqrstuvwxyz'", "HASH256 0x4c 0x20 0xca139bc10c2f660da42666f72e89a225936fc60f193c161124a672050c434671 EQUAL", "P2SH,STRICTENC", "OK"],
+
+
+["1","NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 1 EQUAL", "P2SH,STRICTENC", "OK"],
+["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' EQUAL", "P2SH,STRICTENC", "OK"],
+
+["1", "NOP", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", "OK", "Discourage NOPx flag allows OP_NOP"],
+
+["0", "IF NOP10 ENDIF 1", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", "OK",
+ "Discouraged NOPs are allowed if not executed"],
+
+["0", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "OK", "opcodes above NOP10 invalid if executed"],
+["0", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xc0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xc4 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xc5 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xc6 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xc7 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xc8 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xc9 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xca ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xcb ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xcc ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xcd ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xce ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xcf ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xd0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xd1 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xd2 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xd3 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xd4 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xd5 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xd6 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xd7 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xd8 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xd9 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xda ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xdb ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xdc ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xdd ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xde ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xdf ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xe0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xe1 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xe2 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xe3 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xe4 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xe5 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xe6 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xe7 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xe8 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xe9 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xea ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xeb ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xec ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xed ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xee ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xef ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xf0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xf1 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xf2 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xf3 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xf4 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xf5 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xf6 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xf7 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xf8 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xf9 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xfa ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xfb ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xfc ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xfd ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xfe ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xff ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+
+["NOP",
+"'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'",
+"P2SH,STRICTENC", "OK",
+"520 byte push"],
+["1",
+"0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161",
+"P2SH,STRICTENC", "OK",
+"201 opcodes executed. 0x61 is NOP"],
+["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"P2SH,STRICTENC", "OK",
+"1,000 stack size (0x6f is 3DUP)"],
+["1 TOALTSTACK 2 TOALTSTACK 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"1 2 3 4 5 6 7 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"P2SH,STRICTENC", "OK",
+"1,000 stack size (altstack cleared between scriptSig/scriptPubKey)"],
+["'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f 2DUP 0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161",
+"P2SH,STRICTENC", "OK",
+"Max-size (10,000-byte), max-push(520 bytes), max-opcodes(201), max stack size(1,000 items). 0x6f is 3DUP, 0x61 is NOP"],
+
+["0",
+"IF 0x5050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050 ENDIF 1",
+"P2SH,STRICTENC", "OK",
+">201 opcodes, but RESERVED (0x50) doesn't count towards opcode limit."],
+
+["NOP","1", "P2SH,STRICTENC", "OK"],
+
+["1", "0x01 0x01 EQUAL", "P2SH,STRICTENC", "OK", "The following is useful for checking implementations of BN_bn2mpi"],
+["127", "0x01 0x7F EQUAL", "P2SH,STRICTENC", "OK"],
+["128", "0x02 0x8000 EQUAL", "P2SH,STRICTENC", "OK", "Leave room for the sign bit"],
+["32767", "0x02 0xFF7F EQUAL", "P2SH,STRICTENC", "OK"],
+["32768", "0x03 0x008000 EQUAL", "P2SH,STRICTENC", "OK"],
+["8388607", "0x03 0xFFFF7F EQUAL", "P2SH,STRICTENC", "OK"],
+["8388608", "0x04 0x00008000 EQUAL", "P2SH,STRICTENC", "OK"],
+["2147483647", "0x04 0xFFFFFF7F EQUAL", "P2SH,STRICTENC", "OK"],
+["2147483648", "0x05 0x0000008000 EQUAL", "P2SH,STRICTENC", "OK"],
+["549755813887", "0x05 0xFFFFFFFF7F EQUAL", "P2SH,STRICTENC", "OK"],
+["549755813888", "0x06 0xFFFFFFFF7F EQUAL", "P2SH,STRICTENC", "OK"],
+["9223372036854775807", "0x08 0xFFFFFFFFFFFFFF7F EQUAL", "P2SH,STRICTENC", "OK"],
+["-1", "0x01 0x81 EQUAL", "P2SH,STRICTENC", "OK", "Numbers are little-endian with the MSB being a sign bit"],
+["-127", "0x01 0xFF EQUAL", "P2SH,STRICTENC", "OK"],
+["-128", "0x02 0x8080 EQUAL", "P2SH,STRICTENC", "OK"],
+["-32767", "0x02 0xFFFF EQUAL", "P2SH,STRICTENC", "OK"],
+["-32768", "0x03 0x008080 EQUAL", "P2SH,STRICTENC", "OK"],
+["-8388607", "0x03 0xFFFFFF EQUAL", "P2SH,STRICTENC", "OK"],
+["-8388608", "0x04 0x00008080 EQUAL", "P2SH,STRICTENC", "OK"],
+["-2147483647", "0x04 0xFFFFFFFF EQUAL", "P2SH,STRICTENC", "OK"],
+["-2147483648", "0x05 0x0000008080 EQUAL", "P2SH,STRICTENC", "OK"],
+["-4294967295", "0x05 0xFFFFFFFF80 EQUAL", "P2SH,STRICTENC", "OK"],
+["-549755813887", "0x05 0xFFFFFFFFFF EQUAL", "P2SH,STRICTENC", "OK"],
+["-549755813888", "0x06 0x000000008080 EQUAL", "P2SH,STRICTENC", "OK"],
+["-9223372036854775807", "0x08 0xFFFFFFFFFFFFFFFF EQUAL", "P2SH,STRICTENC", "OK"],
+
+["2147483647", "1ADD 2147483648 EQUAL", "P2SH,STRICTENC", "OK", "We can do math on 4-byte integers, and compare 5-byte ones"],
+["2147483647", "1ADD 1", "P2SH,STRICTENC", "OK"],
+["-2147483647", "1ADD 1", "P2SH,STRICTENC", "OK"],
+
+["1", "0x02 0x0100 EQUAL NOT", "P2SH,STRICTENC", "OK", "Not the same byte array..."],
+["1", "0x02 0x0100 NUMEQUAL", "P2SH,STRICTENC", "OK", "... but they are numerically equal"],
+["11", "0x4c 0x03 0x0b0000 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["0", "0x01 0x80 EQUAL NOT", "P2SH,STRICTENC", "OK"],
+["0", "0x01 0x80 NUMEQUAL", "P2SH,STRICTENC", "OK", "Zero numerically equals negative zero"],
+["0", "0x02 0x0080 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["0x03 0x000080", "0x04 0x00000080 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["0x03 0x100080", "0x04 0x10000080 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["0x03 0x100000", "0x04 0x10000000 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+
+["NOP", "NOP 1", "P2SH,STRICTENC", "OK", "The following tests check the if(stack.size() < N) tests in each opcode"],
+["1", "IF 1 ENDIF", "P2SH,STRICTENC", "OK", "They are here to catch copy-and-paste errors"],
+["0", "NOTIF 1 ENDIF", "P2SH,STRICTENC", "OK", "Most of them are duplicated elsewhere,"],
+["1", "VERIFY 1", "P2SH,STRICTENC", "OK", "but, hey, more is always better, right?"],
+
+["0", "TOALTSTACK 1", "P2SH,STRICTENC", "OK"],
+["1", "TOALTSTACK FROMALTSTACK", "P2SH,STRICTENC", "OK"],
+["0 0", "2DROP 1", "P2SH,STRICTENC", "OK"],
+["0 1", "2DUP", "P2SH,STRICTENC", "OK"],
+["0 0 1", "3DUP", "P2SH,STRICTENC", "OK"],
+["0 1 0 0", "2OVER", "P2SH,STRICTENC", "OK"],
+["0 1 0 0 0 0", "2ROT", "P2SH,STRICTENC", "OK"],
+["0 1 0 0", "2SWAP", "P2SH,STRICTENC", "OK"],
+["1", "IFDUP", "P2SH,STRICTENC", "OK"],
+["NOP", "DEPTH 1", "P2SH,STRICTENC", "OK"],
+["0", "DROP 1", "P2SH,STRICTENC", "OK"],
+["1", "DUP", "P2SH,STRICTENC", "OK"],
+["0 1", "NIP", "P2SH,STRICTENC", "OK"],
+["1 0", "OVER", "P2SH,STRICTENC", "OK"],
+["1 0 0 0 3", "PICK", "P2SH,STRICTENC", "OK"],
+["1 0", "PICK", "P2SH,STRICTENC", "OK"],
+["1 0 0 0 3", "ROLL", "P2SH,STRICTENC", "OK"],
+["1 0", "ROLL", "P2SH,STRICTENC", "OK"],
+["1 0 0", "ROT", "P2SH,STRICTENC", "OK"],
+["1 0", "SWAP", "P2SH,STRICTENC", "OK"],
+["0 1", "TUCK", "P2SH,STRICTENC", "OK"],
+
+["1", "SIZE", "P2SH,STRICTENC", "OK"],
+
+["0 0", "EQUAL", "P2SH,STRICTENC", "OK"],
+["0 0", "EQUALVERIFY 1", "P2SH,STRICTENC", "OK"],
+["0 0 1", "EQUAL EQUAL", "P2SH,STRICTENC", "OK", "OP_0 and bools must have identical byte representations"],
+
+["0", "1ADD", "P2SH,STRICTENC", "OK"],
+["2", "1SUB", "P2SH,STRICTENC", "OK"],
+["-1", "NEGATE", "P2SH,STRICTENC", "OK"],
+["-1", "ABS", "P2SH,STRICTENC", "OK"],
+["0", "NOT", "P2SH,STRICTENC", "OK"],
+["-1", "0NOTEQUAL", "P2SH,STRICTENC", "OK"],
+
+["1 0", "ADD", "P2SH,STRICTENC", "OK"],
+["1 0", "SUB", "P2SH,STRICTENC", "OK"],
+["-1 -1", "BOOLAND", "P2SH,STRICTENC", "OK"],
+["-1 0", "BOOLOR", "P2SH,STRICTENC", "OK"],
+["0 0", "NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["0 0", "NUMEQUALVERIFY 1", "P2SH,STRICTENC", "OK"],
+["-1 0", "NUMNOTEQUAL", "P2SH,STRICTENC", "OK"],
+["-1 0", "LESSTHAN", "P2SH,STRICTENC", "OK"],
+["1 0", "GREATERTHAN", "P2SH,STRICTENC", "OK"],
+["0 0", "LESSTHANOREQUAL", "P2SH,STRICTENC", "OK"],
+["0 0", "GREATERTHANOREQUAL", "P2SH,STRICTENC", "OK"],
+["-1 0", "MIN", "P2SH,STRICTENC", "OK"],
+["1 0", "MAX", "P2SH,STRICTENC", "OK"],
+["-1 -1 0", "WITHIN", "P2SH,STRICTENC", "OK"],
+
+["0", "RIPEMD160", "P2SH,STRICTENC", "OK"],
+["0", "SHA1", "P2SH,STRICTENC", "OK"],
+["0", "SHA256", "P2SH,STRICTENC", "OK"],
+["0", "HASH160", "P2SH,STRICTENC", "OK"],
+["0", "HASH256", "P2SH,STRICTENC", "OK"],
+["NOP", "CODESEPARATOR 1", "P2SH,STRICTENC", "OK"],
+
+["NOP", "NOP1 1", "P2SH,STRICTENC", "OK"],
+["NOP", "CHECKLOCKTIMEVERIFY 1", "P2SH,STRICTENC", "OK"],
+["NOP", "NOP3 1", "P2SH,STRICTENC", "OK"],
+["NOP", "NOP4 1", "P2SH,STRICTENC", "OK"],
+["NOP", "NOP5 1", "P2SH,STRICTENC", "OK"],
+["NOP", "NOP6 1", "P2SH,STRICTENC", "OK"],
+["NOP", "NOP7 1", "P2SH,STRICTENC", "OK"],
+["NOP", "NOP8 1", "P2SH,STRICTENC", "OK"],
+["NOP", "NOP9 1", "P2SH,STRICTENC", "OK"],
+["NOP", "NOP10 1", "P2SH,STRICTENC", "OK"],
+
+["", "0 0 0 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "CHECKMULTISIG is allowed to have zero keys and/or sigs"],
+["", "0 0 0 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 0 1 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "Zero sigs means no sigs are checked"],
+["", "0 0 0 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+
+["", "0 0 0 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "CHECKMULTISIG is allowed to have zero keys and/or sigs"],
+["", "0 0 0 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 0 1 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "Zero sigs means no sigs are checked"],
+["", "0 0 0 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+
+["", "0 0 'a' 'b' 2 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "Test from up to 20 pubkeys, all not checked"],
+["", "0 0 'a' 'b' 'c' 3 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 4 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 5 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 6 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 7 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 8 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 9 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 10 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 11 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 12 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 13 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 14 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 15 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 16 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 17 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 18 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 19 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 2 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 3 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 4 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 5 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 6 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 7 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 8 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 9 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 10 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 11 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 12 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 13 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 14 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 15 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 16 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 17 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 18 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 19 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+
+["",
+"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",
+"P2SH,STRICTENC", "OK",
+"nOpCount is incremented by the number of keys evaluated in addition to the usual one op per op. In this case we have zero keys, so we can execute 201 CHECKMULTISIGS"],
+
+["1",
+"0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY",
+"P2SH,STRICTENC", "OK"],
+
+["",
+"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", "OK",
+"Even though there are no signatures being checked nOpCount is incremented by the number of keys."],
+
+["1",
+"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", "OK"],
+
+["0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "OK", "Very basic P2SH"],
+["0x4c 0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "OK"],
+
+["0x40 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242",
+"0x4d 0x4000 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 EQUAL",
+"P2SH,STRICTENC", "OK",
+"Basic PUSH signedness check"],
+
+["0x4c 0x40 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242",
+"0x4d 0x4000 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 EQUAL",
+"P2SH,STRICTENC", "OK",
+"Basic PUSHDATA1 signedness check"],
+
+["all PUSHDATA forms are equivalent"],
+
+["0x4c 0x4b 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "0x4b 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 EQUAL", "", "OK", "PUSHDATA1 of 75 bytes equals direct push of it"],
+["0x4d 0xFF00 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "0x4c 0xFF 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 EQUAL", "", "OK", "PUSHDATA2 of 255 bytes equals PUSHDATA1 of it"],
+
+["0x00", "SIZE 0 EQUAL", "P2SH,STRICTENC", "OK", "Basic OP_0 execution"],
+
+["Numeric pushes"],
+
+["0x01 0x81", "0x4f EQUAL", "", "OK", "OP1_NEGATE pushes 0x81"],
+["0x01 0x01", "0x51 EQUAL", "", "OK", "OP_1 pushes 0x01"],
+["0x01 0x02", "0x52 EQUAL", "", "OK", "OP_2 pushes 0x02"],
+["0x01 0x03", "0x53 EQUAL", "", "OK", "OP_3 pushes 0x03"],
+["0x01 0x04", "0x54 EQUAL", "", "OK", "OP_4 pushes 0x04"],
+["0x01 0x05", "0x55 EQUAL", "", "OK", "OP_5 pushes 0x05"],
+["0x01 0x06", "0x56 EQUAL", "", "OK", "OP_6 pushes 0x06"],
+["0x01 0x07", "0x57 EQUAL", "", "OK", "OP_7 pushes 0x07"],
+["0x01 0x08", "0x58 EQUAL", "", "OK", "OP_8 pushes 0x08"],
+["0x01 0x09", "0x59 EQUAL", "", "OK", "OP_9 pushes 0x09"],
+["0x01 0x0a", "0x5a EQUAL", "", "OK", "OP_10 pushes 0x0a"],
+["0x01 0x0b", "0x5b EQUAL", "", "OK", "OP_11 pushes 0x0b"],
+["0x01 0x0c", "0x5c EQUAL", "", "OK", "OP_12 pushes 0x0c"],
+["0x01 0x0d", "0x5d EQUAL", "", "OK", "OP_13 pushes 0x0d"],
+["0x01 0x0e", "0x5e EQUAL", "", "OK", "OP_14 pushes 0x0e"],
+["0x01 0x0f", "0x5f EQUAL", "", "OK", "OP_15 pushes 0x0f"],
+["0x01 0x10", "0x60 EQUAL", "", "OK", "OP_16 pushes 0x10"],
+
+["Equivalency of different numeric encodings"],
+
+["0x02 0x8000", "128 NUMEQUAL", "", "OK", "0x8000 equals 128"],
+["0x01 0x00", "0 NUMEQUAL", "", "OK", "0x00 numequals 0"],
+["0x01 0x80", "0 NUMEQUAL", "", "OK", "0x80 (negative zero) numequals 0"],
+["0x02 0x0080", "0 NUMEQUAL", "", "OK", "0x0080 numequals 0"],
+["0x02 0x0500", "5 NUMEQUAL", "", "OK", "0x0500 numequals 5"],
+["0x03 0xff7f80", "0x02 0xffff NUMEQUAL", "", "OK", ""],
+["0x03 0xff7f00", "0x02 0xff7f NUMEQUAL", "", "OK", ""],
+["0x04 0xffff7f80", "0x03 0xffffff NUMEQUAL", "", "OK", ""],
+["0x04 0xffff7f00", "0x03 0xffff7f NUMEQUAL", "", "OK", ""],
+
+["Unevaluated non-minimal pushes are ignored"],
+
+["0 IF 0x4c 0x00 ENDIF 1", "", "MINIMALDATA", "OK", "non-minimal PUSHDATA1 ignored"],
+["0 IF 0x4d 0x0000 ENDIF 1", "", "MINIMALDATA", "OK", "non-minimal PUSHDATA2 ignored"],
+["0 IF 0x4c 0x00000000 ENDIF 1", "", "MINIMALDATA", "OK", "non-minimal PUSHDATA4 ignored"],
+["0 IF 0x01 0x81 ENDIF 1", "", "MINIMALDATA", "OK", "1NEGATE equiv"],
+["0 IF 0x01 0x01 ENDIF 1", "", "MINIMALDATA", "OK", "OP_1 equiv"],
+["0 IF 0x01 0x02 ENDIF 1", "", "MINIMALDATA", "OK", "OP_2 equiv"],
+["0 IF 0x01 0x03 ENDIF 1", "", "MINIMALDATA", "OK", "OP_3 equiv"],
+["0 IF 0x01 0x04 ENDIF 1", "", "MINIMALDATA", "OK", "OP_4 equiv"],
+["0 IF 0x01 0x05 ENDIF 1", "", "MINIMALDATA", "OK", "OP_5 equiv"],
+["0 IF 0x01 0x06 ENDIF 1", "", "MINIMALDATA", "OK", "OP_6 equiv"],
+["0 IF 0x01 0x07 ENDIF 1", "", "MINIMALDATA", "OK", "OP_7 equiv"],
+["0 IF 0x01 0x08 ENDIF 1", "", "MINIMALDATA", "OK", "OP_8 equiv"],
+["0 IF 0x01 0x09 ENDIF 1", "", "MINIMALDATA", "OK", "OP_9 equiv"],
+["0 IF 0x01 0x0a ENDIF 1", "", "MINIMALDATA", "OK", "OP_10 equiv"],
+["0 IF 0x01 0x0b ENDIF 1", "", "MINIMALDATA", "OK", "OP_11 equiv"],
+["0 IF 0x01 0x0c ENDIF 1", "", "MINIMALDATA", "OK", "OP_12 equiv"],
+["0 IF 0x01 0x0d ENDIF 1", "", "MINIMALDATA", "OK", "OP_13 equiv"],
+["0 IF 0x01 0x0e ENDIF 1", "", "MINIMALDATA", "OK", "OP_14 equiv"],
+["0 IF 0x01 0x0f ENDIF 1", "", "MINIMALDATA", "OK", "OP_15 equiv"],
+["0 IF 0x01 0x10 ENDIF 1", "", "MINIMALDATA", "OK", "OP_16 equiv"],
+
+["Numeric minimaldata rules are only applied when a stack item is numerically evaluated; the push itself is allowed"],
+
+["0x01 0x00", "1", "MINIMALDATA", "OK"],
+["0x01 0x80", "1", "MINIMALDATA", "OK"],
+["0x02 0x0180", "1", "MINIMALDATA", "OK"],
+["0x02 0x0100", "1", "MINIMALDATA", "OK"],
+["0x02 0x0200", "1", "MINIMALDATA", "OK"],
+["0x02 0x0300", "1", "MINIMALDATA", "OK"],
+["0x02 0x0400", "1", "MINIMALDATA", "OK"],
+["0x02 0x0500", "1", "MINIMALDATA", "OK"],
+["0x02 0x0600", "1", "MINIMALDATA", "OK"],
+["0x02 0x0700", "1", "MINIMALDATA", "OK"],
+["0x02 0x0800", "1", "MINIMALDATA", "OK"],
+["0x02 0x0900", "1", "MINIMALDATA", "OK"],
+["0x02 0x0a00", "1", "MINIMALDATA", "OK"],
+["0x02 0x0b00", "1", "MINIMALDATA", "OK"],
+["0x02 0x0c00", "1", "MINIMALDATA", "OK"],
+["0x02 0x0d00", "1", "MINIMALDATA", "OK"],
+["0x02 0x0e00", "1", "MINIMALDATA", "OK"],
+["0x02 0x0f00", "1", "MINIMALDATA", "OK"],
+["0x02 0x1000", "1", "MINIMALDATA", "OK"],
+
+["Valid version of the 'Test every numeric-accepting opcode for correct handling of the numeric minimal encoding rule' script_invalid test"],
+
+["1 0x02 0x0000", "PICK DROP", "", "OK"],
+["1 0x02 0x0000", "ROLL DROP 1", "", "OK"],
+["0x02 0x0000", "1ADD DROP 1", "", "OK"],
+["0x02 0x0000", "1SUB DROP 1", "", "OK"],
+["0x02 0x0000", "NEGATE DROP 1", "", "OK"],
+["0x02 0x0000", "ABS DROP 1", "", "OK"],
+["0x02 0x0000", "NOT DROP 1", "", "OK"],
+["0x02 0x0000", "0NOTEQUAL DROP 1", "", "OK"],
+
+["0 0x02 0x0000", "ADD DROP 1", "", "OK"],
+["0x02 0x0000 0", "ADD DROP 1", "", "OK"],
+["0 0x02 0x0000", "SUB DROP 1", "", "OK"],
+["0x02 0x0000 0", "SUB DROP 1", "", "OK"],
+["0 0x02 0x0000", "BOOLAND DROP 1", "", "OK"],
+["0x02 0x0000 0", "BOOLAND DROP 1", "", "OK"],
+["0 0x02 0x0000", "BOOLOR DROP 1", "", "OK"],
+["0x02 0x0000 0", "BOOLOR DROP 1", "", "OK"],
+["0 0x02 0x0000", "NUMEQUAL DROP 1", "", "OK"],
+["0x02 0x0000 1", "NUMEQUAL DROP 1", "", "OK"],
+["0 0x02 0x0000", "NUMEQUALVERIFY 1", "", "OK"],
+["0x02 0x0000 0", "NUMEQUALVERIFY 1", "", "OK"],
+["0 0x02 0x0000", "NUMNOTEQUAL DROP 1", "", "OK"],
+["0x02 0x0000 0", "NUMNOTEQUAL DROP 1", "", "OK"],
+["0 0x02 0x0000", "LESSTHAN DROP 1", "", "OK"],
+["0x02 0x0000 0", "LESSTHAN DROP 1", "", "OK"],
+["0 0x02 0x0000", "GREATERTHAN DROP 1", "", "OK"],
+["0x02 0x0000 0", "GREATERTHAN DROP 1", "", "OK"],
+["0 0x02 0x0000", "LESSTHANOREQUAL DROP 1", "", "OK"],
+["0x02 0x0000 0", "LESSTHANOREQUAL DROP 1", "", "OK"],
+["0 0x02 0x0000", "GREATERTHANOREQUAL DROP 1", "", "OK"],
+["0x02 0x0000 0", "GREATERTHANOREQUAL DROP 1", "", "OK"],
+["0 0x02 0x0000", "MIN DROP 1", "", "OK"],
+["0x02 0x0000 0", "MIN DROP 1", "", "OK"],
+["0 0x02 0x0000", "MAX DROP 1", "", "OK"],
+["0x02 0x0000 0", "MAX DROP 1", "", "OK"],
+
+["0x02 0x0000 0 0", "WITHIN DROP 1", "", "OK"],
+["0 0x02 0x0000 0", "WITHIN DROP 1", "", "OK"],
+["0 0 0x02 0x0000", "WITHIN DROP 1", "", "OK"],
+
+["0 0 0x02 0x0000", "CHECKMULTISIG DROP 1", "", "OK"],
+["0 0x02 0x0000 0", "CHECKMULTISIG DROP 1", "", "OK"],
+["0 0x02 0x0000 0 1", "CHECKMULTISIG DROP 1", "", "OK"],
+["0 0 0x02 0x0000", "CHECKMULTISIGVERIFY 1", "", "OK"],
+["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", "", "OK"],
+
+["While not really correctly DER encoded, the empty signature is allowed by"],
+["STRICTENC to provide a compact way to provide a delibrately invalid signature."],
+["0", "0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 CHECKSIG NOT", "STRICTENC", "OK"],
+["0 0", "1 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 1 CHECKMULTISIG NOT", "STRICTENC", "OK"],
+
+["CHECKMULTISIG evaluation order tests. CHECKMULTISIG evaluates signatures and"],
+["pubkeys in a specific order, and will exit early if the number of signatures"],
+["left to check is greater than the number of keys left. As STRICTENC fails the"],
+["script when it reaches an invalidly encoded signature or pubkey, we can use it"],
+["to test the exact order in which signatures and pubkeys are evaluated by"],
+["distinguishing CHECKMULTISIG returning false on the stack and the script as a"],
+["whole failing."],
+["See also the corresponding inverted versions of these tests in script_invalid.json"],
+[
+ "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501",
+ "2 0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT",
+ "STRICTENC", "OK",
+ "2-of-2 CHECKMULTISIG NOT with the second pubkey invalid, and both signatures validly encoded. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid pubkey."
+],
+[
+ "0 0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501",
+ "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT",
+ "STRICTENC", "OK",
+ "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but second signature invalid. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid signature."
+],
+
+["Increase test coverage for DERSIG"],
+["0x4a 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "", "OK", "Overly long signature is correctly encoded"],
+["0x25 0x30220220000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "", "OK", "Missing S is correctly encoded"],
+["0x27 0x3024021077777777777777777777777777777777020a7777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "S with invalid S length is correctly encoded"],
+["0x27 0x302403107777777777777777777777777777777702107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Non-integer R is correctly encoded"],
+["0x27 0x302402107777777777777777777777777777777703107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Non-integer S is correctly encoded"],
+["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Zero-length R is correctly encoded"],
+["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "", "OK", "Zero-length S is correctly encoded for DERSIG"],
+["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Negative S is correctly encoded"],
+
+["", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "Test the test: we should have an empty stack after scriptSig evaluation"],
+[" ", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "and multiple spaces should not change that."],
+[" ", "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","BAD_OPCODE", "PUSHDATA1 with not enough bytes"],
+["0x4d0200ff","0x01 NOP", "P2SH,STRICTENC","BAD_OPCODE", "PUSHDATA2 with not enough bytes"],
+["0x4e03000000ffff","0x01 NOP", "P2SH,STRICTENC","BAD_OPCODE", "PUSHDATA4 with not enough bytes"],
+
+["1", "IF 0x50 ENDIF 1", "P2SH,STRICTENC","BAD_OPCODE", "0x50 is reserved"],
+["0x52", "0x5f ADD 0x60 EQUAL", "P2SH,STRICTENC","EVAL_FALSE", "0x51 through 0x60 push 1 through 16 onto stack"],
+["0","NOP", "P2SH,STRICTENC","EVAL_FALSE",""],
+["1", "IF VER ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VER non-functional"],
+["0", "IF VERIF ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VERIF illegal everywhere"],
+["0", "IF ELSE 1 ELSE VERIF ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VERIF illegal everywhere"],
+["0", "IF VERNOTIF ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VERNOTIF illegal everywhere"],
+["0", "IF ELSE 1 ELSE VERNOTIF ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VERNOTIF illegal everywhere"],
+
+["1 IF", "1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "IF/ENDIF can't span scriptSig/scriptPubKey"],
+["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", "OP_RETURN", "Multiple ELSEs"],
+["1", "IF 1 ELSE ELSE RETURN ENDIF", "P2SH,STRICTENC", "OP_RETURN"],
+
+["1", "ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "Malformed IF/ELSE/ENDIF sequence"],
+["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", "OP_RETURN", "canonical prunable txout format"],
+["0 IF", "RETURN ENDIF 1", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "still prunable because IF/ENDIF can't span scriptSig/scriptPubKey"],
+
+["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", "INVALID_ALTSTACK_OPERATION", "alt stack not shared between sig/pubkey"],
+
+["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", "DISABLED_OPCODE", "CAT disabled"],
+["'a' 'b' 0", "IF CAT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "CAT disabled"],
+["'abc' 1 1", "SUBSTR", "P2SH,STRICTENC", "DISABLED_OPCODE", "SUBSTR disabled"],
+["'abc' 1 1 0", "IF SUBSTR ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "SUBSTR disabled"],
+["'abc' 2 0", "IF LEFT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "LEFT disabled"],
+["'abc' 2 0", "IF RIGHT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "RIGHT disabled"],
+
+["NOP", "SIZE 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+
+["'abc'", "IF INVERT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "INVERT disabled"],
+["1 2 0 IF AND ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "AND disabled"],
+["1 2 0 IF OR ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "OR disabled"],
+["1 2 0 IF XOR ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "XOR disabled"],
+["2 0 IF 2MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "2MUL disabled"],
+["2 0 IF 2DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "2DIV disabled"],
+["2 2 0 IF MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "MUL disabled"],
+["2 2 0 IF DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "DIV disabled"],
+["2 2 0 IF MOD ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "MOD disabled"],
+["2 2 0 IF LSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "LSHIFT disabled"],
+["2 2 0 IF RSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "RSHIFT disabled"],
+
+["", "EQUAL NOT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "EQUAL must error when there are no stack items"],
+["0", "EQUAL NOT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "EQUAL must error when there are not 2 stack items"],
+["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", "UNKNOWN_ERROR", "arithmetic operands must be in range [-2^31...2^31] "],
+["-2147483648 0 ADD", "NOP", "P2SH,STRICTENC", "UNKNOWN_ERROR", "arithmetic operands must be in range [-2^31...2^31] "],
+["2147483647 DUP ADD", "4294967294 NUMEQUAL", "P2SH,STRICTENC", "UNKNOWN_ERROR", "NUMEQUAL must be in numeric range"],
+["'abcdef' NOT", "0 EQUAL", "P2SH,STRICTENC", "UNKNOWN_ERROR", "NOT is an arithmetic operand"],
+
+["2 DUP MUL", "4 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"],
+["2 DUP DIV", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"],
+["2 2MUL", "4 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"],
+["2 2DIV", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"],
+["7 3 MOD", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"],
+["2 2 LSHIFT", "8 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"],
+["2 1 RSHIFT", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"],
+
+["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", "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", "DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in scriptSig"],
+
+["1 0x01 0xb9", "HASH160 0x14 0x15727299b05b45fdaf9ac9ecf7565cfe27c3e567 EQUAL",
+ "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in redeemScript"],
+
+["0x50","1", "P2SH,STRICTENC", "BAD_OPCODE", "opcode 0x50 is reserved"],
+["1", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "opcodes above NOP10 invalid if executed"],
+["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", "UNBALANCED_CONDITIONAL", "invalid because scriptSig and scriptPubKey are processed separately"],
+
+["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",
+"PUSH_SIZE",
+">520 byte push"],
+["0",
+"IF 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' ENDIF 1",
+"P2SH,STRICTENC",
+"PUSH_SIZE",
+">520 byte push in non-executed IF branch"],
+["1",
+"0x61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161",
+"P2SH,STRICTENC",
+"OP_COUNT",
+">201 opcodes executed. 0x61 is NOP"],
+["0",
+"IF 0x6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161 ENDIF 1",
+"P2SH,STRICTENC",
+"OP_COUNT",
+">201 opcodes including non-executed IF branch. 0x61 is NOP"],
+["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"1 2 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"P2SH,STRICTENC",
+"STACK_SIZE",
+">1,000 stack size (0x6f is 3DUP)"],
+["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"1 TOALTSTACK 2 TOALTSTACK 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"P2SH,STRICTENC",
+"STACK_SIZE",
+">1,000 stack+altstack 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",
+"SCRIPT_SIZE",
+"10,001-byte scriptPubKey"],
+
+["NOP1","NOP10", "P2SH,STRICTENC", "EVAL_FALSE"],
+
+["1","VER", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VER is reserved"],
+["1","VERIF", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VERIF is reserved"],
+["1","VERNOTIF", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VERNOTIF is reserved"],
+["1","RESERVED", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED is reserved"],
+["1","RESERVED1", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED1 is reserved"],
+["1","RESERVED2", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED2 is reserved"],
+["1","0xba", "P2SH,STRICTENC", "BAD_OPCODE", "0xba == OP_NOP10 + 1"],
+
+["2147483648", "1ADD 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"],
+["2147483648", "NEGATE 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"],
+["-2147483648", "1ADD 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "Because we use a sign bit, -2147483648 is also 5 bytes"],
+["2147483647", "1ADD 1SUB 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers, even if the result is 4-bytes"],
+["2147483648", "1SUB 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers, even if the result is 4-bytes"],
+
+["2147483648 1", "BOOLOR 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do BOOLOR on 5-byte integers (but we can still do IF etc)"],
+["2147483648 1", "BOOLAND 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do BOOLAND on 5-byte integers"],
+
+["1", "1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "ENDIF without IF"],
+["1", "IF 1", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "IF without ENDIF"],
+["1 IF 1", "ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "IFs don't carry over"],
+
+["NOP", "IF 1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "The following tests check the if(stack.size() < N) tests in each opcode"],
+["NOP", "NOTIF 1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "They are here to catch copy-and-paste errors"],
+["NOP", "VERIFY 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "Most of them are duplicated elsewhere,"],
+
+["NOP", "TOALTSTACK 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "but, hey, more is always better, right?"],
+["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", "INVALID_STACK_OPERATION", "CHECKSIG must error when there are no stack items"],
+["0", "CHECKSIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKSIG must error when there are not 2 stack items"],
+["", "CHECKMULTISIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKMULTISIG must error when there are no stack items"],
+["", "-1 CHECKMULTISIG NOT", "STRICTENC", "PUBKEY_COUNT", "CHECKMULTISIG must error when the specified number of pubkeys is negative"],
+["", "1 CHECKMULTISIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKMULTISIG must error when there are not enough pubkeys on the stack"],
+["", "-1 0 CHECKMULTISIG NOT", "STRICTENC", "SIG_COUNT", "CHECKMULTISIG must error when the specified number of signatures is negative"],
+["", "1 'pk1' 1 CHECKMULTISIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKMULTISIG must error when there are not enough signatures on the stack"],
+["", "'dummy' 'sig1' 1 'pk1' 1 CHECKMULTISIG IF 1 ENDIF", "", "EVAL_FALSE", "CHECKMULTISIG must push false to stack when signature is invalid when NOT in strict enc mode"],
+
+["",
+"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",
+"OP_COUNT",
+"202 CHECKMULTISIGS, fails due to 201 op limit"],
+
+["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",
+"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",
+"OP_COUNT",
+"Fails due to 201 sig op limit"],
+
+["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",
+"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", "PUBKEY_COUNT", "nPubKeys > 20"],
+["0 'sig' 1 0", "CHECKMULTISIG 1", "P2SH,STRICTENC", "SIG_COUNT", "nSigs > nPubKeys"],
+
+
+["NOP 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "SIG_PUSHONLY", "Tests for Script.IsPushOnly()"],
+["NOP1 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "SIG_PUSHONLY"],
+
+["0 0x01 0x50", "HASH160 0x14 0xece424a6bb6ddf4db592c0faed60685047a361b1 EQUAL", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED in P2SH should fail"],
+["0 0x01 VER", "HASH160 0x14 0x0f4d7845db968f2a81b530b6f3c1d6246d4c7e01 EQUAL", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VER in P2SH should fail"],
+
+["0x00", "'00' EQUAL", "P2SH,STRICTENC", "EVAL_FALSE", "Basic OP_0 execution"],
+
+["MINIMALDATA enforcement for PUSHDATAs"],
+
+["0x4c 0x00", "DROP 1", "MINIMALDATA", "MINIMALDATA", "Empty vector minimally represented by OP_0"],
+["0x01 0x81", "DROP 1", "MINIMALDATA", "MINIMALDATA", "-1 minimally represented by OP_1NEGATE"],
+["0x01 0x01", "DROP 1", "MINIMALDATA", "MINIMALDATA", "1 to 16 minimally represented by OP_1 to OP_16"],
+["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",
+ "MINIMALDATA",
+ "PUSHDATA1 of 72 bytes minimally represented by direct push"],
+
+["0x4d 0xFF00 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA",
+ "MINIMALDATA",
+ "PUSHDATA2 of 255 bytes minimally represented by PUSHDATA1"],
+
+["0x4e 0x00010000 0x11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA",
+ "MINIMALDATA",
+ "PUSHDATA4 of 256 bytes minimally represented by PUSHDATA2"],
+
+["MINIMALDATA enforcement for numeric arguments"],
+
+["0x01 0x00", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 0"],
+["0x02 0x0000", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 0"],
+["0x01 0x80", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "0x80 (negative zero) numequals 0"],
+["0x02 0x0080", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 0"],
+["0x02 0x0500", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 5"],
+["0x03 0x050000", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 5"],
+["0x02 0x0580", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals -5"],
+["0x03 0x050080", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals -5"],
+["0x03 0xff7f80", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "Minimal encoding is 0xffff"],
+["0x03 0xff7f00", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "Minimal encoding is 0xff7f"],
+["0x04 0xffff7f80", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "Minimal encoding is 0xffffff"],
+["0x04 0xffff7f00", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "Minimal encoding is 0xffff7f"],
+
+["Test every numeric-accepting opcode for correct handling of the numeric minimal encoding rule"],
+
+["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"],
+["pubkeys/signatures so they fail due to the STRICTENC rules on validly encoded"],
+["signatures and pubkeys."],
+[
+ "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501",
+ "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0 2 CHECKMULTISIG NOT",
+ "STRICTENC",
+ "PUBKEYTYPE",
+ "2-of-2 CHECKMULTISIG NOT with the first pubkey invalid, and both signatures validly encoded."
+],
+[
+ "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 1",
+ "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT",
+ "STRICTENC",
+ "SIG_DER",
+ "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but first signature invalid."
+],
+[
+ "0 0x47 0x304402205451ce65ad844dbb978b8bdedf5082e33b43cae8279c30f2c74d9e9ee49a94f802203fe95a7ccf74da7a232ee523ef4a53cb4d14bdd16289680cdb97a63819b8f42f01 0x46 0x304402205451ce65ad844dbb978b8bdedf5082e33b43cae8279c30f2c74d9e9ee49a94f802203fe95a7ccf74da7a232ee523ef4a53cb4d14bdd16289680cdb97a63819b8f42f",
+ "2 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 3 CHECKMULTISIG",
+ "P2SH,STRICTENC",
+ "SIG_DER",
+ "2-of-3 with one valid and one invalid signature due to parse error, nSigs > validSigs"
+],
+
+["Increase DERSIG test coverage"],
+["0x4a 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Overly long signature is incorrectly encoded for DERSIG"],
+["0x25 0x30220220000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Missing S is incorrectly encoded for DERSIG"],
+["0x27 0x3024021077777777777777777777777777777777020a7777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "S with invalid S length is incorrectly encoded for DERSIG"],
+["0x27 0x302403107777777777777777777777777777777702107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Non-integer R is incorrectly encoded for DERSIG"],
+["0x27 0x302402107777777777777777777777777777777703107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Non-integer S is incorrectly encoded for DERSIG"],
+["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Zero-length R is incorrectly encoded for DERSIG"],
+["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Zero-length S is incorrectly encoded for DERSIG"],
+["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Negative S is incorrectly encoded for DERSIG"],
+
+["Automatically generated test cases"],
+[
+ "0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001",
+ "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
+ "",
+ "OK",
+ "P2PK"
+],
+[
+ "0x47 0x304402200a5c6163f07b8c3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001",
+ "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
+ "",
+ "EVAL_FALSE",
+ "P2PK, bad sig"
+],
+[
+ "0x47 0x304402206e05a6fe23c59196ffe176c9ddc31e73a9885638f9d1328d47c0c703863b8876022076feb53811aa5b04e0e79f938eb19906cc5e67548bc555a8e8b8b0fc603d840c01 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508",
+ "DUP HASH160 0x14 0x1018853670f9f3b0582c5b9ee8ce93764ac32b93 EQUALVERIFY CHECKSIG",
+ "",
+ "OK",
+ "P2PKH"
+],
+[
+ "0x47 0x3044022034bb0494b50b8ef130e2185bb220265b9284ef5b4b8a8da4d8415df489c83b5102206259a26d9cc0a125ac26af6153b17c02956855ebe1467412f066e402f5f05d1201 0x21 0x03363d90d446b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640",
+ "DUP HASH160 0x14 0xc0834c0c158f53be706d234c38fd52de7eece656 EQUALVERIFY CHECKSIG",
+ "",
+ "EQUALVERIFY",
+ "P2PKH, bad pubkey"
+],
+[
+ "0x47 0x304402204710a85181663b32d25c70ec2bbd14adff5ddfff6cb50d09e155ef5f541fc86c0220056b0cc949be9386ecc5f6c2ac0493269031dbb185781db90171b54ac127790281",
+ "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
+ "",
+ "OK",
+ "P2PK anyonecanpay"
+],
+[
+ "0x47 0x304402204710a85181663b32d25c70ec2bbd14adff5ddfff6cb50d09e155ef5f541fc86c0220056b0cc949be9386ecc5f6c2ac0493269031dbb185781db90171b54ac127790201",
+ "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
+ "",
+ "EVAL_FALSE",
+ "P2PK anyonecanpay marked with normal hashtype"
+],
+[
+ "0x47 0x3044022003fef42ed6c7be8917441218f525a60e2431be978e28b7aca4d7a532cc413ae8022067a1f82c74e8d69291b90d148778405c6257bbcfc2353cc38a3e1f22bf44254601 0x23 0x210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac",
+ "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL",
+ "P2SH",
+ "OK",
+ "P2SH(P2PK)"
+],
+[
+ "0x47 0x3044022003fef42ed6c7be8917441218f525a60e2431be978e28b7aca4d7a532cc413ae8022067a1f82c74e8d69291b90d148778405c6257bbcfc2353cc38a3e1f22bf44254601 0x23 0x210279be667ef9dcbbac54a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac",
+ "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL",
+ "P2SH",
+ "EVAL_FALSE",
+ "P2SH(P2PK), bad redeemscript"
+],
+[
+ "0x47 0x304402204e2eb034be7b089534ac9e798cf6a2c79f38bcb34d1b179efd6f2de0841735db022071461beb056b5a7be1819da6a3e3ce3662831ecc298419ca101eb6887b5dd6a401 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac",
+ "HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL",
+ "",
+ "OK",
+ "P2SH(P2PKH), bad sig but no VERIFY_P2SH"
+],
+[
+ "0x47 0x304402204e2eb034be7b089534ac9e798cf6a2c79f38bcb34d1b179efd6f2de0841735db022071461beb056b5a7be1819da6a3e3ce3662831ecc298419ca101eb6887b5dd6a401 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac",
+ "HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL",
+ "P2SH",
+ "EQUALVERIFY",
+ "P2SH(P2PKH), bad sig"
+],
+[
+ "0 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901",
+ "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
+ "",
+ "OK",
+ "3-of-3"
+],
+[
+ "0 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0",
+ "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
+ "",
+ "EVAL_FALSE",
+ "3-of-3, 2 sigs"
+],
+[
+ "0 0x47 0x304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001 0x47 0x30440220563e5b3b1fc11662a84bc5ea2a32cc3819703254060ba30d639a1aaf2d5068ad0220601c1f47ddc76d93284dd9ed68f7c9974c4a0ea7cbe8a247d6bc3878567a5fca01 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae",
+ "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL",
+ "P2SH",
+ "OK",
+ "P2SH(2-of-3)"
+],
+[
+ "0 0x47 0x304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001 0 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae",
+ "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL",
+ "P2SH",
+ "EVAL_FALSE",
+ "P2SH(2-of-3), 1 sig"
+],
+[
+ "0x47 0x304402200060558477337b9022e70534f1fea71a318caf836812465a2509931c5e7c4987022078ec32bd50ac9e03a349ba953dfd9fe1c8d2dd8bdb1d38ddca844d3d5c78c11801",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "",
+ "OK",
+ "P2PK with too much R padding but no DERSIG"
+],
+[
+ "0x47 0x304402200060558477337b9022e70534f1fea71a318caf836812465a2509931c5e7c4987022078ec32bd50ac9e03a349ba953dfd9fe1c8d2dd8bdb1d38ddca844d3d5c78c11801",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "DERSIG",
+ "SIG_DER",
+ "P2PK with too much R padding"
+],
+[
+ "0x48 0x304502202de8c03fc525285c9c535631019a5f2af7c6454fa9eb392a3756a4917c420edd02210046130bf2baf7cfc065067c8b9e33a066d9c15edcea9feb0ca2d233e3597925b401",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "",
+ "OK",
+ "P2PK with too much S padding but no DERSIG"
+],
+[
+ "0x48 0x304502202de8c03fc525285c9c535631019a5f2af7c6454fa9eb392a3756a4917c420edd02210046130bf2baf7cfc065067c8b9e33a066d9c15edcea9feb0ca2d233e3597925b401",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "DERSIG",
+ "SIG_DER",
+ "P2PK with too much S padding"
+],
+[
+ "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "",
+ "OK",
+ "P2PK with too little R padding but no DERSIG"
+],
+[
+ "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "DERSIG",
+ "SIG_DER",
+ "P2PK with too little R padding"
+],
+[
+ "0x47 0x30440220005ece1335e7f757a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601",
+ "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
+ "",
+ "OK",
+ "P2PK NOT with bad sig with too much R padding but no DERSIG"
+],
+[
+ "0x47 0x30440220005ece1335e7f757a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601",
+ "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
+ "DERSIG",
+ "SIG_DER",
+ "P2PK NOT with bad sig with too much R padding"
+],
+[
+ "0x47 0x30440220005ece1335e7f657a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601",
+ "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
+ "",
+ "EVAL_FALSE",
+ "P2PK NOT with too much R padding but no DERSIG"
+],
+[
+ "0x47 0x30440220005ece1335e7f657a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601",
+ "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
+ "DERSIG",
+ "SIG_DER",
+ "P2PK NOT with too much R padding"
+],
+[
+ "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "",
+ "OK",
+ "BIP66 example 1, without DERSIG"
+],
+[
+ "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "DERSIG",
+ "SIG_DER",
+ "BIP66 example 1, with DERSIG"
+],
+[
+ "0x47 0x304402208e43c0b91f7c1e5bc58e41c8185f8a6086e111b0090187968a86f2822462d3c902200a58f4076b1133b18ff1dc83ee51676e44c60cc608d9534e0df5ace0424fc0be01",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+ "",
+ "EVAL_FALSE",
+ "BIP66 example 2, without DERSIG"
+],
+[
+ "0x47 0x304402208e43c0b91f7c1e5bc58e41c8185f8a6086e111b0090187968a86f2822462d3c902200a58f4076b1133b18ff1dc83ee51676e44c60cc608d9534e0df5ace0424fc0be01",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+ "DERSIG",
+ "SIG_DER",
+ "BIP66 example 2, with DERSIG"
+],
+[
+ "0",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "",
+ "EVAL_FALSE",
+ "BIP66 example 3, without DERSIG"
+],
+[
+ "0",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "DERSIG",
+ "EVAL_FALSE",
+ "BIP66 example 3, with DERSIG"
+],
+[
+ "0",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+ "",
+ "OK",
+ "BIP66 example 4, without DERSIG"
+],
+[
+ "0",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+ "DERSIG",
+ "OK",
+ "BIP66 example 4, with DERSIG"
+],
+[
+ "1",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "",
+ "EVAL_FALSE",
+ "BIP66 example 5, without DERSIG"
+],
+[
+ "1",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "DERSIG",
+ "SIG_DER",
+ "BIP66 example 5, with DERSIG"
+],
+[
+ "1",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+ "",
+ "OK",
+ "BIP66 example 6, without DERSIG"
+],
+[
+ "1",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+ "DERSIG",
+ "SIG_DER",
+ "BIP66 example 6, with DERSIG"
+],
+[
+ "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0x47 0x3044022027c2714269ca5aeecc4d70edc88ba5ee0e3da4986e9216028f489ab4f1b8efce022022bd545b4951215267e4c5ceabd4c5350331b2e4a0b6494c56f361fa5a57a1a201",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
+ "",
+ "OK",
+ "BIP66 example 7, without DERSIG"
+],
+[
+ "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0x47 0x3044022027c2714269ca5aeecc4d70edc88ba5ee0e3da4986e9216028f489ab4f1b8efce022022bd545b4951215267e4c5ceabd4c5350331b2e4a0b6494c56f361fa5a57a1a201",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
+ "DERSIG",
+ "SIG_DER",
+ "BIP66 example 7, with DERSIG"
+],
+[
+ "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0x47 0x3044022079ea80afd538d9ada421b5101febeb6bc874e01dde5bca108c1d0479aec339a4022004576db8f66130d1df686ccf00935703689d69cf539438da1edab208b0d63c4801",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
+ "",
+ "EVAL_FALSE",
+ "BIP66 example 8, without DERSIG"
+],
+[
+ "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0x47 0x3044022079ea80afd538d9ada421b5101febeb6bc874e01dde5bca108c1d0479aec339a4022004576db8f66130d1df686ccf00935703689d69cf539438da1edab208b0d63c4801",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
+ "DERSIG",
+ "SIG_DER",
+ "BIP66 example 8, with DERSIG"
+],
+[
+ "0 0 0x47 0x3044022081aa9d436f2154e8b6d600516db03d78de71df685b585a9807ead4210bd883490220534bb6bdf318a419ac0749660b60e78d17d515558ef369bf872eff405b676b2e01",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
+ "",
+ "EVAL_FALSE",
+ "BIP66 example 9, without DERSIG"
+],
+[
+ "0 0 0x47 0x3044022081aa9d436f2154e8b6d600516db03d78de71df685b585a9807ead4210bd883490220534bb6bdf318a419ac0749660b60e78d17d515558ef369bf872eff405b676b2e01",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
+ "DERSIG",
+ "SIG_DER",
+ "BIP66 example 9, with DERSIG"
+],
+[
+ "0 0 0x47 0x30440220da6f441dc3b4b2c84cfa8db0cd5b34ed92c9e01686de5a800d40498b70c0dcac02207c2cf91b0c32b860c4cd4994be36cfb84caf8bb7c3a8e4d96a31b2022c5299c501",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
+ "",
+ "OK",
+ "BIP66 example 10, without DERSIG"
+],
+[
+ "0 0 0x47 0x30440220da6f441dc3b4b2c84cfa8db0cd5b34ed92c9e01686de5a800d40498b70c0dcac02207c2cf91b0c32b860c4cd4994be36cfb84caf8bb7c3a8e4d96a31b2022c5299c501",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
+ "DERSIG",
+ "SIG_DER",
+ "BIP66 example 10, with DERSIG"
+],
+[
+ "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
+ "",
+ "EVAL_FALSE",
+ "BIP66 example 11, without DERSIG"
+],
+[
+ "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
+ "DERSIG",
+ "EVAL_FALSE",
+ "BIP66 example 11, with DERSIG"
+],
+[
+ "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
+ "",
+ "OK",
+ "BIP66 example 12, without DERSIG"
+],
+[
+ "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
+ "DERSIG",
+ "OK",
+ "BIP66 example 12, with DERSIG"
+],
+[
+ "0x48 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb12510101",
+ "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
+ "",
+ "OK",
+ "P2PK with multi-byte hashtype, without DERSIG"
+],
+[
+ "0x48 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb12510101",
+ "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
+ "DERSIG",
+ "SIG_DER",
+ "P2PK with multi-byte hashtype, with DERSIG"
+],
+[
+ "0x48 0x304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef001",
+ "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
+ "",
+ "OK",
+ "P2PK with high S but no LOW_S"
+],
+[
+ "0x48 0x304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef001",
+ "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
+ "LOW_S",
+ "SIG_HIGH_S",
+ "P2PK with high S"
+],
+[
+ "0x47 0x3044022057292e2d4dfe775becdd0a9e6547997c728cdf35390f6a017da56d654d374e4902206b643be2fc53763b4e284845bfea2c597d2dc7759941dce937636c9d341b71ed01",
+ "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
+ "",
+ "OK",
+ "P2PK with hybrid pubkey but no STRICTENC"
+],
+[
+ "0x47 0x3044022057292e2d4dfe775becdd0a9e6547997c728cdf35390f6a017da56d654d374e4902206b643be2fc53763b4e284845bfea2c597d2dc7759941dce937636c9d341b71ed01",
+ "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
+ "STRICTENC",
+ "PUBKEYTYPE",
+ "P2PK with hybrid pubkey"
+],
+[
+ "0x47 0x30440220035d554e3153c14950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101",
+ "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
+ "",
+ "EVAL_FALSE",
+ "P2PK NOT with hybrid pubkey but no STRICTENC"
+],
+[
+ "0x47 0x30440220035d554e3153c14950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101",
+ "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
+ "STRICTENC",
+ "PUBKEYTYPE",
+ "P2PK NOT with hybrid pubkey"
+],
+[
+ "0x47 0x30440220035d554e3153c04950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101",
+ "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
+ "",
+ "OK",
+ "P2PK NOT with invalid hybrid pubkey but no STRICTENC"
+],
+[
+ "0x47 0x30440220035d554e3153c04950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101",
+ "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
+ "STRICTENC",
+ "PUBKEYTYPE",
+ "P2PK NOT with invalid hybrid pubkey"
+],
+[
+ "0 0x47 0x304402202e79441ad1baf5a07fb86bae3753184f6717d9692680947ea8b6e8b777c69af1022079a262e13d868bb5a0964fefe3ba26942e1b0669af1afb55ef3344bc9d4fc4c401",
+ "1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
+ "",
+ "OK",
+ "1-of-2 with the second 1 hybrid pubkey and no STRICTENC"
+],
+[
+ "0 0x47 0x304402202e79441ad1baf5a07fb86bae3753184f6717d9692680947ea8b6e8b777c69af1022079a262e13d868bb5a0964fefe3ba26942e1b0669af1afb55ef3344bc9d4fc4c401",
+ "1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
+ "STRICTENC",
+ "OK",
+ "1-of-2 with the second 1 hybrid pubkey"
+],
+[
+ "0 0x47 0x3044022079c7824d6c868e0e1a273484e28c2654a27d043c8a27f49f52cb72efed0759090220452bbbf7089574fa082095a4fc1b3a16bafcf97a3a34d745fafc922cce66b27201",
+ "1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 2 CHECKMULTISIG",
+ "STRICTENC",
+ "PUBKEYTYPE",
+ "1-of-2 with the first 1 hybrid pubkey"
+],
+[
+ "0x47 0x304402206177d513ec2cda444c021a1f4f656fc4c72ba108ae063e157eb86dc3575784940220666fc66702815d0e5413bb9b1df22aed44f5f1efb8b99d41dd5dc9a5be6d205205",
+ "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
+ "",
+ "OK",
+ "P2PK with undefined hashtype but no STRICTENC"
+],
+[
+ "0x47 0x304402206177d513ec2cda444c021a1f4f656fc4c72ba108ae063e157eb86dc3575784940220666fc66702815d0e5413bb9b1df22aed44f5f1efb8b99d41dd5dc9a5be6d205205",
+ "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
+ "STRICTENC",
+ "SIG_HASHTYPE",
+ "P2PK with undefined hashtype"
+],
+[
+ "0x47 0x304402207409b5b320296e5e2136a7b281a7f803028ca4ca44e2b83eebd46932677725de02202d4eea1c8d3c98e6f42614f54764e6e5e6542e213eb4d079737e9a8b6e9812ec05",
+ "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT",
+ "",
+ "OK",
+ "P2PK NOT with invalid sig and undefined hashtype but no STRICTENC"
+],
+[
+ "0x47 0x304402207409b5b320296e5e2136a7b281a7f803028ca4ca44e2b83eebd46932677725de02202d4eea1c8d3c98e6f42614f54764e6e5e6542e213eb4d079737e9a8b6e9812ec05",
+ "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT",
+ "STRICTENC",
+ "SIG_HASHTYPE",
+ "P2PK NOT with invalid sig and undefined hashtype"
+],
+[
+ "1 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901",
+ "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
+ "",
+ "OK",
+ "3-of-3 with nonzero dummy but no NULLDUMMY"
+],
+[
+ "1 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901",
+ "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
+ "NULLDUMMY",
+ "SIG_NULLDUMMY",
+ "3-of-3 with nonzero dummy"
+],
+[
+ "1 0x47 0x304402201bb2edab700a5d020236df174fefed78087697143731f659bea59642c759c16d022061f42cdbae5bcd3e8790f20bf76687443436e94a634321c16a72aa54cbc7c2ea01 0x47 0x304402204bb4a64f2a6e5c7fb2f07fef85ee56fde5e6da234c6a984262307a20e99842d702206f8303aaba5e625d223897e2ffd3f88ef1bcffef55f38dc3768e5f2e94c923f901 0x47 0x3044022040c2809b71fffb155ec8b82fe7a27f666bd97f941207be4e14ade85a1249dd4d02204d56c85ec525dd18e29a0533d5ddf61b6b1bb32980c2f63edf951aebf7a27bfe01",
+ "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT",
+ "",
+ "OK",
+ "3-of-3 NOT with invalid sig and nonzero dummy but no NULLDUMMY"
+],
+[
+ "1 0x47 0x304402201bb2edab700a5d020236df174fefed78087697143731f659bea59642c759c16d022061f42cdbae5bcd3e8790f20bf76687443436e94a634321c16a72aa54cbc7c2ea01 0x47 0x304402204bb4a64f2a6e5c7fb2f07fef85ee56fde5e6da234c6a984262307a20e99842d702206f8303aaba5e625d223897e2ffd3f88ef1bcffef55f38dc3768e5f2e94c923f901 0x47 0x3044022040c2809b71fffb155ec8b82fe7a27f666bd97f941207be4e14ade85a1249dd4d02204d56c85ec525dd18e29a0533d5ddf61b6b1bb32980c2f63edf951aebf7a27bfe01",
+ "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT",
+ "NULLDUMMY",
+ "SIG_NULLDUMMY",
+ "3-of-3 NOT with invalid sig with nonzero dummy"
+],
+[
+ "0 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901 DUP",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
+ "",
+ "OK",
+ "2-of-2 with two identical keys and sigs pushed using OP_DUP but no SIGPUSHONLY"
+],
+[
+ "0 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901 DUP",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
+ "SIGPUSHONLY",
+ "SIG_PUSHONLY",
+ "2-of-2 with two identical keys and sigs pushed using OP_DUP"
+],
+[
+ "0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac",
+ "HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL",
+ "",
+ "OK",
+ "P2SH(P2PK) with non-push scriptSig but no P2SH or SIGPUSHONLY"
+],
+[
+ "0x47 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb125101 NOP8",
+ "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
+ "",
+ "OK",
+ "P2PK with non-push scriptSig but with P2SH validation"
+],
+[
+ "0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac",
+ "HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL",
+ "P2SH",
+ "SIG_PUSHONLY",
+ "P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY"
+],
+[
+ "0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac",
+ "HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL",
+ "SIGPUSHONLY",
+ "SIG_PUSHONLY",
+ "P2SH(P2PK) with non-push scriptSig but not P2SH"
+],
+[
+ "0 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
+ "SIGPUSHONLY",
+ "OK",
+ "2-of-2 with two identical keys and sigs pushed"
+],
+[
+ "11 0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001",
+ "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
+ "P2SH",
+ "OK",
+ "P2PK with unnecessary input but no CLEANSTACK"
+],
+[
+ "11 0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001",
+ "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
+ "CLEANSTACK,P2SH",
+ "CLEANSTACK",
+ "P2PK with unnecessary input"
+],
+[
+ "11 0x47 0x304402202f7505132be14872581f35d74b759212d9da40482653f1ffa3116c3294a4a51702206adbf347a2240ca41c66522b1a22a41693610b76a8e7770645dc721d1635854f01 0x43 0x410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
+ "HASH160 0x14 0x31edc23bdafda4639e669f89ad6b2318dd79d032 EQUAL",
+ "P2SH",
+ "OK",
+ "P2SH with unnecessary input but no CLEANSTACK"
+],
+[
+ "11 0x47 0x304402202f7505132be14872581f35d74b759212d9da40482653f1ffa3116c3294a4a51702206adbf347a2240ca41c66522b1a22a41693610b76a8e7770645dc721d1635854f01 0x43 0x410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
+ "HASH160 0x14 0x31edc23bdafda4639e669f89ad6b2318dd79d032 EQUAL",
+ "CLEANSTACK,P2SH",
+ "CLEANSTACK",
+ "P2SH with unnecessary input"
+],
+[
+ "0x47 0x304402202f7505132be14872581f35d74b759212d9da40482653f1ffa3116c3294a4a51702206adbf347a2240ca41c66522b1a22a41693610b76a8e7770645dc721d1635854f01 0x43 0x410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
+ "HASH160 0x14 0x31edc23bdafda4639e669f89ad6b2318dd79d032 EQUAL",
+ "CLEANSTACK,P2SH",
+ "OK",
+ "P2SH with CLEANSTACK"
+],
+
+["The End"]
+]
diff --git a/src/test/data/script_valid.json b/src/test/data/script_valid.json
deleted file mode 100644
index e5f0d17b04..0000000000
--- a/src/test/data/script_valid.json
+++ /dev/null
@@ -1,911 +0,0 @@
-[
-["Format is: [scriptSig, scriptPubKey, flags, ... comments]"],
-["It is evaluated as if there was a crediting coinbase transaction with two 0"],
-["pushes as scriptSig, and one output of 0 satoshi and given scriptPubKey,"],
-["followed by a spending transaction which spends this output as only input (and"],
-["correct prevout hash), using the given scriptSig. All nLockTimes are 0, all"],
-["nSequences are max."],
-
-["", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "Test the test: we should have an empty stack after scriptSig evaluation"],
-[" ", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "and multiple spaces should not change that."],
-[" ", "DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-[" ", "DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["1 2", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "Similarly whitespace around and between symbols"],
-["1 2", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC"],
-[" 1 2", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC"],
-["1 2 ", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC"],
-[" 1 2 ", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC"],
-
-["1", "", "P2SH,STRICTENC"],
-["0x02 0x01 0x00", "", "P2SH,STRICTENC", "all bytes are significant, not only the last one"],
-["0x09 0x00000000 0x00000000 0x10", "", "P2SH,STRICTENC", "equals zero when cast to Int64"],
-
-["0x01 0x0b", "11 EQUAL", "P2SH,STRICTENC", "push 1 byte"],
-["0x02 0x417a", "'Az' EQUAL", "P2SH,STRICTENC"],
-["0x4b 0x417a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a",
- "'Azzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' EQUAL", "P2SH,STRICTENC", "push 75 bytes"],
-
-["0x4c 0x01 0x07","7 EQUAL", "P2SH,STRICTENC", "0x4c is OP_PUSHDATA1"],
-["0x4d 0x0100 0x08","8 EQUAL", "P2SH,STRICTENC", "0x4d is OP_PUSHDATA2"],
-["0x4e 0x01000000 0x09","9 EQUAL", "P2SH,STRICTENC", "0x4e is OP_PUSHDATA4"],
-
-["0x4c 0x00","0 EQUAL", "P2SH,STRICTENC"],
-["0x4d 0x0000","0 EQUAL", "P2SH,STRICTENC"],
-["0x4e 0x00000000","0 EQUAL", "P2SH,STRICTENC"],
-["0x4f 1000 ADD","999 EQUAL", "P2SH,STRICTENC"],
-["0", "IF 0x50 ENDIF 1", "P2SH,STRICTENC", "0x50 is reserved (ok if not executed)"],
-["0x51", "0x5f ADD 0x60 EQUAL", "P2SH,STRICTENC", "0x51 through 0x60 push 1 through 16 onto stack"],
-["1","NOP", "P2SH,STRICTENC"],
-["0", "IF VER ELSE 1 ENDIF", "P2SH,STRICTENC", "VER non-functional (ok if not executed)"],
-["0", "IF RESERVED RESERVED1 RESERVED2 ELSE 1 ENDIF", "P2SH,STRICTENC", "RESERVED ok in un-executed IF"],
-
-["1", "DUP IF ENDIF", "P2SH,STRICTENC"],
-["1", "IF 1 ENDIF", "P2SH,STRICTENC"],
-["1", "DUP IF ELSE ENDIF", "P2SH,STRICTENC"],
-["1", "IF 1 ELSE ENDIF", "P2SH,STRICTENC"],
-["0", "IF ELSE 1 ENDIF", "P2SH,STRICTENC"],
-
-["1 1", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"],
-["1 0", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"],
-["1 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"],
-["0 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"],
-
-["1 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"],
-["1 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"],
-["1 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"],
-["0 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"],
-
-["0", "IF 0 ELSE 1 ELSE 0 ENDIF", "P2SH,STRICTENC", "Multiple ELSE's are valid and executed inverts on each ELSE encountered"],
-["1", "IF 1 ELSE 0 ELSE ENDIF", "P2SH,STRICTENC"],
-["1", "IF ELSE 0 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["1", "IF 1 ELSE 0 ELSE 1 ENDIF ADD 2 EQUAL", "P2SH,STRICTENC"],
-["'' 1", "IF SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ENDIF 0x14 0x68ca4fec736264c13b859bac43d5173df6871682 EQUAL", "P2SH,STRICTENC"],
-
-["1", "NOTIF 0 ELSE 1 ELSE 0 ENDIF", "P2SH,STRICTENC", "Multiple ELSE's are valid and execution inverts on each ELSE encountered"],
-["0", "NOTIF 1 ELSE 0 ELSE ENDIF", "P2SH,STRICTENC"],
-["0", "NOTIF ELSE 0 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "NOTIF 1 ELSE 0 ELSE 1 ENDIF ADD 2 EQUAL", "P2SH,STRICTENC"],
-["'' 0", "NOTIF SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ENDIF 0x14 0x68ca4fec736264c13b859bac43d5173df6871682 EQUAL", "P2SH,STRICTENC"],
-
-["0", "IF 1 IF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 1 IF 1 ELSE RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL", "P2SH,STRICTENC", "Nested ELSE ELSE"],
-["1", "NOTIF 0 NOTIF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 0 NOTIF 1 ELSE RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL", "P2SH,STRICTENC"],
-
-["0", "IF RETURN ENDIF 1", "P2SH,STRICTENC", "RETURN only works if executed"],
-
-["1 1", "VERIFY", "P2SH,STRICTENC"],
-["1 0x05 0x01 0x00 0x00 0x00 0x00", "VERIFY", "P2SH,STRICTENC", "values >4 bytes can be cast to boolean"],
-["1 0x01 0x80", "IF 0 ENDIF", "P2SH,STRICTENC", "negative 0 is false"],
-
-["10 0 11 TOALTSTACK DROP FROMALTSTACK", "ADD 21 EQUAL", "P2SH,STRICTENC"],
-["'gavin_was_here' TOALTSTACK 11 FROMALTSTACK", "'gavin_was_here' EQUALVERIFY 11 EQUAL", "P2SH,STRICTENC"],
-
-["0 IFDUP", "DEPTH 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC"],
-["1 IFDUP", "DEPTH 2 EQUALVERIFY 1 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC"],
-["0x05 0x0100000000 IFDUP", "DEPTH 2 EQUALVERIFY 0x05 0x0100000000 EQUAL", "P2SH,STRICTENC", "IFDUP dups non ints"],
-["0 DROP", "DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["0", "DUP 1 ADD 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC"],
-["0 1", "NIP", "P2SH,STRICTENC"],
-["1 0", "OVER DEPTH 3 EQUALVERIFY", "P2SH,STRICTENC"],
-["22 21 20", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC"],
-["22 21 20", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC"],
-["22 21 20", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC"],
-["22 21 20", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"],
-["22 21 20", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"],
-["22 21 20", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"],
-["22 21 20", "ROT 22 EQUAL", "P2SH,STRICTENC"],
-["22 21 20", "ROT DROP 20 EQUAL", "P2SH,STRICTENC"],
-["22 21 20", "ROT DROP DROP 21 EQUAL", "P2SH,STRICTENC"],
-["22 21 20", "ROT ROT 21 EQUAL", "P2SH,STRICTENC"],
-["22 21 20", "ROT ROT ROT 20 EQUAL", "P2SH,STRICTENC"],
-["25 24 23 22 21 20", "2ROT 24 EQUAL", "P2SH,STRICTENC"],
-["25 24 23 22 21 20", "2ROT DROP 25 EQUAL", "P2SH,STRICTENC"],
-["25 24 23 22 21 20", "2ROT 2DROP 20 EQUAL", "P2SH,STRICTENC"],
-["25 24 23 22 21 20", "2ROT 2DROP DROP 21 EQUAL", "P2SH,STRICTENC"],
-["25 24 23 22 21 20", "2ROT 2DROP 2DROP 22 EQUAL", "P2SH,STRICTENC"],
-["25 24 23 22 21 20", "2ROT 2DROP 2DROP DROP 23 EQUAL", "P2SH,STRICTENC"],
-["25 24 23 22 21 20", "2ROT 2ROT 22 EQUAL", "P2SH,STRICTENC"],
-["25 24 23 22 21 20", "2ROT 2ROT 2ROT 20 EQUAL", "P2SH,STRICTENC"],
-["1 0", "SWAP 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC"],
-["0 1", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP", "P2SH,STRICTENC"],
-["13 14", "2DUP ROT EQUALVERIFY EQUAL", "P2SH,STRICTENC"],
-["-1 0 1 2", "3DUP DEPTH 7 EQUALVERIFY ADD ADD 3 EQUALVERIFY 2DROP 0 EQUALVERIFY", "P2SH,STRICTENC"],
-["1 2 3 5", "2OVER ADD ADD 8 EQUALVERIFY ADD ADD 6 EQUAL", "P2SH,STRICTENC"],
-["1 3 5 7", "2SWAP ADD 4 EQUALVERIFY ADD 12 EQUAL", "P2SH,STRICTENC"],
-["0", "SIZE 0 EQUAL", "P2SH,STRICTENC"],
-["1", "SIZE 1 EQUAL", "P2SH,STRICTENC"],
-["127", "SIZE 1 EQUAL", "P2SH,STRICTENC"],
-["128", "SIZE 2 EQUAL", "P2SH,STRICTENC"],
-["32767", "SIZE 2 EQUAL", "P2SH,STRICTENC"],
-["32768", "SIZE 3 EQUAL", "P2SH,STRICTENC"],
-["8388607", "SIZE 3 EQUAL", "P2SH,STRICTENC"],
-["8388608", "SIZE 4 EQUAL", "P2SH,STRICTENC"],
-["2147483647", "SIZE 4 EQUAL", "P2SH,STRICTENC"],
-["2147483648", "SIZE 5 EQUAL", "P2SH,STRICTENC"],
-["549755813887", "SIZE 5 EQUAL", "P2SH,STRICTENC"],
-["549755813888", "SIZE 6 EQUAL", "P2SH,STRICTENC"],
-["9223372036854775807", "SIZE 8 EQUAL", "P2SH,STRICTENC"],
-["-1", "SIZE 1 EQUAL", "P2SH,STRICTENC"],
-["-127", "SIZE 1 EQUAL", "P2SH,STRICTENC"],
-["-128", "SIZE 2 EQUAL", "P2SH,STRICTENC"],
-["-32767", "SIZE 2 EQUAL", "P2SH,STRICTENC"],
-["-32768", "SIZE 3 EQUAL", "P2SH,STRICTENC"],
-["-8388607", "SIZE 3 EQUAL", "P2SH,STRICTENC"],
-["-8388608", "SIZE 4 EQUAL", "P2SH,STRICTENC"],
-["-2147483647", "SIZE 4 EQUAL", "P2SH,STRICTENC"],
-["-2147483648", "SIZE 5 EQUAL", "P2SH,STRICTENC"],
-["-549755813887", "SIZE 5 EQUAL", "P2SH,STRICTENC"],
-["-549755813888", "SIZE 6 EQUAL", "P2SH,STRICTENC"],
-["-9223372036854775807", "SIZE 8 EQUAL", "P2SH,STRICTENC"],
-["'abcdefghijklmnopqrstuvwxyz'", "SIZE 26 EQUAL", "P2SH,STRICTENC"],
-
-["42", "SIZE 1 EQUALVERIFY 42 EQUAL", "P2SH,STRICTENC", "SIZE does not consume argument"],
-
-["2 -2 ADD", "0 EQUAL", "P2SH,STRICTENC"],
-["2147483647 -2147483647 ADD", "0 EQUAL", "P2SH,STRICTENC"],
-["-1 -1 ADD", "-2 EQUAL", "P2SH,STRICTENC"],
-
-["0 0","EQUAL", "P2SH,STRICTENC"],
-["1 1 ADD", "2 EQUAL", "P2SH,STRICTENC"],
-["1 1ADD", "2 EQUAL", "P2SH,STRICTENC"],
-["111 1SUB", "110 EQUAL", "P2SH,STRICTENC"],
-["111 1 ADD 12 SUB", "100 EQUAL", "P2SH,STRICTENC"],
-["0 ABS", "0 EQUAL", "P2SH,STRICTENC"],
-["16 ABS", "16 EQUAL", "P2SH,STRICTENC"],
-["-16 ABS", "-16 NEGATE EQUAL", "P2SH,STRICTENC"],
-["0 NOT", "NOP", "P2SH,STRICTENC"],
-["1 NOT", "0 EQUAL", "P2SH,STRICTENC"],
-["11 NOT", "0 EQUAL", "P2SH,STRICTENC"],
-["0 0NOTEQUAL", "0 EQUAL", "P2SH,STRICTENC"],
-["1 0NOTEQUAL", "1 EQUAL", "P2SH,STRICTENC"],
-["111 0NOTEQUAL", "1 EQUAL", "P2SH,STRICTENC"],
-["-111 0NOTEQUAL", "1 EQUAL", "P2SH,STRICTENC"],
-["1 1 BOOLAND", "NOP", "P2SH,STRICTENC"],
-["1 0 BOOLAND", "NOT", "P2SH,STRICTENC"],
-["0 1 BOOLAND", "NOT", "P2SH,STRICTENC"],
-["0 0 BOOLAND", "NOT", "P2SH,STRICTENC"],
-["16 17 BOOLAND", "NOP", "P2SH,STRICTENC"],
-["1 1 BOOLOR", "NOP", "P2SH,STRICTENC"],
-["1 0 BOOLOR", "NOP", "P2SH,STRICTENC"],
-["0 1 BOOLOR", "NOP", "P2SH,STRICTENC"],
-["0 0 BOOLOR", "NOT", "P2SH,STRICTENC"],
-["16 17 BOOLOR", "NOP", "P2SH,STRICTENC"],
-["11 10 1 ADD", "NUMEQUAL", "P2SH,STRICTENC"],
-["11 10 1 ADD", "NUMEQUALVERIFY 1", "P2SH,STRICTENC"],
-["11 10 1 ADD", "NUMNOTEQUAL NOT", "P2SH,STRICTENC"],
-["111 10 1 ADD", "NUMNOTEQUAL", "P2SH,STRICTENC"],
-["11 10", "LESSTHAN NOT", "P2SH,STRICTENC"],
-["4 4", "LESSTHAN NOT", "P2SH,STRICTENC"],
-["10 11", "LESSTHAN", "P2SH,STRICTENC"],
-["-11 11", "LESSTHAN", "P2SH,STRICTENC"],
-["-11 -10", "LESSTHAN", "P2SH,STRICTENC"],
-["11 10", "GREATERTHAN", "P2SH,STRICTENC"],
-["4 4", "GREATERTHAN NOT", "P2SH,STRICTENC"],
-["10 11", "GREATERTHAN NOT", "P2SH,STRICTENC"],
-["-11 11", "GREATERTHAN NOT", "P2SH,STRICTENC"],
-["-11 -10", "GREATERTHAN NOT", "P2SH,STRICTENC"],
-["11 10", "LESSTHANOREQUAL NOT", "P2SH,STRICTENC"],
-["4 4", "LESSTHANOREQUAL", "P2SH,STRICTENC"],
-["10 11", "LESSTHANOREQUAL", "P2SH,STRICTENC"],
-["-11 11", "LESSTHANOREQUAL", "P2SH,STRICTENC"],
-["-11 -10", "LESSTHANOREQUAL", "P2SH,STRICTENC"],
-["11 10", "GREATERTHANOREQUAL", "P2SH,STRICTENC"],
-["4 4", "GREATERTHANOREQUAL", "P2SH,STRICTENC"],
-["10 11", "GREATERTHANOREQUAL NOT", "P2SH,STRICTENC"],
-["-11 11", "GREATERTHANOREQUAL NOT", "P2SH,STRICTENC"],
-["-11 -10", "GREATERTHANOREQUAL NOT", "P2SH,STRICTENC"],
-["1 0 MIN", "0 NUMEQUAL", "P2SH,STRICTENC"],
-["0 1 MIN", "0 NUMEQUAL", "P2SH,STRICTENC"],
-["-1 0 MIN", "-1 NUMEQUAL", "P2SH,STRICTENC"],
-["0 -2147483647 MIN", "-2147483647 NUMEQUAL", "P2SH,STRICTENC"],
-["2147483647 0 MAX", "2147483647 NUMEQUAL", "P2SH,STRICTENC"],
-["0 100 MAX", "100 NUMEQUAL", "P2SH,STRICTENC"],
-["-100 0 MAX", "0 NUMEQUAL", "P2SH,STRICTENC"],
-["0 -2147483647 MAX", "0 NUMEQUAL", "P2SH,STRICTENC"],
-["0 0 1", "WITHIN", "P2SH,STRICTENC"],
-["1 0 1", "WITHIN NOT", "P2SH,STRICTENC"],
-["0 -2147483647 2147483647", "WITHIN", "P2SH,STRICTENC"],
-["-1 -100 100", "WITHIN", "P2SH,STRICTENC"],
-["11 -100 100", "WITHIN", "P2SH,STRICTENC"],
-["-2147483647 -100 100", "WITHIN NOT", "P2SH,STRICTENC"],
-["2147483647 -100 100", "WITHIN NOT", "P2SH,STRICTENC"],
-
-["2147483647 2147483647 SUB", "0 EQUAL", "P2SH,STRICTENC"],
-["2147483647 DUP ADD", "4294967294 EQUAL", "P2SH,STRICTENC", ">32 bit EQUAL is valid"],
-["2147483647 NEGATE DUP ADD", "-4294967294 EQUAL", "P2SH,STRICTENC"],
-
-["''", "RIPEMD160 0x14 0x9c1185a5c5e9fc54612808977ee8f548b2258d31 EQUAL", "P2SH,STRICTENC"],
-["'a'", "RIPEMD160 0x14 0x0bdc9d2d256b3ee9daae347be6f4dc835a467ffe EQUAL", "P2SH,STRICTENC"],
-["'abcdefghijklmnopqrstuvwxyz'", "RIPEMD160 0x14 0xf71c27109c692c1b56bbdceb5b9d2865b3708dbc EQUAL", "P2SH,STRICTENC"],
-["''", "SHA1 0x14 0xda39a3ee5e6b4b0d3255bfef95601890afd80709 EQUAL", "P2SH,STRICTENC"],
-["'a'", "SHA1 0x14 0x86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 EQUAL", "P2SH,STRICTENC"],
-["'abcdefghijklmnopqrstuvwxyz'", "SHA1 0x14 0x32d10c7b8cf96570ca04ce37f2a19d84240d3a89 EQUAL", "P2SH,STRICTENC"],
-["''", "SHA256 0x20 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 EQUAL", "P2SH,STRICTENC"],
-["'a'", "SHA256 0x20 0xca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb EQUAL", "P2SH,STRICTENC"],
-["'abcdefghijklmnopqrstuvwxyz'", "SHA256 0x20 0x71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73 EQUAL", "P2SH,STRICTENC"],
-["''", "DUP HASH160 SWAP SHA256 RIPEMD160 EQUAL", "P2SH,STRICTENC"],
-["''", "DUP HASH256 SWAP SHA256 SHA256 EQUAL", "P2SH,STRICTENC"],
-["''", "NOP HASH160 0x14 0xb472a266d0bd89c13706a4132ccfb16f7c3b9fcb EQUAL", "P2SH,STRICTENC"],
-["'a'", "HASH160 NOP 0x14 0x994355199e516ff76c4fa4aab39337b9d84cf12b EQUAL", "P2SH,STRICTENC"],
-["'abcdefghijklmnopqrstuvwxyz'", "HASH160 0x4c 0x14 0xc286a1af0947f58d1ad787385b1c2c4a976f9e71 EQUAL", "P2SH,STRICTENC"],
-["''", "HASH256 0x20 0x5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456 EQUAL", "P2SH,STRICTENC"],
-["'a'", "HASH256 0x20 0xbf5d3affb73efd2ec6c36ad3112dd933efed63c4e1cbffcfa88e2759c144f2d8 EQUAL", "P2SH,STRICTENC"],
-["'abcdefghijklmnopqrstuvwxyz'", "HASH256 0x4c 0x20 0xca139bc10c2f660da42666f72e89a225936fc60f193c161124a672050c434671 EQUAL", "P2SH,STRICTENC"],
-
-
-["1","NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 1 EQUAL", "P2SH,STRICTENC"],
-["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' EQUAL", "P2SH,STRICTENC"],
-
-["1", "NOP", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", "Discourage NOPx flag allows OP_NOP"],
-
-["0", "IF NOP10 ENDIF 1", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS",
- "Discouraged NOPs are allowed if not executed"],
-
-["0", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "opcodes above NOP10 invalid if executed"],
-["0", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xc0 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xc4 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xc5 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xc6 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xc7 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xc8 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xc9 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xca ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xcb ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xcc ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xcd ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xce ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xcf ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xd0 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xd1 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xd2 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xd3 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xd4 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xd5 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xd6 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xd7 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xd8 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xd9 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xda ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xdb ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xdc ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xdd ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xde ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xdf ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xe0 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xe1 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xe2 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xe3 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xe4 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xe5 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xe6 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xe7 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xe8 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xe9 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xea ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xeb ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xec ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xed ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xee ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xef ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xf0 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xf1 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xf2 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xf3 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xf4 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xf5 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xf6 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xf7 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xf8 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xf9 ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xfa ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xfb ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xfc ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xfd ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xfe ELSE 1 ENDIF", "P2SH,STRICTENC"],
-["0", "IF 0xff ELSE 1 ENDIF", "P2SH,STRICTENC"],
-
-["NOP",
-"'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'",
-"P2SH,STRICTENC",
-"520 byte push"],
-["1",
-"0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161",
-"P2SH,STRICTENC",
-"201 opcodes executed. 0x61 is NOP"],
-["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
-"1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
-"P2SH,STRICTENC",
-"1,000 stack size (0x6f is 3DUP)"],
-["1 TOALTSTACK 2 TOALTSTACK 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
-"1 2 3 4 5 6 7 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
-"P2SH,STRICTENC",
-"1,000 stack size (altstack cleared between scriptSig/scriptPubKey)"],
-["'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
-"'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f 2DUP 0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161",
-"P2SH,STRICTENC",
-"Max-size (10,000-byte), max-push(520 bytes), max-opcodes(201), max stack size(1,000 items). 0x6f is 3DUP, 0x61 is NOP"],
-
-["0",
-"IF 0x5050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050 ENDIF 1",
-"P2SH,STRICTENC",
-">201 opcodes, but RESERVED (0x50) doesn't count towards opcode limit."],
-
-["NOP","1", "P2SH,STRICTENC"],
-
-["1", "0x01 0x01 EQUAL", "P2SH,STRICTENC", "The following is useful for checking implementations of BN_bn2mpi"],
-["127", "0x01 0x7F EQUAL", "P2SH,STRICTENC"],
-["128", "0x02 0x8000 EQUAL", "P2SH,STRICTENC", "Leave room for the sign bit"],
-["32767", "0x02 0xFF7F EQUAL", "P2SH,STRICTENC"],
-["32768", "0x03 0x008000 EQUAL", "P2SH,STRICTENC"],
-["8388607", "0x03 0xFFFF7F EQUAL", "P2SH,STRICTENC"],
-["8388608", "0x04 0x00008000 EQUAL", "P2SH,STRICTENC"],
-["2147483647", "0x04 0xFFFFFF7F EQUAL", "P2SH,STRICTENC"],
-["2147483648", "0x05 0x0000008000 EQUAL", "P2SH,STRICTENC"],
-["549755813887", "0x05 0xFFFFFFFF7F EQUAL", "P2SH,STRICTENC"],
-["549755813888", "0x06 0xFFFFFFFF7F EQUAL", "P2SH,STRICTENC"],
-["9223372036854775807", "0x08 0xFFFFFFFFFFFFFF7F EQUAL", "P2SH,STRICTENC"],
-["-1", "0x01 0x81 EQUAL", "P2SH,STRICTENC", "Numbers are little-endian with the MSB being a sign bit"],
-["-127", "0x01 0xFF EQUAL", "P2SH,STRICTENC"],
-["-128", "0x02 0x8080 EQUAL", "P2SH,STRICTENC"],
-["-32767", "0x02 0xFFFF EQUAL", "P2SH,STRICTENC"],
-["-32768", "0x03 0x008080 EQUAL", "P2SH,STRICTENC"],
-["-8388607", "0x03 0xFFFFFF EQUAL", "P2SH,STRICTENC"],
-["-8388608", "0x04 0x00008080 EQUAL", "P2SH,STRICTENC"],
-["-2147483647", "0x04 0xFFFFFFFF EQUAL", "P2SH,STRICTENC"],
-["-2147483648", "0x05 0x0000008080 EQUAL", "P2SH,STRICTENC"],
-["-4294967295", "0x05 0xFFFFFFFF80 EQUAL", "P2SH,STRICTENC"],
-["-549755813887", "0x05 0xFFFFFFFFFF EQUAL", "P2SH,STRICTENC"],
-["-549755813888", "0x06 0x000000008080 EQUAL", "P2SH,STRICTENC"],
-["-9223372036854775807", "0x08 0xFFFFFFFFFFFFFFFF EQUAL", "P2SH,STRICTENC"],
-
-["2147483647", "1ADD 2147483648 EQUAL", "P2SH,STRICTENC", "We can do math on 4-byte integers, and compare 5-byte ones"],
-["2147483647", "1ADD 1", "P2SH,STRICTENC"],
-["-2147483647", "1ADD 1", "P2SH,STRICTENC"],
-
-["1", "0x02 0x0100 EQUAL NOT", "P2SH,STRICTENC", "Not the same byte array..."],
-["1", "0x02 0x0100 NUMEQUAL", "P2SH,STRICTENC", "... but they are numerically equal"],
-["11", "0x4c 0x03 0x0b0000 NUMEQUAL", "P2SH,STRICTENC"],
-["0", "0x01 0x80 EQUAL NOT", "P2SH,STRICTENC"],
-["0", "0x01 0x80 NUMEQUAL", "P2SH,STRICTENC", "Zero numerically equals negative zero"],
-["0", "0x02 0x0080 NUMEQUAL", "P2SH,STRICTENC"],
-["0x03 0x000080", "0x04 0x00000080 NUMEQUAL", "P2SH,STRICTENC"],
-["0x03 0x100080", "0x04 0x10000080 NUMEQUAL", "P2SH,STRICTENC"],
-["0x03 0x100000", "0x04 0x10000000 NUMEQUAL", "P2SH,STRICTENC"],
-
-["NOP", "NOP 1", "P2SH,STRICTENC", "The following tests check the if(stack.size() < N) tests in each opcode"],
-["1", "IF 1 ENDIF", "P2SH,STRICTENC", "They are here to catch copy-and-paste errors"],
-["0", "NOTIF 1 ENDIF", "P2SH,STRICTENC", "Most of them are duplicated elsewhere,"],
-["1", "VERIFY 1", "P2SH,STRICTENC", "but, hey, more is always better, right?"],
-
-["0", "TOALTSTACK 1", "P2SH,STRICTENC"],
-["1", "TOALTSTACK FROMALTSTACK", "P2SH,STRICTENC"],
-["0 0", "2DROP 1", "P2SH,STRICTENC"],
-["0 1", "2DUP", "P2SH,STRICTENC"],
-["0 0 1", "3DUP", "P2SH,STRICTENC"],
-["0 1 0 0", "2OVER", "P2SH,STRICTENC"],
-["0 1 0 0 0 0", "2ROT", "P2SH,STRICTENC"],
-["0 1 0 0", "2SWAP", "P2SH,STRICTENC"],
-["1", "IFDUP", "P2SH,STRICTENC"],
-["NOP", "DEPTH 1", "P2SH,STRICTENC"],
-["0", "DROP 1", "P2SH,STRICTENC"],
-["1", "DUP", "P2SH,STRICTENC"],
-["0 1", "NIP", "P2SH,STRICTENC"],
-["1 0", "OVER", "P2SH,STRICTENC"],
-["1 0 0 0 3", "PICK", "P2SH,STRICTENC"],
-["1 0", "PICK", "P2SH,STRICTENC"],
-["1 0 0 0 3", "ROLL", "P2SH,STRICTENC"],
-["1 0", "ROLL", "P2SH,STRICTENC"],
-["1 0 0", "ROT", "P2SH,STRICTENC"],
-["1 0", "SWAP", "P2SH,STRICTENC"],
-["0 1", "TUCK", "P2SH,STRICTENC"],
-
-["1", "SIZE", "P2SH,STRICTENC"],
-
-["0 0", "EQUAL", "P2SH,STRICTENC"],
-["0 0", "EQUALVERIFY 1", "P2SH,STRICTENC"],
-["0 0 1", "EQUAL EQUAL", "P2SH,STRICTENC", "OP_0 and bools must have identical byte representations"],
-
-["0", "1ADD", "P2SH,STRICTENC"],
-["2", "1SUB", "P2SH,STRICTENC"],
-["-1", "NEGATE", "P2SH,STRICTENC"],
-["-1", "ABS", "P2SH,STRICTENC"],
-["0", "NOT", "P2SH,STRICTENC"],
-["-1", "0NOTEQUAL", "P2SH,STRICTENC"],
-
-["1 0", "ADD", "P2SH,STRICTENC"],
-["1 0", "SUB", "P2SH,STRICTENC"],
-["-1 -1", "BOOLAND", "P2SH,STRICTENC"],
-["-1 0", "BOOLOR", "P2SH,STRICTENC"],
-["0 0", "NUMEQUAL", "P2SH,STRICTENC"],
-["0 0", "NUMEQUALVERIFY 1", "P2SH,STRICTENC"],
-["-1 0", "NUMNOTEQUAL", "P2SH,STRICTENC"],
-["-1 0", "LESSTHAN", "P2SH,STRICTENC"],
-["1 0", "GREATERTHAN", "P2SH,STRICTENC"],
-["0 0", "LESSTHANOREQUAL", "P2SH,STRICTENC"],
-["0 0", "GREATERTHANOREQUAL", "P2SH,STRICTENC"],
-["-1 0", "MIN", "P2SH,STRICTENC"],
-["1 0", "MAX", "P2SH,STRICTENC"],
-["-1 -1 0", "WITHIN", "P2SH,STRICTENC"],
-
-["0", "RIPEMD160", "P2SH,STRICTENC"],
-["0", "SHA1", "P2SH,STRICTENC"],
-["0", "SHA256", "P2SH,STRICTENC"],
-["0", "HASH160", "P2SH,STRICTENC"],
-["0", "HASH256", "P2SH,STRICTENC"],
-["NOP", "CODESEPARATOR 1", "P2SH,STRICTENC"],
-
-["NOP", "NOP1 1", "P2SH,STRICTENC"],
-["NOP", "CHECKLOCKTIMEVERIFY 1", "P2SH,STRICTENC"],
-["NOP", "NOP3 1", "P2SH,STRICTENC"],
-["NOP", "NOP4 1", "P2SH,STRICTENC"],
-["NOP", "NOP5 1", "P2SH,STRICTENC"],
-["NOP", "NOP6 1", "P2SH,STRICTENC"],
-["NOP", "NOP7 1", "P2SH,STRICTENC"],
-["NOP", "NOP8 1", "P2SH,STRICTENC"],
-["NOP", "NOP9 1", "P2SH,STRICTENC"],
-["NOP", "NOP10 1", "P2SH,STRICTENC"],
-
-["", "0 0 0 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "CHECKMULTISIG is allowed to have zero keys and/or sigs"],
-["", "0 0 0 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 0 1 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "Zero sigs means no sigs are checked"],
-["", "0 0 0 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-
-["", "0 0 0 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "CHECKMULTISIG is allowed to have zero keys and/or sigs"],
-["", "0 0 0 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 0 1 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "Zero sigs means no sigs are checked"],
-["", "0 0 0 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-
-["", "0 0 'a' 'b' 2 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "Test from up to 20 pubkeys, all not checked"],
-["", "0 0 'a' 'b' 'c' 3 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 4 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 5 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 6 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 7 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 8 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 9 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 10 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 11 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 12 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 13 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 14 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 15 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 16 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 17 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 18 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 19 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 2 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 3 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 4 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 5 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 6 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 7 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 8 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 9 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 10 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 11 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 12 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 13 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 14 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 15 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 16 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 17 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 18 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 19 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC"],
-
-["",
-"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",
-"P2SH,STRICTENC",
-"nOpCount is incremented by the number of keys evaluated in addition to the usual one op per op. In this case we have zero keys, so we can execute 201 CHECKMULTISIGS"],
-
-["1",
-"0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY",
-"P2SH,STRICTENC"],
-
-["",
-"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",
-"Even though there are no signatures being checked nOpCount is incremented by the number of keys."],
-
-["1",
-"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"],
-
-["0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "Very basic P2SH"],
-["0x4c 0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC"],
-
-["0x40 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242",
-"0x4d 0x4000 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 EQUAL",
-"P2SH,STRICTENC",
-"Basic PUSH signedness check"],
-
-["0x4c 0x40 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242",
-"0x4d 0x4000 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 EQUAL",
-"P2SH,STRICTENC",
-"Basic PUSHDATA1 signedness check"],
-
-["all PUSHDATA forms are equivalent"],
-
-["0x4c 0x4b 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "0x4b 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 EQUAL", "", "PUSHDATA1 of 75 bytes equals direct push of it"],
-["0x4d 0xFF00 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "0x4c 0xFF 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 EQUAL", "", "PUSHDATA2 of 255 bytes equals PUSHDATA1 of it"],
-
-["0x00", "SIZE 0 EQUAL", "P2SH,STRICTENC", "Basic OP_0 execution"],
-
-["Numeric pushes"],
-
-["0x01 0x81", "0x4f EQUAL", "", "OP1_NEGATE pushes 0x81"],
-["0x01 0x01", "0x51 EQUAL", "", "OP_1 pushes 0x01"],
-["0x01 0x02", "0x52 EQUAL", "", "OP_2 pushes 0x02"],
-["0x01 0x03", "0x53 EQUAL", "", "OP_3 pushes 0x03"],
-["0x01 0x04", "0x54 EQUAL", "", "OP_4 pushes 0x04"],
-["0x01 0x05", "0x55 EQUAL", "", "OP_5 pushes 0x05"],
-["0x01 0x06", "0x56 EQUAL", "", "OP_6 pushes 0x06"],
-["0x01 0x07", "0x57 EQUAL", "", "OP_7 pushes 0x07"],
-["0x01 0x08", "0x58 EQUAL", "", "OP_8 pushes 0x08"],
-["0x01 0x09", "0x59 EQUAL", "", "OP_9 pushes 0x09"],
-["0x01 0x0a", "0x5a EQUAL", "", "OP_10 pushes 0x0a"],
-["0x01 0x0b", "0x5b EQUAL", "", "OP_11 pushes 0x0b"],
-["0x01 0x0c", "0x5c EQUAL", "", "OP_12 pushes 0x0c"],
-["0x01 0x0d", "0x5d EQUAL", "", "OP_13 pushes 0x0d"],
-["0x01 0x0e", "0x5e EQUAL", "", "OP_14 pushes 0x0e"],
-["0x01 0x0f", "0x5f EQUAL", "", "OP_15 pushes 0x0f"],
-["0x01 0x10", "0x60 EQUAL", "", "OP_16 pushes 0x10"],
-
-["Equivalency of different numeric encodings"],
-
-["0x02 0x8000", "128 NUMEQUAL", "", "0x8000 equals 128"],
-["0x01 0x00", "0 NUMEQUAL", "", "0x00 numequals 0"],
-["0x01 0x80", "0 NUMEQUAL", "", "0x80 (negative zero) numequals 0"],
-["0x02 0x0080", "0 NUMEQUAL", "", "0x0080 numequals 0"],
-["0x02 0x0500", "5 NUMEQUAL", "", "0x0500 numequals 5"],
-["0x03 0xff7f80", "0x02 0xffff NUMEQUAL", "", ""],
-["0x03 0xff7f00", "0x02 0xff7f NUMEQUAL", "", ""],
-["0x04 0xffff7f80", "0x03 0xffffff NUMEQUAL", "", ""],
-["0x04 0xffff7f00", "0x03 0xffff7f NUMEQUAL", "", ""],
-
-["Unevaluated non-minimal pushes are ignored"],
-
-["0 IF 0x4c 0x00 ENDIF 1", "", "MINIMALDATA", "non-minimal PUSHDATA1 ignored"],
-["0 IF 0x4d 0x0000 ENDIF 1", "", "MINIMALDATA", "non-minimal PUSHDATA2 ignored"],
-["0 IF 0x4c 0x00000000 ENDIF 1", "", "MINIMALDATA", "non-minimal PUSHDATA4 ignored"],
-["0 IF 0x01 0x81 ENDIF 1", "", "MINIMALDATA", "1NEGATE equiv"],
-["0 IF 0x01 0x01 ENDIF 1", "", "MINIMALDATA", "OP_1 equiv"],
-["0 IF 0x01 0x02 ENDIF 1", "", "MINIMALDATA", "OP_2 equiv"],
-["0 IF 0x01 0x03 ENDIF 1", "", "MINIMALDATA", "OP_3 equiv"],
-["0 IF 0x01 0x04 ENDIF 1", "", "MINIMALDATA", "OP_4 equiv"],
-["0 IF 0x01 0x05 ENDIF 1", "", "MINIMALDATA", "OP_5 equiv"],
-["0 IF 0x01 0x06 ENDIF 1", "", "MINIMALDATA", "OP_6 equiv"],
-["0 IF 0x01 0x07 ENDIF 1", "", "MINIMALDATA", "OP_7 equiv"],
-["0 IF 0x01 0x08 ENDIF 1", "", "MINIMALDATA", "OP_8 equiv"],
-["0 IF 0x01 0x09 ENDIF 1", "", "MINIMALDATA", "OP_9 equiv"],
-["0 IF 0x01 0x0a ENDIF 1", "", "MINIMALDATA", "OP_10 equiv"],
-["0 IF 0x01 0x0b ENDIF 1", "", "MINIMALDATA", "OP_11 equiv"],
-["0 IF 0x01 0x0c ENDIF 1", "", "MINIMALDATA", "OP_12 equiv"],
-["0 IF 0x01 0x0d ENDIF 1", "", "MINIMALDATA", "OP_13 equiv"],
-["0 IF 0x01 0x0e ENDIF 1", "", "MINIMALDATA", "OP_14 equiv"],
-["0 IF 0x01 0x0f ENDIF 1", "", "MINIMALDATA", "OP_15 equiv"],
-["0 IF 0x01 0x10 ENDIF 1", "", "MINIMALDATA", "OP_16 equiv"],
-
-["Numeric minimaldata rules are only applied when a stack item is numerically evaluated; the push itself is allowed"],
-
-["0x01 0x00", "1", "MINIMALDATA"],
-["0x01 0x80", "1", "MINIMALDATA"],
-["0x02 0x0180", "1", "MINIMALDATA"],
-["0x02 0x0100", "1", "MINIMALDATA"],
-["0x02 0x0200", "1", "MINIMALDATA"],
-["0x02 0x0300", "1", "MINIMALDATA"],
-["0x02 0x0400", "1", "MINIMALDATA"],
-["0x02 0x0500", "1", "MINIMALDATA"],
-["0x02 0x0600", "1", "MINIMALDATA"],
-["0x02 0x0700", "1", "MINIMALDATA"],
-["0x02 0x0800", "1", "MINIMALDATA"],
-["0x02 0x0900", "1", "MINIMALDATA"],
-["0x02 0x0a00", "1", "MINIMALDATA"],
-["0x02 0x0b00", "1", "MINIMALDATA"],
-["0x02 0x0c00", "1", "MINIMALDATA"],
-["0x02 0x0d00", "1", "MINIMALDATA"],
-["0x02 0x0e00", "1", "MINIMALDATA"],
-["0x02 0x0f00", "1", "MINIMALDATA"],
-["0x02 0x1000", "1", "MINIMALDATA"],
-
-["Valid version of the 'Test every numeric-accepting opcode for correct handling of the numeric minimal encoding rule' script_invalid test"],
-
-["1 0x02 0x0000", "PICK DROP", ""],
-["1 0x02 0x0000", "ROLL DROP 1", ""],
-["0x02 0x0000", "1ADD DROP 1", ""],
-["0x02 0x0000", "1SUB DROP 1", ""],
-["0x02 0x0000", "NEGATE DROP 1", ""],
-["0x02 0x0000", "ABS DROP 1", ""],
-["0x02 0x0000", "NOT DROP 1", ""],
-["0x02 0x0000", "0NOTEQUAL DROP 1", ""],
-
-["0 0x02 0x0000", "ADD DROP 1", ""],
-["0x02 0x0000 0", "ADD DROP 1", ""],
-["0 0x02 0x0000", "SUB DROP 1", ""],
-["0x02 0x0000 0", "SUB DROP 1", ""],
-["0 0x02 0x0000", "BOOLAND DROP 1", ""],
-["0x02 0x0000 0", "BOOLAND DROP 1", ""],
-["0 0x02 0x0000", "BOOLOR DROP 1", ""],
-["0x02 0x0000 0", "BOOLOR DROP 1", ""],
-["0 0x02 0x0000", "NUMEQUAL DROP 1", ""],
-["0x02 0x0000 1", "NUMEQUAL DROP 1", ""],
-["0 0x02 0x0000", "NUMEQUALVERIFY 1", ""],
-["0x02 0x0000 0", "NUMEQUALVERIFY 1", ""],
-["0 0x02 0x0000", "NUMNOTEQUAL DROP 1", ""],
-["0x02 0x0000 0", "NUMNOTEQUAL DROP 1", ""],
-["0 0x02 0x0000", "LESSTHAN DROP 1", ""],
-["0x02 0x0000 0", "LESSTHAN DROP 1", ""],
-["0 0x02 0x0000", "GREATERTHAN DROP 1", ""],
-["0x02 0x0000 0", "GREATERTHAN DROP 1", ""],
-["0 0x02 0x0000", "LESSTHANOREQUAL DROP 1", ""],
-["0x02 0x0000 0", "LESSTHANOREQUAL DROP 1", ""],
-["0 0x02 0x0000", "GREATERTHANOREQUAL DROP 1", ""],
-["0x02 0x0000 0", "GREATERTHANOREQUAL DROP 1", ""],
-["0 0x02 0x0000", "MIN DROP 1", ""],
-["0x02 0x0000 0", "MIN DROP 1", ""],
-["0 0x02 0x0000", "MAX DROP 1", ""],
-["0x02 0x0000 0", "MAX DROP 1", ""],
-
-["0x02 0x0000 0 0", "WITHIN DROP 1", ""],
-["0 0x02 0x0000 0", "WITHIN DROP 1", ""],
-["0 0 0x02 0x0000", "WITHIN DROP 1", ""],
-
-["0 0 0x02 0x0000", "CHECKMULTISIG DROP 1", ""],
-["0 0x02 0x0000 0", "CHECKMULTISIG DROP 1", ""],
-["0 0x02 0x0000 0 1", "CHECKMULTISIG DROP 1", ""],
-["0 0 0x02 0x0000", "CHECKMULTISIGVERIFY 1", ""],
-["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", ""],
-
-["While not really correctly DER encoded, the empty signature is allowed by"],
-["STRICTENC to provide a compact way to provide a delibrately invalid signature."],
-["0", "0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 CHECKSIG NOT", "STRICTENC"],
-["0 0", "1 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 1 CHECKMULTISIG NOT", "STRICTENC"],
-
-["CHECKMULTISIG evaluation order tests. CHECKMULTISIG evaluates signatures and"],
-["pubkeys in a specific order, and will exit early if the number of signatures"],
-["left to check is greater than the number of keys left. As STRICTENC fails the"],
-["script when it reaches an invalidly encoded signature or pubkey, we can use it"],
-["to test the exact order in which signatures and pubkeys are evaluated by"],
-["distinguishing CHECKMULTISIG returning false on the stack and the script as a"],
-["whole failing."],
-["See also the corresponding inverted versions of these tests in script_invalid.json"],
-[
- "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501",
- "2 0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT",
- "STRICTENC",
- "2-of-2 CHECKMULTISIG NOT with the second pubkey invalid, and both signatures validly encoded. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid pubkey."
-],
-[
- "0 0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501",
- "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT",
- "STRICTENC",
- "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but second signature invalid. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid signature."
-],
-
-["Increase test coverage for DERSIG"],
-["0x4a 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "", "Overly long signature is correctly encoded"],
-["0x25 0x30220220000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "", "Missing S is correctly encoded"],
-["0x27 0x3024021077777777777777777777777777777777020a7777777777777777777777777777777701", "0 CHECKSIG NOT", "", "S with invalid S length is correctly encoded"],
-["0x27 0x302403107777777777777777777777777777777702107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "Non-integer R is correctly encoded"],
-["0x27 0x302402107777777777777777777777777777777703107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "Non-integer S is correctly encoded"],
-["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "Zero-length R is correctly encoded"],
-["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "", "Zero-length S is correctly encoded for DERSIG"],
-["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "", "Negative S is correctly encoded"],
-
-["Automatically generated test cases"],
-[
- "0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001",
- "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
- "",
- "P2PK"
-],
-[
- "0x47 0x304402206e05a6fe23c59196ffe176c9ddc31e73a9885638f9d1328d47c0c703863b8876022076feb53811aa5b04e0e79f938eb19906cc5e67548bc555a8e8b8b0fc603d840c01 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508",
- "DUP HASH160 0x14 0x1018853670f9f3b0582c5b9ee8ce93764ac32b93 EQUALVERIFY CHECKSIG",
- "",
- "P2PKH"
-],
-[
- "0x47 0x304402204710a85181663b32d25c70ec2bbd14adff5ddfff6cb50d09e155ef5f541fc86c0220056b0cc949be9386ecc5f6c2ac0493269031dbb185781db90171b54ac127790281",
- "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
- "",
- "P2PK anyonecanpay"
-],
-[
- "0x47 0x3044022003fef42ed6c7be8917441218f525a60e2431be978e28b7aca4d7a532cc413ae8022067a1f82c74e8d69291b90d148778405c6257bbcfc2353cc38a3e1f22bf44254601 0x23 0x210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac",
- "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL",
- "P2SH",
- "P2SH(P2PK)"
-],
-[
- "0x47 0x304402204e2eb034be7b089534ac9e798cf6a2c79f38bcb34d1b179efd6f2de0841735db022071461beb056b5a7be1819da6a3e3ce3662831ecc298419ca101eb6887b5dd6a401 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac",
- "HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL",
- "",
- "P2SH(P2PKH), bad sig but no VERIFY_P2SH"
-],
-[
- "0 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901",
- "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
- "",
- "3-of-3"
-],
-[
- "0 0x47 0x304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001 0x47 0x30440220563e5b3b1fc11662a84bc5ea2a32cc3819703254060ba30d639a1aaf2d5068ad0220601c1f47ddc76d93284dd9ed68f7c9974c4a0ea7cbe8a247d6bc3878567a5fca01 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae",
- "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL",
- "P2SH",
- "P2SH(2-of-3)"
-],
-[
- "0x47 0x304402200060558477337b9022e70534f1fea71a318caf836812465a2509931c5e7c4987022078ec32bd50ac9e03a349ba953dfd9fe1c8d2dd8bdb1d38ddca844d3d5c78c11801",
- "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
- "",
- "P2PK with too much R padding but no DERSIG"
-],
-[
- "0x48 0x304502202de8c03fc525285c9c535631019a5f2af7c6454fa9eb392a3756a4917c420edd02210046130bf2baf7cfc065067c8b9e33a066d9c15edcea9feb0ca2d233e3597925b401",
- "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
- "",
- "P2PK with too much S padding but no DERSIG"
-],
-[
- "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201",
- "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
- "",
- "P2PK with too little R padding but no DERSIG"
-],
-[
- "0x47 0x30440220005ece1335e7f757a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601",
- "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
- "",
- "P2PK NOT with bad sig with too much R padding but no DERSIG"
-],
-[
- "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201",
- "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
- "",
- "BIP66 example 1, without DERSIG"
-],
-[
- "0",
- "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
- "",
- "BIP66 example 4, without DERSIG"
-],
-[
- "0",
- "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
- "DERSIG",
- "BIP66 example 4, with DERSIG"
-],
-[
- "1",
- "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
- "",
- "BIP66 example 6, without DERSIG"
-],
-[
- "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0x47 0x3044022027c2714269ca5aeecc4d70edc88ba5ee0e3da4986e9216028f489ab4f1b8efce022022bd545b4951215267e4c5ceabd4c5350331b2e4a0b6494c56f361fa5a57a1a201",
- "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
- "",
- "BIP66 example 7, without DERSIG"
-],
-[
- "0 0 0x47 0x30440220da6f441dc3b4b2c84cfa8db0cd5b34ed92c9e01686de5a800d40498b70c0dcac02207c2cf91b0c32b860c4cd4994be36cfb84caf8bb7c3a8e4d96a31b2022c5299c501",
- "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
- "",
- "BIP66 example 10, without DERSIG"
-],
-[
- "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0",
- "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
- "",
- "BIP66 example 12, without DERSIG"
-],
-[
- "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0",
- "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
- "DERSIG",
- "BIP66 example 12, with DERSIG"
-],
-[
- "0x48 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb12510101",
- "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
- "",
- "P2PK with multi-byte hashtype, without DERSIG"
-],
-[
- "0x48 0x304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef001",
- "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
- "",
- "P2PK with high S but no LOW_S"
-],
-[
- "0x47 0x3044022057292e2d4dfe775becdd0a9e6547997c728cdf35390f6a017da56d654d374e4902206b643be2fc53763b4e284845bfea2c597d2dc7759941dce937636c9d341b71ed01",
- "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
- "",
- "P2PK with hybrid pubkey but no STRICTENC"
-],
-[
- "0x47 0x30440220035d554e3153c04950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101",
- "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
- "",
- "P2PK NOT with invalid hybrid pubkey but no STRICTENC"
-],
-[
- "0 0x47 0x304402202e79441ad1baf5a07fb86bae3753184f6717d9692680947ea8b6e8b777c69af1022079a262e13d868bb5a0964fefe3ba26942e1b0669af1afb55ef3344bc9d4fc4c401",
- "1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
- "",
- "1-of-2 with the second 1 hybrid pubkey and no STRICTENC"
-],
-[
- "0 0x47 0x304402202e79441ad1baf5a07fb86bae3753184f6717d9692680947ea8b6e8b777c69af1022079a262e13d868bb5a0964fefe3ba26942e1b0669af1afb55ef3344bc9d4fc4c401",
- "1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
- "STRICTENC",
- "1-of-2 with the second 1 hybrid pubkey"
-],
-[
- "0x47 0x304402206177d513ec2cda444c021a1f4f656fc4c72ba108ae063e157eb86dc3575784940220666fc66702815d0e5413bb9b1df22aed44f5f1efb8b99d41dd5dc9a5be6d205205",
- "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
- "",
- "P2PK with undefined hashtype but no STRICTENC"
-],
-[
- "0x47 0x304402207409b5b320296e5e2136a7b281a7f803028ca4ca44e2b83eebd46932677725de02202d4eea1c8d3c98e6f42614f54764e6e5e6542e213eb4d079737e9a8b6e9812ec05",
- "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT",
- "",
- "P2PK NOT with invalid sig and undefined hashtype but no STRICTENC"
-],
-[
- "1 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901",
- "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
- "",
- "3-of-3 with nonzero dummy but no NULLDUMMY"
-],
-[
- "1 0x47 0x304402201bb2edab700a5d020236df174fefed78087697143731f659bea59642c759c16d022061f42cdbae5bcd3e8790f20bf76687443436e94a634321c16a72aa54cbc7c2ea01 0x47 0x304402204bb4a64f2a6e5c7fb2f07fef85ee56fde5e6da234c6a984262307a20e99842d702206f8303aaba5e625d223897e2ffd3f88ef1bcffef55f38dc3768e5f2e94c923f901 0x47 0x3044022040c2809b71fffb155ec8b82fe7a27f666bd97f941207be4e14ade85a1249dd4d02204d56c85ec525dd18e29a0533d5ddf61b6b1bb32980c2f63edf951aebf7a27bfe01",
- "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT",
- "",
- "3-of-3 NOT with invalid sig and nonzero dummy but no NULLDUMMY"
-],
-[
- "0 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901 DUP",
- "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
- "",
- "2-of-2 with two identical keys and sigs pushed using OP_DUP but no SIGPUSHONLY"
-],
-[
- "0 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901",
- "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
- "SIGPUSHONLY",
- "2-of-2 with two identical keys and sigs pushed"
-],
-[
- "11 0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001",
- "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
- "P2SH",
- "P2PK with unnecessary input but no CLEANSTACK"
-],
-[
- "11 0x47 0x304402202f7505132be14872581f35d74b759212d9da40482653f1ffa3116c3294a4a51702206adbf347a2240ca41c66522b1a22a41693610b76a8e7770645dc721d1635854f01 0x43 0x410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
- "HASH160 0x14 0x31edc23bdafda4639e669f89ad6b2318dd79d032 EQUAL",
- "P2SH",
- "P2SH with unnecessary input but no CLEANSTACK"
-],
-[
- "0x47 0x304402202f7505132be14872581f35d74b759212d9da40482653f1ffa3116c3294a4a51702206adbf347a2240ca41c66522b1a22a41693610b76a8e7770645dc721d1635854f01 0x43 0x410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
- "HASH160 0x14 0x31edc23bdafda4639e669f89ad6b2318dd79d032 EQUAL",
- "CLEANSTACK,P2SH",
- "P2SH with CLEANSTACK"
-],
-
-["The End"]
-]
diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp
index e399315870..081d57831d 100644
--- a/src/test/dbwrapper_tests.cpp
+++ b/src/test/dbwrapper_tests.cpp
@@ -39,7 +39,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper)
uint256 res;
// Ensure that we're doing real obfuscation when obfuscate=true
- BOOST_CHECK(obfuscate != is_null_key(dbw.GetObfuscateKey()));
+ BOOST_CHECK(obfuscate != is_null_key(dbwrapper_private::GetObfuscateKey(dbw)));
BOOST_CHECK(dbw.Write(key, in));
BOOST_CHECK(dbw.Read(key, res));
@@ -64,7 +64,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_batch)
uint256 in3 = GetRandHash();
uint256 res;
- CDBBatch batch(&dbw.GetObfuscateKey());
+ CDBBatch batch(dbw);
batch.Write(key, in);
batch.Write(key2, in2);
@@ -156,7 +156,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate)
BOOST_CHECK_EQUAL(res2.ToString(), in.ToString());
BOOST_CHECK(!odbw.IsEmpty()); // There should be existing data
- BOOST_CHECK(is_null_key(odbw.GetObfuscateKey())); // The key should be an empty string
+ BOOST_CHECK(is_null_key(dbwrapper_private::GetObfuscateKey(odbw))); // The key should be an empty string
uint256 in2 = GetRandHash();
uint256 res3;
@@ -193,7 +193,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex)
// Check that the key/val we wrote with unobfuscated wrapper doesn't exist
uint256 res2;
BOOST_CHECK(!odbw.Read(key, res2));
- BOOST_CHECK(!is_null_key(odbw.GetObfuscateKey()));
+ BOOST_CHECK(!is_null_key(dbwrapper_private::GetObfuscateKey(odbw)));
uint256 in2 = GetRandHash();
uint256 res3;
diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp
index fa352ace8f..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,7 +96,7 @@ 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();
@@ -281,11 +281,11 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
// 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);
+ 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:
*
@@ -317,6 +317,110 @@ BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
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);
+}
+
BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
{
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index f3297e074d..ab6485081c 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -247,13 +247,40 @@ 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);
diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp
index edf1650ca5..d48a68ba54 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -9,12 +9,10 @@
#include "script/script_error.h"
#include "script/interpreter.h"
#include "script/sign.h"
+#include "script/ismine.h"
#include "uint256.h"
#include "test/test_bitcoin.h"
-#ifdef ENABLE_WALLET
-#include "wallet/wallet_ismine.h"
-#endif
#include <boost/foreach.hpp>
#include <boost/test/unit_test.hpp>
@@ -210,10 +208,8 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
CTxDestination addr;
BOOST_CHECK(ExtractDestination(s, addr));
BOOST_CHECK(addr == keyaddr[0]);
-#ifdef ENABLE_WALLET
BOOST_CHECK(IsMine(keystore, s));
BOOST_CHECK(!IsMine(emptykeystore, s));
-#endif
}
{
vector<valtype> solutions;
@@ -225,10 +221,8 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
CTxDestination addr;
BOOST_CHECK(ExtractDestination(s, addr));
BOOST_CHECK(addr == keyaddr[0]);
-#ifdef ENABLE_WALLET
BOOST_CHECK(IsMine(keystore, s));
BOOST_CHECK(!IsMine(emptykeystore, s));
-#endif
}
{
vector<valtype> solutions;
@@ -239,11 +233,9 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
BOOST_CHECK_EQUAL(solutions.size(), 4U);
CTxDestination addr;
BOOST_CHECK(!ExtractDestination(s, addr));
-#ifdef ENABLE_WALLET
BOOST_CHECK(IsMine(keystore, s));
BOOST_CHECK(!IsMine(emptykeystore, s));
BOOST_CHECK(!IsMine(partialkeystore, s));
-#endif
}
{
vector<valtype> solutions;
@@ -258,11 +250,9 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
BOOST_CHECK(addrs[0] == keyaddr[0]);
BOOST_CHECK(addrs[1] == keyaddr[1]);
BOOST_CHECK(nRequired == 1);
-#ifdef ENABLE_WALLET
BOOST_CHECK(IsMine(keystore, s));
BOOST_CHECK(!IsMine(emptykeystore, s));
BOOST_CHECK(!IsMine(partialkeystore, s));
-#endif
}
{
vector<valtype> solutions;
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/prevector_tests.cpp b/src/test/prevector_tests.cpp
index 01a45b540d..b39b903530 100644
--- a/src/test/prevector_tests.cpp
+++ b/src/test/prevector_tests.cpp
@@ -19,9 +19,11 @@ template<unsigned int N, typename T>
class prevector_tester {
typedef std::vector<T> realtype;
realtype real_vector;
+ realtype real_vector_alt;
typedef prevector<N, T> pretype;
pretype pre_vector;
+ pretype pre_vector_alt;
typedef typename pretype::size_type Size;
@@ -149,6 +151,12 @@ public:
pre_vector.shrink_to_fit();
test();
}
+
+ void swap() {
+ real_vector.swap(real_vector_alt);
+ pre_vector.swap(pre_vector_alt);
+ test();
+ }
};
BOOST_AUTO_TEST_CASE(PrevectorTestInt)
@@ -204,12 +212,15 @@ BOOST_AUTO_TEST_CASE(PrevectorTestInt)
if (test.size() > 0) {
test.update(insecure_rand() % test.size(), insecure_rand());
}
- if (((r >> 11) & 1024) == 11) {
+ if (((r >> 11) % 1024) == 11) {
test.clear();
}
- if (((r >> 21) & 512) == 12) {
+ if (((r >> 21) % 512) == 12) {
test.assign(insecure_rand() % 32, insecure_rand());
}
+ if (((r >> 15) % 64) == 3) {
+ test.swap();
+ }
}
}
}
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index d6309ca384..bbda6a48f4 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -11,6 +11,7 @@
#include "test/test_bitcoin.h"
#include <boost/algorithm/string.hpp>
+#include <boost/assign/list_of.hpp>
#include <boost/test/unit_test.hpp>
#include <univalue.h>
@@ -36,7 +37,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);
@@ -308,4 +309,27 @@ BOOST_AUTO_TEST_CASE(rpc_ban)
BOOST_CHECK_EQUAL(adr.get_str(), "2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/128");
}
+BOOST_AUTO_TEST_CASE(rpc_convert_values_generatetoaddress)
+{
+ UniValue result;
+
+ BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("101")("mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a")));
+ BOOST_CHECK_EQUAL(result[0].get_int(), 101);
+ BOOST_CHECK_EQUAL(result[1].get_str(), "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a");
+
+ BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("101")("mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU")));
+ BOOST_CHECK_EQUAL(result[0].get_int(), 101);
+ BOOST_CHECK_EQUAL(result[1].get_str(), "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU");
+
+ BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("1")("mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a")("9")));
+ BOOST_CHECK_EQUAL(result[0].get_int(), 1);
+ BOOST_CHECK_EQUAL(result[1].get_str(), "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a");
+ BOOST_CHECK_EQUAL(result[2].get_int(), 9);
+
+ BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("1")("mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU")("9")));
+ BOOST_CHECK_EQUAL(result[0].get_int(), 1);
+ BOOST_CHECK_EQUAL(result[1].get_str(), "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU");
+ BOOST_CHECK_EQUAL(result[2].get_int(), 9);
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp
index 28b85e8d29..d10284fe94 100644
--- a/src/test/script_P2SH_tests.cpp
+++ b/src/test/script_P2SH_tests.cpp
@@ -9,12 +9,9 @@
#include "script/script.h"
#include "script/script_error.h"
#include "script/sign.h"
+#include "script/ismine.h"
#include "test/test_bitcoin.h"
-#ifdef ENABLE_WALLET
-#include "wallet/wallet_ismine.h"
-#endif
-
#include <vector>
#include <boost/test/unit_test.hpp>
@@ -101,9 +98,7 @@ BOOST_AUTO_TEST_CASE(sign)
txTo[i].vin[0].prevout.n = i;
txTo[i].vin[0].prevout.hash = txFrom.GetHash();
txTo[i].vout[0].nValue = 1;
-#ifdef ENABLE_WALLET
BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
-#endif
}
for (int i = 0; i < 8; i++)
{
@@ -198,9 +193,7 @@ BOOST_AUTO_TEST_CASE(set)
txTo[i].vin[0].prevout.hash = txFrom.GetHash();
txTo[i].vout[0].nValue = 1*CENT;
txTo[i].vout[0].scriptPubKey = inner[i];
-#ifdef ENABLE_WALLET
BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
-#endif
}
for (int i = 0; i < 4; i++)
{
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 30e3f37e14..d42187f912 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -2,8 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "data/script_invalid.json.h"
-#include "data/script_valid.json.h"
+#include "data/script_tests.json.h"
#include "core_io.h"
#include "key.h"
@@ -145,13 +144,14 @@ CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CMu
return txSpend;
}
-void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, bool expect, const std::string& message, int scriptError)
+void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, const std::string& message, int scriptError)
{
+ bool expect = (scriptError == SCRIPT_ERR_OK);
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(scriptError == -1 || err == scriptError, std::string(FormatScriptError(err)) + " where " + std::string(FormatScriptError((ScriptError_t)scriptError)) + " expected: " + message);
+ BOOST_CHECK_MESSAGE(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;
@@ -263,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_), scriptError(-1)
+ TestBuilder(const CScript& redeemScript, const std::string& comment_, int flags_, bool P2SH = false) : scriptPubKey(redeemScript), havePush(false), comment(comment_), flags(flags_), scriptError(SCRIPT_ERR_OK)
{
if (P2SH) {
creditTx = BuildCreditingTransaction(CScript() << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL);
@@ -349,11 +349,11 @@ public:
return *this;
}
- TestBuilder& Test(bool expect)
+ TestBuilder& Test()
{
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, expect ? SCRIPT_ERR_OK : scriptError);
+ DoTest(creditTx.vout[0].scriptPubKey, spendTx.vin[0].scriptSig, flags, comment, scriptError);
*this = copy;
return *this;
}
@@ -365,9 +365,8 @@ public:
array.push_back(FormatScript(spendTx.vin[0].scriptSig));
array.push_back(FormatScript(creditTx.vout[0].scriptPubKey));
array.push_back(FormatScriptFlags(flags));
+ array.push_back(FormatScriptError((ScriptError_t)scriptError));
array.push_back(comment);
- if (scriptError != -1)
- array.push_back(FormatScriptError((ScriptError_t)scriptError));
return array;
}
@@ -381,331 +380,328 @@ public:
return creditTx.vout[0].scriptPubKey;
}
};
+
+std::string JSONPrettyPrint(const UniValue& univalue)
+{
+ std::string ret = univalue.write(4);
+ // Workaround for libunivalue pretty printer, which puts a space between comma's and newlines
+ size_t pos = 0;
+ while ((pos = ret.find(" \n", pos)) != std::string::npos) {
+ ret.replace(pos, 2, "\n");
+ pos++;
+ }
+ return ret;
+}
}
BOOST_AUTO_TEST_CASE(script_build)
{
const KeyData keys;
- std::vector<TestBuilder> good;
- std::vector<TestBuilder> bad;
-
- good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
- "P2PK", 0
- ).PushSig(keys.key0));
- bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
- "P2PK, bad sig", 0
- ).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).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").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).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().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).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().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").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").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").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).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").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").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").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").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").ScriptError(SCRIPT_ERR_SIG_DER));
- bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
- "BIP66 example 3, without DERSIG", 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).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));
- good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT,
- "BIP66 example 4, with DERSIG", SCRIPT_VERIFY_DERSIG
- ).Num(0));
- bad.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
- "BIP66 example 5, without DERSIG", 0
- ).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).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).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).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).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).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").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").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").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).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).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));
- good.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT,
- "BIP66 example 12, with DERSIG", SCRIPT_VERIFY_DERSIG
- ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0));
- good.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
- "P2PK with multi-byte hashtype, without DERSIG", 0
- ).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").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).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).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).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).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).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));
- 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", SCRIPT_VERIFY_STRICTENC
- ).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).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).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).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).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).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).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().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().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).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().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());
-
-
- std::set<std::string> tests_good;
- std::set<std::string> tests_bad;
+ std::vector<TestBuilder> tests;
+
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "P2PK", 0
+ ).PushSig(keys.key0));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "P2PK, bad sig", 0
+ ).PushSig(keys.key0).DamagePush(10).ScriptError(SCRIPT_ERR_EVAL_FALSE));
+
+ tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey1C.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG,
+ "P2PKH", 0
+ ).PushSig(keys.key1).Push(keys.pubkey1C));
+ tests.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).ScriptError(SCRIPT_ERR_EQUALVERIFY));
+
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
+ "P2PK anyonecanpay", 0
+ ).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_ANYONECANPAY));
+ tests.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").ScriptError(SCRIPT_ERR_EVAL_FALSE));
+
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG,
+ "P2SH(P2PK)", SCRIPT_VERIFY_P2SH, true
+ ).PushSig(keys.key0).PushRedeem());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG,
+ "P2SH(P2PK), bad redeemscript", SCRIPT_VERIFY_P2SH, true
+ ).PushSig(keys.key0).PushRedeem().DamagePush(10).ScriptError(SCRIPT_ERR_EVAL_FALSE));
+
+ tests.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());
+ tests.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().ScriptError(SCRIPT_ERR_EQUALVERIFY));
+
+ tests.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));
+ tests.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).ScriptError(SCRIPT_ERR_EVAL_FALSE));
+
+ tests.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());
+ tests.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().ScriptError(SCRIPT_ERR_EVAL_FALSE));
+
+ tests.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"));
+ tests.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").ScriptError(SCRIPT_ERR_SIG_DER));
+ tests.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"));
+ tests.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").ScriptError(SCRIPT_ERR_SIG_DER));
+ tests.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"));
+ tests.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").ScriptError(SCRIPT_ERR_SIG_DER));
+ tests.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));
+ tests.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).ScriptError(SCRIPT_ERR_SIG_DER));
+ tests.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").ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.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").ScriptError(SCRIPT_ERR_SIG_DER));
+
+ tests.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"));
+ tests.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").ScriptError(SCRIPT_ERR_SIG_DER));
+ tests.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").ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.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").ScriptError(SCRIPT_ERR_SIG_DER));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
+ "BIP66 example 3, without DERSIG", 0
+ ).Num(0).ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
+ "BIP66 example 3, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(0).ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT,
+ "BIP66 example 4, without DERSIG", 0
+ ).Num(0));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT,
+ "BIP66 example 4, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(0));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
+ "BIP66 example 5, without DERSIG", 0
+ ).Num(1).ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
+ "BIP66 example 5, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(1).ScriptError(SCRIPT_ERR_SIG_DER));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT,
+ "BIP66 example 6, without DERSIG", 0
+ ).Num(1));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT,
+ "BIP66 example 6, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(1).ScriptError(SCRIPT_ERR_SIG_DER));
+ tests.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));
+ tests.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).ScriptError(SCRIPT_ERR_SIG_DER));
+ tests.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).ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.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).ScriptError(SCRIPT_ERR_SIG_DER));
+ tests.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").ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.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").ScriptError(SCRIPT_ERR_SIG_DER));
+ tests.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"));
+ tests.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").ScriptError(SCRIPT_ERR_SIG_DER));
+ tests.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).ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.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).ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.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));
+ tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT,
+ "BIP66 example 12, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
+ "P2PK with multi-byte hashtype, without DERSIG", 0
+ ).PushSig(keys.key2, SIGHASH_ALL).EditPush(70, "01", "0101"));
+ tests.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").ScriptError(SCRIPT_ERR_SIG_DER));
+
+ tests.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));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
+ "P2PK with high S", SCRIPT_VERIFY_LOW_S
+ ).PushSig(keys.key2, SIGHASH_ALL, 32, 33).ScriptError(SCRIPT_ERR_SIG_HIGH_S));
+
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG,
+ "P2PK with hybrid pubkey but no STRICTENC", 0
+ ).PushSig(keys.key0, SIGHASH_ALL));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG,
+ "P2PK with hybrid pubkey", SCRIPT_VERIFY_STRICTENC
+ ).PushSig(keys.key0, SIGHASH_ALL).ScriptError(SCRIPT_ERR_PUBKEYTYPE));
+ tests.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).ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT,
+ "P2PK NOT with hybrid pubkey", SCRIPT_VERIFY_STRICTENC
+ ).PushSig(keys.key0, SIGHASH_ALL).ScriptError(SCRIPT_ERR_PUBKEYTYPE));
+ tests.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));
+ tests.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).ScriptError(SCRIPT_ERR_PUBKEYTYPE));
+ tests.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));
+ tests.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", SCRIPT_VERIFY_STRICTENC
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL));
+ tests.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).ScriptError(SCRIPT_ERR_PUBKEYTYPE));
+
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
+ "P2PK with undefined hashtype but no STRICTENC", 0
+ ).PushSig(keys.key1, 5));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
+ "P2PK with undefined hashtype", SCRIPT_VERIFY_STRICTENC
+ ).PushSig(keys.key1, 5).ScriptError(SCRIPT_ERR_SIG_HASHTYPE));
+ tests.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));
+ tests.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).ScriptError(SCRIPT_ERR_SIG_HASHTYPE));
+
+ tests.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));
+ tests.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).ScriptError(SCRIPT_ERR_SIG_NULLDUMMY));
+ tests.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));
+ tests.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).ScriptError(SCRIPT_ERR_SIG_NULLDUMMY));
+
+ tests.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));
+ tests.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).ScriptError(SCRIPT_ERR_SIG_PUSHONLY));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
+ "P2SH(P2PK) with non-push scriptSig but no P2SH or SIGPUSHONLY", 0, true
+ ).PushSig(keys.key2).Add(CScript() << OP_NOP8).PushRedeem());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
+ "P2PK with non-push scriptSig but with P2SH validation", 0
+ ).PushSig(keys.key2).Add(CScript() << OP_NOP8));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
+ "P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY", SCRIPT_VERIFY_P2SH, true
+ ).PushSig(keys.key2).Add(CScript() << OP_NOP8).PushRedeem().ScriptError(SCRIPT_ERR_SIG_PUSHONLY));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
+ "P2SH(P2PK) with non-push scriptSig but not P2SH", SCRIPT_VERIFY_SIGPUSHONLY, true
+ ).PushSig(keys.key2).Add(CScript() << OP_NOP8).PushRedeem().ScriptError(SCRIPT_ERR_SIG_PUSHONLY));
+ tests.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));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "P2PK with unnecessary input but no CLEANSTACK", SCRIPT_VERIFY_P2SH
+ ).Num(11).PushSig(keys.key0));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "P2PK with unnecessary input", SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH
+ ).Num(11).PushSig(keys.key0).ScriptError(SCRIPT_ERR_CLEANSTACK));
+ tests.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());
+ tests.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().ScriptError(SCRIPT_ERR_CLEANSTACK));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "P2SH with CLEANSTACK", SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH, true
+ ).PushSig(keys.key0).PushRedeem());
+
+
+ std::set<std::string> tests_set;
{
- UniValue json_good = read_json(std::string(json_tests::script_valid, json_tests::script_valid + sizeof(json_tests::script_valid)));
- UniValue json_bad = read_json(std::string(json_tests::script_invalid, json_tests::script_invalid + sizeof(json_tests::script_invalid)));
+ UniValue json_tests = read_json(std::string(json_tests::script_tests, json_tests::script_tests + sizeof(json_tests::script_tests)));
- for (unsigned int idx = 0; idx < json_good.size(); idx++) {
- const UniValue& tv = json_good[idx];
- 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(1,4));
+ for (unsigned int idx = 0; idx < json_tests.size(); idx++) {
+ const UniValue& tv = json_tests[idx];
+ tests_set.insert(JSONPrettyPrint(tv.get_array()));
}
}
- std::string strGood;
- std::string strBad;
+ std::string strGen;
- BOOST_FOREACH(TestBuilder& test, good) {
- test.Test(true);
- std::string str = test.GetJSON().write(1,4);
+ BOOST_FOREACH(TestBuilder& test, tests) {
+ test.Test();
+ std::string str = JSONPrettyPrint(test.GetJSON());
#ifndef UPDATE_JSON_TESTS
- if (tests_good.count(str) == 0) {
+ if (tests_set.count(str) == 0) {
BOOST_CHECK_MESSAGE(false, "Missing auto script_valid test: " + test.GetComment());
}
#endif
- strGood += str + ",\n";
- }
- BOOST_FOREACH(TestBuilder& test, bad) {
- test.Test(false);
- 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());
- }
-#endif
- strBad += str + ",\n";
+ strGen += str + ",\n";
}
#ifdef UPDATE_JSON_TESTS
- FILE* valid = fopen("script_valid.json.gen", "w");
- fputs(strGood.c_str(), valid);
- fclose(valid);
- FILE* invalid = fopen("script_invalid.json.gen", "w");
- fputs(strBad.c_str(), invalid);
- fclose(invalid);
+ FILE* file = fopen("script_tests.json.gen", "w");
+ fputs(strGen.c_str(), file);
+ fclose(file);
#endif
}
-BOOST_AUTO_TEST_CASE(script_valid)
+BOOST_AUTO_TEST_CASE(script_json_test)
{
- // Read tests from test/data/script_valid.json
+ // Read tests from test/data/script_tests.json
// Format is an array of arrays
- // Inner arrays are [ "scriptSig", "scriptPubKey", "flags" ]
+ // Inner arrays are [ "scriptSig", "scriptPubKey", "flags", "expected_scripterror" ]
// ... where scriptSig and scriptPubKey are stringified
// scripts.
- UniValue tests = read_json(std::string(json_tests::script_valid, json_tests::script_valid + sizeof(json_tests::script_valid)));
+ UniValue tests = read_json(std::string(json_tests::script_tests, json_tests::script_tests + sizeof(json_tests::script_tests)));
for (unsigned int idx = 0; idx < tests.size(); idx++) {
UniValue test = tests[idx];
string strTest = test.write();
- if (test.size() < 3) // Allow size > 3; extra stuff ignored (useful for comments)
+ if (test.size() < 4) // Allow size > 3; extra stuff ignored (useful for comments)
{
if (test.size() != 1) {
BOOST_ERROR("Bad test: " << strTest);
@@ -717,36 +713,9 @@ BOOST_AUTO_TEST_CASE(script_valid)
string scriptPubKeyString = test[1].get_str();
CScript scriptPubKey = ParseScript(scriptPubKeyString);
unsigned int scriptflags = ParseScriptFlags(test[2].get_str());
+ int scriptError = ParseScriptError(test[3].get_str());
- DoTest(scriptPubKey, scriptSig, scriptflags, true, strTest, SCRIPT_ERR_OK);
- }
-}
-
-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();
- if (test.size() < 3) // Allow size > 2; extra stuff ignored (useful for comments)
- {
- if (test.size() != 1) {
- BOOST_ERROR("Bad test: " << strTest);
- }
- continue;
- }
- string scriptSigString = test[0].get_str();
- CScript scriptSig = ParseScript(scriptSigString);
- 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, scriptError);
+ DoTest(scriptPubKey, scriptSig, scriptflags, strTest, scriptError);
}
}
diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp
index c0fd99aca2..bec2c7459d 100644
--- a/src/test/serialize_tests.cpp
+++ b/src/test/serialize_tests.cpp
@@ -160,6 +160,27 @@ BOOST_AUTO_TEST_CASE(varints)
}
}
+BOOST_AUTO_TEST_CASE(varints_bitpatterns)
+{
+ CDataStream ss(SER_DISK, 0);
+ ss << VARINT(0); BOOST_CHECK_EQUAL(HexStr(ss), "00"); ss.clear();
+ ss << VARINT(0x7f); BOOST_CHECK_EQUAL(HexStr(ss), "7f"); ss.clear();
+ ss << VARINT((int8_t)0x7f); BOOST_CHECK_EQUAL(HexStr(ss), "7f"); ss.clear();
+ ss << VARINT(0x80); BOOST_CHECK_EQUAL(HexStr(ss), "8000"); ss.clear();
+ ss << VARINT((uint8_t)0x80); BOOST_CHECK_EQUAL(HexStr(ss), "8000"); ss.clear();
+ ss << VARINT(0x1234); BOOST_CHECK_EQUAL(HexStr(ss), "a334"); ss.clear();
+ ss << VARINT((int16_t)0x1234); BOOST_CHECK_EQUAL(HexStr(ss), "a334"); ss.clear();
+ ss << VARINT(0xffff); BOOST_CHECK_EQUAL(HexStr(ss), "82fe7f"); ss.clear();
+ ss << VARINT((uint16_t)0xffff); BOOST_CHECK_EQUAL(HexStr(ss), "82fe7f"); ss.clear();
+ ss << VARINT(0x123456); BOOST_CHECK_EQUAL(HexStr(ss), "c7e756"); ss.clear();
+ ss << VARINT((int32_t)0x123456); BOOST_CHECK_EQUAL(HexStr(ss), "c7e756"); ss.clear();
+ ss << VARINT(0x80123456U); BOOST_CHECK_EQUAL(HexStr(ss), "86ffc7e756"); ss.clear();
+ ss << VARINT((uint32_t)0x80123456U); BOOST_CHECK_EQUAL(HexStr(ss), "86ffc7e756"); ss.clear();
+ ss << VARINT(0xffffffff); BOOST_CHECK_EQUAL(HexStr(ss), "8efefefe7f"); ss.clear();
+ ss << VARINT(0x7fffffffffffffffLL); BOOST_CHECK_EQUAL(HexStr(ss), "fefefefefefefefe7f"); ss.clear();
+ ss << VARINT(0xffffffffffffffffULL); BOOST_CHECK_EQUAL(HexStr(ss), "80fefefefefefefefe7f"); ss.clear();
+}
+
BOOST_AUTO_TEST_CASE(compactsize)
{
CDataStream ss(SER_DISK, 0);
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index 39586d7bb4..9bcb07626a 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -17,10 +17,8 @@
#include "txdb.h"
#include "txmempool.h"
#include "ui_interface.h"
-#ifdef ENABLE_WALLET
-#include "wallet/db.h"
-#include "wallet/wallet.h"
-#endif
+#include "rpc/server.h"
+#include "rpc/register.h"
#include "test/testutil.h"
@@ -28,9 +26,6 @@
#include <boost/test/unit_test.hpp>
#include <boost/thread.hpp>
-CClientUIInterface uiInterface; // Declared but not defined in ui_interface.h
-CWallet* pwalletMain;
-
extern bool fPrintToConsole;
extern void noui_connect();
@@ -53,10 +48,9 @@ BasicTestingSetup::~BasicTestingSetup()
TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(chainName)
{
const CChainParams& chainparams = Params();
-#ifdef ENABLE_WALLET
- bitdb.MakeMock();
- walletRegisterRPCCommands();
-#endif
+ // 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);
ClearDatadirCache();
pathTemp = GetTempPath() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000)));
boost::filesystem::create_directories(pathTemp);
@@ -65,12 +59,6 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha
pcoinsdbview = new CCoinsViewDB(1 << 23, true);
pcoinsTip = new CCoinsViewCache(pcoinsdbview);
InitBlockIndex(chainparams);
-#ifdef ENABLE_WALLET
- bool fFirstRun;
- pwalletMain = new CWallet("wallet.dat");
- pwalletMain->LoadWallet(fFirstRun);
- RegisterValidationInterface(pwalletMain);
-#endif
nScriptCheckThreads = 3;
for (int i=0; i < nScriptCheckThreads-1; i++)
threadGroup.create_thread(&ThreadScriptCheck);
@@ -82,19 +70,10 @@ TestingSetup::~TestingSetup()
UnregisterNodeSignals(GetNodeSignals());
threadGroup.interrupt_all();
threadGroup.join_all();
-#ifdef ENABLE_WALLET
- UnregisterValidationInterface(pwalletMain);
- delete pwalletMain;
- pwalletMain = NULL;
-#endif
UnloadBlockIndex();
delete pcoinsTip;
delete pcoinsdbview;
delete pblocktree;
-#ifdef ENABLE_WALLET
- bitdb.Flush(true);
- bitdb.Reset();
-#endif
boost::filesystem::remove_all(pathTemp);
}
@@ -152,7 +131,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..57f66f6c6d 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>
@@ -24,8 +25,7 @@ struct BasicTestingSetup {
};
/** Testing setup that configures a complete environment.
- * Included are data directory, coins database, script check threads
- * and wallet (if enabled) setup.
+ * Included are data directory, coins database, script check threads setup.
*/
struct TestingSetup: public BasicTestingSetup {
CCoinsViewDB *pcoinsdbview;
@@ -71,7 +71,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/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 43e8ae9b36..b99f952a0d 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -200,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));
@@ -219,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 1c7bc2dbee..47d834c7b4 100644
--- a/src/torcontrol.cpp
+++ b/src/torcontrol.cpp
@@ -438,7 +438,7 @@ void TorController::add_onion_cb(TorControlConnection& conn, const TorControlRep
private_key = i->second;
}
- service = CService(service_id+".onion", GetListenPort(), false);
+ service = CService(service_id+".onion", GetListenPort());
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());
diff --git a/src/txdb.cpp b/src/txdb.cpp
index f99e11f26e..5fbaeb608a 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -49,7 +49,7 @@ uint256 CCoinsViewDB::GetBestBlock() const {
}
bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) {
- CDBBatch batch(&db.GetObfuscateKey());
+ CDBBatch batch(db);
size_t count = 0;
size_t changed = 0;
for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
@@ -94,54 +94,52 @@ bool CBlockTreeDB::ReadLastBlockFile(int &nFile) {
return Read(DB_LAST_BLOCK, nFile);
}
-bool CCoinsViewDB::GetStats(CCoinsStats &stats) const {
+CCoinsViewCursor *CCoinsViewDB::Cursor() const
+{
+ CCoinsViewDBCursor *i = new CCoinsViewDBCursor(const_cast<CDBWrapper*>(&db)->NewIterator(), GetBestBlock());
/* It seems that there are no "const iterators" for LevelDB. Since we
only need read operations on it, use a const-cast to get around
that restriction. */
- boost::scoped_ptr<CDBIterator> pcursor(const_cast<CDBWrapper*>(&db)->NewIterator());
- pcursor->Seek(DB_COINS);
+ i->pcursor->Seek(DB_COINS);
+ // Cache key of first record
+ i->pcursor->GetKey(i->keyTmp);
+ return i;
+}
- CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
- stats.hashBlock = GetBestBlock();
- ss << stats.hashBlock;
- CAmount nTotalAmount = 0;
- while (pcursor->Valid()) {
- boost::this_thread::interruption_point();
- std::pair<char, uint256> key;
- CCoins coins;
- if (pcursor->GetKey(key) && key.first == DB_COINS) {
- if (pcursor->GetValue(coins)) {
- stats.nTransactions++;
- for (unsigned int i=0; i<coins.vout.size(); i++) {
- const CTxOut &out = coins.vout[i];
- if (!out.IsNull()) {
- stats.nTransactionOutputs++;
- ss << VARINT(i+1);
- ss << out;
- nTotalAmount += out.nValue;
- }
- }
- stats.nSerializedSize += 32 + pcursor->GetValueSize();
- ss << VARINT(0);
- } else {
- return error("CCoinsViewDB::GetStats() : unable to read value");
- }
- } else {
- break;
- }
- pcursor->Next();
- }
- {
- LOCK(cs_main);
- stats.nHeight = mapBlockIndex.find(stats.hashBlock)->second->nHeight;
+bool CCoinsViewDBCursor::GetKey(uint256 &key) const
+{
+ // Return cached key
+ if (keyTmp.first == DB_COINS) {
+ key = keyTmp.second;
+ return true;
}
- stats.hashSerialized = ss.GetHash();
- stats.nTotalAmount = nTotalAmount;
- return true;
+ return false;
+}
+
+bool CCoinsViewDBCursor::GetValue(CCoins &coins) const
+{
+ return pcursor->GetValue(coins);
+}
+
+unsigned int CCoinsViewDBCursor::GetValueSize() const
+{
+ return pcursor->GetValueSize();
+}
+
+bool CCoinsViewDBCursor::Valid() const
+{
+ return keyTmp.first == DB_COINS;
+}
+
+void CCoinsViewDBCursor::Next()
+{
+ pcursor->Next();
+ if (!pcursor->Valid() || !pcursor->GetKey(keyTmp))
+ keyTmp.first = 0; // Invalidate cached key after last record so that Valid() and GetKey() return false
}
bool CBlockTreeDB::WriteBatchSync(const std::vector<std::pair<int, const CBlockFileInfo*> >& fileInfo, int nLastFile, const std::vector<const CBlockIndex*>& blockinfo) {
- CDBBatch batch(&GetObfuscateKey());
+ CDBBatch batch(*this);
for (std::vector<std::pair<int, const CBlockFileInfo*> >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) {
batch.Write(make_pair(DB_BLOCK_FILES, it->first), *it->second);
}
@@ -157,7 +155,7 @@ bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) {
}
bool CBlockTreeDB::WriteTxIndex(const std::vector<std::pair<uint256, CDiskTxPos> >&vect) {
- CDBBatch batch(&GetObfuscateKey());
+ CDBBatch batch(*this);
for (std::vector<std::pair<uint256,CDiskTxPos> >::const_iterator it=vect.begin(); it!=vect.end(); it++)
batch.Write(make_pair(DB_TXINDEX, it->first), it->second);
return WriteBatch(batch);
diff --git a/src/txdb.h b/src/txdb.h
index 22e0c5704c..749802f0e5 100644
--- a/src/txdb.h
+++ b/src/txdb.h
@@ -26,6 +26,8 @@ static const int64_t nMaxDbCache = sizeof(void*) > 4 ? 16384 : 1024;
//! min. -dbcache in (MiB)
static const int64_t nMinDbCache = 4;
+class CCoinsViewDBCursor;
+
/** CCoinsView backed by the coin database (chainstate/) */
class CCoinsViewDB : public CCoinsView
{
@@ -38,7 +40,29 @@ public:
bool HaveCoins(const uint256 &txid) const;
uint256 GetBestBlock() const;
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock);
- bool GetStats(CCoinsStats &stats) const;
+ CCoinsViewCursor *Cursor() const;
+};
+
+/** Specialization of CCoinsViewCursor to iterate over a CCoinsViewDB */
+class CCoinsViewDBCursor: public CCoinsViewCursor
+{
+public:
+ ~CCoinsViewDBCursor() {}
+
+ bool GetKey(uint256 &key) const;
+ bool GetValue(CCoins &coins) const;
+ unsigned int GetValueSize() const;
+
+ bool Valid() const;
+ void Next();
+
+private:
+ CCoinsViewDBCursor(CDBIterator* pcursorIn, const uint256 &hashBlockIn):
+ CCoinsViewCursor(hashBlockIn), pcursor(pcursorIn) {}
+ boost::scoped_ptr<CDBIterator> pcursor;
+ std::pair<char, uint256> keyTmp;
+
+ friend class CCoinsViewDB;
};
/** Access to the block database (blocks/index/) */
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index eee6cbf855..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) || !CheckSequenceLocks(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);
}
@@ -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();
}
@@ -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 7a2a1ef432..de4ba0b371 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
@@ -58,33 +74,40 @@ class CTxMemPoolEntry
{
private:
CTransaction tx;
- CAmount nFee; //! Cached to avoid expensive parent-transaction lookups
- size_t nTxSize; //! ... and avoid recomputing tx size
- size_t nModSize; //! ... and modified size for priority
- size_t nUsageSize; //! ... and total memory usage
- int64_t nTime; //! Local time when entering the mempool
- double entryPriority; //! Priority when entering the mempool
- unsigned int entryHeight; //! Chain height when entering the mempool
- bool hadNoDependencies; //! Not dependent on any other txs when it entered the mempool
- CAmount inChainInputValue; //! Sum of all txin values that are already in blockchain
- 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
+ CAmount nFee; //!< Cached to avoid expensive parent-transaction lookups
+ size_t nTxSize; //!< ... and avoid recomputing tx size
+ size_t nModSize; //!< ... and modified size for priority
+ size_t nUsageSize; //!< ... and total memory usage
+ int64_t nTime; //!< Local time when entering the mempool
+ double entryPriority; //!< Priority when entering the mempool
+ unsigned int entryHeight; //!< Chain height when entering the mempool
+ bool hadNoDependencies; //!< Not dependent on any other txs when it entered the mempool
+ CAmount inChainInputValue; //!< Sum of all txin values that are already in blockchain
+ 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
// descendants as well. if nCountWithDescendants is 0, treat this entry as
// dirty, and nSizeWithDescendants and nModFeesWithDescendants will not be
// correct.
- uint64_t nCountWithDescendants; //! number of descendant transactions
- uint64_t nSizeWithDescendants; //! ... and size
- CAmount nModFeesWithDescendants; //! ... and total fees (all including us)
+ uint64_t nCountWithDescendants; //!< number of descendant transactions
+ 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,10 +274,34 @@ 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;
@@ -329,18 +399,18 @@ public:
class CTxMemPool
{
private:
- uint32_t nCheckFrequency; //! Value n means that n times in 2^32 we check.
+ uint32_t nCheckFrequency; //!< Value n means that n times in 2^32 we check.
unsigned int nTransactionsUpdated;
CBlockPolicyEstimator* minerPolicyEstimator;
- uint64_t totalTxSize; //! sum of all mempool tx' byte sizes
- uint64_t cachedInnerUsage; //! sum of dynamic memory usage of all the map elements (NOT the maps themselves)
+ uint64_t totalTxSize; //!< sum of all mempool tx' byte sizes
+ uint64_t cachedInnerUsage; //!< sum of dynamic memory usage of all the map elements (NOT the maps themselves)
CFeeRate minReasonableRelayFee;
mutable int64_t lastRollingFeeUpdate;
mutable bool blockSinceLastRollingFeeBump;
- mutable double rollingMinimumFeeRate; //! minimum fee to get into the pool, decreases exponentially
+ mutable double rollingMinimumFeeRate; //!< minimum fee to get into the pool, decreases exponentially
void trackPackageRemoved(const CFeeRate& rate);
@@ -364,12 +434,18 @@ public:
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;
@@ -428,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,
@@ -453,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
@@ -477,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
@@ -520,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
@@ -555,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.cpp b/src/ui_interface.cpp
new file mode 100644
index 0000000000..c778e40a90
--- /dev/null
+++ b/src/ui_interface.cpp
@@ -0,0 +1,24 @@
+// Copyright (c) 2010-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 "ui_interface.h"
+#include "util.h"
+
+CClientUIInterface uiInterface;
+
+bool InitError(const std::string& str)
+{
+ uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_ERROR);
+ return false;
+}
+
+void InitWarning(const std::string& str)
+{
+ uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_WARNING);
+}
+
+std::string AmountErrMsg(const char* const optname, const std::string& strValue)
+{
+ return strprintf(_("Invalid amount for -%s=<amount>: '%s'"), optname, strValue);
+}
diff --git a/src/ui_interface.h b/src/ui_interface.h
index 967d243270..a27918c507 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;
@@ -101,6 +100,14 @@ public:
boost::signals2::signal<void (void)> BannedListChanged;
};
+/** Show warning message **/
+void InitWarning(const std::string& str);
+
+/** Show error message **/
+bool InitError(const std::string& str);
+
+std::string AmountErrMsg(const char* const optname, const std::string& strValue);
+
extern CClientUIInterface uiInterface;
#endif // BITCOIN_UI_INTERFACE_H
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 59f58f2c55..00b75fbdbe 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -471,9 +471,7 @@ boost::filesystem::path GetDefaultDataDir()
pathRet = fs::path(pszHome);
#ifdef MAC_OSX
// Mac
- pathRet /= "Library/Application Support";
- TryCreateDirectory(pathRet);
- return pathRet / "Bitcoin";
+ return pathRet / "Library/Application Support/Bitcoin";
#else
// Unix
return pathRet / ".bitcoin";
diff --git a/src/utiltime.cpp b/src/utiltime.cpp
index 91b40d9991..da590f8889 100644
--- a/src/utiltime.cpp
+++ b/src/utiltime.cpp
@@ -14,7 +14,7 @@
using namespace std;
-static int64_t nMockTime = 0; //! For unit testing
+static int64_t nMockTime = 0; //!< For unit testing
int64_t GetTime()
{
diff --git a/src/version.h b/src/version.h
index af2eb8eab6..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;
@@ -36,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..78feb8ab0c
--- /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) {
+ // Optimization: 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/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 077b352547..623037e766 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -82,15 +82,11 @@ void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
std::string rbfStatus = "no";
if (confirms <= 0) {
LOCK(mempool.cs);
- if (!mempool.exists(hash)) {
- if (SignalsOptInRBF(wtx)) {
- rbfStatus = "yes";
- } else {
- rbfStatus = "unknown";
- }
- } else if (IsRBFOptIn(*mempool.mapTx.find(hash), mempool)) {
+ RBFTransactionState rbfState = IsRBFOptIn(wtx, mempool);
+ if (rbfState == RBF_TRANSACTIONSTATE_UNKNOWN)
+ rbfStatus = "unknown";
+ else if (rbfState == RBF_TRANSACTIONSTATE_REPLACEABLE_BIP125)
rbfStatus = "yes";
- }
}
entry.push_back(Pair("bip125-replaceable", rbfStatus));
@@ -1346,6 +1342,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,6 +1435,7 @@ 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"
@@ -2098,16 +2096,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"
@@ -2441,19 +2440,26 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
- "fundrawtransaction \"hexstring\" includeWatching\n"
+ "fundrawtransaction \"hexstring\" ( options )\n"
"\nAdd inputs to a transaction until it has enough in value to meet its out value.\n"
"This will not modify existing inputs, and will add one change output to the outputs.\n"
"Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n"
"The inputs added will not be signed, use signrawtransaction for that.\n"
"Note that all existing inputs must have their previous output transaction be in the wallet.\n"
- "Note that all inputs selected must be of standard form and P2SH scripts must be"
+ "Note that all inputs selected must be of standard form and P2SH scripts must be\n"
"in the wallet using importaddress or addmultisigaddress (to calculate fees).\n"
"You can see whether this is the case by checking the \"solvable\" field in the listunspent output.\n"
"Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n"
"\nArguments:\n"
- "1. \"hexstring\" (string, required) The hex string of the raw transaction\n"
- "2. includeWatching (boolean, optional, default false) Also select inputs which are watch only\n"
+ "1. \"hexstring\" (string, required) The hex string of the raw transaction\n"
+ "2. options (object, optional)\n"
+ " {\n"
+ " \"changeAddress\" (string, optional, default pool address) The bitcoin address to receive the change\n"
+ " \"changePosition\" (numeric, optional, default random) The index of the change output\n"
+ " \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n"
+ " \"lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n"
+ " }\n"
+ " for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}\n"
"\nResult:\n"
"{\n"
" \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n"
@@ -2472,7 +2478,44 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
+ HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
);
- RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL));
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR));
+
+ CTxDestination changeAddress = CNoDestination();
+ int changePosition = -1;
+ bool includeWatching = false;
+ bool lockUnspents = false;
+
+ if (params.size() > 1) {
+ if (params[1].type() == UniValue::VBOOL) {
+ // backward compatibility bool only fallback
+ includeWatching = params[1].get_bool();
+ }
+ else {
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VOBJ));
+
+ UniValue options = params[1];
+
+ RPCTypeCheckObj(options, boost::assign::map_list_of("changeAddress", UniValue::VSTR)("changePosition", UniValue::VNUM)("includeWatching", UniValue::VBOOL)("lockUnspents", UniValue::VBOOL), true, true);
+
+ if (options.exists("changeAddress")) {
+ CBitcoinAddress address(options["changeAddress"].get_str());
+
+ if (!address.IsValid())
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "changeAddress must be a valid bitcoin address");
+
+ changeAddress = address.Get();
+ }
+
+ if (options.exists("changePosition"))
+ changePosition = options["changePosition"].get_int();
+
+ if (options.exists("includeWatching"))
+ includeWatching = options["includeWatching"].get_bool();
+
+ if (options.exists("lockUnspents"))
+ lockUnspents = options["lockUnspents"].get_bool();
+ }
+ }
// parse hex string from parameter
CTransaction origTx;
@@ -2482,20 +2525,19 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
if (origTx.vout.size() == 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "TX must have at least one output");
- bool includeWatching = false;
- if (params.size() > 1)
- includeWatching = params[1].get_bool();
+ if (changePosition != -1 && (changePosition < 0 || changePosition > origTx.vout.size()))
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "changePosition out of bounds");
CMutableTransaction tx(origTx);
CAmount nFee;
string strFailReason;
- int nChangePos = -1;
- if(!pwalletMain->FundTransaction(tx, nFee, nChangePos, strFailReason, includeWatching))
+
+ if(!pwalletMain->FundTransaction(tx, nFee, changePosition, strFailReason, includeWatching, lockUnspents, changeAddress))
throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason);
UniValue result(UniValue::VOBJ);
result.push_back(Pair("hex", EncodeHexTx(tx)));
- result.push_back(Pair("changepos", nChangePos));
+ result.push_back(Pair("changepos", changePosition));
result.push_back(Pair("fee", ValueFromAmount(nFee)));
return result;
@@ -2507,8 +2549,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 },
@@ -2533,6 +2577,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 },
@@ -2554,16 +2599,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/test/accounting_tests.cpp b/src/wallet/test/accounting_tests.cpp
index dad191c684..d075b2b641 100644
--- a/src/test/accounting_tests.cpp
+++ b/src/wallet/test/accounting_tests.cpp
@@ -5,7 +5,7 @@
#include "wallet/wallet.h"
#include "wallet/walletdb.h"
-#include "test/test_bitcoin.h"
+#include "wallet/test/wallet_test_fixture.h"
#include <stdint.h>
@@ -14,7 +14,7 @@
extern CWallet* pwalletMain;
-BOOST_FIXTURE_TEST_SUITE(accounting_tests, TestingSetup)
+BOOST_FIXTURE_TEST_SUITE(accounting_tests, WalletTestingSetup)
static void
GetResults(CWalletDB& walletdb, std::map<CAmount, CAccountingEntry>& results)
diff --git a/src/test/rpc_wallet_tests.cpp b/src/wallet/test/rpc_wallet_tests.cpp
index 3443be2093..4e7d177f51 100644
--- a/src/test/rpc_wallet_tests.cpp
+++ b/src/wallet/test/rpc_wallet_tests.cpp
@@ -9,7 +9,7 @@
#include "main.h"
#include "wallet/wallet.h"
-#include "test/test_bitcoin.h"
+#include "wallet/test/wallet_test_fixture.h"
#include <boost/algorithm/string.hpp>
#include <boost/test/unit_test.hpp>
@@ -23,7 +23,7 @@ extern UniValue CallRPC(string args);
extern CWallet* pwalletMain;
-BOOST_FIXTURE_TEST_SUITE(rpc_wallet_tests, TestingSetup)
+BOOST_FIXTURE_TEST_SUITE(rpc_wallet_tests, WalletTestingSetup)
BOOST_AUTO_TEST_CASE(rpc_addmultisig)
{
diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp
new file mode 100644
index 0000000000..9036ee26d8
--- /dev/null
+++ b/src/wallet/test/wallet_test_fixture.cpp
@@ -0,0 +1,28 @@
+#include "wallet/test/wallet_test_fixture.h"
+
+#include "rpc/server.h"
+#include "wallet/db.h"
+#include "wallet/wallet.h"
+
+WalletTestingSetup::WalletTestingSetup(const std::string& chainName):
+ TestingSetup(chainName)
+{
+ bitdb.MakeMock();
+
+ bool fFirstRun;
+ pwalletMain = new CWallet("wallet_test.dat");
+ pwalletMain->LoadWallet(fFirstRun);
+ RegisterValidationInterface(pwalletMain);
+
+ RegisterWalletRPCCommands(tableRPC);
+}
+
+WalletTestingSetup::~WalletTestingSetup()
+{
+ UnregisterValidationInterface(pwalletMain);
+ delete pwalletMain;
+ pwalletMain = NULL;
+
+ bitdb.Flush(true);
+ bitdb.Reset();
+}
diff --git a/src/wallet/test/wallet_test_fixture.h b/src/wallet/test/wallet_test_fixture.h
new file mode 100644
index 0000000000..97a6d98397
--- /dev/null
+++ b/src/wallet/test/wallet_test_fixture.h
@@ -0,0 +1,18 @@
+// 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_WALLET_TEST_FIXTURE_H
+#define BITCOIN_WALLET_TEST_FIXTURE_H
+
+#include "test/test_bitcoin.h"
+
+/** Testing setup and teardown for wallet.
+ */
+struct WalletTestingSetup: public TestingSetup {
+ WalletTestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
+ ~WalletTestingSetup();
+};
+
+#endif
+
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 06c9c903e4..387b223589 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -9,7 +9,7 @@
#include <utility>
#include <vector>
-#include "test/test_bitcoin.h"
+#include "wallet/test/wallet_test_fixture.h"
#include <boost/foreach.hpp>
#include <boost/test/unit_test.hpp>
@@ -25,7 +25,7 @@ using namespace std;
typedef set<pair<const CWalletTx*,unsigned int> > CoinSet;
-BOOST_FIXTURE_TEST_SUITE(wallet_tests, TestingSetup)
+BOOST_FIXTURE_TEST_SUITE(wallet_tests, WalletTestingSetup)
static CWallet wallet;
static vector<COutput> vCoins;
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 5900828247..29d7138547 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -23,6 +23,7 @@
#include "timedata.h"
#include "txmempool.h"
#include "util.h"
+#include "ui_interface.h"
#include "utilmoneystr.h"
#include <assert.h>
@@ -33,6 +34,7 @@
using namespace std;
+CWallet* pwalletMain = NULL;
/** Transaction fee set by the user */
CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE);
unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET;
@@ -364,8 +366,17 @@ void CWallet::Flush(bool shutdown)
bitdb.Flush(shutdown);
}
-bool CWallet::Verify(const string& walletFile, string& warningString, string& errorString)
+bool CWallet::Verify()
{
+ std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT);
+
+ LogPrintf("Using wallet %s\n", walletFile);
+ uiInterface.InitMessage(_("Verifying wallet..."));
+
+ // Wallet file must be a plain filename without a directory
+ if (walletFile != boost::filesystem::basename(walletFile) + boost::filesystem::extension(walletFile))
+ return InitError(strprintf(_("Wallet %s resides outside data directory %s"), walletFile, GetDataDir().string()));
+
if (!bitdb.Open(GetDataDir()))
{
// try moving the database env out of the way
@@ -381,9 +392,7 @@ bool CWallet::Verify(const string& walletFile, string& warningString, string& er
// try again
if (!bitdb.Open(GetDataDir())) {
// if it still fails, it probably means we can't even create the database env
- string msg = strprintf(_("Error initializing wallet database environment %s!"), GetDataDir());
- errorString += msg;
- return true;
+ return InitError(strprintf(_("Error initializing wallet database environment %s!"), GetDataDir()));
}
}
@@ -399,14 +408,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 file corrupt, data salvaged!"
+ InitWarning(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());
+ walletFile, "wallet.{timestamp}.bak", GetDataDir()));
}
if (r == CDBEnv::RECOVER_FAIL)
- errorString += strprintf(_("%s corrupt, salvage failed"), walletFile);
+ return InitError(strprintf(_("%s corrupt, salvage failed"), walletFile));
}
return true;
@@ -1268,7 +1277,9 @@ bool CWalletTx::RelayWalletTransaction()
{
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;
}
}
@@ -1578,7 +1589,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();
}
}
@@ -1623,7 +1634,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();
}
}
@@ -1668,11 +1679,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),
@@ -1840,10 +1856,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)
@@ -1903,7 +1918,7 @@ bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*
return res;
}
-bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nChangePosRet, std::string& strFailReason, bool includeWatching)
+bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const CTxDestination& destChange)
{
vector<CRecipient> vecSend;
@@ -1915,6 +1930,7 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nC
}
CCoinControl coinControl;
+ coinControl.destChange = destChange;
coinControl.fAllowOtherInputs = true;
coinControl.fAllowWatchOnly = includeWatching;
BOOST_FOREACH(const CTxIn& txin, tx.vin)
@@ -1922,35 +1938,35 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nC
CReserveKey reservekey(this);
CWalletTx wtx;
- if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosRet, strFailReason, &coinControl, false))
+ if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosInOut, strFailReason, &coinControl, false))
return false;
- if (nChangePosRet != -1)
- tx.vout.insert(tx.vout.begin() + nChangePosRet, wtx.vout[nChangePosRet]);
+ if (nChangePosInOut != -1)
+ tx.vout.insert(tx.vout.begin() + nChangePosInOut, wtx.vout[nChangePosInOut]);
// 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 (!coinControl.IsSelected(txin.prevout))
{
- if (txin.prevout.hash == origTxIn.prevout.hash && txin.prevout.n == origTxIn.prevout.n)
+ tx.vin.push_back(txin);
+
+ if (lockUnspents)
{
- found = true;
- break;
+ LOCK2(cs_main, cs_wallet);
+ LockCoin(txin.prevout);
}
}
- if (!found)
- tx.vin.push_back(txin);
}
return true;
}
bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet,
- int& nChangePosRet, std::string& strFailReason, const CCoinControl* coinControl, bool sign)
+ int& nChangePosInOut, std::string& strFailReason, const CCoinControl* coinControl, bool sign)
{
CAmount nValue = 0;
+ int nChangePosRequest = nChangePosInOut;
unsigned int nSubtractFeeFromAmount = 0;
BOOST_FOREACH (const CRecipient& recipient, vecSend)
{
@@ -2009,14 +2025,17 @@ 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)
{
+ nChangePosInOut = nChangePosRequest;
txNew.vin.clear();
txNew.vout.clear();
wtxNew.fFromMe = true;
- nChangePosRet = -1;
bool fFirst = true;
CAmount nValueToSelect = nValue;
@@ -2058,7 +2077,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;
@@ -2136,14 +2155,24 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
// add the dust to the fee.
if (newTxOut.IsDust(::minRelayTxFee))
{
+ nChangePosInOut = -1;
nFeeRet += nChange;
reservekey.ReturnKey();
}
else
{
- // Insert change txn at random position:
- nChangePosRet = GetRandInt(txNew.vout.size()+1);
- vector<CTxOut>::iterator position = txNew.vout.begin()+nChangePosRet;
+ if (nChangePosInOut == -1)
+ {
+ // Insert change txn at random position:
+ nChangePosInOut = GetRandInt(txNew.vout.size()+1);
+ }
+ else if (nChangePosInOut > txNew.vout.size())
+ {
+ strFailReason = _("Change index out of range");
+ return false;
+ }
+
+ vector<CTxOut>::iterator position = txNew.vout.begin()+nChangePosInOut;
txNew.vout.insert(position, newTxOut);
}
}
@@ -2354,6 +2383,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)
{
@@ -2563,12 +2617,19 @@ bool CWallet::GetKeyFromPool(CPubKey& result)
int64_t CWallet::GetOldestKeyPoolTime()
{
- int64_t nIndex = 0;
- CKeyPool keypool;
- ReserveKeyFromKeyPool(nIndex, keypool);
- if (nIndex == -1)
+ LOCK(cs_wallet);
+
+ // if the keypool is empty, return <NOW>
+ if (setKeyPool.empty())
return GetTime();
- ReturnKey(nIndex);
+
+ // load oldest key from keypool, get time and return
+ CKeyPool keypool;
+ CWalletDB walletdb(strWalletFile);
+ int64_t nIndex = *(setKeyPool.begin());
+ if (!walletdb.ReadPool(nIndex, keypool))
+ throw runtime_error("GetOldestKeyPoolTime(): read oldest key in keypool failed");
+ assert(keypool.vchPubKey.IsValid());
return keypool.nTime;
}
@@ -2794,13 +2855,13 @@ void CWallet::GetScriptForMining(boost::shared_ptr<CReserveScript> &script)
script->reserveScript = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
}
-void CWallet::LockCoin(COutPoint& output)
+void CWallet::LockCoin(const COutPoint& output)
{
AssertLockHeld(cs_wallet); // setLockedCoins
setLockedCoins.insert(output);
}
-void CWallet::UnlockCoin(COutPoint& output)
+void CWallet::UnlockCoin(const COutPoint& output)
{
AssertLockHeld(cs_wallet); // setLockedCoins
setLockedCoins.erase(output);
@@ -2971,7 +3032,8 @@ std::string CWallet::GetWalletHelpString(bool showDebug)
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"));
- strUsage += HelpMessageOpt("-sendfreetransactions", strprintf(_("Send transactions as zero-fee transactions if possible (default: %u)"), DEFAULT_SEND_FREE_TRANSACTIONS));
+ 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"));
@@ -2993,20 +3055,20 @@ std::string CWallet::GetWalletHelpString(bool showDebug)
return strUsage;
}
-CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWalletFile, std::string& warningString, std::string& errorString)
+bool CWallet::InitLoadWallet()
{
+ std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT);
+
// 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);
+ CWallet *tempWallet = new CWallet(walletFile);
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;
+ return InitError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
}
delete tempWallet;
@@ -3017,32 +3079,27 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall
int64_t nStart = GetTimeMillis();
bool fFirstRun = true;
- CWallet *walletInstance = new CWallet(strWalletFile);
+ CWallet *walletInstance = new CWallet(walletFile);
DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
if (nLoadWalletRet != DB_LOAD_OK)
{
if (nLoadWalletRet == DB_CORRUPT)
- errorString += strprintf(_("Error loading %s: Wallet corrupted"), strWalletFile) + "\n";
+ return InitError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
else if (nLoadWalletRet == DB_NONCRITICAL_ERROR)
{
- warningString += strprintf(_("Error reading %s! All keys read correctly, but transaction data"
+ InitWarning(strprintf(_("Error reading %s! All keys read correctly, but transaction data"
" or address book entries might be missing or incorrect."),
- strWalletFile);
+ walletFile));
}
else if (nLoadWalletRet == DB_TOO_NEW)
- errorString += strprintf(_("Error loading %s: Wallet requires newer version of %s"),
- strWalletFile, _(PACKAGE_NAME)) +
- "\n";
+ return InitError(strprintf(_("Error loading %s: Wallet requires newer version of %s"),
+ walletFile, _(PACKAGE_NAME)));
else if (nLoadWalletRet == DB_NEED_REWRITE)
{
- errorString += strprintf(_("Wallet needed to be rewritten: restart %s to complete"), _(PACKAGE_NAME)) + "\n";
- LogPrintf("%s", errorString);
+ return InitError(strprintf(_("Wallet needed to be rewritten: restart %s to complete"), _(PACKAGE_NAME)));
}
else
- errorString += strprintf(_("Error loading %s"), strWalletFile) + "\n";
-
- if (!errorString.empty())
- return NULL;
+ return InitError(strprintf(_("Error loading %s"), walletFile));
}
if (GetBoolArg("-upgradewallet", fFirstRun))
@@ -3058,8 +3115,7 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall
LogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
if (nMaxVersion < walletInstance->GetVersion())
{
- errorString += _("Cannot downgrade wallet") + "\n";
- return NULL;
+ return InitError(_("Cannot downgrade wallet"));
}
walletInstance->SetMaxVersion(nMaxVersion);
}
@@ -3073,10 +3129,7 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall
if (walletInstance->GetKeyFromPool(newDefaultKey)) {
walletInstance->SetDefaultKey(newDefaultKey);
if (!walletInstance->SetAddressBook(walletInstance->vchDefaultKey.GetID(), "", "receive"))
- {
- errorString += _("Cannot write default address") += "\n";
- return NULL;
- }
+ return InitError(_("Cannot write default address") += "\n");
}
walletInstance->SetBestChain(chainActive.GetLocator());
@@ -3091,7 +3144,7 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall
pindexRescan = chainActive.Genesis();
else
{
- CWalletDB walletdb(strWalletFile);
+ CWalletDB walletdb(walletFile);
CBlockLocator locator;
if (walletdb.ReadBestBlock(locator))
pindexRescan = FindForkInGlobalIndex(chainActive, locator);
@@ -3110,10 +3163,7 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall
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;
- }
+ 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..."));
@@ -3127,7 +3177,7 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall
// Restore wallet transaction metadata after -zapwallettxes=1
if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2")
{
- CWalletDB walletdb(strWalletFile);
+ CWalletDB walletdb(walletFile);
BOOST_FOREACH(const CWalletTx& wtxOld, vWtx)
{
@@ -3151,7 +3201,62 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall
}
walletInstance->SetBroadcastTransactions(GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
- return walletInstance;
+ pwalletMain = walletInstance;
+ return true;
+}
+
+bool CWallet::ParameterInteraction()
+{
+ if (mapArgs.count("-mintxfee"))
+ {
+ CAmount n = 0;
+ if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0)
+ CWallet::minTxFee = CFeeRate(n);
+ else
+ return InitError(AmountErrMsg("mintxfee", mapArgs["-mintxfee"]));
+ }
+ if (mapArgs.count("-fallbackfee"))
+ {
+ CAmount nFeePerK = 0;
+ if (!ParseMoney(mapArgs["-fallbackfee"], nFeePerK))
+ return InitError(strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'"), mapArgs["-fallbackfee"]));
+ if (nFeePerK > HIGH_TX_FEE_PER_KB)
+ InitWarning(_("-fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available."));
+ CWallet::fallbackFee = CFeeRate(nFeePerK);
+ }
+ if (mapArgs.count("-paytxfee"))
+ {
+ CAmount nFeePerK = 0;
+ if (!ParseMoney(mapArgs["-paytxfee"], nFeePerK))
+ return InitError(AmountErrMsg("paytxfee", mapArgs["-paytxfee"]));
+ if (nFeePerK > HIGH_TX_FEE_PER_KB)
+ InitWarning(_("-paytxfee is set very high! This is the transaction fee you will pay if you send a transaction."));
+ payTxFee = CFeeRate(nFeePerK, 1000);
+ if (payTxFee < ::minRelayTxFee)
+ {
+ return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
+ mapArgs["-paytxfee"], ::minRelayTxFee.ToString()));
+ }
+ }
+ if (mapArgs.count("-maxtxfee"))
+ {
+ CAmount nMaxFee = 0;
+ if (!ParseMoney(mapArgs["-maxtxfee"], nMaxFee))
+ return InitError(AmountErrMsg("maxtxfee", mapArgs["-maxtxfee"]));
+ if (nMaxFee > HIGH_MAX_TX_FEE)
+ InitWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
+ maxTxFee = nMaxFee;
+ if (CFeeRate(maxTxFee, 1000) < ::minRelayTxFee)
+ {
+ return InitError(strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
+ mapArgs["-maxtxfee"], ::minRelayTxFee.ToString()));
+ }
+ }
+ nTxConfirmTarget = GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET);
+ bSpendZeroConfChange = GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
+ fSendFreeTransactions = GetBoolArg("-sendfreetransactions", DEFAULT_SEND_FREE_TRANSACTIONS);
+
+ return true;
}
CKeyPool::CKeyPool()
@@ -3231,5 +3336,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 37a84153b4..c3bd343edd 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -12,8 +12,8 @@
#include "ui_interface.h"
#include "utilstrencodings.h"
#include "validationinterface.h"
+#include "script/ismine.h"
#include "wallet/crypter.h"
-#include "wallet/wallet_ismine.h"
#include "wallet/walletdb.h"
#include "wallet/rpcwallet.h"
@@ -28,6 +28,8 @@
#include <boost/shared_ptr.hpp>
+extern CWallet* pwalletMain;
+
/**
* Settings
*/
@@ -226,11 +228,11 @@ public:
mapValue_t mapValue;
std::vector<std::pair<std::string, std::string> > vOrderForm;
unsigned int fTimeReceivedIsTxTime;
- unsigned int nTimeReceived; //! time received by this node
+ unsigned int nTimeReceived; //!< time received by this node
unsigned int nTimeSmart;
char fFromMe;
std::string strFromAccount;
- int64_t nOrderPos; //! position in ordered transaction list
+ int64_t nOrderPos; //!< position in ordered transaction list
// memory only
mutable bool fDebitCached;
@@ -322,7 +324,7 @@ public:
}
READWRITE(*(CMerkleTx*)this);
- std::vector<CMerkleTx> vUnused; //! Used to be vtxPrev
+ std::vector<CMerkleTx> vUnused; //!< Used to be vtxPrev
READWRITE(vUnused);
READWRITE(mapValue);
READWRITE(vOrderForm);
@@ -464,7 +466,7 @@ public:
std::string strOtherAccount;
std::string strComment;
mapValue_t mapValue;
- int64_t nOrderPos; //! position in ordered transaction list
+ int64_t nOrderPos; //!< position in ordered transaction list
uint64_t nEntryNo;
CAccountingEntry()
@@ -545,7 +547,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;
@@ -666,8 +668,8 @@ public:
bool IsSpent(const uint256& hash, unsigned int n) const;
bool IsLockedCoin(uint256 hash, unsigned int n) const;
- void LockCoin(COutPoint& output);
- void UnlockCoin(COutPoint& output);
+ void LockCoin(const COutPoint& output);
+ void UnlockCoin(const COutPoint& output);
void UnlockAllCoins();
void ListLockedCoins(std::vector<COutPoint>& vOutpts);
@@ -738,13 +740,14 @@ public:
* Insert additional inputs into the transaction by
* calling CreateTransaction();
*/
- bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosRet, std::string& strFailReason, bool includeWatching);
+ bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const CTxDestination& destChange = CNoDestination());
/**
* Create a new transaction paying the recipients with a set of coins
* selected by SelectCoins(); Also create the change output, when needed
+ * @note passing nChangePosInOut as -1 will result in setting a random position
*/
- bool CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosRet,
+ bool CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut,
std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true);
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
@@ -793,6 +796,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);
@@ -841,7 +845,7 @@ public:
void Flush(bool shutdown=false);
//! Verify the wallet database and perform salvage if required
- static bool Verify(const std::string& walletFile, std::string& warningString, std::string& errorString);
+ static bool Verify();
/**
* Address book entry changed.
@@ -876,8 +880,11 @@ public:
/* 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);
+ /* Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */
+ static bool InitLoadWallet();
+
+ /* Wallets parameter interaction */
+ static bool ParameterInteraction();
};
/** A key allocated from the key pool. */
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index 0a4a1dae2f..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
diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h
index 7e8cc4084e..fe6c366343 100644
--- a/src/wallet/walletdb.h
+++ b/src/wallet/walletdb.h
@@ -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..b6c907980f 100644
--- a/src/zmq/zmqpublishnotifier.cpp
+++ b/src/zmq/zmqpublishnotifier.cpp
@@ -9,6 +9,11 @@
static std::multimap<std::string, CZMQAbstractPublishNotifier*> mapPublishNotifiers;
+static const char *MSG_HASHBLOCK = "hashblock";
+static const char *MSG_HASHTX = "hashtx";
+static const char *MSG_RAWBLOCK = "rawblock";
+static const char *MSG_RAWTX = "rawtx";
+
// Internal function to send multipart message
static int zmq_send_multipart(void *sock, const void* data, size_t size, ...)
{
@@ -69,6 +74,7 @@ bool CZMQAbstractPublishNotifier::Initialize(void *pcontext)
if (rc!=0)
{
zmqError("Failed to bind address");
+ zmq_close(psocket);
return false;
}
@@ -117,6 +123,23 @@ void CZMQAbstractPublishNotifier::Shutdown()
psocket = 0;
}
+bool CZMQAbstractPublishNotifier::SendMessage(const char *command, const void* data, size_t size)
+{
+ assert(psocket);
+
+ /* send three parts, command & data & a LE 4byte sequence number */
+ unsigned char msgseq[sizeof(uint32_t)];
+ WriteLE32(&msgseq[0], nSequence);
+ int rc = zmq_send_multipart(psocket, command, strlen(command), data, size, msgseq, (size_t)sizeof(uint32_t), (void*)0);
+ if (rc == -1)
+ return false;
+
+ /* increment memory only sequence number after sending */
+ nSequence++;
+
+ return true;
+}
+
bool CZMQPublishHashBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
{
uint256 hash = pindex->GetBlockHash();
@@ -124,8 +147,7 @@ bool CZMQPublishHashBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
char data[32];
for (unsigned int i = 0; i < 32; i++)
data[31 - i] = hash.begin()[i];
- int rc = zmq_send_multipart(psocket, "hashblock", 9, data, 32, 0);
- return rc == 0;
+ return SendMessage(MSG_HASHBLOCK, data, 32);
}
bool CZMQPublishHashTransactionNotifier::NotifyTransaction(const CTransaction &transaction)
@@ -135,8 +157,7 @@ bool CZMQPublishHashTransactionNotifier::NotifyTransaction(const CTransaction &t
char data[32];
for (unsigned int i = 0; i < 32; i++)
data[31 - i] = hash.begin()[i];
- int rc = zmq_send_multipart(psocket, "hashtx", 6, data, 32, 0);
- return rc == 0;
+ return SendMessage(MSG_HASHTX, data, 32);
}
bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
@@ -157,8 +178,7 @@ bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
ss << block;
}
- int rc = zmq_send_multipart(psocket, "rawblock", 8, &(*ss.begin()), ss.size(), 0);
- return rc == 0;
+ return SendMessage(MSG_RAWBLOCK, &(*ss.begin()), ss.size());
}
bool CZMQPublishRawTransactionNotifier::NotifyTransaction(const CTransaction &transaction)
@@ -167,6 +187,5 @@ bool CZMQPublishRawTransactionNotifier::NotifyTransaction(const CTransaction &tr
LogPrint("zmq", "zmq: Publish rawtx %s\n", hash.GetHex());
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << transaction;
- int rc = zmq_send_multipart(psocket, "rawtx", 5, &(*ss.begin()), ss.size(), 0);
- return rc == 0;
+ return SendMessage(MSG_RAWTX, &(*ss.begin()), ss.size());
}
diff --git a/src/zmq/zmqpublishnotifier.h b/src/zmq/zmqpublishnotifier.h
index 44d5cbea67..22f02a3d0d 100644
--- a/src/zmq/zmqpublishnotifier.h
+++ b/src/zmq/zmqpublishnotifier.h
@@ -11,7 +11,19 @@ class CBlockIndex;
class CZMQAbstractPublishNotifier : public CZMQAbstractNotifier
{
+private:
+ uint32_t nSequence; //! upcounting per message sequence number
+
public:
+
+ /* send zmq multipart message
+ parts:
+ * command
+ * data
+ * message sequence number
+ */
+ bool SendMessage(const char *command, const void* data, size_t size);
+
bool Initialize(void *pcontext);
void Shutdown();
};