diff options
-rw-r--r-- | .travis.yml | 2 | ||||
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | README.md | 4 | ||||
-rw-r--r-- | configure.ac | 47 | ||||
-rw-r--r-- | doc/build-openbsd.md | 30 | ||||
-rw-r--r-- | doc/release-notes.md | 10 | ||||
-rw-r--r-- | doc/zmq.md | 12 | ||||
-rwxr-xr-x | qa/pull-tester/rpc-tests.py | 117 | ||||
-rwxr-xr-x | qa/pull-tester/rpc-tests.sh | 89 | ||||
-rw-r--r--[-rwxr-xr-x] | qa/pull-tester/run-bitcoind-for-test.sh.in | 0 | ||||
-rw-r--r--[-rwxr-xr-x] | qa/pull-tester/tests_config.py.in (renamed from qa/pull-tester/tests-config.sh.in) | 4 | ||||
-rw-r--r-- | qa/rpc-tests/README.md | 10 | ||||
-rw-r--r-- | src/policy/policy.cpp | 4 | ||||
-rw-r--r-- | src/script/script.cpp | 10 | ||||
-rw-r--r-- | src/script/script.h | 2 | ||||
-rw-r--r-- | src/script/standard.cpp | 23 | ||||
-rw-r--r-- | src/script/standard.h | 2 | ||||
-rw-r--r-- | src/test/transaction_tests.cpp | 21 | ||||
-rw-r--r-- | src/util.cpp | 7 |
19 files changed, 215 insertions, 181 deletions
diff --git a/.travis.yml b/.travis.yml index 3e7077ab26..8e9684826f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -69,6 +69,6 @@ script: - make $MAKEJOBS $GOAL || ( echo "Build failure. Verbose build follows." && make $GOAL V=1 ; false ) - export LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/depends/$HOST/lib - if [ "$RUN_TESTS" = "true" ]; then make check; fi - - if [ "$RUN_TESTS" = "true" ]; then qa/pull-tester/rpc-tests.sh; fi + - if [ "$RUN_TESTS" = "true" ]; then qa/pull-tester/rpc-tests.py; fi after_script: - if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then (echo "Upload goes here. Something like: scp -r $BASE_OUTDIR server" || echo "upload failed"); fi diff --git a/Makefile.am b/Makefile.am index dfde0d43ec..8a7140398f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -204,7 +204,7 @@ endif dist_noinst_SCRIPTS = autogen.sh -EXTRA_DIST = $(top_srcdir)/share/genbuild.sh qa/pull-tester/rpc-tests.sh qa/rpc-tests $(DIST_DOCS) $(WINDOWS_PACKAGING) $(OSX_PACKAGING) +EXTRA_DIST = $(top_srcdir)/share/genbuild.sh qa/pull-tester/rpc-tests.py qa/pull-tester/tests_config.py qa/rpc-tests $(DIST_DOCS) $(WINDOWS_PACKAGING) $(OSX_PACKAGING) CLEANFILES = $(OSX_DMG) $(BITCOIN_WIN_INSTALLER) @@ -28,7 +28,7 @@ Development Process The `master` branch is regularly built and tested, but is not guaranteed to be completely stable. [Tags](https://github.com/bitcoin/bitcoin/tags) are created -regularly to indicate new official, stable release versions of Bitcoin. +regularly to indicate new official, stable release versions of Bitcoin Core. The contribution workflow is described in [CONTRIBUTING.md](CONTRIBUTING.md). @@ -53,7 +53,7 @@ submit new unit tests for old code. Unit tests can be compiled and run (assuming There are also regression and integration tests of the RPC interface, written in Python, that are run automatically on the build server. -These tests can be run with: `qa/pull-tester/rpc-tests.sh` +These tests can be run with: `qa/pull-tester/rpc-tests.py` Every pull request is built for both Windows and Linux on a dedicated server, and unit and sanity tests are automatically run. The binaries produced may be diff --git a/configure.ac b/configure.ac index 18215a900d..c28c4d11e3 100644 --- a/configure.ac +++ b/configure.ac @@ -69,8 +69,8 @@ PKG_PROG_PKG_CONFIG # Enable wallet AC_ARG_ENABLE([wallet], - [AS_HELP_STRING([--enable-wallet], - [enable wallet (default is yes)])], + [AS_HELP_STRING([--disable-wallet], + [disable wallet (enabled by default)])], [enable_wallet=$enableval], [enable_wallet=yes]) @@ -87,7 +87,7 @@ AC_ARG_ENABLE([upnp-default], [use_upnp_default=no]) AC_ARG_ENABLE(tests, - AS_HELP_STRING([--enable-tests],[compile tests (default is yes)]), + AS_HELP_STRING([--disable-tests],[do not compile tests (default is to compile)]), [use_tests=$enableval], [use_tests=yes]) @@ -108,8 +108,8 @@ AC_ARG_WITH([qrencode], [use_qr=auto]) AC_ARG_ENABLE([hardening], - [AS_HELP_STRING([--enable-hardening], - [attempt to harden the resulting executables (default is yes)])], + [AS_HELP_STRING([--disable-hardening], + [do not attempt to harden the resulting executables (default is to harden)])], [use_hardening=$enableval], [use_hardening=yes]) @@ -120,8 +120,8 @@ AC_ARG_ENABLE([reduce-exports], [use_reduce_exports=no]) AC_ARG_ENABLE([ccache], - [AS_HELP_STRING([--enable-ccache], - [use ccache for building (default is yes if ccache is found)])], + [AS_HELP_STRING([--disable-ccache], + [do not use ccache for building (default is to use if found)])], [use_ccache=$enableval], [use_ccache=auto]) @@ -167,7 +167,7 @@ fi ## compatibility with the legacy buildsystem. ## if test "x$CXXFLAGS_overridden" = "xno"; then - CXXFLAGS="$CXXFLAGS -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter" + CXXFLAGS="$CXXFLAGS -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter -Wno-self-assign" fi CPPFLAGS="$CPPFLAGS -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS" @@ -724,27 +724,12 @@ else fi fi -CFLAGS_TEMP="$CFLAGS" +CXXFLAGS_TEMP="$CXXFLAGS" LIBS_TEMP="$LIBS" -CFLAGS="$CFLAGS $SSL_CFLAGS $CRYPTO_CFLAGS" +CXXFLAGS="$CXXFLAGS $SSL_CFLAGS $CRYPTO_CFLAGS" LIBS="$LIBS $SSL_LIBS $CRYPTO_LIBS" AC_CHECK_HEADER([openssl/ec.h],, AC_MSG_ERROR(OpenSSL ec header missing),) - -AC_MSG_CHECKING(for a supported OpenSSL version) -AC_LINK_IFELSE([AC_LANG_PROGRAM([[ - #include <openssl/rand.h> - ]], - [[RAND_egd(NULL);]])], - [AC_MSG_RESULT(yes)], - [ - AC_ARG_WITH([libressl], - [AS_HELP_STRING([--with-libressl],[Build with system LibreSSL (default is no; DANGEROUS; NOT SUPPORTED)])], - [AC_MSG_WARN([Detected LibreSSL: This is NOT supported, and may break consensus compatibility!])], - [AC_MSG_ERROR([Detected LibreSSL: This is NOT supported, and may break consensus compatibility!])] - )] -) - -CFLAGS="$CFLAGS_TEMP" +CXXFLAGS="$CXXFLAGS_TEMP" LIBS="$LIBS_TEMP" BITCOIN_QT_PATH_PROGS([PROTOC], [protoc],$protoc_bin_path) @@ -924,7 +909,7 @@ AC_SUBST(MINIUPNPC_CPPFLAGS) AC_SUBST(MINIUPNPC_LIBS) AC_CONFIG_FILES([Makefile src/Makefile share/setup.nsi share/qt/Info.plist src/test/buildenv.py]) AC_CONFIG_FILES([qa/pull-tester/run-bitcoind-for-test.sh],[chmod +x qa/pull-tester/run-bitcoind-for-test.sh]) -AC_CONFIG_FILES([qa/pull-tester/tests-config.sh],[chmod +x qa/pull-tester/tests-config.sh]) +AC_CONFIG_FILES([qa/pull-tester/tests_config.py],[chmod +x qa/pull-tester/tests_config.py]) dnl boost's m4 checks do something really nasty: they export these vars. As a dnl result, they leak into secp256k1's configure and crazy things happen. @@ -964,3 +949,11 @@ case $host in chmod 755 libtool ;; esac + +dnl Replace the BUILDDIR path with the correct Windows path if compiling on Native Windows +case ${OS} in + *Windows*) + sed 's/BUILDDIR="\/\([[a-z]]\)/BUILDDIR="\1:/' qa/pull-tester/tests_config.py > qa/pull-tester/tests_config-2.py + mv qa/pull-tester/tests_config-2.py qa/pull-tester/tests_config.py + ;; +esac diff --git a/doc/build-openbsd.md b/doc/build-openbsd.md index 28fa784515..a26b52465e 100644 --- a/doc/build-openbsd.md +++ b/doc/build-openbsd.md @@ -70,24 +70,6 @@ config_opts="runtime-link=shared threadapi=pthread threading=multi link=static v ./b2 -d0 -j4 ${config_opts} --prefix=${BOOST_PREFIX} install ``` -### OpenSSL - -OpenBSD uses a replacement of OpenSSL: LibreSSL. This can cause compatibility issues, hence `./configure` will bark if you try to compile with this library: - - Detected LibreSSL: This is NOT supported, and may break consensus compatibility! - -To install a 'real' OpenSSL use: - - pkg_add openssl - -Any program linked against this library can only be used after setting the dynamic library path: - - export LD_LIBRARY_PATH="/usr/local/lib/eopenssl" - -(otherwise there will be an error about not being able to find `libcrypto.so.1.0`) - -Alternatively, pass `--with-libressl` to `./configure`, however as the warning says, this is NOT supported, and may cause problems syncing the chain, or the node to fork off the network in unexpected circumstances. - ### Building BerkeleyDB BerkeleyDB is only necessary for the wallet functionality. To skip this, pass `--disable-wallet` to `./configure`. @@ -124,28 +106,24 @@ export AUTOCONF_VERSION=2.69 # replace this with the autoconf version that you i export AUTOMAKE_VERSION=1.15 # replace this with the automake version that you installed ./autogen.sh ``` +Make sure `BDB_PREFIX` and `BOOST_PREFIX` are set to the appropriate paths from the above steps. To configure with wallet: ```bash ./configure --with-gui=no --with-boost=$BOOST_PREFIX \ CC=egcc CXX=eg++ CPP=ecpp \ - SSL_CFLAGS="-I/usr/local/include/eopenssl" SSL_LIBS="-L/usr/local/lib/eopenssl -lssl" \ - CRYPTO_CFLAGS="-I/usr/local/include/eopenssl" CRYPTO_LIBS="-L/usr/local/lib/eopenssl -lcrypto" \ LDFLAGS="-L${BDB_PREFIX}/lib/" CPPFLAGS="-I${BDB_PREFIX}/include/" ``` To configure without wallet: ```bash ./configure --disable-wallet --with-gui=no --with-boost=$BOOST_PREFIX \ - CC=egcc CXX=eg++ CPP=ecpp \ - SSL_CFLAGS="-I/usr/local/include/eopenssl" SSL_LIBS="-L/usr/local/lib/eopenssl -lssl" \ - CRYPTO_CFLAGS="-I/usr/local/include/eopenssl" CRYPTO_LIBS="-L/usr/local/lib/eopenssl -lcrypto" + CC=egcc CXX=eg++ CPP=ecpp ``` Build and run the tests: ```bash gmake -export LD_LIBRARY_PATH="/usr/local/lib/eopenssl" gmake check ``` @@ -164,9 +142,7 @@ pkg_add llvm boost ``` ```bash -./configure --disable-wallet --with-gui=no CC=clang CXX=clang++ \ - SSL_CFLAGS="-I/usr/local/include/eopenssl" SSL_LIBS="-L/usr/local/lib/eopenssl -lssl" \ - CRYPTO_CFLAGS="-I/usr/local/include/eopenssl" CRYPTO_LIBS="-L/usr/local/lib/eopenssl -lcrypto" +./configure --disable-wallet --with-gui=no CC=clang CXX=clang++ gmake ``` diff --git a/doc/release-notes.md b/doc/release-notes.md index 70623a3939..78ab3516f6 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -105,6 +105,16 @@ In this version, it is only enforced for peers that send protocol versions removed. It is recommended to update SPV clients to check for the `NODE_BLOOM` service bit for nodes that report versions newer than 70011. +Any sequence of pushdatas in OP_RETURN outputs now allowed +---------------------------------------------------------- + +Previously OP_RETURN outputs with a payload were only relayed and mined if they +had a single pushdata. This restriction has been lifted to allow any +combination of data pushes and numeric constant opcodes (OP_1 to OP_16). The +limit on OP_RETURN output size is now applied to the entire serialized +scriptPubKey, 83 bytes by default. (the previous 80 byte default plus three +bytes overhead) + Merkle branches removed from wallet ----------------------------------- diff --git a/doc/zmq.md b/doc/zmq.md index 358d29d046..484b005cf4 100644 --- a/doc/zmq.md +++ b/doc/zmq.md @@ -43,14 +43,14 @@ operation. ## Enabling -By default, the ZeroMQ port functionality is enabled. Two steps are -required to enable--compiling in the ZeroMQ code, and configuring -runtime operation on the command-line or configuration file. +By default, the ZeroMQ feature is automatically compiled in if the +necessary prerequisites are found. To disable, use --disable-zmq +during the *configure* step of building bitcoind: - $ ./configure --enable-zmq (other options) + $ ./configure --disable-zmq (other options) -This will produce a binary that is capable of providing the ZeroMQ -facility, but will not do so until also configured properly. +To actually enable operation, one must set the appropriate options on +the commandline or in the configuration file. ## Usage diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py new file mode 100755 index 0000000000..58098bdec5 --- /dev/null +++ b/qa/pull-tester/rpc-tests.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python2 +# Copyright (c) 2014 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# Run Regression Test Suite +# + +import os +import sys +import subprocess +import re +from tests_config import * +from sets import Set + +#If imported values are not defined then set to zero (or disabled) +if not vars().has_key('ENABLE_WALLET'): + ENABLE_WALLET=0 +if not vars().has_key('ENABLE_BITCOIND'): + ENABLE_BITCOIND=0 +if not vars().has_key('ENABLE_UTILS'): + ENABLE_UTILS=0 +if not vars().has_key('ENABLE_ZMQ'): + ENABLE_ZMQ=0 + +#Create a set to store arguments and create the passOn string +opts = Set() +passOn = "" +p = re.compile("^--") +for i in range(1,len(sys.argv)): + if (p.match(sys.argv[i]) or sys.argv[i] == "-h"): + passOn += " " + sys.argv[i] + else: + opts.add(sys.argv[i]) + +#Set env vars +buildDir = BUILDDIR +os.environ["BITCOIND"] = buildDir + '/src/bitcoind' + EXEEXT +os.environ["BITCOINCLI"] = buildDir + '/src/bitcoin-cli' + EXEEXT + +#Disable Windows tests by default +if EXEEXT == ".exe" and "-win" not in opts: + print "Win tests currently disabled. Use -win option to enable" + sys.exit(0) + +#Tests +testScripts = [ + 'wallet.py', + 'listtransactions.py', + 'mempool_resurrect_test.py', + 'txn_doublespend.py --mineblock', + 'txn_clone.py', + 'getchaintips.py', + 'rawtransactions.py', + 'rest.py', + 'mempool_spendcoinbase.py', + 'mempool_coinbase_spends.py', + 'httpbasics.py', + 'zapwallettxes.py', + 'proxy_test.py', + 'merkle_blocks.py', + 'fundrawtransaction.py', + 'signrawtransactions.py', + 'walletbackup.py', + 'nodehandling.py', + 'reindex.py', + 'decodescript.py', + 'p2p-fullblocktest.py', +] +testScriptsExt = [ + 'bipdersig-p2p.py', + 'bipdersig.py', + 'getblocktemplate_longpoll.py', + 'getblocktemplate_proposals.py', + 'txn_doublespend.py', + 'txn_clone.py --mineblock', + 'pruning.py', + 'forknotify.py', + 'invalidateblock.py', + 'keypool.py', + 'receivedby.py', + 'rpcbind_test.py', +# 'script_test.py', + 'smartfees.py', + 'maxblocksinflight.py', + 'invalidblockrequest.py', +# 'forknotify.py', + 'p2p-acceptblock.py', + 'mempool_packages.py', +] + +#Enable ZMQ tests +if ENABLE_ZMQ == 1: + testScripts.append('zmq_test.py') + +if(ENABLE_WALLET == 1 and ENABLE_UTILS == 1 and ENABLE_BITCOIND == 1): + rpcTestDir = buildDir + '/qa/rpc-tests/' + #Run Tests + for i in range(len(testScripts)): + if (len(opts) == 0 or (len(opts) == 1 and "-win" in opts ) or '-extended' in opts + or testScripts[i] in opts or re.sub(".py$", "", testScripts[i]) in opts ): + print "Running testscript " + testScripts[i] + "..." + subprocess.call(rpcTestDir + testScripts[i] + " --srcdir " + buildDir + '/src ' + passOn,shell=True) + #exit if help is called so we print just one set of instructions + p = re.compile(" -h| --help") + if p.match(passOn): + sys.exit(0) + + #Run Extended Tests + for i in range(len(testScriptsExt)): + if ('-extended' in opts or testScriptsExt[i] in opts + or re.sub(".py$", "", testScriptsExt[i]) in opts): + print "Running 2nd level testscript " + testScriptsExt[i] + "..." + subprocess.call(rpcTestDir + testScriptsExt[i] + " --srcdir " + buildDir + '/src ' + passOn,shell=True) +else: + print "No rpc tests to run. Wallet, utils, and bitcoind must all be enabled" diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh deleted file mode 100755 index 7e1d2e8e50..0000000000 --- a/qa/pull-tester/rpc-tests.sh +++ /dev/null @@ -1,89 +0,0 @@ -#!/bin/bash -set -e - -CURDIR=$(cd $(dirname "$0"); pwd) -# Get BUILDDIR and REAL_BITCOIND -. "${CURDIR}/tests-config.sh" - -export BITCOIND=${REAL_BITCOIND} -export BITCOINCLI=${REAL_BITCOINCLI} - -if [ "x${EXEEXT}" = "x.exe" ]; then - echo "Win tests currently disabled" - exit 0 -fi - -#Run the tests - -testScripts=( - 'wallet.py' - 'listtransactions.py' - 'mempool_resurrect_test.py' - 'txn_doublespend.py --mineblock' - 'txn_clone.py' - 'getchaintips.py' - 'rawtransactions.py' - 'rest.py' - 'mempool_spendcoinbase.py' - 'mempool_coinbase_spends.py' - 'httpbasics.py' - 'zapwallettxes.py' - 'proxy_test.py' - 'merkle_blocks.py' - 'fundrawtransaction.py' - 'signrawtransactions.py' - 'walletbackup.py' - 'nodehandling.py' - 'reindex.py' - 'decodescript.py' - 'p2p-fullblocktest.py' -); -testScriptsExt=( - 'bipdersig-p2p.py' - 'bipdersig.py' - 'getblocktemplate_longpoll.py' - 'getblocktemplate_proposals.py' - 'txn_doublespend.py' - 'txn_clone.py --mineblock' - 'pruning.py' - 'forknotify.py' - 'invalidateblock.py' - 'keypool.py' - 'receivedby.py' - 'rpcbind_test.py' -# 'script_test.py' - 'smartfees.py' - 'maxblocksinflight.py' - 'invalidblockrequest.py' -# 'forknotify.py' - 'p2p-acceptblock.py' - 'mempool_packages.py' -); - -if [ "x$ENABLE_ZMQ" = "x1" ]; then - testScripts+=('zmq_test.py') -fi - -extArg="-extended" -passOn=${@#$extArg} - -if [ "x${ENABLE_BITCOIND}${ENABLE_UTILS}${ENABLE_WALLET}" = "x111" ]; then - for (( i = 0; i < ${#testScripts[@]}; i++ )) - do - if [ -z "$1" ] || [ "${1:0:1}" == "-" ] || [ "$1" == "${testScripts[$i]}" ] || [ "$1.py" == "${testScripts[$i]}" ] - then - echo -e "Running testscript \033[1m${testScripts[$i]}...\033[0m" - ${BUILDDIR}/qa/rpc-tests/${testScripts[$i]} --srcdir "${BUILDDIR}/src" ${passOn} - fi - done - for (( i = 0; i < ${#testScriptsExt[@]}; i++ )) - do - if [ "$1" == $extArg ] || [ "$1" == "${testScriptsExt[$i]}" ] || [ "$1.py" == "${testScriptsExt[$i]}" ] - then - echo -e "Running \033[1m2nd level\033[0m testscript \033[1m${testScriptsExt[$i]}...\033[0m" - ${BUILDDIR}/qa/rpc-tests/${testScriptsExt[$i]} --srcdir "${BUILDDIR}/src" ${passOn} - fi - done -else - echo "No rpc tests to run. Wallet, utils, and bitcoind must all be enabled" -fi diff --git a/qa/pull-tester/run-bitcoind-for-test.sh.in b/qa/pull-tester/run-bitcoind-for-test.sh.in index 14ae08e4e5..14ae08e4e5 100755..100644 --- a/qa/pull-tester/run-bitcoind-for-test.sh.in +++ b/qa/pull-tester/run-bitcoind-for-test.sh.in diff --git a/qa/pull-tester/tests-config.sh.in b/qa/pull-tester/tests_config.py.in index e881a95110..937b4231f1 100755..100644 --- a/qa/pull-tester/tests-config.sh.in +++ b/qa/pull-tester/tests_config.py.in @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env python2 # Copyright (c) 2013-2014 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -12,6 +12,4 @@ EXEEXT="@EXEEXT@" @BUILD_BITCOIND_TRUE@ENABLE_BITCOIND=1 @ENABLE_ZMQ_TRUE@ENABLE_ZMQ=1 -REAL_BITCOIND="$BUILDDIR/src/bitcoind${EXEEXT}" -REAL_BITCOINCLI="$BUILDDIR/src/bitcoin-cli${EXEEXT}" diff --git a/qa/rpc-tests/README.md b/qa/rpc-tests/README.md index c6d1721282..3391ee03ae 100644 --- a/qa/rpc-tests/README.md +++ b/qa/rpc-tests/README.md @@ -37,9 +37,13 @@ Helper functions for creating blocks and transactions. Notes ===== -You can run a single test by calling `qa/pull-tester/rpc-tests.sh <testname>`. +You can run any single test by calling qa/pull-tester/rpc-tests.py <testname> -Run all possible tests with `qa/pull-tester/rpc-tests.sh -extended`. +Or you can run any combination of tests by calling `qa/pull-tester/rpc-tests.py <testname1> <testname2> <testname3> ...` + +Run the regression test suite with `qa/pull-tester/rpc-tests.py' + +Run all possible tests with `qa/pull-tester/rpc-tests.py -extended` Possible options: @@ -53,7 +57,7 @@ Possible options: --tracerpc Print out all RPC calls as they are made ``` -If you set the environment variable `PYTHON_DEBUG=1` you will get some debug output (example: `PYTHON_DEBUG=1 qa/pull-tester/rpc-tests.sh wallet`). +If you set the environment variable `PYTHON_DEBUG=1` you will get some debug output (example: `PYTHON_DEBUG=1 qa/pull-tester/rpc-tests.py wallet`). A 200-block -regtest blockchain and wallets for four nodes is created the first time a regression test is run and diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index 169fef4af4..4c96fbf5a5 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -49,7 +49,9 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType) return false; if (m < 1 || m > n) return false; - } + } else if (whichType == TX_NULL_DATA && + (!GetBoolArg("-datacarrier", true) || scriptPubKey.size() > nMaxDatacarrierBytes)) + return false; return whichType != TX_NONSTANDARD; } diff --git a/src/script/script.cpp b/src/script/script.cpp index 58dbade0e2..9a0c067a33 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -144,7 +144,7 @@ const char* GetOpName(opcodetype opcode) case OP_INVALIDOPCODE : return "OP_INVALIDOPCODE"; // Note: - // The template matching params OP_SMALLDATA/etc are defined in opcodetype enum + // The template matching params OP_SMALLINTEGER/etc are defined in opcodetype enum // as kind of implementation hack, they are *NOT* real opcodes. If found in real // Script, just let the default: case deal with them. @@ -210,9 +210,8 @@ bool CScript::IsPayToScriptHash() const this->at(22) == OP_EQUAL); } -bool CScript::IsPushOnly() const +bool CScript::IsPushOnly(const_iterator pc) const { - const_iterator pc = begin(); while (pc < end()) { opcodetype opcode; @@ -227,3 +226,8 @@ bool CScript::IsPushOnly() const } return true; } + +bool CScript::IsPushOnly() const +{ + return this->IsPushOnly(begin()); +} diff --git a/src/script/script.h b/src/script/script.h index f0725bbbf6..cdc9a71bb2 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -167,7 +167,6 @@ enum opcodetype // template matching params - OP_SMALLDATA = 0xf9, OP_SMALLINTEGER = 0xfa, OP_PUBKEYS = 0xfb, OP_PUBKEYHASH = 0xfd, @@ -589,6 +588,7 @@ public: bool IsPayToScriptHash() const; /** Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it consensus-critical). */ + bool IsPushOnly(const_iterator pc) const; bool IsPushOnly() const; /** diff --git a/src/script/standard.cpp b/src/script/standard.cpp index 1d5aac7b34..bfef8afa17 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -51,13 +51,10 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsi // Sender provides N pubkeys, receivers provides M signatures mTemplates.insert(make_pair(TX_MULTISIG, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG)); - - // Empty, provably prunable, data-carrying output - if (GetBoolArg("-datacarrier", true)) - mTemplates.insert(make_pair(TX_NULL_DATA, CScript() << OP_RETURN << OP_SMALLDATA)); - mTemplates.insert(make_pair(TX_NULL_DATA, CScript() << OP_RETURN)); } + vSolutionsRet.clear(); + // Shortcut for pay-to-script-hash, which are more constrained than the other types: // it is always OP_HASH160 20 [20 byte hash] OP_EQUAL if (scriptPubKey.IsPayToScriptHash()) @@ -68,6 +65,16 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsi return true; } + // Provably prunable, data-carrying output + // + // So long as script passes the IsUnspendable() test and all but the first + // byte passes the IsPushOnly() test we don't care what exactly is in the + // script. + if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) { + typeRet = TX_NULL_DATA; + return true; + } + // Scan templates const CScript& script1 = scriptPubKey; BOOST_FOREACH(const PAIRTYPE(txnouttype, CScript)& tplate, mTemplates) @@ -140,12 +147,6 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsi else break; } - else if (opcode2 == OP_SMALLDATA) - { - // small pushdata, <= nMaxDatacarrierBytes - if (vch1.size() > nMaxDatacarrierBytes) - break; - } else if (opcode1 != opcode2 || vch1 != vch2) { // Others must match exactly diff --git a/src/script/standard.h b/src/script/standard.h index 9e17dac700..ae1bbecca0 100644 --- a/src/script/standard.h +++ b/src/script/standard.h @@ -25,7 +25,7 @@ public: CScriptID(const uint160& in) : uint160(in) {} }; -static const unsigned int MAX_OP_RETURN_RELAY = 80; //! bytes +static const unsigned int MAX_OP_RETURN_RELAY = 83; //! bytes (+1 for OP_RETURN, +2 for the pushdata opcodes) extern unsigned nMaxDatacarrierBytes; /** diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index beec396675..9847f6512e 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -351,12 +351,29 @@ BOOST_AUTO_TEST_CASE(test_IsStandard) t.vout[0].scriptPubKey = CScript() << OP_1; BOOST_CHECK(!IsStandardTx(t, reason)); - // 80-byte TX_NULL_DATA (standard) + // MAX_OP_RETURN_RELAY-byte TX_NULL_DATA (standard) t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"); + BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY, t.vout[0].scriptPubKey.size()); BOOST_CHECK(IsStandardTx(t, reason)); - // 81-byte TX_NULL_DATA (non-standard) + // MAX_OP_RETURN_RELAY+1-byte TX_NULL_DATA (non-standard) t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3800"); + BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY + 1, t.vout[0].scriptPubKey.size()); + BOOST_CHECK(!IsStandardTx(t, reason)); + + // Data payload can be encoded in any way... + t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex(""); + BOOST_CHECK(IsStandardTx(t, reason)); + t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("00") << ParseHex("01"); + BOOST_CHECK(IsStandardTx(t, reason)); + // OP_RESERVED *is* considered to be a PUSHDATA type opcode by IsPushOnly()! + t.vout[0].scriptPubKey = CScript() << OP_RETURN << OP_RESERVED << -1 << 0 << ParseHex("01") << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9 << 10 << 11 << 12 << 13 << 14 << 15 << 16; + BOOST_CHECK(IsStandardTx(t, reason)); + t.vout[0].scriptPubKey = CScript() << OP_RETURN << 0 << ParseHex("01") << 2 << ParseHex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + BOOST_CHECK(IsStandardTx(t, reason)); + + // ...so long as it only contains PUSHDATA's + t.vout[0].scriptPubKey = CScript() << OP_RETURN << OP_RETURN; BOOST_CHECK(!IsStandardTx(t, reason)); // TX_NULL_DATA w/o PUSHDATA diff --git a/src/util.cpp b/src/util.cpp index f50d25e17a..8192a7c71c 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -280,10 +280,13 @@ int LogPrintStr(const std::string &str) { int ret = 0; // Returns total number of characters written static bool fStartedNewLine = true; + + string strTimestamped = LogTimestampStr(str, &fStartedNewLine); + if (fPrintToConsole) { // print to console - ret = fwrite(str.data(), 1, str.size(), stdout); + ret = fwrite(strTimestamped.data(), 1, strTimestamped.size(), stdout); fflush(stdout); } else if (fPrintToDebugLog) @@ -291,8 +294,6 @@ int LogPrintStr(const std::string &str) boost::call_once(&DebugPrintInit, debugPrintInitFlag); boost::mutex::scoped_lock scoped_lock(*mutexDebugLog); - string strTimestamped = LogTimestampStr(str, &fStartedNewLine); - // buffer if we haven't opened the log yet if (fileout == NULL) { assert(vMsgsBeforeOpenLog); |