aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml10
-rw-r--r--contrib/linearize/README.md5
-rwxr-xr-xcontrib/linearize/linearize-data.py79
-rwxr-xr-xcontrib/macdeploy/macdeployqtplus29
-rw-r--r--depends/funcs.mk4
-rw-r--r--depends/packages/qt.mk5
-rw-r--r--depends/patches/qt/qt5-tablet-osx.patch20
-rw-r--r--doc/dnsseed-policy.md3
-rw-r--r--doc/translation_process.md10
-rw-r--r--qa/rpc-tests/util.py10
-rw-r--r--src/Makefile.am16
-rw-r--r--src/Makefile.test.include3
-rw-r--r--src/addrman.cpp6
-rw-r--r--src/addrman.h6
-rw-r--r--src/alert.h4
-rw-r--r--src/allocators.h1
-rw-r--r--src/base58.cpp8
-rw-r--r--src/base58.h3
-rw-r--r--src/bitcoin-cli.cpp4
-rw-r--r--src/bitcoin-tx.cpp24
-rw-r--r--src/bloom.cpp3
-rw-r--r--src/bloom.h2
-rw-r--r--src/chainparams.cpp21
-rw-r--r--src/chainparams.h3
-rw-r--r--src/chainparamsbase.h2
-rw-r--r--src/checkpoints.cpp4
-rw-r--r--src/checkpoints.h2
-rw-r--r--src/coins.cpp38
-rw-r--r--src/coins.h8
-rw-r--r--src/core.cpp12
-rw-r--r--src/core.h35
-rw-r--r--src/core_io.h2
-rw-r--r--src/core_read.cpp13
-rw-r--r--src/core_write.cpp8
-rw-r--r--src/crypter.cpp2
-rw-r--r--src/crypter.h2
-rw-r--r--src/crypto/ripemd160.cpp1
-rw-r--r--src/crypto/sha1.cpp1
-rw-r--r--src/crypto/sha2.cpp1
-rw-r--r--src/db.cpp1
-rw-r--r--src/db.h6
-rw-r--r--src/hash.h2
-rw-r--r--src/init.cpp10
-rw-r--r--src/keystore.cpp2
-rw-r--r--src/leveldbwrapper.h3
-rw-r--r--src/main.cpp191
-rw-r--r--src/main.h43
-rw-r--r--src/miner.cpp7
-rw-r--r--src/net.cpp15
-rw-r--r--src/net.h2
-rw-r--r--src/netbase.cpp90
-rw-r--r--src/netbase.h7
-rw-r--r--src/pow.h2
-rw-r--r--src/protocol.h15
-rw-r--r--src/qt/bitcoinunits.cpp5
-rw-r--r--src/qt/coincontroldialog.cpp4
-rw-r--r--src/qt/overviewpage.cpp2
-rw-r--r--src/qt/paymentserver.cpp8
-rw-r--r--src/qt/recentrequeststablemodel.h12
-rw-r--r--src/qt/test/paymentrequestdata.h4
-rw-r--r--src/qt/test/paymentservertests.cpp9
-rw-r--r--src/qt/test/paymentservertests.h8
-rw-r--r--src/qt/test/test_main.cpp7
-rw-r--r--src/qt/test/uritests.cpp4
-rw-r--r--src/qt/test/uritests.h4
-rw-r--r--src/qt/transactiondesc.cpp2
-rw-r--r--src/qt/transactionrecord.cpp2
-rw-r--r--src/qt/transactiontablemodel.cpp14
-rw-r--r--src/qt/transactionview.cpp2
-rw-r--r--src/qt/walletmodel.cpp20
-rw-r--r--src/qt/walletmodel.h37
-rw-r--r--src/random.cpp4
-rw-r--r--src/rpcblockchain.cpp2
-rw-r--r--src/rpcclient.cpp2
-rw-r--r--src/rpcdump.cpp3
-rw-r--r--src/rpcmining.cpp6
-rw-r--r--src/rpcmisc.cpp4
-rw-r--r--src/rpcnet.cpp1
-rw-r--r--src/rpcprotocol.cpp2
-rw-r--r--src/rpcrawtransaction.cpp21
-rw-r--r--src/rpcserver.cpp2
-rw-r--r--src/rpcwallet.cpp2
-rw-r--r--src/script/compressor.cpp127
-rw-r--r--src/script/compressor.h84
-rw-r--r--src/script/interpreter.cpp (renamed from src/script.cpp)1047
-rw-r--r--src/script/interpreter.h45
-rw-r--r--src/script/script.cpp295
-rw-r--r--src/script/script.h (renamed from src/script.h)484
-rw-r--r--src/script/sign.cpp260
-rw-r--r--src/script/sign.h24
-rw-r--r--src/script/standard.cpp254
-rw-r--r--src/script/standard.h56
-rw-r--r--src/serialize.h8
-rw-r--r--src/sync.cpp3
-rw-r--r--src/test/DoS_tests.cpp19
-rw-r--r--src/test/base58_tests.cpp2
-rw-r--r--src/test/canonical_tests.cpp4
-rw-r--r--src/test/data/bitcoin-util-test.json3
-rw-r--r--src/test/data/script_invalid.json657
-rw-r--r--src/test/data/script_valid.json940
-rw-r--r--src/test/data/txcreate2.hex1
-rw-r--r--src/test/key_tests.cpp2
-rw-r--r--src/test/multisig_tests.cpp16
-rw-r--r--src/test/script_P2SH_tests.cpp13
-rw-r--r--src/test/script_tests.cpp17
-rw-r--r--src/test/scriptnum_tests.cpp2
-rw-r--r--src/test/sighash_tests.cpp3
-rw-r--r--src/test/sigopcount_tests.cpp2
-rw-r--r--src/test/transaction_tests.cpp8
-rw-r--r--src/timedata.h4
-rw-r--r--src/txdb.cpp3
-rw-r--r--src/txmempool.cpp18
-rw-r--r--src/txmempool.h1
-rw-r--r--src/uint256.h5
-rw-r--r--src/univalue/univalue_write.cpp18
-rw-r--r--src/util.cpp1
-rw-r--r--src/util.h2
-rw-r--r--src/utilstrencodings.cpp3
-rw-r--r--src/version.cpp1
-rw-r--r--src/wallet.cpp45
-rw-r--r--src/wallet.h57
-rw-r--r--src/wallet_ismine.cpp91
-rw-r--r--src/wallet_ismine.h28
-rw-r--r--src/walletdb.cpp11
-rw-r--r--src/walletdb.h2
125 files changed, 3055 insertions, 2610 deletions
diff --git a/.travis.yml b/.travis.yml
index 2073e71769..7580adf5c4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,22 +14,26 @@ env:
- CCACHE_TEMPDIR=/tmp/.ccache-temp
- CCACHE_COMPRESS=1
- BASE_OUTDIR=$TRAVIS_BUILD_DIR/out
+ - SDK_URL=https://bitcoincore.org/depends-sources/sdks
cache:
apt: true
directories:
- depends/built
+ - depends/sdk-sources
- $HOME/.ccache
matrix:
fast_finish: true
include:
- compiler: "true 1"
- env: HOST=arm-linux-gnueabihf PACKAGES="g++-arm-linux-gnueabihf" DEP_OPTS="NO_QT=1" GOAL="install" BITCOIN_CONFIG"--enable-glibc-back-compat"
+ env: HOST=arm-linux-gnueabihf PACKAGES="g++-arm-linux-gnueabihf" DEP_OPTS="NO_QT=1" GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat"
- compiler: "true 2"
env: HOST=x86_64-unknown-linux-gnu DEP_OPTS="NO_QT=1 NO_WALLET=1 NO_UPNP=1" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat"
- compiler: "true 3"
env: HOST=x86_64-unknown-linux-gnu RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat"
- compiler: "true 4"
env: HOST=i686-pc-linux-gnu PACKAGES="g++-multilib" RUN_TESTS=true GOAL="install" BITCOIN_CONFIG="--enable-glibc-back-compat"
+ - compiler: "true 5"
+ env: HOST=x86_64-apple-darwin11 PACKAGES="gcc-multilib g++-multilib cmake libcap-dev libz-dev libbz2-dev" OSX_SDK=10.7 GOAL="deploy"
- compiler: "true 6"
env: HOST=x86_64-w64-mingw32 PACKAGES="nsis gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 binutils-mingw-w64-x86-64 mingw-w64-dev" GOAL="deploy"
- compiler: "true 7"
@@ -39,7 +43,9 @@ install:
- if [ -n "$PACKAGES" ]; then travis_retry sudo apt-get install --no-upgrade -qq $PACKAGES; fi
before_script:
- unset CC; unset CXX
- - mkdir -p depends/SDKs
+ - mkdir -p depends/SDKs depends/sdk-sources
+ - if [ -n "$OSX_SDK" -a ! -f depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then wget $SDK_URL/MacOSX${OSX_SDK}.sdk.tar.gz -O depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi
+ - if [ -n "$OSX_SDK" -a -f depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then tar -C depends/SDKs -xf depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi
- make $MAKEJOBS -C depends HOST=$HOST $DEP_OPTS || (echo "Build failure. Verbose build follows." && make -C depends V=1 HOST=$HOST $DEP_OPTS)
script:
- OUTDIR=$BASE_OUTDIR/$TRAVIS_PULL_REQUEST/$TRAVIS_JOB_NUMBER-$HOST
diff --git a/contrib/linearize/README.md b/contrib/linearize/README.md
index b5c6e7824e..157586e4d4 100644
--- a/contrib/linearize/README.md
+++ b/contrib/linearize/README.md
@@ -27,6 +27,7 @@ output.
Optional config file setting for linearize-data:
* "netmagic": network magic number
* "max_out_sz": maximum output file size (default 1000*1000*1000)
-* "split_year": Split files when a new year is first seen, in addition to
+* "split_timestamp": Split files when a new month is first seen, in addition to
reaching a maximum file size.
-
+* "file_timestamp": Set each file's last-modified time to that of the
+most recent block in that file.
diff --git a/contrib/linearize/linearize-data.py b/contrib/linearize/linearize-data.py
index ea94f25fae..3b5d198c14 100755
--- a/contrib/linearize/linearize-data.py
+++ b/contrib/linearize/linearize-data.py
@@ -10,11 +10,13 @@
import json
import struct
import re
+import os
import base64
import httplib
import sys
import hashlib
import datetime
+import time
settings = {}
@@ -58,10 +60,12 @@ def calc_hash_str(blk_hdr):
hash_str = hash.encode('hex')
return hash_str
-def get_blk_year(blk_hdr):
+def get_blk_dt(blk_hdr):
members = struct.unpack("<I", blk_hdr[68:68+4])
- dt = datetime.datetime.fromtimestamp(members[0])
- return dt.year
+ nTime = members[0]
+ dt = datetime.datetime.fromtimestamp(nTime)
+ dt_ym = datetime.datetime(dt.year, dt.month, 1)
+ return (dt_ym, nTime)
def get_block_hashes(settings):
blkindex = []
@@ -86,22 +90,31 @@ def copydata(settings, blkindex, blkset):
outFn = 0
outsz = 0
outF = None
+ outFname = None
blkCount = 0
- lastYear = 0
- splitYear = False
+ lastDate = datetime.datetime(2000, 1, 1)
+ highTS = 1408893517 - 315360000
+ timestampSplit = False
fileOutput = True
+ setFileTime = False
maxOutSz = settings['max_out_sz']
if 'output' in settings:
fileOutput = False
- if settings['split_year'] != 0:
- splitYear = True
+ if settings['file_timestamp'] != 0:
+ setFileTime = True
+ if settings['split_timestamp'] != 0:
+ timestampSplit = True
while True:
if not inF:
fname = "%s/blk%05d.dat" % (settings['input'], inFn)
print("Input file" + fname)
- inF = open(fname, "rb")
+ try:
+ inF = open(fname, "rb")
+ except IOError:
+ print "Done"
+ return
inhdr = inF.read(8)
if (not inhdr or (inhdr[0] == "\0")):
@@ -125,36 +138,49 @@ def copydata(settings, blkindex, blkset):
print("Skipping unknown block " + hash_str)
continue
+ if blkindex[blkCount] != hash_str:
+ print("Out of order block.")
+ print("Expected " + blkindex[blkCount])
+ print("Got " + hash_str)
+ sys.exit(1)
+
if not fileOutput and ((outsz + inLen) > maxOutSz):
outF.close()
+ if setFileTime:
+ os.utime(outFname, (int(time.time()), highTS))
outF = None
+ outFname = None
outFn = outFn + 1
outsz = 0
- if splitYear:
- blkYear = get_blk_year(blk_hdr)
- if blkYear > lastYear:
- print("New year " + str(blkYear) + " @ " + hash_str)
- lastYear = blkYear
- if outF:
- outF.close()
- outF = None
- outFn = outFn + 1
- outsz = 0
+ (blkDate, blkTS) = get_blk_dt(blk_hdr)
+ if timestampSplit and (blkDate > lastDate):
+ print("New month " + blkDate.strftime("%Y-%m") + " @ " + hash_str)
+ lastDate = blkDate
+ if outF:
+ outF.close()
+ if setFileTime:
+ os.utime(outFname, (int(time.time()), highTS))
+ outF = None
+ outFname = None
+ outFn = outFn + 1
+ outsz = 0
if not outF:
if fileOutput:
- fname = settings['output_file']
+ outFname = settings['output_file']
else:
- fname = "%s/blk%05d.dat" % (settings['output'], outFn)
- print("Output file" + fname)
- outF = open(fname, "wb")
+ outFname = "%s/blk%05d.dat" % (settings['output'], outFn)
+ print("Output file" + outFname)
+ outF = open(outFname, "wb")
outF.write(inhdr)
outF.write(rawblock)
outsz = outsz + inLen + 8
blkCount = blkCount + 1
+ if blkTS > highTS:
+ highTS = blkTS
if (blkCount % 1000) == 0:
print("Wrote " + str(blkCount) + " blocks")
@@ -184,13 +210,16 @@ if __name__ == '__main__':
settings['input'] = 'input'
if 'hashlist' not in settings:
settings['hashlist'] = 'hashlist.txt'
- if 'split_year' not in settings:
- settings['split_year'] = 0
+ if 'file_timestamp' not in settings:
+ settings['file_timestamp'] = 0
+ if 'split_timestamp' not in settings:
+ settings['split_timestamp'] = 0
if 'max_out_sz' not in settings:
settings['max_out_sz'] = 1000L * 1000 * 1000
settings['max_out_sz'] = long(settings['max_out_sz'])
- settings['split_year'] = int(settings['split_year'])
+ settings['split_timestamp'] = int(settings['split_timestamp'])
+ settings['file_timestamp'] = int(settings['file_timestamp'])
settings['netmagic'] = settings['netmagic'].decode('hex')
if 'output_file' not in settings and 'output' not in settings:
diff --git a/contrib/macdeploy/macdeployqtplus b/contrib/macdeploy/macdeployqtplus
index 23b57a76b3..5ab6a222dd 100755
--- a/contrib/macdeploy/macdeployqtplus
+++ b/contrib/macdeploy/macdeployqtplus
@@ -37,7 +37,10 @@ class FrameworkInfo(object):
self.sourceFilePath = ""
self.destinationDirectory = ""
self.sourceResourcesDirectory = ""
+ self.sourceVersionContentsDirectory = ""
+ self.sourceContentsDirectory = ""
self.destinationResourcesDirectory = ""
+ self.destinationVersionContentsDirectory = ""
def __eq__(self, other):
if self.__class__ == other.__class__:
@@ -141,7 +144,11 @@ class FrameworkInfo(object):
info.destinationDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, info.binaryDirectory)
info.sourceResourcesDirectory = os.path.join(info.frameworkPath, "Resources")
+ info.sourceContentsDirectory = os.path.join(info.frameworkPath, "Contents")
+ info.sourceVersionContentsDirectory = os.path.join(info.frameworkPath, "Versions", info.version, "Contents")
info.destinationResourcesDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, "Resources")
+ info.destinationContentsDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, "Contents")
+ info.destinationVersionContentsDirectory = os.path.join(cls.bundleFrameworkDirectory, info.frameworkName, "Versions", info.version, "Contents")
return info
@@ -275,6 +282,13 @@ def copyFramework(framework, path, verbose):
os.chmod(toPath, permissions.st_mode | stat.S_IWRITE)
if not framework.isDylib(): # Copy resources for real frameworks
+
+ linkfrom = os.path.join(path, "Contents/Frameworks/", framework.frameworkName, framework.binaryName)
+ linkto = os.path.join(framework.binaryPath)
+ if not os.path.exists(linkfrom):
+ os.symlink(linkto, linkfrom)
+ if verbose >= 2:
+ print "Linked:", linkfrom, "->", linkto
fromResourcesDir = framework.sourceResourcesDirectory
if os.path.exists(fromResourcesDir):
toResourcesDir = os.path.join(path, framework.destinationResourcesDirectory)
@@ -282,6 +296,21 @@ def copyFramework(framework, path, verbose):
if verbose >= 3:
print "Copied resources:", fromResourcesDir
print " to:", toResourcesDir
+ fromContentsDir = framework.sourceVersionContentsDirectory
+ if not os.path.exists(fromContentsDir):
+ fromContentsDir = framework.sourceContentsDirectory
+ if os.path.exists(fromContentsDir):
+ toContentsDir = os.path.join(path, framework.destinationVersionContentsDirectory)
+ shutil.copytree(fromContentsDir, toContentsDir)
+ contentslinkfrom = os.path.join(path, framework.destinationContentsDirectory)
+ if not os.path.exists(contentslinkfrom):
+ contentslinkto = os.path.join("Versions/", framework.version, "Contents")
+ os.symlink(contentslinkto, contentslinkfrom)
+ if verbose >= 3:
+ print "Linked:", contentslinkfrom, "->", contentslinkto
+ if verbose >= 3:
+ 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")
diff --git a/depends/funcs.mk b/depends/funcs.mk
index 280706efb3..28bfb85492 100644
--- a/depends/funcs.mk
+++ b/depends/funcs.mk
@@ -22,8 +22,8 @@ endef
define fetch_file
(test -f $(SOURCES_PATH)/$(4) || \
( mkdir -p $$($(1)_extract_dir) && \
- ( $(build_DOWNLOAD) "$$($(1)_extract_dir)/$(3).temp" "$(2)/$(3)" || \
- $(build_DOWNLOAD) "$$($(1)_extract_dir)/$(3).temp" "$(FALLBACK_DOWNLOAD_PATH)/$(3)" ) && \
+ ( $(build_DOWNLOAD) "$$($(1)_extract_dir)/$(4).temp" "$(2)/$(3)" || \
+ $(build_DOWNLOAD) "$$($(1)_extract_dir)/$(4).temp" "$(FALLBACK_DOWNLOAD_PATH)/$(3)" ) && \
echo "$(5) $$($(1)_extract_dir)/$(4).temp" > $$($(1)_extract_dir)/.$(4).hash && \
$(build_SHA256SUM) -c $$($(1)_extract_dir)/.$(4).hash && \
mv $$($(1)_extract_dir)/$(4).temp $(SOURCES_PATH)/$(4) ))
diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk
index cce7d6e6ef..e719e2e506 100644
--- a/depends/packages/qt.mk
+++ b/depends/packages/qt.mk
@@ -7,7 +7,7 @@ $(package)_dependencies=openssl
$(package)_linux_dependencies=freetype fontconfig dbus libxcb libX11 xproto libXext
$(package)_build_subdir=qtbase
$(package)_qt_libs=corelib network widgets gui plugins testlib
-$(package)_patches=mac-qmake.conf fix-xcb-include-order.patch
+$(package)_patches=mac-qmake.conf fix-xcb-include-order.patch qt5-tablet-osx.patch
define $(package)_set_vars
$(package)_config_opts = -release -opensource -confirm-license
@@ -52,7 +52,8 @@ define $(package)_preprocess_cmds
cp -f qtbase/mkspecs/macx-clang/Info.plist.app qtbase/mkspecs/macx-clang-linux/ &&\
cp -f qtbase/mkspecs/macx-clang/qplatformdefs.h qtbase/mkspecs/macx-clang-linux/ &&\
cp -f $($(package)_patch_dir)/mac-qmake.conf qtbase/mkspecs/macx-clang-linux/qmake.conf && \
- patch -p1 < $($(package)_patch_dir)/fix-xcb-include-order.patch
+ patch -p1 < $($(package)_patch_dir)/fix-xcb-include-order.patch && \
+ patch -p1 < $($(package)_patch_dir)/qt5-tablet-osx.patch
endef
define $(package)_config_cmds
diff --git a/depends/patches/qt/qt5-tablet-osx.patch b/depends/patches/qt/qt5-tablet-osx.patch
new file mode 100644
index 0000000000..7deabf8d4e
--- /dev/null
+++ b/depends/patches/qt/qt5-tablet-osx.patch
@@ -0,0 +1,20 @@
+--- old/qtbase/src/widgets/kernel/qwidgetwindow.cpp 2014-09-05 20:45:18.717570370 -0400
++++ new/qtbase/src/widgets/kernel/qwidgetwindow.cpp 2014-09-05 20:52:38.653576561 -0400
+@@ -57,7 +57,7 @@
+ Q_WIDGETS_EXPORT extern bool qt_tab_all_widgets();
+
+ QWidget *qt_button_down = 0; // widget got last button-down
+-static QWidget *qt_tablet_target = 0;
++static QPointer<QWidget> qt_tablet_target = 0;
+
+ // popup control
+ QWidget *qt_popup_down = 0; // popup that contains the pressed widget
+@@ -96,8 +96,6 @@
+
+ QWidgetWindow::~QWidgetWindow()
+ {
+- if (m_widget == qt_tablet_target)
+- qt_tablet_target = 0;
+ }
+
+ #ifndef QT_NO_ACCESSIBILITY
diff --git a/doc/dnsseed-policy.md b/doc/dnsseed-policy.md
index 73e307f7cd..66a1757ac5 100644
--- a/doc/dnsseed-policy.md
+++ b/doc/dnsseed-policy.md
@@ -3,6 +3,9 @@ Expectations for DNS Seed operators
Bitcoin Core attempts to minimize the level of trust in DNS seeds,
but DNS seeds still pose a small amount of risk for the network.
+As such, DNS seeds must be run by entities which have some minimum
+level of trust within the Bitcoin community.
+
Other implementations of Bitcoin software may also use the same
seeds and may be more exposed. In light of this exposure this
document establishes some basic expectations for the expectations
diff --git a/doc/translation_process.md b/doc/translation_process.md
index 61a0a0ffed..9475b1dc72 100644
--- a/doc/translation_process.md
+++ b/doc/translation_process.md
@@ -17,10 +17,12 @@ automated.
This file must be updated whenever a new translation is added. Please note that
files must end with `.qm`, not `.ts`.
- <qresource prefix="/translations">
- <file alias="en">locale/bitcoin_en.qm</file>
- ...
- </qresource>
+```xml
+<qresource prefix="/translations">
+ <file alias="en">locale/bitcoin_en.qm</file>
+ ...
+</qresource>
+```
### src/qt/locale/
diff --git a/qa/rpc-tests/util.py b/qa/rpc-tests/util.py
index da2b6df197..87baadc5d6 100644
--- a/qa/rpc-tests/util.py
+++ b/qa/rpc-tests/util.py
@@ -10,7 +10,7 @@ import os
import sys
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "python-bitcoinrpc"))
-from decimal import Decimal
+from decimal import Decimal, ROUND_DOWN
import json
import random
import shutil
@@ -230,10 +230,12 @@ def make_change(from_node, amount_in, amount_out, fee):
change = amount_in - amount
if change > amount*2:
# Create an extra change output to break up big inputs
- outputs[from_node.getnewaddress()] = float(change/2)
- change = change/2
+ change_address = from_node.getnewaddress()
+ # Split change in two, being careful of rounding:
+ outputs[change_address] = Decimal(change/2).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN)
+ change = amount_in - amount - outputs[change_address]
if change > 0:
- outputs[from_node.getnewaddress()] = float(change)
+ outputs[from_node.getnewaddress()] = change
return outputs
def send_zeropri_transaction(from_node, to_node, amount, fee):
diff --git a/src/Makefile.am b/src/Makefile.am
index 35fca6570f..94a582dfac 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -98,7 +98,11 @@ BITCOIN_CORE_H = \
rpcclient.h \
rpcprotocol.h \
rpcserver.h \
- script.h \
+ script/compressor.h \
+ script/interpreter.h \
+ script/script.h \
+ script/sign.h \
+ script/standard.h \
serialize.h \
sync.h \
threadsafety.h \
@@ -113,8 +117,9 @@ BITCOIN_CORE_H = \
utilmoneystr.h \
utiltime.h \
version.h \
- walletdb.h \
wallet.h \
+ wallet_ismine.h \
+ walletdb.h \
compat/sanity.h
JSON_H = \
@@ -169,6 +174,7 @@ libbitcoin_wallet_a_SOURCES = \
rpcdump.cpp \
rpcwallet.cpp \
wallet.cpp \
+ wallet_ismine.cpp \
walletdb.cpp \
$(BITCOIN_CORE_H)
@@ -206,7 +212,11 @@ libbitcoin_common_a_SOURCES = \
keystore.cpp \
netbase.cpp \
protocol.cpp \
- script.cpp \
+ script/compressor.cpp \
+ script/interpreter.cpp \
+ script/script.cpp \
+ script/sign.cpp \
+ script/standard.cpp \
$(BITCOIN_CORE_H)
# util: shared between all executables.
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index b4360831bb..ab449f3e71 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -13,7 +13,8 @@ EXTRA_DIST += \
test/data/tt-delout1-out.hex \
test/data/tt-locktime317000-out.hex \
test/data/tx394b54bb.hex \
- test/data/txcreate1.hex
+ test/data/txcreate1.hex \
+ test/data/txcreate2.hex
JSON_TEST_FILES = \
test/data/script_valid.json \
diff --git a/src/addrman.cpp b/src/addrman.cpp
index 704766dbf8..68948ac7ff 100644
--- a/src/addrman.cpp
+++ b/src/addrman.cpp
@@ -45,13 +45,13 @@ bool CAddrInfo::IsTerrible(int64_t nNow) const
if (nTime > nNow + 10*60) // came in a flying DeLorean
return true;
- if (nTime==0 || nNow-nTime > ADDRMAN_HORIZON_DAYS*86400) // not seen in over a month
+ if (nTime==0 || nNow-nTime > ADDRMAN_HORIZON_DAYS*24*60*60) // not seen in recent history
return true;
- if (nLastSuccess==0 && nAttempts>=ADDRMAN_RETRIES) // tried three times and never a success
+ if (nLastSuccess==0 && nAttempts>=ADDRMAN_RETRIES) // tried N times and never a success
return true;
- if (nNow-nLastSuccess > ADDRMAN_MIN_FAIL_DAYS*86400 && nAttempts>=ADDRMAN_MAX_FAILURES) // 10 successive failures in the last week
+ if (nNow-nLastSuccess > ADDRMAN_MIN_FAIL_DAYS*24*60*60 && nAttempts>=ADDRMAN_MAX_FAILURES) // N successive failures in the last week
return true;
return false;
diff --git a/src/addrman.h b/src/addrman.h
index 0790802b5c..5fd698f18a 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -46,7 +46,7 @@ private:
public:
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
@@ -268,7 +268,7 @@ public:
// This format is more complex, but significantly smaller (at most 1.5 MiB), and supports
// changes to the ADDRMAN_ parameters without breaking the on-disk structure.
//
- // We don't use IMPLEMENT_SERIALIZE since the serialization and deserialization code has
+ // We don't use ADD_SERIALIZE_METHODS since the serialization and deserialization code has
// very little in common.
template<typename Stream>
void Serialize(Stream &s, int nType, int nVersionDummy) const
@@ -424,7 +424,7 @@ public:
Check();
}
if (fRet)
- LogPrint("addrman", "Added %s from %s: %i tried, %i new\n", addr.ToStringIPPort().c_str(), source.ToString(), nTried, nNew);
+ LogPrint("addrman", "Added %s from %s: %i tried, %i new\n", addr.ToStringIPPort(), source.ToString(), nTried, nNew);
return fRet;
}
diff --git a/src/alert.h b/src/alert.h
index 4a8736d60b..5ecf94cea8 100644
--- a/src/alert.h
+++ b/src/alert.h
@@ -46,7 +46,7 @@ public:
std::string strStatusBar;
std::string strReserved;
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
@@ -84,7 +84,7 @@ public:
SetNull();
}
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
diff --git a/src/allocators.h b/src/allocators.h
index 0b1c9fea68..65a7d08987 100644
--- a/src/allocators.h
+++ b/src/allocators.h
@@ -12,6 +12,7 @@
#include <boost/thread/mutex.hpp>
#include <boost/thread/once.hpp>
+
#include <openssl/crypto.h> // for OPENSSL_cleanse()
/**
diff --git a/src/base58.cpp b/src/base58.cpp
index c9e91beef1..76f0404a18 100644
--- a/src/base58.cpp
+++ b/src/base58.cpp
@@ -215,9 +215,13 @@ bool CBitcoinAddress::Set(const CTxDestination &dest) {
}
bool CBitcoinAddress::IsValid() const {
+ return IsValid(Params());
+}
+
+bool CBitcoinAddress::IsValid(const CChainParams &params) const {
bool fCorrectSize = vchData.size() == 20;
- bool fKnownVersion = vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS) ||
- vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS);
+ bool fKnownVersion = vchVersion == params.Base58Prefix(CChainParams::PUBKEY_ADDRESS) ||
+ vchVersion == params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
return fCorrectSize && fKnownVersion;
}
diff --git a/src/base58.h b/src/base58.h
index 70681f589a..15bf710f5e 100644
--- a/src/base58.h
+++ b/src/base58.h
@@ -16,7 +16,7 @@
#include "chainparams.h"
#include "key.h"
-#include "script.h"
+#include "script/script.h"
#include <string>
#include <vector>
@@ -104,6 +104,7 @@ public:
bool Set(const CScriptID &id);
bool Set(const CTxDestination &dest);
bool IsValid() const;
+ bool IsValid(const CChainParams &params) const;
CBitcoinAddress() {}
CBitcoinAddress(const CTxDestination &dest) { Set(dest); }
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index 871aaf93df..badb376cb3 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -3,11 +3,11 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "util.h"
+#include "chainparamsbase.h"
#include "init.h"
#include "rpcclient.h"
#include "rpcprotocol.h"
-#include "chainparamsbase.h"
+#include "util.h"
#include "utilstrencodings.h"
#include "version.h"
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index 5f547bba83..354d6ba41d 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -3,21 +3,24 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "base58.h"
-#include "util.h"
-#include "utilmoneystr.h"
#include "core.h"
-#include "main.h" // for MAX_BLOCK_SIZE
+#include "core_io.h"
#include "keystore.h"
+#include "main.h" // for MAX_BLOCK_SIZE
+#include "script/script.h"
+#include "script/sign.h"
#include "ui_interface.h" // for _(...)
#include "univalue/univalue.h"
-#include "core_io.h"
+#include "util.h"
+#include "utilmoneystr.h"
#include <stdio.h>
-#include <boost/assign/list_of.hpp>
+
#include <boost/algorithm/string.hpp>
+#include <boost/assign/list_of.hpp>
-using namespace std;
using namespace boost::assign;
+using namespace std;
static bool fCreateBlank;
static map<string,UniValue> registers;
@@ -235,8 +238,7 @@ static void MutateTxAddOutScript(CMutableTransaction& tx, const string& strInput
// separate VALUE:SCRIPT in string
size_t pos = strInput.find(':');
if ((pos == string::npos) ||
- (pos == 0) ||
- (pos == (strInput.size() - 1)))
+ (pos == 0))
throw runtime_error("TX output missing separator");
// extract and validate VALUE
@@ -418,12 +420,12 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr)
// Sign what we can:
for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
CTxIn& txin = mergedTx.vin[i];
- CCoins coins;
- if (!view.GetCoins(txin.prevout.hash, coins) || !coins.IsAvailable(txin.prevout.n)) {
+ const CCoins* coins = view.AccessCoins(txin.prevout.hash);
+ if (!coins || !coins->IsAvailable(txin.prevout.n)) {
fComplete = false;
continue;
}
- const CScript& prevPubKey = coins.vout[txin.prevout.n].scriptPubKey;
+ const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey;
txin.scriptSig.clear();
// Only sign SIGHASH_SINGLE if there's a corresponding output:
diff --git a/src/bloom.cpp b/src/bloom.cpp
index e34041336f..cef74a3a54 100644
--- a/src/bloom.cpp
+++ b/src/bloom.cpp
@@ -5,7 +5,8 @@
#include "bloom.h"
#include "core.h"
-#include "script.h"
+#include "script/script.h"
+#include "script/standard.h"
#include <math.h>
#include <stdlib.h>
diff --git a/src/bloom.h b/src/bloom.h
index 4a710928cc..143e3b4c79 100644
--- a/src/bloom.h
+++ b/src/bloom.h
@@ -62,7 +62,7 @@ public:
CBloomFilter(unsigned int nElements, double nFPRate, unsigned int nTweak, unsigned char nFlagsIn);
CBloomFilter() : isFull(true), isEmpty(false), nHashFuncs(0), nTweak(0), nFlags(0) {}
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index ce99f268f3..179db5a818 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -99,7 +99,6 @@ public:
vSeeds.push_back(CDNSSeedData("dashjr.org", "dnsseed.bitcoin.dashjr.org"));
vSeeds.push_back(CDNSSeedData("bitcoinstats.com", "seed.bitcoinstats.com"));
vSeeds.push_back(CDNSSeedData("bitnodes.io", "seed.bitnodes.io"));
- vSeeds.push_back(CDNSSeedData("open-nodes.org", "seeds.bitcoin.open-nodes.org"));
vSeeds.push_back(CDNSSeedData("xf2.org", "bitseed.xf2.org"));
base58Prefixes[PUBKEY_ADDRESS] = list_of(0);
@@ -156,6 +155,7 @@ public:
vSeeds.push_back(CDNSSeedData("alexykot.me", "testnet-seed.alexykot.me"));
vSeeds.push_back(CDNSSeedData("bitcoin.petertodd.org", "testnet-seed.bitcoin.petertodd.org"));
vSeeds.push_back(CDNSSeedData("bluematt.me", "testnet-seed.bluematt.me"));
+ vSeeds.push_back(CDNSSeedData("bitcoin.schildbach.de", "testnet-seed.bitcoin.schildbach.de"));
base58Prefixes[PUBKEY_ADDRESS] = list_of(111);
base58Prefixes[SCRIPT_ADDRESS] = list_of(196);
@@ -221,24 +221,25 @@ const CChainParams &Params() {
return *pCurrentParams;
}
-void SelectParams(CBaseChainParams::Network network) {
- SelectBaseParams(network);
+CChainParams &Params(CBaseChainParams::Network network) {
switch (network) {
case CBaseChainParams::MAIN:
- pCurrentParams = &mainParams;
- break;
+ return mainParams;
case CBaseChainParams::TESTNET:
- pCurrentParams = &testNetParams;
- break;
+ return testNetParams;
case CBaseChainParams::REGTEST:
- pCurrentParams = &regTestParams;
- break;
+ return regTestParams;
default:
assert(false && "Unimplemented network");
- return;
+ return mainParams;
}
}
+void SelectParams(CBaseChainParams::Network network) {
+ SelectBaseParams(network);
+ pCurrentParams = &Params(network);
+}
+
bool SelectParamsFromCommandLine() {
if (!SelectBaseParamsFromCommandLine())
return false;
diff --git a/src/chainparams.h b/src/chainparams.h
index 95b972bd7f..e5dfc87c6d 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -111,6 +111,9 @@ protected:
*/
const CChainParams &Params();
+/** Return parameters for the given network. */
+CChainParams &Params(CBaseChainParams::Network network);
+
/** Sets the params returned by Params() to those for the given network. */
void SelectParams(CBaseChainParams::Network network);
diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h
index 2d3a07b44a..743c8c541a 100644
--- a/src/chainparamsbase.h
+++ b/src/chainparamsbase.h
@@ -5,8 +5,8 @@
#ifndef BITCOIN_CHAIN_PARAMS_BASE_H
#define BITCOIN_CHAIN_PARAMS_BASE_H
-#include <vector>
#include <string>
+#include <vector>
/**
* CBaseChainParams defines the base parameters (shared between bitcoin-cli and bitcoind)
diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp
index 717f0b90fe..c41deea7ce 100644
--- a/src/checkpoints.cpp
+++ b/src/checkpoints.cpp
@@ -146,7 +146,7 @@ namespace Checkpoints {
return checkpoints.rbegin()->first;
}
- CBlockIndex* GetLastCheckpoint(const std::map<uint256, CBlockIndex*>& mapBlockIndex)
+ CBlockIndex* GetLastCheckpoint()
{
if (!fEnabled)
return NULL;
@@ -156,7 +156,7 @@ namespace Checkpoints {
BOOST_REVERSE_FOREACH(const MapCheckpoints::value_type& i, checkpoints)
{
const uint256& hash = i.second;
- std::map<uint256, CBlockIndex*>::const_iterator t = mapBlockIndex.find(hash);
+ BlockMap::const_iterator t = mapBlockIndex.find(hash);
if (t != mapBlockIndex.end())
return t->second;
}
diff --git a/src/checkpoints.h b/src/checkpoints.h
index 52cdc35559..6d3f2d4935 100644
--- a/src/checkpoints.h
+++ b/src/checkpoints.h
@@ -22,7 +22,7 @@ namespace Checkpoints {
int GetTotalBlocksEstimate();
// Returns last CBlockIndex* in mapBlockIndex that is a checkpoint
- CBlockIndex* GetLastCheckpoint(const std::map<uint256, CBlockIndex*>& mapBlockIndex);
+ CBlockIndex* GetLastCheckpoint();
double GuessVerificationProgress(CBlockIndex *pindex, bool fSigchecks = true);
diff --git a/src/coins.cpp b/src/coins.cpp
index 7bfb84ef3e..34485db2bd 100644
--- a/src/coins.cpp
+++ b/src/coins.cpp
@@ -110,9 +110,13 @@ CCoins &CCoinsViewCache::GetCoins(const uint256 &txid) {
return it->second;
}
-const CCoins &CCoinsViewCache::GetCoins(const uint256 &txid) const {
- /* Avoid redundant implementation with the const-cast. */
- return const_cast<CCoinsViewCache*>(this)->GetCoins(txid);
+const CCoins* CCoinsViewCache::AccessCoins(const uint256 &txid) const {
+ CCoinsMap::const_iterator it = FetchCoins(txid);
+ if (it == cacheCoins.end()) {
+ return NULL;
+ } else {
+ return &it->second;
+ }
}
bool CCoinsViewCache::SetCoins(const uint256 &txid, const CCoins &coins) {
@@ -162,9 +166,9 @@ unsigned int CCoinsViewCache::GetCacheSize() const {
const CTxOut &CCoinsViewCache::GetOutputFor(const CTxIn& input) const
{
- const CCoins &coins = GetCoins(input.prevout.hash);
- assert(coins.IsAvailable(input.prevout.n));
- return coins.vout[input.prevout.n];
+ const CCoins* coins = AccessCoins(input.prevout.hash);
+ assert(coins && coins->IsAvailable(input.prevout.n));
+ return coins->vout[input.prevout.n];
}
int64_t CCoinsViewCache::GetValueIn(const CTransaction& tx) const
@@ -182,19 +186,12 @@ int64_t CCoinsViewCache::GetValueIn(const CTransaction& tx) const
bool CCoinsViewCache::HaveInputs(const CTransaction& tx) const
{
if (!tx.IsCoinBase()) {
- // first check whether information about the prevout hash is available
for (unsigned int i = 0; i < tx.vin.size(); i++) {
const COutPoint &prevout = tx.vin[i].prevout;
- if (!HaveCoins(prevout.hash))
- return false;
- }
-
- // then check whether the actual outputs are available
- for (unsigned int i = 0; i < tx.vin.size(); i++) {
- const COutPoint &prevout = tx.vin[i].prevout;
- const CCoins &coins = GetCoins(prevout.hash);
- if (!coins.IsAvailable(prevout.n))
+ const CCoins* coins = AccessCoins(prevout.hash);
+ if (!coins || !coins->IsAvailable(prevout.n)) {
return false;
+ }
}
}
return true;
@@ -207,10 +204,11 @@ double CCoinsViewCache::GetPriority(const CTransaction &tx, int nHeight) const
double dResult = 0.0;
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
- const CCoins &coins = GetCoins(txin.prevout.hash);
- if (!coins.IsAvailable(txin.prevout.n)) continue;
- if (coins.nHeight < nHeight) {
- dResult += coins.vout[txin.prevout.n].nValue * (nHeight-coins.nHeight);
+ const CCoins* coins = AccessCoins(txin.prevout.hash);
+ assert(coins);
+ if (!coins->IsAvailable(txin.prevout.n)) continue;
+ if (coins->nHeight < nHeight) {
+ dResult += coins->vout[txin.prevout.n].nValue * (nHeight-coins->nHeight);
}
}
return tx.ComputePriority(dResult);
diff --git a/src/coins.h b/src/coins.h
index e70b19ff8f..bf61f55aac 100644
--- a/src/coins.h
+++ b/src/coins.h
@@ -344,11 +344,13 @@ public:
bool SetBestBlock(const uint256 &hashBlock);
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock);
+ // Return a pointer to CCoins in the cache, or NULL if not found. This is
+ // more efficient than GetCoins. Modifications to other cache entries are
+ // allowed while accessing the returned pointer.
+ const CCoins* AccessCoins(const uint256 &txid) const;
+
// Return a modifiable reference to a CCoins. Check HaveCoins first.
- // Many methods explicitly require a CCoinsViewCache because of this method, to reduce
- // copying.
CCoins &GetCoins(const uint256 &txid);
- const CCoins &GetCoins(const uint256 &txid) const;
// Push the modifications applied to this cache to its base.
// Failure to call this method before destruction will cause the changes to be forgotten.
diff --git a/src/core.cpp b/src/core.cpp
index 8dcda0126a..491e4fa68b 100644
--- a/src/core.cpp
+++ b/src/core.cpp
@@ -124,6 +124,14 @@ int64_t CTransaction::GetValueOut() const
double CTransaction::ComputePriority(double dPriorityInputs, unsigned int nTxSize) const
{
+ nTxSize = CalculateModifiedSize(nTxSize);
+ if (nTxSize == 0) return 0.0;
+
+ return dPriorityInputs / nTxSize;
+}
+
+unsigned int CTransaction::CalculateModifiedSize(unsigned int nTxSize) const
+{
// In order to avoid disincentivizing cleaning up the UTXO set we don't count
// the constant overhead for each txin and up to 110 bytes of scriptSig (which
// is enough to cover a compressed pubkey p2sh redemption) for priority.
@@ -131,14 +139,14 @@ double CTransaction::ComputePriority(double dPriorityInputs, unsigned int nTxSiz
// risk encouraging people to create junk outputs to redeem later.
if (nTxSize == 0)
nTxSize = ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION);
+
BOOST_FOREACH(const CTxIn& txin, vin)
{
unsigned int offset = 41U + std::min(110U, (unsigned int)txin.scriptSig.size());
if (nTxSize > offset)
nTxSize -= offset;
}
- if (nTxSize == 0) return 0.0;
- return dPriorityInputs / nTxSize;
+ return nTxSize;
}
std::string CTransaction::ToString() const
diff --git a/src/core.h b/src/core.h
index 34c00c4142..9a2ac47487 100644
--- a/src/core.h
+++ b/src/core.h
@@ -6,7 +6,8 @@
#ifndef BITCOIN_CORE_H
#define BITCOIN_CORE_H
-#include "script.h"
+#include "script/compressor.h"
+#include "script/script.h"
#include "serialize.h"
#include "uint256.h"
@@ -31,7 +32,7 @@ public:
COutPoint() { SetNull(); }
COutPoint(uint256 hashIn, uint32_t nIn) { hash = hashIn; n = nIn; }
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
@@ -91,7 +92,7 @@ public:
explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=std::numeric_limits<unsigned int>::max());
CTxIn(uint256 hashPrevTx, uint32_t nOut, CScript scriptSigIn=CScript(), uint32_t nSequenceIn=std::numeric_limits<uint32_t>::max());
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
@@ -145,7 +146,7 @@ public:
friend bool operator>=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK >= b.nSatoshisPerK; }
std::string ToString() const;
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
@@ -170,7 +171,7 @@ public:
CTxOut(int64_t nValueIn, CScript scriptPubKeyIn);
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
@@ -253,18 +254,16 @@ public:
CTransaction& operator=(const CTransaction& tx);
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- bool fRead = ser_action.ForRead();
-
READWRITE(*const_cast<int32_t*>(&this->nVersion));
nVersion = this->nVersion;
READWRITE(*const_cast<std::vector<CTxIn>*>(&vin));
READWRITE(*const_cast<std::vector<CTxOut>*>(&vout));
READWRITE(*const_cast<uint32_t*>(&nLockTime));
- if (fRead)
+ if (ser_action.ForRead())
UpdateHash();
}
@@ -284,6 +283,9 @@ public:
// Compute priority, given priority of inputs and (optionally) tx size
double ComputePriority(double dPriorityInputs, unsigned int nTxSize=0) const;
+ // Compute modified tx size for priority calculation (optionally given tx size)
+ unsigned int CalculateModifiedSize(unsigned int nTxSize=0) const;
+
bool IsCoinBase() const
{
return (vin.size() == 1 && vin[0].prevout.IsNull());
@@ -313,7 +315,7 @@ struct CMutableTransaction
CMutableTransaction();
CMutableTransaction(const CTransaction& tx);
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
@@ -342,12 +344,11 @@ public:
CTxOutCompressor(CTxOut &txoutIn) : txout(txoutIn) { }
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- bool fRead = ser_action.ForRead();
- if (!fRead) {
+ if (!ser_action.ForRead()) {
uint64_t nVal = CompressAmount(txout.nValue);
READWRITE(VARINT(nVal));
} else {
@@ -410,7 +411,7 @@ public:
// undo information for all txins
std::vector<CTxInUndo> vprevout;
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
@@ -443,7 +444,7 @@ public:
SetNull();
}
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
@@ -500,7 +501,7 @@ public:
*((CBlockHeader*)this) = header;
}
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
@@ -550,7 +551,7 @@ struct CBlockLocator
vHave = vHaveIn;
}
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
diff --git a/src/core_io.h b/src/core_io.h
index adf74cce32..6268a3bf58 100644
--- a/src/core_io.h
+++ b/src/core_io.h
@@ -8,9 +8,9 @@
#include <string>
#include <vector>
-class uint256;
class CScript;
class CTransaction;
+class uint256;
class UniValue;
// core_read.cpp
diff --git a/src/core_read.cpp b/src/core_read.cpp
index 57f1397f18..6bd3d9a4fa 100644
--- a/src/core_read.cpp
+++ b/src/core_read.cpp
@@ -3,21 +3,22 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "core_io.h"
+
#include "core.h"
+#include "script/script.h"
#include "serialize.h"
-#include "script.h"
+#include "univalue/univalue.h"
#include "util.h"
-#include <boost/assign/list_of.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/predicate.hpp>
-#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/replace.hpp>
-#include "univalue/univalue.h"
+#include <boost/algorithm/string/split.hpp>
+#include <boost/assign/list_of.hpp>
-using namespace std;
using namespace boost;
using namespace boost::algorithm;
+using namespace std;
CScript ParseScript(std::string s)
{
@@ -97,7 +98,7 @@ bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx)
try {
ssData >> tx;
}
- catch (std::exception &e) {
+ catch (const std::exception &) {
return false;
}
diff --git a/src/core_write.cpp b/src/core_write.cpp
index e66e75515c..cd64aabf63 100644
--- a/src/core_write.cpp
+++ b/src/core_write.cpp
@@ -3,13 +3,15 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "core_io.h"
-#include "univalue/univalue.h"
-#include "script.h"
+
+#include "base58.h"
#include "core.h"
+#include "script/script.h"
+#include "script/standard.h"
#include "serialize.h"
+#include "univalue/univalue.h"
#include "util.h"
#include "utilmoneystr.h"
-#include "base58.h"
#include <boost/foreach.hpp>
diff --git a/src/crypter.cpp b/src/crypter.cpp
index 8f5822dfc5..a872df7024 100644
--- a/src/crypter.cpp
+++ b/src/crypter.cpp
@@ -4,7 +4,7 @@
#include "crypter.h"
-#include "script.h"
+#include "script/script.h"
#include "util.h"
#include <string>
diff --git a/src/crypter.h b/src/crypter.h
index 59efc76508..c7424c9b20 100644
--- a/src/crypter.h
+++ b/src/crypter.h
@@ -43,7 +43,7 @@ public:
// such as the various parameters to scrypt
std::vector<unsigned char> vchOtherDerivationParameters;
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
diff --git a/src/crypto/ripemd160.cpp b/src/crypto/ripemd160.cpp
index 24bd318d43..b5e9f0df49 100644
--- a/src/crypto/ripemd160.cpp
+++ b/src/crypto/ripemd160.cpp
@@ -5,6 +5,7 @@
#include "crypto/ripemd160.h"
#include "crypto/common.h"
+
#include <string.h>
// Internal implementation code.
diff --git a/src/crypto/sha1.cpp b/src/crypto/sha1.cpp
index 304401a50f..819abab579 100644
--- a/src/crypto/sha1.cpp
+++ b/src/crypto/sha1.cpp
@@ -5,6 +5,7 @@
#include "crypto/sha1.h"
#include "crypto/common.h"
+
#include <string.h>
// Internal implementation code.
diff --git a/src/crypto/sha2.cpp b/src/crypto/sha2.cpp
index 99a251cb12..72f191afcd 100644
--- a/src/crypto/sha2.cpp
+++ b/src/crypto/sha2.cpp
@@ -5,6 +5,7 @@
#include "crypto/sha2.h"
#include "crypto/common.h"
+
#include <string.h>
// Internal implementation code.
diff --git a/src/db.cpp b/src/db.cpp
index 4ffbd61edd..edbff6fd49 100644
--- a/src/db.cpp
+++ b/src/db.cpp
@@ -20,6 +20,7 @@
#include <boost/filesystem.hpp>
#include <boost/thread.hpp>
#include <boost/version.hpp>
+
#include <openssl/rand.h>
using namespace std;
diff --git a/src/db.h b/src/db.h
index bba267b84f..999750ff3f 100644
--- a/src/db.h
+++ b/src/db.h
@@ -15,12 +15,14 @@
#include <vector>
#include <boost/filesystem/path.hpp>
+
#include <db_cxx.h>
-struct CBlockLocator;
class CDiskBlockIndex;
class COutPoint;
+struct CBlockLocator;
+
extern unsigned int nWalletDBUpdated;
void ThreadFlushWalletDB(const std::string& strWalletFile);
@@ -129,7 +131,7 @@ protected:
CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK, CLIENT_VERSION);
ssValue >> value;
}
- catch (std::exception &e) {
+ catch (const std::exception &) {
return false;
}
diff --git a/src/hash.h b/src/hash.h
index 98a2d1fb11..bdcd4afb47 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -6,8 +6,8 @@
#ifndef BITCOIN_HASH_H
#define BITCOIN_HASH_H
-#include "crypto/sha2.h"
#include "crypto/ripemd160.h"
+#include "crypto/sha2.h"
#include "serialize.h"
#include "uint256.h"
#include "version.h"
diff --git a/src/init.cpp b/src/init.cpp
index 1450e3481f..67f53e044c 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -11,6 +11,7 @@
#include "addrman.h"
#include "checkpoints.h"
+#include "compat/sanity.h"
#include "key.h"
#include "main.h"
#include "miner.h"
@@ -32,7 +33,6 @@
#ifndef WIN32
#include <signal.h>
#endif
-#include "compat/sanity.h"
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/replace.hpp>
@@ -226,6 +226,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += " -dbcache=<n> " + strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache) + "\n";
strUsage += " -loadblock=<file> " + _("Imports blocks from external blk000??.dat file") + " " + _("on startup") + "\n";
strUsage += " -maxorphanblocks=<n> " + strprintf(_("Keep at most <n> unconnectable blocks in memory (default: %u)"), DEFAULT_MAX_ORPHAN_BLOCKS) + "\n";
+ strUsage += " -maxorphantx=<n> " + strprintf(_("Keep at most <n> unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS) + "\n";
strUsage += " -par=<n> " + strprintf(_("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)"), -(int)boost::thread::hardware_concurrency(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS) + "\n";
strUsage += " -pid=<file> " + _("Specify pid file (default: bitcoind.pid)") + "\n";
strUsage += " -reindex " + _("Rebuild block chain index from current blk000??.dat files") + " " + _("on startup") + "\n";
@@ -401,9 +402,11 @@ void ThreadImport(std::vector<boost::filesystem::path> vImportFiles)
int nFile = 0;
while (true) {
CDiskBlockPos pos(nFile, 0);
+ if (!boost::filesystem::exists(GetBlockPosFilename(pos, "blk")))
+ break; // No block files left to reindex
FILE *file = OpenBlockFile(pos, true);
if (!file)
- break;
+ break; // This error is logged in OpenBlockFile
LogPrintf("Reindexing block file blk%05u.dat...\n", (unsigned int)nFile);
LoadExternalBlockFile(file, &pos);
nFile++;
@@ -630,7 +633,6 @@ bool AppInit2(boost::thread_group& threadGroup)
fPrintToConsole = GetBoolArg("-printtoconsole", false);
fLogTimestamps = GetBoolArg("-logtimestamps", true);
fLogIPs = GetBoolArg("-logips", false);
- setvbuf(stdout, NULL, _IOLBF, 0);
#ifdef ENABLE_WALLET
bool fDisableWallet = GetBoolArg("-disablewallet", false);
#endif
@@ -1031,7 +1033,7 @@ bool AppInit2(boost::thread_group& threadGroup)
{
string strMatch = mapArgs["-printblock"];
int nFound = 0;
- for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
+ for (BlockMap::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
{
uint256 hash = (*mi).first;
if (boost::algorithm::starts_with(hash.ToString(), strMatch))
diff --git a/src/keystore.cpp b/src/keystore.cpp
index 72ae9b0a30..98bc0e9e28 100644
--- a/src/keystore.cpp
+++ b/src/keystore.cpp
@@ -7,7 +7,7 @@
#include "crypter.h"
#include "key.h"
-#include "script.h"
+#include "script/script.h"
#include "util.h"
#include <boost/foreach.hpp>
diff --git a/src/leveldbwrapper.h b/src/leveldbwrapper.h
index 452df92839..29bc71f99d 100644
--- a/src/leveldbwrapper.h
+++ b/src/leveldbwrapper.h
@@ -10,6 +10,7 @@
#include "version.h"
#include <boost/filesystem/path.hpp>
+
#include <leveldb/db.h>
#include <leveldb/write_batch.h>
@@ -99,7 +100,7 @@ public:
try {
CDataStream ssValue(strValue.data(), strValue.data() + strValue.size(), SER_DISK, CLIENT_VERSION);
ssValue >> value;
- } catch(std::exception &e) {
+ } catch(const std::exception &) {
return false;
}
return true;
diff --git a/src/main.cpp b/src/main.cpp
index 4aebdadd3b..90f4e48af0 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -38,7 +38,7 @@ using namespace boost;
CCriticalSection cs_main;
-map<uint256, CBlockIndex*> mapBlockIndex;
+BlockMap mapBlockIndex;
CChain chainActive;
int64_t nTimeBestReceived = 0;
CWaitableCriticalSection csBestBlock;
@@ -63,8 +63,13 @@ struct COrphanBlock {
map<uint256, COrphanBlock*> mapOrphanBlocks;
multimap<uint256, COrphanBlock*> mapOrphanBlocksByPrev;
-map<uint256, CTransaction> mapOrphanTransactions;
+struct COrphanTx {
+ CTransaction tx;
+ NodeId fromPeer;
+};
+map<uint256, COrphanTx> mapOrphanTransactions;
map<uint256, set<uint256> > mapOrphanTransactionsByPrev;
+void EraseOrphansFor(NodeId peer);
// Constant stuff for coinbase transactions we create:
CScript COINBASE_FLAGS;
@@ -264,6 +269,7 @@ void FinalizeNode(NodeId nodeid) {
mapBlocksInFlight.erase(entry.hash);
BOOST_FOREACH(const uint256& hash, state->vBlocksToDownload)
mapBlocksToDownload.erase(hash);
+ EraseOrphansFor(nodeid);
mapNodeState.erase(nodeid);
}
@@ -328,7 +334,7 @@ void ProcessBlockAvailability(NodeId nodeid) {
assert(state != NULL);
if (state->hashLastUnknownBlock != 0) {
- map<uint256, CBlockIndex*>::iterator itOld = mapBlockIndex.find(state->hashLastUnknownBlock);
+ BlockMap::iterator itOld = mapBlockIndex.find(state->hashLastUnknownBlock);
if (itOld != mapBlockIndex.end() && itOld->second->nChainWork > 0) {
if (state->pindexBestKnownBlock == NULL || itOld->second->nChainWork >= state->pindexBestKnownBlock->nChainWork)
state->pindexBestKnownBlock = itOld->second;
@@ -344,7 +350,7 @@ void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) {
ProcessBlockAvailability(nodeid);
- map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(hash);
+ BlockMap::iterator it = mapBlockIndex.find(hash);
if (it != mapBlockIndex.end() && it->second->nChainWork > 0) {
// An actually better block was announced.
if (state->pindexBestKnownBlock == NULL || it->second->nChainWork >= state->pindexBestKnownBlock->nChainWork)
@@ -434,7 +440,7 @@ CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const {
CBlockIndex *CChain::FindFork(const CBlockLocator &locator) const {
// Find the first block the caller has in the main chain
BOOST_FOREACH(const uint256& hash, locator.vHave) {
- std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
+ BlockMap::iterator mi = mapBlockIndex.find(hash);
if (mi != mapBlockIndex.end())
{
CBlockIndex* pindex = (*mi).second;
@@ -461,7 +467,7 @@ CBlockTreeDB *pblocktree = NULL;
// mapOrphanTransactions
//
-bool AddOrphanTx(const CTransaction& tx)
+bool AddOrphanTx(const CTransaction& tx, NodeId peer)
{
uint256 hash = tx.GetHash();
if (mapOrphanTransactions.count(hash))
@@ -481,29 +487,50 @@ bool AddOrphanTx(const CTransaction& tx)
return false;
}
- mapOrphanTransactions[hash] = tx;
+ mapOrphanTransactions[hash].tx = tx;
+ mapOrphanTransactions[hash].fromPeer = peer;
BOOST_FOREACH(const CTxIn& txin, tx.vin)
mapOrphanTransactionsByPrev[txin.prevout.hash].insert(hash);
- LogPrint("mempool", "stored orphan tx %s (mapsz %u)\n", hash.ToString(),
- mapOrphanTransactions.size());
+ LogPrint("mempool", "stored orphan tx %s (mapsz %u prevsz %u)\n", hash.ToString(),
+ mapOrphanTransactions.size(), mapOrphanTransactionsByPrev.size());
return true;
}
void static EraseOrphanTx(uint256 hash)
{
- if (!mapOrphanTransactions.count(hash))
+ map<uint256, COrphanTx>::iterator it = mapOrphanTransactions.find(hash);
+ if (it == mapOrphanTransactions.end())
return;
- const CTransaction& tx = mapOrphanTransactions[hash];
- BOOST_FOREACH(const CTxIn& txin, tx.vin)
+ BOOST_FOREACH(const CTxIn& txin, it->second.tx.vin)
+ {
+ map<uint256, set<uint256> >::iterator itPrev = mapOrphanTransactionsByPrev.find(txin.prevout.hash);
+ if (itPrev == mapOrphanTransactionsByPrev.end())
+ continue;
+ itPrev->second.erase(hash);
+ if (itPrev->second.empty())
+ mapOrphanTransactionsByPrev.erase(itPrev);
+ }
+ mapOrphanTransactions.erase(it);
+}
+
+void EraseOrphansFor(NodeId peer)
+{
+ int nErased = 0;
+ map<uint256, COrphanTx>::iterator iter = mapOrphanTransactions.begin();
+ while (iter != mapOrphanTransactions.end())
{
- mapOrphanTransactionsByPrev[txin.prevout.hash].erase(hash);
- if (mapOrphanTransactionsByPrev[txin.prevout.hash].empty())
- mapOrphanTransactionsByPrev.erase(txin.prevout.hash);
+ map<uint256, COrphanTx>::iterator maybeErase = iter++; // increment to avoid iterator becoming invalid
+ if (maybeErase->second.fromPeer == peer)
+ {
+ EraseOrphanTx(maybeErase->second.tx.GetHash());
+ ++nErased;
+ }
}
- mapOrphanTransactions.erase(hash);
+ if (nErased > 0) LogPrint("mempool", "Erased %d orphan tx from peer %d\n", nErased, peer);
}
+
unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans)
{
unsigned int nEvicted = 0;
@@ -511,7 +538,7 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans)
{
// Evict a random orphan:
uint256 randomhash = GetRandHash();
- map<uint256, CTransaction>::iterator it = mapOrphanTransactions.lower_bound(randomhash);
+ map<uint256, COrphanTx>::iterator it = mapOrphanTransactions.lower_bound(randomhash);
if (it == mapOrphanTransactions.end())
it = mapOrphanTransactions.begin();
EraseOrphanTx(it->first);
@@ -1017,9 +1044,9 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
int nHeight = -1;
{
CCoinsViewCache &view = *pcoinsTip;
- CCoins coins;
- if (view.GetCoins(hash, coins))
- nHeight = coins.nHeight;
+ const CCoins* coins = view.AccessCoins(hash);
+ if (coins)
+ nHeight = coins->nHeight;
}
if (nHeight > 0)
pindexSlow = chainActive[nHeight];
@@ -1371,19 +1398,20 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
for (unsigned int i = 0; i < tx.vin.size(); i++)
{
const COutPoint &prevout = tx.vin[i].prevout;
- const CCoins &coins = inputs.GetCoins(prevout.hash);
+ const CCoins *coins = inputs.AccessCoins(prevout.hash);
+ assert(coins);
// If prev is coinbase, check that it's matured
- if (coins.IsCoinBase()) {
- if (nSpendHeight - coins.nHeight < COINBASE_MATURITY)
+ if (coins->IsCoinBase()) {
+ if (nSpendHeight - coins->nHeight < COINBASE_MATURITY)
return state.Invalid(
- error("CheckInputs() : tried to spend coinbase at depth %d", nSpendHeight - coins.nHeight),
+ error("CheckInputs() : tried to spend coinbase at depth %d", nSpendHeight - coins->nHeight),
REJECT_INVALID, "bad-txns-premature-spend-of-coinbase");
}
// Check for negative or overflow input values
- nValueIn += coins.vout[prevout.n].nValue;
- if (!MoneyRange(coins.vout[prevout.n].nValue) || !MoneyRange(nValueIn))
+ nValueIn += coins->vout[prevout.n].nValue;
+ if (!MoneyRange(coins->vout[prevout.n].nValue) || !MoneyRange(nValueIn))
return state.DoS(100, error("CheckInputs() : txin values out of range"),
REJECT_INVALID, "bad-txns-inputvalues-outofrange");
@@ -1413,10 +1441,11 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
if (fScriptChecks) {
for (unsigned int i = 0; i < tx.vin.size(); i++) {
const COutPoint &prevout = tx.vin[i].prevout;
- const CCoins &coins = inputs.GetCoins(prevout.hash);
+ const CCoins* coins = inputs.AccessCoins(prevout.hash);
+ assert(coins);
// Verify signature
- CScriptCheck check(coins, tx, i, flags, 0);
+ CScriptCheck check(*coins, tx, i, flags, 0);
if (pvChecks) {
pvChecks->push_back(CScriptCheck());
check.swap(pvChecks->back());
@@ -1428,7 +1457,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
// arguments; if so, don't trigger DoS protection to
// avoid splitting the network between upgraded and
// non-upgraded nodes.
- CScriptCheck check(coins, tx, i,
+ CScriptCheck check(*coins, tx, i,
flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, 0);
if (check())
return state.Invalid(false, REJECT_NONSTANDARD, "non-mandatory-script-verify-flag");
@@ -1614,8 +1643,8 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
(pindex->nHeight==91880 && pindex->GetBlockHash() == uint256("0x00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721")));
if (fEnforceBIP30) {
BOOST_FOREACH(const CTransaction& tx, block.vtx) {
- const uint256& hash = tx.GetHash();
- if (view.HaveCoins(hash) && !view.GetCoins(hash).IsPruned())
+ const CCoins* coins = view.AccessCoins(tx.GetHash());
+ if (coins && !coins->IsPruned())
return state.DoS(100, error("ConnectBlock() : tried to overwrite transaction"),
REJECT_INVALID, "bad-txns-BIP30");
}
@@ -1773,11 +1802,6 @@ bool static WriteChainState(CValidationState &state) {
void static UpdateTip(CBlockIndex *pindexNew) {
chainActive.SetTip(pindexNew);
- // Update best block in wallet (so we can detect restored wallets)
- bool fIsInitialDownload = IsInitialBlockDownload();
- if ((chainActive.Height() % 20160) == 0 || (!fIsInitialDownload && (chainActive.Height() % 144) == 0))
- g_signals.SetBestChain(chainActive.GetLocator());
-
// New best block
nTimeBestReceived = GetTime();
mempool.AddTransactionsUpdated(1);
@@ -1790,7 +1814,7 @@ void static UpdateTip(CBlockIndex *pindexNew) {
cvBlockChange.notify_all();
// Check the version of the last 100 blocks to see if we need to upgrade:
- if (!fIsInitialDownload)
+ if (!IsInitialBlockDownload())
{
int nUpgraded = 0;
const CBlockIndex* pindex = chainActive.Tip();
@@ -1907,6 +1931,11 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
BOOST_FOREACH(const CTransaction &tx, pblock->vtx) {
SyncWithWallets(tx, pblock);
}
+ // Update best block in wallet (so we can detect restored wallets)
+ // Emit this signal after the SyncWithWallets signals as the wallet relies on that everything up to this point has been synced
+ if ((chainActive.Height() % 20160) == 0 || ((chainActive.Height() % 144) == 0 && !IsInitialBlockDownload()))
+ g_signals.SetBestChain(chainActive.GetLocator());
+
int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1;
LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001);
LogPrint("bench", "- Connect block: %.2fms [%.2fs]\n", (nTime6 - nTime1) * 0.001, nTimeTotal * 0.000001);
@@ -2068,7 +2097,7 @@ CBlockIndex* AddToBlockIndex(CBlockHeader& block)
{
// Check for duplicate
uint256 hash = block.GetHash();
- std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(hash);
+ BlockMap::iterator it = mapBlockIndex.find(hash);
if (it != mapBlockIndex.end())
return it->second;
@@ -2079,9 +2108,9 @@ CBlockIndex* AddToBlockIndex(CBlockHeader& block)
LOCK(cs_nBlockSequenceId);
pindexNew->nSequenceId = nBlockSequenceId++;
}
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
+ BlockMap::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
pindexNew->phashBlock = &((*mi).first);
- map<uint256, CBlockIndex*>::iterator miPrev = mapBlockIndex.find(block.hashPrevBlock);
+ BlockMap::iterator miPrev = mapBlockIndex.find(block.hashPrevBlock);
if (miPrev != mapBlockIndex.end())
{
pindexNew->pprev = (*miPrev).second;
@@ -2294,7 +2323,7 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex
AssertLockHeld(cs_main);
// Check for duplicate
uint256 hash = block.GetHash();
- std::map<uint256, CBlockIndex*>::iterator miSelf = mapBlockIndex.find(hash);
+ BlockMap::iterator miSelf = mapBlockIndex.find(hash);
CBlockIndex *pindex = NULL;
if (miSelf != mapBlockIndex.end()) {
pindex = miSelf->second;
@@ -2302,7 +2331,7 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex
return state.Invalid(error("AcceptBlock() : block is marked invalid"), 0, "duplicate");
}
- CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex);
+ CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint();
if (pcheckpoint && block.hashPrevBlock != (chainActive.Tip() ? chainActive.Tip()->GetBlockHash() : uint256(0)))
{
// Extra checks to prevent "fill up memory by spamming with bogus blocks"
@@ -2323,7 +2352,7 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex
CBlockIndex* pindexPrev = NULL;
int nHeight = 0;
if (hash != Params().HashGenesisBlock()) {
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
+ BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
if (mi == mapBlockIndex.end())
return state.DoS(10, error("AcceptBlock() : prev block not found"), 0, "bad-prevblk");
pindexPrev = (*mi).second;
@@ -2345,7 +2374,7 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex
REJECT_CHECKPOINT, "checkpoint mismatch");
// Don't accept any forks from the main chain prior to last checkpoint
- CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex);
+ CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint();
if (pcheckpoint && nHeight < pcheckpoint->nHeight)
return state.DoS(100, error("AcceptBlock() : forked chain older than last checkpoint (height %d)", nHeight));
@@ -2517,7 +2546,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
return error("ProcessBlock() : CheckBlock FAILED");
// If we don't already have its previous block (with full data), shunt it off to holding area until we get it
- std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(pblock->hashPrevBlock);
+ BlockMap::iterator it = mapBlockIndex.find(pblock->hashPrevBlock);
if (pblock->hashPrevBlock != 0 && (it == mapBlockIndex.end() || !(it->second->nStatus & BLOCK_HAVE_DATA)))
{
LogPrintf("ProcessBlock: ORPHAN BLOCK %lu, prev=%s\n", (unsigned long)mapOrphanBlocks.size(), pblock->hashPrevBlock.ToString());
@@ -2766,7 +2795,7 @@ FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly)
{
if (pos.IsNull())
return NULL;
- boost::filesystem::path path = GetDataDir() / "blocks" / strprintf("%s%05u.dat", prefix, pos.nFile);
+ boost::filesystem::path path = GetBlockPosFilename(pos, prefix);
boost::filesystem::create_directories(path.parent_path());
FILE* file = fopen(path.string().c_str(), "rb+");
if (!file && !fReadOnly)
@@ -2793,13 +2822,18 @@ FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly) {
return OpenDiskFile(pos, "rev", fReadOnly);
}
+boost::filesystem::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix)
+{
+ return GetDataDir() / "blocks" / strprintf("%s%05u.dat", prefix, pos.nFile);
+}
+
CBlockIndex * InsertBlockIndex(uint256 hash)
{
if (hash == 0)
return NULL;
// Return existing
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
+ BlockMap::iterator mi = mapBlockIndex.find(hash);
if (mi != mapBlockIndex.end())
return (*mi).second;
@@ -2876,7 +2910,7 @@ bool static LoadBlockIndexDB()
LogPrintf("LoadBlockIndexDB(): transaction index %s\n", fTxIndex ? "enabled" : "disabled");
// Load pointer to end of best chain
- std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
+ BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
if (it == mapBlockIndex.end())
return true;
chainActive.SetTip(it->second);
@@ -3034,7 +3068,7 @@ void PrintBlockTree()
AssertLockHeld(cs_main);
// pre-compute tree structure
map<CBlockIndex*, vector<CBlockIndex*> > mapNext;
- for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
+ for (BlockMap::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
{
CBlockIndex* pindex = (*mi).second;
mapNext[pindex->pprev].push_back(pindex);
@@ -3134,7 +3168,7 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
blkdat >> nSize;
if (nSize < 80 || nSize > MAX_BLOCK_SIZE)
continue;
- } catch (std::exception &e) {
+ } catch (const std::exception &) {
// no valid block header found; don't complain
break;
}
@@ -3280,13 +3314,13 @@ void static ProcessGetData(CNode* pfrom)
if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK)
{
bool send = false;
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(inv.hash);
+ BlockMap::iterator mi = mapBlockIndex.find(inv.hash);
if (mi != mapBlockIndex.end())
{
// If the requested block is at a height below our last
// checkpoint, only serve it if it's in the checkpointed chain
int nHeight = mi->second->nHeight;
- CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex);
+ CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint();
if (pcheckpoint && nHeight < pcheckpoint->nHeight) {
if (!chainActive.Contains(mi->second))
{
@@ -3638,6 +3672,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
// Track requests for our stuff
g_signals.Inventory(inv.hash);
+
+ if (pfrom->nSendSize > (SendBufferSize() * 2)) {
+ Misbehaving(pfrom->GetId(), 50);
+ return error("send buffer size() = %u", pfrom->nSendSize);
+ }
}
}
@@ -3711,7 +3750,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
if (locator.IsNull())
{
// If locator is null, return the hashStop block
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashStop);
+ BlockMap::iterator mi = mapBlockIndex.find(hashStop);
if (mi == mapBlockIndex.end())
return true;
pindex = (*mi).second;
@@ -3767,33 +3806,47 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
mempool.mapTx.size());
// Recursively process any orphan transactions that depended on this one
+ set<NodeId> setMisbehaving;
for (unsigned int i = 0; i < vWorkQueue.size(); i++)
{
- uint256 hashPrev = vWorkQueue[i];
- for (set<uint256>::iterator mi = mapOrphanTransactionsByPrev[hashPrev].begin();
- mi != mapOrphanTransactionsByPrev[hashPrev].end();
+ map<uint256, set<uint256> >::iterator itByPrev = mapOrphanTransactionsByPrev.find(vWorkQueue[i]);
+ if (itByPrev == mapOrphanTransactionsByPrev.end())
+ continue;
+ for (set<uint256>::iterator mi = itByPrev->second.begin();
+ mi != itByPrev->second.end();
++mi)
{
const uint256& orphanHash = *mi;
- const CTransaction& orphanTx = mapOrphanTransactions[orphanHash];
+ const CTransaction& orphanTx = mapOrphanTransactions[orphanHash].tx;
+ NodeId fromPeer = mapOrphanTransactions[orphanHash].fromPeer;
bool fMissingInputs2 = false;
// Use a dummy CValidationState so someone can't setup nodes to counter-DoS based on orphan
// resolution (that is, feeding people an invalid transaction based on LegitTxX in order to get
// anyone relaying LegitTxX banned)
CValidationState stateDummy;
+ vEraseQueue.push_back(orphanHash);
+
+ if (setMisbehaving.count(fromPeer))
+ continue;
if (AcceptToMemoryPool(mempool, stateDummy, orphanTx, true, &fMissingInputs2))
{
LogPrint("mempool", " accepted orphan tx %s\n", orphanHash.ToString());
RelayTransaction(orphanTx);
mapAlreadyAskedFor.erase(CInv(MSG_TX, orphanHash));
vWorkQueue.push_back(orphanHash);
- vEraseQueue.push_back(orphanHash);
}
else if (!fMissingInputs2)
{
- // invalid or too-little-fee orphan
- vEraseQueue.push_back(orphanHash);
+ int nDos = 0;
+ if (stateDummy.IsInvalid(nDos) && nDos > 0)
+ {
+ // Punish peer that gave us an invalid orphan tx
+ Misbehaving(fromPeer, nDos);
+ setMisbehaving.insert(fromPeer);
+ LogPrint("mempool", " invalid orphan tx %s\n", orphanHash.ToString());
+ }
+ // too-little-fee orphan
LogPrint("mempool", " removed orphan tx %s\n", orphanHash.ToString());
}
mempool.check(pcoinsTip);
@@ -3805,10 +3858,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
}
else if (fMissingInputs)
{
- AddOrphanTx(tx);
+ AddOrphanTx(tx, pfrom->GetId());
// DoS prevention: do not allow mapOrphanTransactions to grow unbounded
- unsigned int nEvicted = LimitOrphanTxSize(MAX_ORPHAN_TRANSACTIONS);
+ unsigned int nMaxOrphanTx = (unsigned int)std::max((int64_t)0, GetArg("-maxorphantx", DEFAULT_MAX_ORPHAN_TRANSACTIONS));
+ unsigned int nEvicted = LimitOrphanTxSize(nMaxOrphanTx);
if (nEvicted > 0)
LogPrint("mempool", "mapOrphan overflow, removed %u tx\n", nEvicted);
} else if (pfrom->fWhitelisted) {
@@ -4136,7 +4190,7 @@ bool ProcessMessages(CNode* pfrom)
// Scan for message start
if (memcmp(msg.hdr.pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE) != 0) {
- LogPrintf("\n\nPROCESSMESSAGE: INVALID MESSAGESTART\n\n");
+ LogPrintf("PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", msg.hdr.GetCommand(), pfrom->id);
fOk = false;
break;
}
@@ -4145,7 +4199,7 @@ bool ProcessMessages(CNode* pfrom)
CMessageHeader& hdr = msg.hdr;
if (!hdr.IsValid())
{
- LogPrintf("\n\nPROCESSMESSAGE: ERRORS IN HEADER %s\n\n\n", hdr.GetCommand());
+ LogPrintf("PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", hdr.GetCommand(), pfrom->id);
continue;
}
string strCommand = hdr.GetCommand();
@@ -4312,7 +4366,9 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
if (pto->addr.IsLocal())
LogPrintf("Warning: not banning local peer %s!\n", pto->addr.ToString());
else
+ {
CNode::Ban(pto->addr);
+ }
}
state.fShouldBan = false;
}
@@ -4392,7 +4448,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
if (!pto->fDisconnect && state.nBlocksInFlight &&
state.nLastBlockReceive < state.nLastBlockProcess - BLOCK_DOWNLOAD_TIMEOUT*1000000 &&
state.vBlocksInFlight.front().nTime < state.nLastBlockProcess - 2*BLOCK_DOWNLOAD_TIMEOUT*1000000) {
- LogPrintf("Peer %s is stalling block download, disconnecting\n", state.name.c_str());
+ LogPrintf("Peer %s is stalling block download, disconnecting\n", state.name);
pto->fDisconnect = true;
}
@@ -4502,7 +4558,7 @@ bool CBlockUndo::ReadFromDisk(const CDiskBlockPos &pos, const uint256 &hashBlock
}
std::string CBlockFileInfo::ToString() const {
- return strprintf("CBlockFileInfo(blocks=%u, size=%u, heights=%u...%u, time=%s...%s)", nBlocks, nSize, nHeightFirst, nHeightLast, DateTimeStrFormat("%Y-%m-%d", nTimeFirst).c_str(), DateTimeStrFormat("%Y-%m-%d", nTimeLast).c_str());
+ 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));
}
@@ -4513,7 +4569,7 @@ public:
CMainCleanup() {}
~CMainCleanup() {
// block headers
- std::map<uint256, CBlockIndex*>::iterator it1 = mapBlockIndex.begin();
+ BlockMap::iterator it1 = mapBlockIndex.begin();
for (; it1 != mapBlockIndex.end(); it1++)
delete (*it1).second;
mapBlockIndex.clear();
@@ -4526,5 +4582,6 @@ public:
// orphan transactions
mapOrphanTransactions.clear();
+ mapOrphanTransactionsByPrev.clear();
}
} instance_of_cmaincleanup;
diff --git a/src/main.h b/src/main.h
index 31a1131b83..f83db59849 100644
--- a/src/main.h
+++ b/src/main.h
@@ -15,7 +15,8 @@
#include "core.h"
#include "net.h"
#include "pow.h"
-#include "script.h"
+#include "script/script.h"
+#include "script/standard.h"
#include "sync.h"
#include "txmempool.h"
#include "uint256.h"
@@ -29,6 +30,8 @@
#include <utility>
#include <vector>
+#include <boost/unordered_map.hpp>
+
class CBlockIndex;
class CBloomFilter;
class CInv;
@@ -48,8 +51,8 @@ static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
static const unsigned int MAX_P2SH_SIGOPS = 15;
/** The maximum number of sigops we're willing to relay/mine in a single tx */
static const unsigned int MAX_TX_SIGOPS = MAX_BLOCK_SIGOPS/5;
-/** The maximum number of orphan transactions kept in memory */
-static const unsigned int MAX_ORPHAN_TRANSACTIONS = MAX_BLOCK_SIZE/100;
+/** Default for -maxorphantx, maximum number of orphan transactions kept in memory */
+static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100;
/** Default for -maxorphanblocks, maximum number of orphan blocks kept in memory */
static const unsigned int DEFAULT_MAX_ORPHAN_BLOCKS = 750;
/** The maximum size of a blk?????.dat file (since 0.8) */
@@ -81,11 +84,16 @@ static const unsigned char REJECT_DUST = 0x41;
static const unsigned char REJECT_INSUFFICIENTFEE = 0x42;
static const unsigned char REJECT_CHECKPOINT = 0x43;
+struct BlockHasher
+{
+ size_t operator()(const uint256& hash) const { return hash.GetLow64(); }
+};
extern CScript COINBASE_FLAGS;
extern CCriticalSection cs_main;
extern CTxMemPool mempool;
-extern std::map<uint256, CBlockIndex*> mapBlockIndex;
+typedef boost::unordered_map<uint256, CBlockIndex*, BlockHasher> BlockMap;
+extern BlockMap mapBlockIndex;
extern uint64_t nLastBlockTx;
extern uint64_t nLastBlockSize;
extern const std::string strMessageMagic;
@@ -138,6 +146,8 @@ bool CheckDiskSpace(uint64_t nAdditionalBytes = 0);
FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly = false);
/** Open an undo file (rev?????.dat) */
FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly = false);
+/** Translation to a filesystem path */
+boost::filesystem::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix);
/** Import blocks from an external file */
bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp = NULL);
/** Initialize a new block tree database + block data on disk */
@@ -197,7 +207,7 @@ struct CDiskBlockPos
int nFile;
unsigned int nPos;
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
@@ -230,7 +240,7 @@ struct CDiskTxPos : public CDiskBlockPos
{
unsigned int nTxOffset; // after header
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
@@ -313,7 +323,7 @@ class CBlockUndo
public:
std::vector<CTxUndo> vtxundo; // for all but the coinbase
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
@@ -420,16 +430,14 @@ protected:
public:
// serialization implementation
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- bool fRead = ser_action.ForRead();
-
READWRITE(nTransactions);
READWRITE(vHash);
std::vector<unsigned char> vBytes;
- if (fRead) {
+ if (ser_action.ForRead()) {
READWRITE(vBytes);
CPartialMerkleTree &us = *(const_cast<CPartialMerkleTree*>(this));
us.vBits.resize(vBytes.size() * 8);
@@ -498,7 +506,7 @@ public:
uint64_t nTimeFirst; // earliest time of block in file
uint64_t nTimeLast; // latest time of block in file
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
@@ -548,15 +556,16 @@ enum BlockStatus {
BLOCK_VALID_TRANSACTIONS = 3, // only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid, no duplicate txids, sigops, size, merkle root
BLOCK_VALID_CHAIN = 4, // outputs do not overspend inputs, no double spends, coinbase output ok, immature coinbase spends, BIP30
BLOCK_VALID_SCRIPTS = 5, // scripts/signatures ok
- BLOCK_VALID_MASK = 7,
+ BLOCK_VALID_MASK = BLOCK_VALID_HEADER | BLOCK_VALID_TREE | BLOCK_VALID_TRANSACTIONS |
+ BLOCK_VALID_CHAIN | BLOCK_VALID_SCRIPTS,
BLOCK_HAVE_DATA = 8, // full block available in blk*.dat
BLOCK_HAVE_UNDO = 16, // undo data available in rev*.dat
- BLOCK_HAVE_MASK = 24,
+ BLOCK_HAVE_MASK = BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO,
BLOCK_FAILED_VALID = 32, // stage after last reached validness failed
BLOCK_FAILED_CHILD = 64, // descends from failed block
- BLOCK_FAILED_MASK = 96
+ BLOCK_FAILED_MASK = BLOCK_FAILED_VALID | BLOCK_FAILED_CHILD,
};
/** The block chain is a tree shaped structure starting with the
@@ -772,7 +781,7 @@ public:
hashPrev = (pprev ? pprev->GetBlockHash() : 0);
}
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
@@ -994,7 +1003,7 @@ public:
// thus the filter will likely be modified.
CMerkleBlock(const CBlock& block, CBloomFilter& filter);
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
diff --git a/src/miner.cpp b/src/miner.cpp
index 96dc80a26d..d05ddbeb1f 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -167,12 +167,13 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
nTotalIn += mempool.mapTx[txin.prevout.hash].GetTx().vout[txin.prevout.n].nValue;
continue;
}
- const CCoins &coins = view.GetCoins(txin.prevout.hash);
+ const CCoins* coins = view.AccessCoins(txin.prevout.hash);
+ assert(coins);
- int64_t nValueIn = coins.vout[txin.prevout.n].nValue;
+ int64_t nValueIn = coins->vout[txin.prevout.n].nValue;
nTotalIn += nValueIn;
- int nConf = pindexPrev->nHeight - coins.nHeight + 1;
+ int nConf = pindexPrev->nHeight - coins->nHeight + 1;
dPriority += (double)nValueIn * nConf;
}
diff --git a/src/net.cpp b/src/net.cpp
index 3966706207..ab547e2fd7 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -48,8 +48,8 @@
#endif
#endif
-using namespace std;
using namespace boost;
+using namespace std;
namespace {
const int MAX_OUTBOUND_CONNECTIONS = 8;
@@ -488,10 +488,6 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
{
addrman.Attempt(addrConnect);
- // Set to non-blocking
- if (!SetSocketNonBlocking(hSocket, true))
- LogPrintf("ConnectNode: Setting socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError()));
-
// Add node
CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false);
pnode->AddRef();
@@ -689,7 +685,7 @@ int CNetMessage::readHeader(const char *pch, unsigned int nBytes)
try {
hdrbuf >> hdr;
}
- catch (std::exception &e) {
+ catch (const std::exception &) {
return -1;
}
@@ -1080,8 +1076,6 @@ void ThreadSocketHandler()
BOOST_FOREACH(CNode* pnode, vNodesCopy)
pnode->Release();
}
-
- MilliSleep(10);
}
}
@@ -1791,7 +1785,6 @@ bool StopNode()
if (semOutbound)
for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
semOutbound->post();
- MilliSleep(50);
DumpAddresses();
return true;
@@ -2109,6 +2102,8 @@ CNode::~CNode()
void CNode::AskFor(const CInv& inv)
{
+ if (mapAskFor.size() > MAPASKFOR_MAX_SZ)
+ return;
// We're using mapAskFor as a priority queue,
// the key is the earliest time the request can be sent
int64_t nRequestTime;
@@ -2117,7 +2112,7 @@ void CNode::AskFor(const CInv& inv)
nRequestTime = it->second;
else
nRequestTime = 0;
- LogPrint("net", "askfor %s %d (%s) peer=%d\n", inv.ToString(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000).c_str(), id);
+ LogPrint("net", "askfor %s %d (%s) peer=%d\n", inv.ToString(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000), id);
// Make sure not to reuse time indexes to keep things in the same order
int64_t nNow = GetTimeMicros() - 1000000;
diff --git a/src/net.h b/src/net.h
index e2700c0975..ad0a1df7e2 100644
--- a/src/net.h
+++ b/src/net.h
@@ -51,6 +51,8 @@ static const bool DEFAULT_UPNP = USE_UPNP;
#else
static const bool DEFAULT_UPNP = false;
#endif
+/** The maximum number of entries in mapAskFor */
+static const size_t MAPASKFOR_MAX_SZ = MAX_INV_SZ;
unsigned int ReceiveFloodSize();
unsigned int SendBufferSize();
diff --git a/src/netbase.cpp b/src/netbase.cpp
index d5821d4465..5819c152a3 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -45,6 +45,9 @@ bool fNameLookup = false;
static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
+// Need ample time for negotiation for very slow proxies such as Tor (milliseconds)
+static const int SOCKS5_RECV_TIMEOUT = 20 * 1000;
+
enum Network ParseNetwork(std::string net) {
boost::to_lower(net);
if (net == "ipv4") return NET_IPV4;
@@ -225,6 +228,63 @@ bool LookupNumeric(const char *pszName, CService& addr, int portDefault)
return Lookup(pszName, addr, portDefault, false);
}
+/**
+ * Convert milliseconds to a struct timeval for select.
+ */
+struct timeval static MillisToTimeval(int64_t nTimeout)
+{
+ struct timeval timeout;
+ timeout.tv_sec = nTimeout / 1000;
+ timeout.tv_usec = (nTimeout % 1000) * 1000;
+ return timeout;
+}
+
+/**
+ * Read bytes from socket. This will either read the full number of bytes requested
+ * or return False on error or timeout.
+ * This function can be interrupted by boost thread interrupt.
+ *
+ * @param data Buffer to receive into
+ * @param len Length of data to receive
+ * @param timeout Timeout in milliseconds for receive operation
+ *
+ * @note This function requires that hSocket is in non-blocking mode.
+ */
+bool static InterruptibleRecv(char* data, size_t len, int timeout, SOCKET& hSocket)
+{
+ int64_t curTime = GetTimeMillis();
+ int64_t endTime = curTime + timeout;
+ // Maximum time to wait in one select call. It will take up until this time (in millis)
+ // to break off in case of an interruption.
+ const int64_t maxWait = 1000;
+ while (len > 0 && curTime < endTime) {
+ ssize_t ret = recv(hSocket, data, len, 0); // Optimistically try the recv first
+ if (ret > 0) {
+ len -= ret;
+ data += ret;
+ } else if (ret == 0) { // Unexpected disconnection
+ return false;
+ } else { // Other error or blocking
+ int nErr = WSAGetLastError();
+ if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) {
+ struct timeval tval = MillisToTimeval(std::min(endTime - curTime, maxWait));
+ fd_set fdset;
+ FD_ZERO(&fdset);
+ FD_SET(hSocket, &fdset);
+ int nRet = select(hSocket + 1, &fdset, NULL, NULL, &tval);
+ if (nRet == SOCKET_ERROR) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ boost::this_thread::interruption_point();
+ curTime = GetTimeMillis();
+ }
+ return len == 0;
+}
+
bool static Socks5(string strDest, int port, SOCKET& hSocket)
{
LogPrintf("SOCKS5 connecting %s\n", strDest);
@@ -243,7 +303,7 @@ bool static Socks5(string strDest, int port, SOCKET& hSocket)
return error("Error sending to proxy");
}
char pchRet1[2];
- if (recv(hSocket, pchRet1, 2, 0) != 2)
+ if (!InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket))
{
CloseSocket(hSocket);
return error("Error reading proxy response");
@@ -259,14 +319,14 @@ bool static Socks5(string strDest, int port, SOCKET& hSocket)
strSocks5 += strDest;
strSocks5 += static_cast<char>((port >> 8) & 0xFF);
strSocks5 += static_cast<char>((port >> 0) & 0xFF);
- ret = send(hSocket, strSocks5.c_str(), strSocks5.size(), MSG_NOSIGNAL);
+ ret = send(hSocket, strSocks5.data(), strSocks5.size(), MSG_NOSIGNAL);
if (ret != (ssize_t)strSocks5.size())
{
CloseSocket(hSocket);
return error("Error sending to proxy");
}
char pchRet2[4];
- if (recv(hSocket, pchRet2, 4, 0) != 4)
+ if (!InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket))
{
CloseSocket(hSocket);
return error("Error reading proxy response");
@@ -300,27 +360,27 @@ bool static Socks5(string strDest, int port, SOCKET& hSocket)
char pchRet3[256];
switch (pchRet2[3])
{
- case 0x01: ret = recv(hSocket, pchRet3, 4, 0) != 4; break;
- case 0x04: ret = recv(hSocket, pchRet3, 16, 0) != 16; break;
+ case 0x01: ret = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, hSocket); break;
+ case 0x04: ret = InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, hSocket); break;
case 0x03:
{
- ret = recv(hSocket, pchRet3, 1, 0) != 1;
- if (ret) {
+ ret = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, hSocket);
+ if (!ret) {
CloseSocket(hSocket);
return error("Error reading from proxy");
}
int nRecv = pchRet3[0];
- ret = recv(hSocket, pchRet3, nRecv, 0) != nRecv;
+ ret = InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket);
break;
}
default: CloseSocket(hSocket); return error("Error: malformed proxy response");
}
- if (ret)
+ if (!ret)
{
CloseSocket(hSocket);
return error("Error reading from proxy");
}
- if (recv(hSocket, pchRet3, 2, 0) != 2)
+ if (!InterruptibleRecv(pchRet3, 2, SOCKS5_RECV_TIMEOUT, hSocket))
{
CloseSocket(hSocket);
return error("Error reading from proxy");
@@ -360,10 +420,7 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
// WSAEINVAL is here because some legacy version of winsock uses it
if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL)
{
- struct timeval timeout;
- timeout.tv_sec = nTimeout / 1000;
- timeout.tv_usec = (nTimeout % 1000) * 1000;
-
+ struct timeval timeout = MillisToTimeval(nTimeout);
fd_set fdset;
FD_ZERO(&fdset);
FD_SET(hSocket, &fdset);
@@ -410,11 +467,6 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe
}
}
- // This is required when using SOCKS5 proxy!
- // CNode::ConnectNode turns the socket back to non-blocking.
- if (!SetSocketNonBlocking(hSocket, false))
- return error("ConnectSocketDirectly: Setting socket to blocking failed, error %s\n", NetworkErrorString(WSAGetLastError()));
-
hSocketRet = hSocket;
return true;
}
diff --git a/src/netbase.h b/src/netbase.h
index 9b52c0a415..9fc5c72eb8 100644
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -88,7 +88,7 @@ class CNetAddr
friend bool operator!=(const CNetAddr& a, const CNetAddr& b);
friend bool operator<(const CNetAddr& a, const CNetAddr& b);
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
@@ -150,15 +150,14 @@ class CService : public CNetAddr
CService(const struct in6_addr& ipv6Addr, unsigned short port);
CService(const struct sockaddr_in6& addr);
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- bool fRead = ser_action.ForRead();
READWRITE(FLATDATA(ip));
unsigned short portN = htons(port);
READWRITE(portN);
- if (fRead)
+ if (ser_action.ForRead())
port = ntohs(portN);
}
};
diff --git a/src/pow.h b/src/pow.h
index 2a0d9b24bb..5d91108ac4 100644
--- a/src/pow.h
+++ b/src/pow.h
@@ -8,8 +8,8 @@
#include <stdint.h>
-class CBlockIndex;
class CBlockHeader;
+class CBlockIndex;
class uint256;
unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock);
diff --git a/src/protocol.h b/src/protocol.h
index e4b0991774..82d29e66de 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -35,7 +35,7 @@ class CMessageHeader
std::string GetCommand() const;
bool IsValid() const;
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
@@ -85,20 +85,17 @@ class CAddress : public CService
void Init();
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- bool fRead = ser_action.ForRead();
-
- CAddress* pthis = const_cast<CAddress*>(this);
- if (fRead)
- pthis->Init();
+ if (ser_action.ForRead())
+ Init();
if (nType & SER_DISK)
READWRITE(nVersion);
if ((nType & SER_DISK) ||
(nVersion >= CADDR_TIME_VERSION && !(nType & SER_GETHASH)))
- READWRITE(nTime);
+ READWRITE(nTime);
READWRITE(nServices);
READWRITE(*(CService*)this);
}
@@ -122,7 +119,7 @@ class CInv
CInv(int typeIn, const uint256& hashIn);
CInv(const std::string& strType, const uint256& hashIn);
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
diff --git a/src/qt/bitcoinunits.cpp b/src/qt/bitcoinunits.cpp
index 6f506d3f25..3215363fa0 100644
--- a/src/qt/bitcoinunits.cpp
+++ b/src/qt/bitcoinunits.cpp
@@ -115,11 +115,6 @@ QString BitcoinUnits::format(int unit, qint64 n, bool fPlus, SeparatorStyle sepa
for (int i = 3; i < q_size; i += 3)
quotient_str.insert(q_size - i, thin_sp);
- int r_size = remainder_str.size();
- if (separators == separatorAlways || (separators == separatorStandard && r_size > 4))
- for (int i = 3, adj = 0; i < r_size ; i += 3, adj++)
- remainder_str.insert(i + adj, thin_sp);
-
if (n < 0)
quotient_str.insert(0, '-');
else if (fPlus && n > 0)
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index 7b30f8de09..d10463fd8f 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -705,7 +705,7 @@ void CoinControlDialog::updateView()
QString sAddress = "";
if(ExtractDestination(out.tx->vout[out.i].scriptPubKey, outputAddress))
{
- sAddress = CBitcoinAddress(outputAddress).ToString().c_str();
+ sAddress = QString::fromStdString(CBitcoinAddress(outputAddress).ToString());
// if listMode or change => show bitcoin address. In tree mode, address is not shown again for direct wallet address outputs
if (!treeMode || (!(sAddress == sWalletAddress)))
@@ -752,7 +752,7 @@ void CoinControlDialog::updateView()
// transaction hash
uint256 txhash = out.tx->GetHash();
- itemOutput->setText(COLUMN_TXHASH, txhash.GetHex().c_str());
+ itemOutput->setText(COLUMN_TXHASH, QString::fromStdString(txhash.GetHex()));
// vout index
itemOutput->setText(COLUMN_VOUT_INDEX, QString::number(out.i));
diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp
index 15501b8a8a..90762bea5d 100644
--- a/src/qt/overviewpage.cpp
+++ b/src/qt/overviewpage.cpp
@@ -172,7 +172,7 @@ void OverviewPage::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64
// for symmetry reasons also show immature label when the watch-only one is shown
ui->labelImmature->setVisible(showImmature || showWatchOnlyImmature);
ui->labelImmatureText->setVisible(showImmature || showWatchOnlyImmature);
- ui->labelWatchImmature->setVisible(showWatchOnlyImmature); // show watch-only immature balance
+ ui->labelWatchImmature->setVisible(showWatchOnlyImmature); // show watch-only immature balance
}
// show/hide watch-only labels
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index f6a4b599de..219a685faf 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -10,6 +10,7 @@
#include "optionsmodel.h"
#include "base58.h"
+#include "chainparams.h"
#include "ui_interface.h"
#include "util.h"
#include "wallet.h"
@@ -200,8 +201,11 @@ bool PaymentServer::ipcParseCommandLine(int argc, char* argv[])
{
CBitcoinAddress address(r.address.toStdString());
- SelectParams(CBaseChainParams::MAIN);
- if (!address.IsValid())
+ if (address.IsValid(Params(CBaseChainParams::MAIN)))
+ {
+ SelectParams(CBaseChainParams::MAIN);
+ }
+ else if (address.IsValid(Params(CBaseChainParams::TESTNET)))
{
SelectParams(CBaseChainParams::TESTNET);
}
diff --git a/src/qt/recentrequeststablemodel.h b/src/qt/recentrequeststablemodel.h
index a558aa4942..3df5971823 100644
--- a/src/qt/recentrequeststablemodel.h
+++ b/src/qt/recentrequeststablemodel.h
@@ -24,23 +24,19 @@ public:
QDateTime date;
SendCoinsRecipient recipient;
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- bool fRead = ser_action.ForRead();
-
- RecentRequestEntry* pthis = const_cast<RecentRequestEntry*>(this);
-
unsigned int nDate = date.toTime_t();
- READWRITE(pthis->nVersion);
- nVersion = pthis->nVersion;
+ READWRITE(this->nVersion);
+ nVersion = this->nVersion;
READWRITE(id);
READWRITE(nDate);
READWRITE(recipient);
- if (fRead)
+ if (ser_action.ForRead())
date = QDateTime::fromTime_t(nDate);
}
};
diff --git a/src/qt/test/paymentrequestdata.h b/src/qt/test/paymentrequestdata.h
index 49558165f0..aeaa7d89a0 100644
--- a/src/qt/test/paymentrequestdata.h
+++ b/src/qt/test/paymentrequestdata.h
@@ -1,3 +1,7 @@
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
//
// Data for paymentservertests.cpp
//
diff --git a/src/qt/test/paymentservertests.cpp b/src/qt/test/paymentservertests.cpp
index e92a7d2b1a..5d7fe96285 100644
--- a/src/qt/test/paymentservertests.cpp
+++ b/src/qt/test/paymentservertests.cpp
@@ -1,3 +1,7 @@
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
#include "paymentservertests.h"
#include "optionsmodel.h"
@@ -21,7 +25,6 @@ X509 *parse_b64der_cert(const char* cert_data)
return cert;
}
-
//
// Test payment request handling
//
@@ -30,7 +33,7 @@ static SendCoinsRecipient handleRequest(PaymentServer* server, std::vector<unsig
{
RecipientCatcher sigCatcher;
QObject::connect(server, SIGNAL(receivedPaymentRequest(SendCoinsRecipient)),
- &sigCatcher, SLOT(getRecipient(SendCoinsRecipient)));
+ &sigCatcher, SLOT(getRecipient(SendCoinsRecipient)));
// Write data to a temp file:
QTemporaryFile f;
@@ -48,7 +51,7 @@ static SendCoinsRecipient handleRequest(PaymentServer* server, std::vector<unsig
QCoreApplication::sendEvent(&object, &event);
QObject::disconnect(server, SIGNAL(receivedPaymentRequest(SendCoinsRecipient)),
- &sigCatcher, SLOT(getRecipient(SendCoinsRecipient)));
+ &sigCatcher, SLOT(getRecipient(SendCoinsRecipient)));
// Return results from sigCatcher
return sigCatcher.recipient;
diff --git a/src/qt/test/paymentservertests.h b/src/qt/test/paymentservertests.h
index 884e535a60..9b6400b0d5 100644
--- a/src/qt/test/paymentservertests.h
+++ b/src/qt/test/paymentservertests.h
@@ -1,3 +1,7 @@
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
#ifndef PAYMENTSERVERTESTS_H
#define PAYMENTSERVERTESTS_H
@@ -15,8 +19,8 @@ private slots:
};
// Dummy class to receive paymentserver signals.
-// If SendCoinsRecipient was a proper QObject, then we could use
-// QSignalSpy... but it's not.
+// If SendCoinsRecipient was a proper QObject, then
+// we could use QSignalSpy... but it's not.
class RecipientCatcher : public QObject
{
Q_OBJECT
diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp
index 03a2381c06..f2161c2f79 100644
--- a/src/qt/test/test_main.cpp
+++ b/src/qt/test/test_main.cpp
@@ -1,11 +1,16 @@
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
#if defined(HAVE_CONFIG_H)
#include "config/bitcoin-config.h"
#endif
+#include "uritests.h"
+
#ifdef ENABLE_WALLET
#include "paymentservertests.h"
#endif
-#include "uritests.h"
#include <QCoreApplication>
#include <QObject>
diff --git a/src/qt/test/uritests.cpp b/src/qt/test/uritests.cpp
index 5c0f4406a7..78a7b1b9b4 100644
--- a/src/qt/test/uritests.cpp
+++ b/src/qt/test/uritests.cpp
@@ -1,3 +1,7 @@
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
#include "uritests.h"
#include "guiutil.h"
diff --git a/src/qt/test/uritests.h b/src/qt/test/uritests.h
index 17d4280a90..1ea6d9f075 100644
--- a/src/qt/test/uritests.h
+++ b/src/qt/test/uritests.h
@@ -1,3 +1,7 @@
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
#ifndef URITESTS_H
#define URITESTS_H
diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp
index 8258e719a3..727b8dc66d 100644
--- a/src/qt/transactiondesc.cpp
+++ b/src/qt/transactiondesc.cpp
@@ -11,7 +11,7 @@
#include "db.h"
#include "main.h"
#include "paymentserver.h"
-#include "script.h"
+#include "script/script.h"
#include "transactionrecord.h"
#include "timedata.h"
#include "ui_interface.h"
diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp
index d7bd25e08b..20c1449c92 100644
--- a/src/qt/transactionrecord.cpp
+++ b/src/qt/transactionrecord.cpp
@@ -170,7 +170,7 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
// Find the block the tx is in
CBlockIndex* pindex = NULL;
- std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(wtx.hashBlock);
+ BlockMap::iterator mi = mapBlockIndex.find(wtx.hashBlock);
if (mi != mapBlockIndex.end())
pindex = (*mi).second;
diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp
index 1a1f726bf8..734c7afc4e 100644
--- a/src/qt/transactiontablemodel.cpp
+++ b/src/qt/transactiontablemodel.cpp
@@ -394,19 +394,25 @@ QVariant TransactionTableModel::txAddressDecoration(const TransactionRecord *wtx
QString TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx, bool tooltip) const
{
+ QString watchAddress;
+ if (tooltip) {
+ // Mark transactions involving watch-only addresses by adding " (watch-only)"
+ watchAddress = wtx->involvesWatchAddress ? QString(" (") + tr("watch-only") + QString(")") : "";
+ }
+
switch(wtx->type)
{
case TransactionRecord::RecvFromOther:
- return QString::fromStdString(wtx->address);
+ return QString::fromStdString(wtx->address) + watchAddress;
case TransactionRecord::RecvWithAddress:
case TransactionRecord::SendToAddress:
case TransactionRecord::Generated:
- return lookupAddress(wtx->address, tooltip);
+ return lookupAddress(wtx->address, tooltip) + watchAddress;
case TransactionRecord::SendToOther:
- return QString::fromStdString(wtx->address);
+ return QString::fromStdString(wtx->address) + watchAddress;
case TransactionRecord::SendToSelf:
default:
- return tr("(n/a)");
+ return tr("(n/a)") + watchAddress;
}
}
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index 2d34d58129..a7ba100cd2 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -331,7 +331,7 @@ void TransactionView::exportClicked()
writer.setModel(transactionProxyModel);
writer.addColumn(tr("Confirmed"), 0, TransactionTableModel::ConfirmedRole);
if (model && model->haveWatchOnly())
- writer.addColumn(tr("Watchonly"), TransactionTableModel::Watchonly);
+ writer.addColumn(tr("Watch-only"), TransactionTableModel::Watchonly);
writer.addColumn(tr("Date"), 0, TransactionTableModel::DateRole);
writer.addColumn(tr("Type"), TransactionTableModel::Type, Qt::EditRole);
writer.addColumn(tr("Label"), 0, TransactionTableModel::LabelRole);
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index 92c22f5692..8d2c2e96d8 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -36,6 +36,7 @@ WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *p
{
fProcessingQueuedTransactions = false;
fHaveWatchOnly = wallet->HaveWatchOnly();
+ fForceCheckBalanceChanged = false;
addressTableModel = new AddressTableModel(wallet, this);
transactionTableModel = new TransactionTableModel(wallet, this);
@@ -121,8 +122,10 @@ void WalletModel::pollBalanceChanged()
if(!lockWallet)
return;
- if(chainActive.Height() != cachedNumBlocks)
+ if(fForceCheckBalanceChanged || chainActive.Height() != cachedNumBlocks)
{
+ fForceCheckBalanceChanged = false;
+
// Balance and number of transactions might have changed
cachedNumBlocks = chainActive.Height();
@@ -167,7 +170,7 @@ void WalletModel::updateTransaction(const QString &hash, int status)
transactionTableModel->updateTransaction(hash, status);
// Balance and number of transactions might have changed
- checkBalanceChanged();
+ fForceCheckBalanceChanged = true;
}
void WalletModel::updateAddressBook(const QString &address, const QString &label,
@@ -344,6 +347,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
}
emit coinsSent(wallet, rcp, transaction_array);
}
+ checkBalanceChanged(); // update balance immediately, otherwise there could be a short noticeable delay until pollBalanceChanged hits
return SendCoinsReturn(OK);
}
@@ -473,11 +477,6 @@ static void NotifyTransactionChanged(WalletModel *walletmodel, CWallet *wallet,
static void ShowProgress(WalletModel *walletmodel, const std::string &title, int nProgress)
{
- // emits signal "showProgress"
- QMetaObject::invokeMethod(walletmodel, "showProgress", Qt::QueuedConnection,
- Q_ARG(QString, QString::fromStdString(title)),
- Q_ARG(int, nProgress));
-
if (nProgress == 0)
fQueueNotifications = true;
@@ -495,6 +494,11 @@ static void ShowProgress(WalletModel *walletmodel, const std::string &title, int
}
std::vector<std::pair<uint256, ChangeType> >().swap(vQueueNotifications); // clear
}
+
+ // emits signal "showProgress"
+ QMetaObject::invokeMethod(walletmodel, "showProgress", Qt::QueuedConnection,
+ Q_ARG(QString, QString::fromStdString(title)),
+ Q_ARG(int, nProgress));
}
static void NotifyWatchonlyChanged(WalletModel *walletmodel, bool fHaveWatchonly)
@@ -618,7 +622,7 @@ void WalletModel::listCoins(std::map<QString, std::vector<COutput> >& mapCoins)
CTxDestination address;
if(!out.fSpendable || !ExtractDestination(cout.tx->vout[cout.i].scriptPubKey, address))
continue;
- mapCoins[CBitcoinAddress(address).ToString().c_str()].push_back(out);
+ mapCoins[QString::fromStdString(CBitcoinAddress(address).ToString())].push_back(out);
}
}
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index 2a9ac4650f..111ae2178c 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -59,24 +59,20 @@ public:
static const int CURRENT_VERSION = 1;
int nVersion;
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- bool fRead = ser_action.ForRead();
-
- SendCoinsRecipient* pthis = const_cast<SendCoinsRecipient*>(this);
-
- std::string sAddress = pthis->address.toStdString();
- std::string sLabel = pthis->label.toStdString();
- std::string sMessage = pthis->message.toStdString();
+ std::string sAddress = address.toStdString();
+ std::string sLabel = label.toStdString();
+ std::string sMessage = message.toStdString();
std::string sPaymentRequest;
- if (!fRead && pthis->paymentRequest.IsInitialized())
- pthis->paymentRequest.SerializeToString(&sPaymentRequest);
- std::string sAuthenticatedMerchant = pthis->authenticatedMerchant.toStdString();
+ if (!ser_action.ForRead() && paymentRequest.IsInitialized())
+ paymentRequest.SerializeToString(&sPaymentRequest);
+ std::string sAuthenticatedMerchant = authenticatedMerchant.toStdString();
- READWRITE(pthis->nVersion);
- nVersion = pthis->nVersion;
+ READWRITE(this->nVersion);
+ nVersion = this->nVersion;
READWRITE(sAddress);
READWRITE(sLabel);
READWRITE(amount);
@@ -84,14 +80,14 @@ public:
READWRITE(sPaymentRequest);
READWRITE(sAuthenticatedMerchant);
- if (fRead)
+ if (ser_action.ForRead())
{
- pthis->address = QString::fromStdString(sAddress);
- pthis->label = QString::fromStdString(sLabel);
- pthis->message = QString::fromStdString(sMessage);
+ address = QString::fromStdString(sAddress);
+ label = QString::fromStdString(sLabel);
+ message = QString::fromStdString(sMessage);
if (!sPaymentRequest.empty())
- pthis->paymentRequest.parse(QByteArray::fromRawData(sPaymentRequest.data(), sPaymentRequest.size()));
- pthis->authenticatedMerchant = QString::fromStdString(sAuthenticatedMerchant);
+ paymentRequest.parse(QByteArray::fromRawData(sPaymentRequest.data(), sPaymentRequest.size()));
+ authenticatedMerchant = QString::fromStdString(sAuthenticatedMerchant);
}
}
};
@@ -203,6 +199,7 @@ private:
CWallet *wallet;
bool fProcessingQueuedTransactions;
bool fHaveWatchOnly;
+ bool fForceCheckBalanceChanged;
// Wallet has an options model for wallet-specific options
// (transaction fee, for example)
@@ -260,7 +257,7 @@ public slots:
void updateTransaction(const QString &hash, int status);
/* New, updated or removed address book entry */
void updateAddressBook(const QString &address, const QString &label, bool isMine, const QString &purpose, int status);
- /* Watchonly added */
+ /* Watch-only added */
void updateWatchOnlyFlag(bool fHaveWatchonly);
/* Current, immature or unconfirmed balance might have changed - emit 'balanceChanged' if so */
void pollBalanceChanged();
diff --git a/src/random.cpp b/src/random.cpp
index 22c942acc0..fb5258a442 100644
--- a/src/random.cpp
+++ b/src/random.cpp
@@ -12,10 +12,12 @@
#include "util.h" // for LogPrint()
#include "utilstrencodings.h" // for GetTime()
+#include <limits>
+
#ifndef WIN32
#include <sys/time.h>
#endif
-#include <limits>
+
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/rand.h>
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index 83fe629351..4b3beae20c 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -392,7 +392,7 @@ Value gettxout(const Array& params, bool fHelp)
if (n<0 || (unsigned int)n>=coins.vout.size() || coins.vout[n].IsNull())
return Value::null;
- std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
+ BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
CBlockIndex *pindex = it->second;
ret.push_back(Pair("bestblock", pindex->GetBlockHash().GetHex()));
if ((unsigned int)coins.nHeight == MEMPOOL_HEIGHT)
diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp
index a0921453cc..81797248b4 100644
--- a/src/rpcclient.cpp
+++ b/src/rpcclient.cpp
@@ -3,7 +3,6 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <set>
#include "rpcclient.h"
#include "rpcprotocol.h"
@@ -11,6 +10,7 @@
#include "ui_interface.h"
#include "chainparams.h" // for Params().RPCPort()
+#include <set>
#include <stdint.h>
using namespace std;
diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp
index c286626fd3..dc73161bf1 100644
--- a/src/rpcdump.cpp
+++ b/src/rpcdump.cpp
@@ -7,8 +7,8 @@
#include "init.h"
#include "main.h"
#include "sync.h"
-#include "utiltime.h"
#include "util.h"
+#include "utiltime.h"
#include "wallet.h"
#include <fstream>
@@ -16,6 +16,7 @@
#include <boost/algorithm/string.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
+
#include "json/json_spirit_value.h"
using namespace json_spirit;
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index e4a5bc4162..82eaf5d037 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -3,14 +3,14 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "rpcserver.h"
#include "chainparams.h"
+#include "core_io.h"
#include "init.h"
#include "net.h"
#include "main.h"
#include "miner.h"
#include "pow.h"
-#include "core_io.h"
+#include "rpcserver.h"
#include "util.h"
#ifdef ENABLE_WALLET
#include "db.h"
@@ -553,7 +553,7 @@ Value submitblock(const Array& params, bool fHelp)
try {
ssBlock >> pblock;
}
- catch (std::exception &e) {
+ catch (const std::exception &) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
}
diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp
index bd992397b8..917c840536 100644
--- a/src/rpcmisc.cpp
+++ b/src/rpcmisc.cpp
@@ -74,8 +74,8 @@ Value getinfo(const Array& params, bool fHelp)
GetProxy(NET_IPV4, proxy);
Object obj;
- obj.push_back(Pair("version", (int)CLIENT_VERSION));
- obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
+ obj.push_back(Pair("version", CLIENT_VERSION));
+ obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
#ifdef ENABLE_WALLET
if (pwalletMain) {
obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp
index 2baa481c4e..4afbe442ee 100644
--- a/src/rpcnet.cpp
+++ b/src/rpcnet.cpp
@@ -13,6 +13,7 @@
#include "util.h"
#include <boost/foreach.hpp>
+
#include "json/json_spirit_value.h"
using namespace json_spirit;
diff --git a/src/rpcprotocol.cpp b/src/rpcprotocol.cpp
index 808b9bbd2a..c99d113bc3 100644
--- a/src/rpcprotocol.cpp
+++ b/src/rpcprotocol.cpp
@@ -5,8 +5,8 @@
#include "rpcprotocol.h"
-#include "util.h"
#include "tinyformat.h"
+#include "util.h"
#include "utilstrencodings.h"
#include "utiltime.h"
#include "version.h"
diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index 7cd704193d..1828a5dc7d 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -11,6 +11,9 @@
#include "main.h"
#include "net.h"
#include "rpcserver.h"
+#include "script/script.h"
+#include "script/sign.h"
+#include "script/standard.h"
#include "uint256.h"
#ifdef ENABLE_WALLET
#include "wallet.h"
@@ -22,10 +25,10 @@
#include "json/json_spirit_utils.h"
#include "json/json_spirit_value.h"
-using namespace std;
using namespace boost;
using namespace boost::assign;
using namespace json_spirit;
+using namespace std;
void ScriptPubKeyToJSON(const CScript& scriptPubKey, Object& out, bool fIncludeHex)
{
@@ -88,7 +91,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
if (hashBlock != 0) {
entry.push_back(Pair("blockhash", hashBlock.GetHex()));
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
+ BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
if (mi != mapBlockIndex.end() && (*mi).second) {
CBlockIndex* pindex = (*mi).second;
if (chainActive.Contains(pindex)) {
@@ -540,7 +543,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
ssData >> tx;
txVariants.push_back(tx);
}
- catch (std::exception &e) {
+ catch (const std::exception &) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
}
}
@@ -565,7 +568,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
BOOST_FOREACH(const CTxIn& txin, mergedTx.vin) {
const uint256& prevHash = txin.prevout.hash;
CCoins coins;
- view.GetCoins(prevHash, coins); // this is certainly allowed to fail
+ view.AccessCoins(prevHash); // this is certainly allowed to fail
}
view.SetBackend(viewDummy); // switch back to avoid locking mempool for too long
@@ -669,12 +672,12 @@ Value signrawtransaction(const Array& params, bool fHelp)
// Sign what we can:
for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
CTxIn& txin = mergedTx.vin[i];
- CCoins coins;
- if (!view.GetCoins(txin.prevout.hash, coins) || !coins.IsAvailable(txin.prevout.n)) {
+ const CCoins* coins = view.AccessCoins(txin.prevout.hash);
+ if (coins == NULL || !coins->IsAvailable(txin.prevout.n)) {
fComplete = false;
continue;
}
- const CScript& prevPubKey = coins.vout[txin.prevout.n].scriptPubKey;
+ const CScript& prevPubKey = coins->vout[txin.prevout.n].scriptPubKey;
txin.scriptSig.clear();
// Only sign SIGHASH_SINGLE if there's a corresponding output:
@@ -732,9 +735,9 @@ Value sendrawtransaction(const Array& params, bool fHelp)
fOverrideFees = params[1].get_bool();
CCoinsViewCache &view = *pcoinsTip;
- CCoins existingCoins;
+ const CCoins* existingCoins = view.AccessCoins(hashTx);
bool fHaveMempool = mempool.exists(hashTx);
- bool fHaveChain = view.GetCoins(hashTx, existingCoins) && existingCoins.nHeight < 1000000000;
+ bool fHaveChain = existingCoins && existingCoins->nHeight < 1000000000;
if (!fHaveMempool && !fHaveChain) {
// push to local node and sync with wallets
CValidationState state;
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index c9133bd3d2..190de62282 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -628,7 +628,7 @@ void StartRPCThreads()
try {
vEndpoints.push_back(ParseEndpoint(addr, defaultPort));
}
- catch(boost::system::system_error &e)
+ catch(const boost::system::system_error &)
{
uiInterface.ThreadSafeMessageBox(
strprintf(_("Could not parse -rpcbind value %s as network address"), addr),
diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp
index 078bbc1f13..997b861e59 100644
--- a/src/rpcwallet.cpp
+++ b/src/rpcwallet.cpp
@@ -1447,7 +1447,7 @@ Value listsinceblock(const Array& params, bool fHelp)
uint256 blockId = 0;
blockId.SetHex(params[0].get_str());
- std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(blockId);
+ BlockMap::iterator it = mapBlockIndex.find(blockId);
if (it != mapBlockIndex.end())
pindex = it->second;
}
diff --git a/src/script/compressor.cpp b/src/script/compressor.cpp
new file mode 100644
index 0000000000..51a3cf6025
--- /dev/null
+++ b/src/script/compressor.cpp
@@ -0,0 +1,127 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "compressor.h"
+
+bool CScriptCompressor::IsToKeyID(CKeyID &hash) const
+{
+ if (script.size() == 25 && script[0] == OP_DUP && script[1] == OP_HASH160
+ && script[2] == 20 && script[23] == OP_EQUALVERIFY
+ && script[24] == OP_CHECKSIG) {
+ memcpy(&hash, &script[3], 20);
+ return true;
+ }
+ return false;
+}
+
+bool CScriptCompressor::IsToScriptID(CScriptID &hash) const
+{
+ if (script.size() == 23 && script[0] == OP_HASH160 && script[1] == 20
+ && script[22] == OP_EQUAL) {
+ memcpy(&hash, &script[2], 20);
+ return true;
+ }
+ return false;
+}
+
+bool CScriptCompressor::IsToPubKey(CPubKey &pubkey) const
+{
+ if (script.size() == 35 && script[0] == 33 && script[34] == OP_CHECKSIG
+ && (script[1] == 0x02 || script[1] == 0x03)) {
+ pubkey.Set(&script[1], &script[34]);
+ return true;
+ }
+ if (script.size() == 67 && script[0] == 65 && script[66] == OP_CHECKSIG
+ && script[1] == 0x04) {
+ pubkey.Set(&script[1], &script[66]);
+ return pubkey.IsFullyValid(); // if not fully valid, a case that would not be compressible
+ }
+ return false;
+}
+
+bool CScriptCompressor::Compress(std::vector<unsigned char> &out) const
+{
+ CKeyID keyID;
+ if (IsToKeyID(keyID)) {
+ out.resize(21);
+ out[0] = 0x00;
+ memcpy(&out[1], &keyID, 20);
+ return true;
+ }
+ CScriptID scriptID;
+ if (IsToScriptID(scriptID)) {
+ out.resize(21);
+ out[0] = 0x01;
+ memcpy(&out[1], &scriptID, 20);
+ return true;
+ }
+ CPubKey pubkey;
+ if (IsToPubKey(pubkey)) {
+ out.resize(33);
+ memcpy(&out[1], &pubkey[1], 32);
+ if (pubkey[0] == 0x02 || pubkey[0] == 0x03) {
+ out[0] = pubkey[0];
+ return true;
+ } else if (pubkey[0] == 0x04) {
+ out[0] = 0x04 | (pubkey[64] & 0x01);
+ return true;
+ }
+ }
+ return false;
+}
+
+unsigned int CScriptCompressor::GetSpecialSize(unsigned int nSize) const
+{
+ if (nSize == 0 || nSize == 1)
+ return 20;
+ if (nSize == 2 || nSize == 3 || nSize == 4 || nSize == 5)
+ return 32;
+ return 0;
+}
+
+bool CScriptCompressor::Decompress(unsigned int nSize, const std::vector<unsigned char> &in)
+{
+ switch(nSize) {
+ case 0x00:
+ script.resize(25);
+ script[0] = OP_DUP;
+ script[1] = OP_HASH160;
+ script[2] = 20;
+ memcpy(&script[3], &in[0], 20);
+ script[23] = OP_EQUALVERIFY;
+ script[24] = OP_CHECKSIG;
+ return true;
+ case 0x01:
+ script.resize(23);
+ script[0] = OP_HASH160;
+ script[1] = 20;
+ memcpy(&script[2], &in[0], 20);
+ script[22] = OP_EQUAL;
+ return true;
+ case 0x02:
+ case 0x03:
+ script.resize(35);
+ script[0] = 33;
+ script[1] = nSize;
+ memcpy(&script[2], &in[0], 32);
+ script[34] = OP_CHECKSIG;
+ return true;
+ case 0x04:
+ case 0x05:
+ unsigned char vch[33] = {};
+ vch[0] = nSize - 2;
+ memcpy(&vch[1], &in[0], 32);
+ CPubKey pubkey(&vch[0], &vch[33]);
+ if (!pubkey.Decompress())
+ return false;
+ assert(pubkey.size() == 65);
+ script.resize(67);
+ script[0] = 65;
+ memcpy(&script[1], pubkey.begin(), 65);
+ script[66] = OP_CHECKSIG;
+ return true;
+ }
+ return false;
+}
diff --git a/src/script/compressor.h b/src/script/compressor.h
new file mode 100644
index 0000000000..53c6bf3ecc
--- /dev/null
+++ b/src/script/compressor.h
@@ -0,0 +1,84 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef H_BITCOIN_SCRIPT_COMPRESSOR
+#define H_BITCOIN_SCRIPT_COMPRESSOR
+
+#include "script/script.h"
+
+/** Compact serializer for scripts.
+ *
+ * It detects common cases and encodes them much more efficiently.
+ * 3 special cases are defined:
+ * * Pay to pubkey hash (encoded as 21 bytes)
+ * * Pay to script hash (encoded as 21 bytes)
+ * * Pay to pubkey starting with 0x02, 0x03 or 0x04 (encoded as 33 bytes)
+ *
+ * Other scripts up to 121 bytes require 1 byte + script length. Above
+ * that, scripts up to 16505 bytes require 2 bytes + script length.
+ */
+class CScriptCompressor
+{
+private:
+ // make this static for now (there are only 6 special scripts defined)
+ // this can potentially be extended together with a new nVersion for
+ // transactions, in which case this value becomes dependent on nVersion
+ // and nHeight of the enclosing transaction.
+ static const unsigned int nSpecialScripts = 6;
+
+ CScript &script;
+protected:
+ // These check for scripts for which a special case with a shorter encoding is defined.
+ // They are implemented separately from the CScript test, as these test for exact byte
+ // sequence correspondences, and are more strict. For example, IsToPubKey also verifies
+ // whether the public key is valid (as invalid ones cannot be represented in compressed
+ // form).
+ bool IsToKeyID(CKeyID &hash) const;
+ bool IsToScriptID(CScriptID &hash) const;
+ bool IsToPubKey(CPubKey &pubkey) const;
+
+ bool Compress(std::vector<unsigned char> &out) const;
+ unsigned int GetSpecialSize(unsigned int nSize) const;
+ bool Decompress(unsigned int nSize, const std::vector<unsigned char> &out);
+public:
+ CScriptCompressor(CScript &scriptIn) : script(scriptIn) { }
+
+ unsigned int GetSerializeSize(int nType, int nVersion) const {
+ std::vector<unsigned char> compr;
+ if (Compress(compr))
+ return compr.size();
+ unsigned int nSize = script.size() + nSpecialScripts;
+ return script.size() + VARINT(nSize).GetSerializeSize(nType, nVersion);
+ }
+
+ template<typename Stream>
+ void Serialize(Stream &s, int nType, int nVersion) const {
+ std::vector<unsigned char> compr;
+ if (Compress(compr)) {
+ s << CFlatData(compr);
+ return;
+ }
+ unsigned int nSize = script.size() + nSpecialScripts;
+ s << VARINT(nSize);
+ s << CFlatData(script);
+ }
+
+ template<typename Stream>
+ void Unserialize(Stream &s, int nType, int nVersion) {
+ unsigned int nSize = 0;
+ s >> VARINT(nSize);
+ if (nSize < nSpecialScripts) {
+ std::vector<unsigned char> vch(GetSpecialSize(nSize), 0x00);
+ s >> REF(CFlatData(vch));
+ Decompress(nSize, vch);
+ return;
+ }
+ nSize -= nSpecialScripts;
+ script.resize(nSize);
+ s >> REF(CFlatData(script));
+ }
+};
+
+#endif // H_BITCOIN_SCRIPT_COMPRESSOR
diff --git a/src/script.cpp b/src/script/interpreter.cpp
index 21883bd41a..471edf1c98 100644
--- a/src/script.cpp
+++ b/src/script/interpreter.cpp
@@ -1,31 +1,23 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2013 The Bitcoin developers
-// Distributed under the MIT/X11 software license, see the accompanying
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "script.h"
+#include "interpreter.h"
+#include "core.h"
#include "crypto/ripemd160.h"
#include "crypto/sha1.h"
#include "crypto/sha2.h"
-#include "core.h"
-#include "hash.h"
-#include "key.h"
-#include "keystore.h"
#include "random.h"
-#include "sync.h"
+#include "script/script.h"
#include "uint256.h"
#include "util.h"
-#include <boost/foreach.hpp>
#include <boost/thread.hpp>
#include <boost/tuple/tuple_comparison.hpp>
-#include <boost/tuple/tuple.hpp>
-
-#include <boost/foreach.hpp>
using namespace std;
-using namespace boost;
typedef vector<unsigned char> valtype;
static const valtype vchFalse(0);
@@ -36,8 +28,6 @@ static const CScriptNum bnOne(1);
static const CScriptNum bnFalse(0);
static const CScriptNum bnTrue(1);
-bool CheckSig(vector<unsigned char> vchSig, const vector<unsigned char> &vchPubKey, const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, int flags);
-
bool CastToBool(const valtype& vch)
{
for (unsigned int i = 0; i < vch.size(); i++)
@@ -53,8 +43,6 @@ bool CastToBool(const valtype& vch)
return false;
}
-
-
//
// Script is a stack machine (like Forth) that evaluates a predicate
// returning a bool indicating valid or not. There are no loops.
@@ -68,165 +56,6 @@ static inline void popstack(vector<valtype>& stack)
stack.pop_back();
}
-
-const char* GetTxnOutputType(txnouttype t)
-{
- switch (t)
- {
- case TX_NONSTANDARD: return "nonstandard";
- case TX_PUBKEY: return "pubkey";
- case TX_PUBKEYHASH: return "pubkeyhash";
- case TX_SCRIPTHASH: return "scripthash";
- case TX_MULTISIG: return "multisig";
- case TX_NULL_DATA: return "nulldata";
- }
- return NULL;
-}
-
-
-const char* GetOpName(opcodetype opcode)
-{
- switch (opcode)
- {
- // push value
- case OP_0 : return "0";
- case OP_PUSHDATA1 : return "OP_PUSHDATA1";
- case OP_PUSHDATA2 : return "OP_PUSHDATA2";
- case OP_PUSHDATA4 : return "OP_PUSHDATA4";
- case OP_1NEGATE : return "-1";
- case OP_RESERVED : return "OP_RESERVED";
- case OP_1 : return "1";
- case OP_2 : return "2";
- case OP_3 : return "3";
- case OP_4 : return "4";
- case OP_5 : return "5";
- case OP_6 : return "6";
- case OP_7 : return "7";
- case OP_8 : return "8";
- case OP_9 : return "9";
- case OP_10 : return "10";
- case OP_11 : return "11";
- case OP_12 : return "12";
- case OP_13 : return "13";
- case OP_14 : return "14";
- case OP_15 : return "15";
- case OP_16 : return "16";
-
- // control
- case OP_NOP : return "OP_NOP";
- case OP_VER : return "OP_VER";
- case OP_IF : return "OP_IF";
- case OP_NOTIF : return "OP_NOTIF";
- case OP_VERIF : return "OP_VERIF";
- case OP_VERNOTIF : return "OP_VERNOTIF";
- case OP_ELSE : return "OP_ELSE";
- case OP_ENDIF : return "OP_ENDIF";
- case OP_VERIFY : return "OP_VERIFY";
- case OP_RETURN : return "OP_RETURN";
-
- // stack ops
- case OP_TOALTSTACK : return "OP_TOALTSTACK";
- case OP_FROMALTSTACK : return "OP_FROMALTSTACK";
- case OP_2DROP : return "OP_2DROP";
- case OP_2DUP : return "OP_2DUP";
- case OP_3DUP : return "OP_3DUP";
- case OP_2OVER : return "OP_2OVER";
- case OP_2ROT : return "OP_2ROT";
- case OP_2SWAP : return "OP_2SWAP";
- case OP_IFDUP : return "OP_IFDUP";
- case OP_DEPTH : return "OP_DEPTH";
- case OP_DROP : return "OP_DROP";
- case OP_DUP : return "OP_DUP";
- case OP_NIP : return "OP_NIP";
- case OP_OVER : return "OP_OVER";
- case OP_PICK : return "OP_PICK";
- case OP_ROLL : return "OP_ROLL";
- case OP_ROT : return "OP_ROT";
- case OP_SWAP : return "OP_SWAP";
- case OP_TUCK : return "OP_TUCK";
-
- // splice ops
- case OP_CAT : return "OP_CAT";
- case OP_SUBSTR : return "OP_SUBSTR";
- case OP_LEFT : return "OP_LEFT";
- case OP_RIGHT : return "OP_RIGHT";
- case OP_SIZE : return "OP_SIZE";
-
- // bit logic
- case OP_INVERT : return "OP_INVERT";
- case OP_AND : return "OP_AND";
- case OP_OR : return "OP_OR";
- case OP_XOR : return "OP_XOR";
- case OP_EQUAL : return "OP_EQUAL";
- case OP_EQUALVERIFY : return "OP_EQUALVERIFY";
- case OP_RESERVED1 : return "OP_RESERVED1";
- case OP_RESERVED2 : return "OP_RESERVED2";
-
- // numeric
- case OP_1ADD : return "OP_1ADD";
- case OP_1SUB : return "OP_1SUB";
- case OP_2MUL : return "OP_2MUL";
- case OP_2DIV : return "OP_2DIV";
- case OP_NEGATE : return "OP_NEGATE";
- case OP_ABS : return "OP_ABS";
- case OP_NOT : return "OP_NOT";
- case OP_0NOTEQUAL : return "OP_0NOTEQUAL";
- case OP_ADD : return "OP_ADD";
- case OP_SUB : return "OP_SUB";
- case OP_MUL : return "OP_MUL";
- case OP_DIV : return "OP_DIV";
- case OP_MOD : return "OP_MOD";
- case OP_LSHIFT : return "OP_LSHIFT";
- case OP_RSHIFT : return "OP_RSHIFT";
- case OP_BOOLAND : return "OP_BOOLAND";
- case OP_BOOLOR : return "OP_BOOLOR";
- case OP_NUMEQUAL : return "OP_NUMEQUAL";
- case OP_NUMEQUALVERIFY : return "OP_NUMEQUALVERIFY";
- case OP_NUMNOTEQUAL : return "OP_NUMNOTEQUAL";
- case OP_LESSTHAN : return "OP_LESSTHAN";
- case OP_GREATERTHAN : return "OP_GREATERTHAN";
- case OP_LESSTHANOREQUAL : return "OP_LESSTHANOREQUAL";
- case OP_GREATERTHANOREQUAL : return "OP_GREATERTHANOREQUAL";
- case OP_MIN : return "OP_MIN";
- case OP_MAX : return "OP_MAX";
- case OP_WITHIN : return "OP_WITHIN";
-
- // crypto
- case OP_RIPEMD160 : return "OP_RIPEMD160";
- case OP_SHA1 : return "OP_SHA1";
- case OP_SHA256 : return "OP_SHA256";
- case OP_HASH160 : return "OP_HASH160";
- case OP_HASH256 : return "OP_HASH256";
- case OP_CODESEPARATOR : return "OP_CODESEPARATOR";
- case OP_CHECKSIG : return "OP_CHECKSIG";
- case OP_CHECKSIGVERIFY : return "OP_CHECKSIGVERIFY";
- case OP_CHECKMULTISIG : return "OP_CHECKMULTISIG";
- case OP_CHECKMULTISIGVERIFY : return "OP_CHECKMULTISIGVERIFY";
-
- // expanson
- case OP_NOP1 : return "OP_NOP1";
- case OP_NOP2 : return "OP_NOP2";
- case OP_NOP3 : return "OP_NOP3";
- case OP_NOP4 : return "OP_NOP4";
- case OP_NOP5 : return "OP_NOP5";
- case OP_NOP6 : return "OP_NOP6";
- case OP_NOP7 : return "OP_NOP7";
- case OP_NOP8 : return "OP_NOP8";
- case OP_NOP9 : return "OP_NOP9";
- case OP_NOP10 : return "OP_NOP10";
-
- case OP_INVALIDOPCODE : return "OP_INVALIDOPCODE";
-
- // Note:
- // The template matching params OP_SMALLDATA/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.
-
- default:
- return "OP_UNKNOWN";
- }
-}
-
bool IsCanonicalPubKey(const valtype &vchPubKey, unsigned int flags) {
if (!(flags & SCRIPT_VERIFY_STRICTENC))
return true;
@@ -240,7 +69,7 @@ bool IsCanonicalPubKey(const valtype &vchPubKey, unsigned int flags) {
if (vchPubKey.size() != 33)
return error("Non-canonical public key: invalid length for compressed key");
} else {
- return error("Non-canonical public key: compressed nor uncompressed");
+ return error("Non-canonical public key: neither compressed nor uncompressed");
}
return true;
}
@@ -964,19 +793,12 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
return false;
}
-
if (!vfExec.empty())
return false;
return true;
}
-
-
-
-
-
-
namespace {
/** Wrapper that serializes like CTransaction, but with the modifications
@@ -1153,8 +975,7 @@ public:
}
};
-bool CheckSig(vector<unsigned char> vchSig, const vector<unsigned char> &vchPubKey, const CScript &scriptCode,
- const CTransaction& txTo, unsigned int nIn, int nHashType, int flags)
+bool CheckSig(vector<unsigned char> vchSig, const vector<unsigned char> &vchPubKey, const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, int flags)
{
static CSignatureCache signatureCache;
@@ -1185,426 +1006,6 @@ bool CheckSig(vector<unsigned char> vchSig, const vector<unsigned char> &vchPubK
return true;
}
-
-
-
-
-
-
-
-
-//
-// Return public keys or hashes from scriptPubKey, for 'standard' transaction types.
-//
-bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsigned char> >& vSolutionsRet)
-{
- // Templates
- static multimap<txnouttype, CScript> mTemplates;
- if (mTemplates.empty())
- {
- // Standard tx, sender provides pubkey, receiver adds signature
- mTemplates.insert(make_pair(TX_PUBKEY, CScript() << OP_PUBKEY << OP_CHECKSIG));
-
- // Bitcoin address tx, sender provides hash of pubkey, receiver provides signature and pubkey
- mTemplates.insert(make_pair(TX_PUBKEYHASH, CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG));
-
- // 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));
- }
-
- // 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())
- {
- typeRet = TX_SCRIPTHASH;
- vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
- vSolutionsRet.push_back(hashBytes);
- return true;
- }
-
- // Scan templates
- const CScript& script1 = scriptPubKey;
- BOOST_FOREACH(const PAIRTYPE(txnouttype, CScript)& tplate, mTemplates)
- {
- const CScript& script2 = tplate.second;
- vSolutionsRet.clear();
-
- opcodetype opcode1, opcode2;
- vector<unsigned char> vch1, vch2;
-
- // Compare
- CScript::const_iterator pc1 = script1.begin();
- CScript::const_iterator pc2 = script2.begin();
- while (true)
- {
- if (pc1 == script1.end() && pc2 == script2.end())
- {
- // Found a match
- typeRet = tplate.first;
- if (typeRet == TX_MULTISIG)
- {
- // Additional checks for TX_MULTISIG:
- unsigned char m = vSolutionsRet.front()[0];
- unsigned char n = vSolutionsRet.back()[0];
- if (m < 1 || n < 1 || m > n || vSolutionsRet.size()-2 != n)
- return false;
- }
- return true;
- }
- if (!script1.GetOp(pc1, opcode1, vch1))
- break;
- if (!script2.GetOp(pc2, opcode2, vch2))
- break;
-
- // Template matching opcodes:
- if (opcode2 == OP_PUBKEYS)
- {
- while (vch1.size() >= 33 && vch1.size() <= 65)
- {
- vSolutionsRet.push_back(vch1);
- if (!script1.GetOp(pc1, opcode1, vch1))
- break;
- }
- if (!script2.GetOp(pc2, opcode2, vch2))
- break;
- // Normal situation is to fall through
- // to other if/else statements
- }
-
- if (opcode2 == OP_PUBKEY)
- {
- if (vch1.size() < 33 || vch1.size() > 65)
- break;
- vSolutionsRet.push_back(vch1);
- }
- else if (opcode2 == OP_PUBKEYHASH)
- {
- if (vch1.size() != sizeof(uint160))
- break;
- vSolutionsRet.push_back(vch1);
- }
- else if (opcode2 == OP_SMALLINTEGER)
- { // Single-byte small integer pushed onto vSolutions
- if (opcode1 == OP_0 ||
- (opcode1 >= OP_1 && opcode1 <= OP_16))
- {
- char n = (char)CScript::DecodeOP_N(opcode1);
- vSolutionsRet.push_back(valtype(1, n));
- }
- else
- break;
- }
- else if (opcode2 == OP_SMALLDATA)
- {
- // small pushdata, <= MAX_OP_RETURN_RELAY bytes
- if (vch1.size() > MAX_OP_RETURN_RELAY)
- break;
- }
- else if (opcode1 != opcode2 || vch1 != vch2)
- {
- // Others must match exactly
- break;
- }
- }
- }
-
- vSolutionsRet.clear();
- typeRet = TX_NONSTANDARD;
- return false;
-}
-
-
-bool Sign1(const CKeyID& address, const CKeyStore& keystore, uint256 hash, int nHashType, CScript& scriptSigRet)
-{
- CKey key;
- if (!keystore.GetKey(address, key))
- return false;
-
- vector<unsigned char> vchSig;
- if (!key.Sign(hash, vchSig))
- return false;
- vchSig.push_back((unsigned char)nHashType);
- scriptSigRet << vchSig;
-
- return true;
-}
-
-bool SignN(const vector<valtype>& multisigdata, const CKeyStore& keystore, uint256 hash, int nHashType, CScript& scriptSigRet)
-{
- int nSigned = 0;
- int nRequired = multisigdata.front()[0];
- for (unsigned int i = 1; i < multisigdata.size()-1 && nSigned < nRequired; i++)
- {
- const valtype& pubkey = multisigdata[i];
- CKeyID keyID = CPubKey(pubkey).GetID();
- if (Sign1(keyID, keystore, hash, nHashType, scriptSigRet))
- ++nSigned;
- }
- return nSigned==nRequired;
-}
-
-//
-// Sign scriptPubKey with private keys stored in keystore, given transaction hash and hash type.
-// Signatures are returned in scriptSigRet (or returns false if scriptPubKey can't be signed),
-// unless whichTypeRet is TX_SCRIPTHASH, in which case scriptSigRet is the redemption script.
-// Returns false if scriptPubKey could not be completely satisfied.
-//
-bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash, int nHashType,
- CScript& scriptSigRet, txnouttype& whichTypeRet)
-{
- scriptSigRet.clear();
-
- vector<valtype> vSolutions;
- if (!Solver(scriptPubKey, whichTypeRet, vSolutions))
- return false;
-
- CKeyID keyID;
- switch (whichTypeRet)
- {
- case TX_NONSTANDARD:
- case TX_NULL_DATA:
- return false;
- case TX_PUBKEY:
- keyID = CPubKey(vSolutions[0]).GetID();
- return Sign1(keyID, keystore, hash, nHashType, scriptSigRet);
- case TX_PUBKEYHASH:
- keyID = CKeyID(uint160(vSolutions[0]));
- if (!Sign1(keyID, keystore, hash, nHashType, scriptSigRet))
- return false;
- else
- {
- CPubKey vch;
- keystore.GetPubKey(keyID, vch);
- scriptSigRet << vch;
- }
- return true;
- case TX_SCRIPTHASH:
- return keystore.GetCScript(uint160(vSolutions[0]), scriptSigRet);
-
- case TX_MULTISIG:
- scriptSigRet << OP_0; // workaround CHECKMULTISIG bug
- return (SignN(vSolutions, keystore, hash, nHashType, scriptSigRet));
- }
- return false;
-}
-
-int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions)
-{
- switch (t)
- {
- case TX_NONSTANDARD:
- case TX_NULL_DATA:
- return -1;
- case TX_PUBKEY:
- return 1;
- case TX_PUBKEYHASH:
- return 2;
- case TX_MULTISIG:
- if (vSolutions.size() < 1 || vSolutions[0].size() < 1)
- return -1;
- return vSolutions[0][0] + 1;
- case TX_SCRIPTHASH:
- return 1; // doesn't include args needed by the script
- }
- return -1;
-}
-
-bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
-{
- vector<valtype> vSolutions;
- if (!Solver(scriptPubKey, whichType, vSolutions))
- return false;
-
- if (whichType == TX_MULTISIG)
- {
- unsigned char m = vSolutions.front()[0];
- unsigned char n = vSolutions.back()[0];
- // Support up to x-of-3 multisig txns as standard
- if (n < 1 || n > 3)
- return false;
- if (m < 1 || m > n)
- return false;
- }
-
- return whichType != TX_NONSTANDARD;
-}
-
-
-unsigned int HaveKeys(const vector<valtype>& pubkeys, const CKeyStore& keystore)
-{
- unsigned int nResult = 0;
- BOOST_FOREACH(const valtype& pubkey, pubkeys)
- {
- CKeyID keyID = CPubKey(pubkey).GetID();
- if (keystore.HaveKey(keyID))
- ++nResult;
- }
- return nResult;
-}
-
-isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest)
-{
- CScript script;
- script.SetDestination(dest);
- return IsMine(keystore, script);
-}
-
-isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
-{
- vector<valtype> vSolutions;
- txnouttype whichType;
- if (!Solver(scriptPubKey, whichType, vSolutions)) {
- if (keystore.HaveWatchOnly(scriptPubKey))
- return ISMINE_WATCH_ONLY;
- return ISMINE_NO;
- }
-
- CKeyID keyID;
- switch (whichType)
- {
- case TX_NONSTANDARD:
- case TX_NULL_DATA:
- break;
- case TX_PUBKEY:
- keyID = CPubKey(vSolutions[0]).GetID();
- if (keystore.HaveKey(keyID))
- return ISMINE_SPENDABLE;
- break;
- case TX_PUBKEYHASH:
- keyID = CKeyID(uint160(vSolutions[0]));
- if (keystore.HaveKey(keyID))
- return ISMINE_SPENDABLE;
- break;
- case TX_SCRIPTHASH:
- {
- CScriptID scriptID = CScriptID(uint160(vSolutions[0]));
- CScript subscript;
- if (keystore.GetCScript(scriptID, subscript)) {
- isminetype ret = IsMine(keystore, subscript);
- if (ret == ISMINE_SPENDABLE)
- return ret;
- }
- break;
- }
- case TX_MULTISIG:
- {
- // Only consider transactions "mine" if we own ALL the
- // keys involved. multi-signature transactions that are
- // partially owned (somebody else has a key that can spend
- // them) enable spend-out-from-under-you attacks, especially
- // in shared-wallet situations.
- vector<valtype> keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1);
- if (HaveKeys(keys, keystore) == keys.size())
- return ISMINE_SPENDABLE;
- break;
- }
- }
-
- if (keystore.HaveWatchOnly(scriptPubKey))
- return ISMINE_WATCH_ONLY;
- return ISMINE_NO;
-}
-
-bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
-{
- vector<valtype> vSolutions;
- txnouttype whichType;
- if (!Solver(scriptPubKey, whichType, vSolutions))
- return false;
-
- if (whichType == TX_PUBKEY)
- {
- addressRet = CPubKey(vSolutions[0]).GetID();
- return true;
- }
- else if (whichType == TX_PUBKEYHASH)
- {
- addressRet = CKeyID(uint160(vSolutions[0]));
- return true;
- }
- else if (whichType == TX_SCRIPTHASH)
- {
- addressRet = CScriptID(uint160(vSolutions[0]));
- return true;
- }
- // Multisig txns have more than one address...
- return false;
-}
-
-bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vector<CTxDestination>& addressRet, int& nRequiredRet)
-{
- addressRet.clear();
- typeRet = TX_NONSTANDARD;
- vector<valtype> vSolutions;
- if (!Solver(scriptPubKey, typeRet, vSolutions))
- return false;
- if (typeRet == TX_NULL_DATA){
- // This is data, not addresses
- return false;
- }
-
- if (typeRet == TX_MULTISIG)
- {
- nRequiredRet = vSolutions.front()[0];
- for (unsigned int i = 1; i < vSolutions.size()-1; i++)
- {
- CTxDestination address = CPubKey(vSolutions[i]).GetID();
- addressRet.push_back(address);
- }
- }
- else
- {
- nRequiredRet = 1;
- CTxDestination address;
- if (!ExtractDestination(scriptPubKey, address))
- return false;
- addressRet.push_back(address);
- }
-
- return true;
-}
-
-class CAffectedKeysVisitor : public boost::static_visitor<void> {
-private:
- const CKeyStore &keystore;
- std::vector<CKeyID> &vKeys;
-
-public:
- CAffectedKeysVisitor(const CKeyStore &keystoreIn, std::vector<CKeyID> &vKeysIn) : keystore(keystoreIn), vKeys(vKeysIn) {}
-
- void Process(const CScript &script) {
- txnouttype type;
- std::vector<CTxDestination> vDest;
- int nRequired;
- if (ExtractDestinations(script, type, vDest, nRequired)) {
- BOOST_FOREACH(const CTxDestination &dest, vDest)
- boost::apply_visitor(*this, dest);
- }
- }
-
- void operator()(const CKeyID &keyId) {
- if (keystore.HaveKey(keyId))
- vKeys.push_back(keyId);
- }
-
- void operator()(const CScriptID &scriptId) {
- CScript script;
- if (keystore.GetCScript(scriptId, script))
- Process(script);
- }
-
- void operator()(const CNoDestination &none) {}
-};
-
-void ExtractAffectedKeys(const CKeyStore &keystore, const CScript& scriptPubKey, std::vector<CKeyID> &vKeys) {
- CAffectedKeysVisitor(keystore, vKeys).Process(scriptPubKey);
-}
-
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn,
unsigned int flags, int nHashType)
{
@@ -1645,437 +1046,3 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C
return true;
}
-
-
-bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
-{
- assert(nIn < txTo.vin.size());
- CTxIn& txin = txTo.vin[nIn];
-
- // Leave out the signature from the hash, since a signature can't sign itself.
- // The checksig op will also drop the signatures from its hash.
- uint256 hash = SignatureHash(fromPubKey, txTo, nIn, nHashType);
-
- txnouttype whichType;
- if (!Solver(keystore, fromPubKey, hash, nHashType, txin.scriptSig, whichType))
- return false;
-
- if (whichType == TX_SCRIPTHASH)
- {
- // Solver returns the subscript that need to be evaluated;
- // the final scriptSig is the signatures from that
- // and then the serialized subscript:
- CScript subscript = txin.scriptSig;
-
- // Recompute txn hash using subscript in place of scriptPubKey:
- uint256 hash2 = SignatureHash(subscript, txTo, nIn, nHashType);
-
- txnouttype subType;
- bool fSolved =
- Solver(keystore, subscript, hash2, nHashType, txin.scriptSig, subType) && subType != TX_SCRIPTHASH;
- // Append serialized subscript whether or not it is completely signed:
- txin.scriptSig << static_cast<valtype>(subscript);
- if (!fSolved) return false;
- }
-
- // Test solution
- return VerifyScript(txin.scriptSig, fromPubKey, txTo, nIn, STANDARD_SCRIPT_VERIFY_FLAGS, 0);
-}
-
-bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
-{
- assert(nIn < txTo.vin.size());
- CTxIn& txin = txTo.vin[nIn];
- assert(txin.prevout.n < txFrom.vout.size());
- const CTxOut& txout = txFrom.vout[txin.prevout.n];
-
- return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, nHashType);
-}
-
-static CScript PushAll(const vector<valtype>& values)
-{
- CScript result;
- BOOST_FOREACH(const valtype& v, values)
- result << v;
- return result;
-}
-
-static CScript CombineMultisig(CScript scriptPubKey, const CMutableTransaction& txTo, unsigned int nIn,
- const vector<valtype>& vSolutions,
- vector<valtype>& sigs1, vector<valtype>& sigs2)
-{
- // Combine all the signatures we've got:
- set<valtype> allsigs;
- BOOST_FOREACH(const valtype& v, sigs1)
- {
- if (!v.empty())
- allsigs.insert(v);
- }
- BOOST_FOREACH(const valtype& v, sigs2)
- {
- if (!v.empty())
- allsigs.insert(v);
- }
-
- // Build a map of pubkey -> signature by matching sigs to pubkeys:
- assert(vSolutions.size() > 1);
- unsigned int nSigsRequired = vSolutions.front()[0];
- unsigned int nPubKeys = vSolutions.size()-2;
- map<valtype, valtype> sigs;
- BOOST_FOREACH(const valtype& sig, allsigs)
- {
- for (unsigned int i = 0; i < nPubKeys; i++)
- {
- const valtype& pubkey = vSolutions[i+1];
- if (sigs.count(pubkey))
- continue; // Already got a sig for this pubkey
-
- if (CheckSig(sig, pubkey, scriptPubKey, txTo, nIn, 0, 0))
- {
- sigs[pubkey] = sig;
- break;
- }
- }
- }
- // Now build a merged CScript:
- unsigned int nSigsHave = 0;
- CScript result; result << OP_0; // pop-one-too-many workaround
- for (unsigned int i = 0; i < nPubKeys && nSigsHave < nSigsRequired; i++)
- {
- if (sigs.count(vSolutions[i+1]))
- {
- result << sigs[vSolutions[i+1]];
- ++nSigsHave;
- }
- }
- // Fill any missing with OP_0:
- for (unsigned int i = nSigsHave; i < nSigsRequired; i++)
- result << OP_0;
-
- return result;
-}
-
-static CScript CombineSignatures(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn,
- const txnouttype txType, const vector<valtype>& vSolutions,
- vector<valtype>& sigs1, vector<valtype>& sigs2)
-{
- switch (txType)
- {
- case TX_NONSTANDARD:
- case TX_NULL_DATA:
- // Don't know anything about this, assume bigger one is correct:
- if (sigs1.size() >= sigs2.size())
- return PushAll(sigs1);
- return PushAll(sigs2);
- case TX_PUBKEY:
- case TX_PUBKEYHASH:
- // Signatures are bigger than placeholders or empty scripts:
- if (sigs1.empty() || sigs1[0].empty())
- return PushAll(sigs2);
- return PushAll(sigs1);
- case TX_SCRIPTHASH:
- if (sigs1.empty() || sigs1.back().empty())
- return PushAll(sigs2);
- else if (sigs2.empty() || sigs2.back().empty())
- return PushAll(sigs1);
- else
- {
- // Recur to combine:
- valtype spk = sigs1.back();
- CScript pubKey2(spk.begin(), spk.end());
-
- txnouttype txType2;
- vector<vector<unsigned char> > vSolutions2;
- Solver(pubKey2, txType2, vSolutions2);
- sigs1.pop_back();
- sigs2.pop_back();
- CScript result = CombineSignatures(pubKey2, txTo, nIn, txType2, vSolutions2, sigs1, sigs2);
- result << spk;
- return result;
- }
- case TX_MULTISIG:
- return CombineMultisig(scriptPubKey, txTo, nIn, vSolutions, sigs1, sigs2);
- }
-
- return CScript();
-}
-
-CScript CombineSignatures(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn,
- const CScript& scriptSig1, const CScript& scriptSig2)
-{
- txnouttype txType;
- vector<vector<unsigned char> > vSolutions;
- Solver(scriptPubKey, txType, vSolutions);
-
- vector<valtype> stack1;
- EvalScript(stack1, scriptSig1, CTransaction(), 0, SCRIPT_VERIFY_STRICTENC, 0);
- vector<valtype> stack2;
- EvalScript(stack2, scriptSig2, CTransaction(), 0, SCRIPT_VERIFY_STRICTENC, 0);
-
- return CombineSignatures(scriptPubKey, txTo, nIn, txType, vSolutions, stack1, stack2);
-}
-
-unsigned int CScript::GetSigOpCount(bool fAccurate) const
-{
- unsigned int n = 0;
- const_iterator pc = begin();
- opcodetype lastOpcode = OP_INVALIDOPCODE;
- while (pc < end())
- {
- opcodetype opcode;
- if (!GetOp(pc, opcode))
- break;
- if (opcode == OP_CHECKSIG || opcode == OP_CHECKSIGVERIFY)
- n++;
- else if (opcode == OP_CHECKMULTISIG || opcode == OP_CHECKMULTISIGVERIFY)
- {
- if (fAccurate && lastOpcode >= OP_1 && lastOpcode <= OP_16)
- n += DecodeOP_N(lastOpcode);
- else
- n += 20;
- }
- lastOpcode = opcode;
- }
- return n;
-}
-
-unsigned int CScript::GetSigOpCount(const CScript& scriptSig) const
-{
- if (!IsPayToScriptHash())
- return GetSigOpCount(true);
-
- // This is a pay-to-script-hash scriptPubKey;
- // get the last item that the scriptSig
- // pushes onto the stack:
- const_iterator pc = scriptSig.begin();
- vector<unsigned char> data;
- while (pc < scriptSig.end())
- {
- opcodetype opcode;
- if (!scriptSig.GetOp(pc, opcode, data))
- return 0;
- if (opcode > OP_16)
- return 0;
- }
-
- /// ... and return its opcount:
- CScript subscript(data.begin(), data.end());
- return subscript.GetSigOpCount(true);
-}
-
-bool CScript::IsPayToScriptHash() const
-{
- // Extra-fast test for pay-to-script-hash CScripts:
- return (this->size() == 23 &&
- this->at(0) == OP_HASH160 &&
- this->at(1) == 0x14 &&
- this->at(22) == OP_EQUAL);
-}
-
-bool CScript::IsPushOnly() const
-{
- const_iterator pc = begin();
- while (pc < end())
- {
- // Note how a script with an invalid PUSHDATA returns False.
- opcodetype opcode;
- if (!GetOp(pc, opcode))
- return false;
-
- // Note that IsPushOnly() *does* consider OP_RESERVED to be a
- // push-type opcode, however execution of OP_RESERVED fails, so
- // it's not relevant to P2SH as the scriptSig would fail prior to
- // the P2SH special validation code being executed.
- if (opcode > OP_16)
- return false;
- }
- return true;
-}
-
-bool CScript::HasCanonicalPushes() const
-{
- const_iterator pc = begin();
- while (pc < end())
- {
- opcodetype opcode;
- std::vector<unsigned char> data;
- if (!GetOp(pc, opcode, data))
- return false;
- if (opcode > OP_16)
- continue;
- if (opcode < OP_PUSHDATA1 && opcode > OP_0 && (data.size() == 1 && data[0] <= 16))
- // Could have used an OP_n code, rather than a 1-byte push.
- return false;
- if (opcode == OP_PUSHDATA1 && data.size() < OP_PUSHDATA1)
- // Could have used a normal n-byte push, rather than OP_PUSHDATA1.
- return false;
- if (opcode == OP_PUSHDATA2 && data.size() <= 0xFF)
- // Could have used an OP_PUSHDATA1.
- return false;
- if (opcode == OP_PUSHDATA4 && data.size() <= 0xFFFF)
- // Could have used an OP_PUSHDATA2.
- return false;
- }
- return true;
-}
-
-class CScriptVisitor : public boost::static_visitor<bool>
-{
-private:
- CScript *script;
-public:
- CScriptVisitor(CScript *scriptin) { script = scriptin; }
-
- bool operator()(const CNoDestination &dest) const {
- script->clear();
- return false;
- }
-
- bool operator()(const CKeyID &keyID) const {
- script->clear();
- *script << OP_DUP << OP_HASH160 << keyID << OP_EQUALVERIFY << OP_CHECKSIG;
- return true;
- }
-
- bool operator()(const CScriptID &scriptID) const {
- script->clear();
- *script << OP_HASH160 << scriptID << OP_EQUAL;
- return true;
- }
-};
-
-void CScript::SetDestination(const CTxDestination& dest)
-{
- boost::apply_visitor(CScriptVisitor(this), dest);
-}
-
-void CScript::SetMultisig(int nRequired, const std::vector<CPubKey>& keys)
-{
- this->clear();
-
- *this << EncodeOP_N(nRequired);
- BOOST_FOREACH(const CPubKey& key, keys)
- *this << key;
- *this << EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
-}
-
-bool CScriptCompressor::IsToKeyID(CKeyID &hash) const
-{
- if (script.size() == 25 && script[0] == OP_DUP && script[1] == OP_HASH160
- && script[2] == 20 && script[23] == OP_EQUALVERIFY
- && script[24] == OP_CHECKSIG) {
- memcpy(&hash, &script[3], 20);
- return true;
- }
- return false;
-}
-
-bool CScriptCompressor::IsToScriptID(CScriptID &hash) const
-{
- if (script.size() == 23 && script[0] == OP_HASH160 && script[1] == 20
- && script[22] == OP_EQUAL) {
- memcpy(&hash, &script[2], 20);
- return true;
- }
- return false;
-}
-
-bool CScriptCompressor::IsToPubKey(CPubKey &pubkey) const
-{
- if (script.size() == 35 && script[0] == 33 && script[34] == OP_CHECKSIG
- && (script[1] == 0x02 || script[1] == 0x03)) {
- pubkey.Set(&script[1], &script[34]);
- return true;
- }
- if (script.size() == 67 && script[0] == 65 && script[66] == OP_CHECKSIG
- && script[1] == 0x04) {
- pubkey.Set(&script[1], &script[66]);
- return pubkey.IsFullyValid(); // if not fully valid, a case that would not be compressible
- }
- return false;
-}
-
-bool CScriptCompressor::Compress(std::vector<unsigned char> &out) const
-{
- CKeyID keyID;
- if (IsToKeyID(keyID)) {
- out.resize(21);
- out[0] = 0x00;
- memcpy(&out[1], &keyID, 20);
- return true;
- }
- CScriptID scriptID;
- if (IsToScriptID(scriptID)) {
- out.resize(21);
- out[0] = 0x01;
- memcpy(&out[1], &scriptID, 20);
- return true;
- }
- CPubKey pubkey;
- if (IsToPubKey(pubkey)) {
- out.resize(33);
- memcpy(&out[1], &pubkey[1], 32);
- if (pubkey[0] == 0x02 || pubkey[0] == 0x03) {
- out[0] = pubkey[0];
- return true;
- } else if (pubkey[0] == 0x04) {
- out[0] = 0x04 | (pubkey[64] & 0x01);
- return true;
- }
- }
- return false;
-}
-
-unsigned int CScriptCompressor::GetSpecialSize(unsigned int nSize) const
-{
- if (nSize == 0 || nSize == 1)
- return 20;
- if (nSize == 2 || nSize == 3 || nSize == 4 || nSize == 5)
- return 32;
- return 0;
-}
-
-bool CScriptCompressor::Decompress(unsigned int nSize, const std::vector<unsigned char> &in)
-{
- switch(nSize) {
- case 0x00:
- script.resize(25);
- script[0] = OP_DUP;
- script[1] = OP_HASH160;
- script[2] = 20;
- memcpy(&script[3], &in[0], 20);
- script[23] = OP_EQUALVERIFY;
- script[24] = OP_CHECKSIG;
- return true;
- case 0x01:
- script.resize(23);
- script[0] = OP_HASH160;
- script[1] = 20;
- memcpy(&script[2], &in[0], 20);
- script[22] = OP_EQUAL;
- return true;
- case 0x02:
- case 0x03:
- script.resize(35);
- script[0] = 33;
- script[1] = nSize;
- memcpy(&script[2], &in[0], 32);
- script[34] = OP_CHECKSIG;
- return true;
- case 0x04:
- case 0x05:
- unsigned char vch[33] = {};
- vch[0] = nSize - 2;
- memcpy(&vch[1], &in[0], 32);
- CPubKey pubkey(&vch[0], &vch[33]);
- if (!pubkey.Decompress())
- return false;
- assert(pubkey.size() == 65);
- script.resize(67);
- script[0] = 65;
- memcpy(&script[1], pubkey.begin(), 65);
- script[66] = OP_CHECKSIG;
- return true;
- }
- return false;
-}
diff --git a/src/script/interpreter.h b/src/script/interpreter.h
new file mode 100644
index 0000000000..6fbcd92a3d
--- /dev/null
+++ b/src/script/interpreter.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef H_BITCOIN_SCRIPT_INTERPRETER
+#define H_BITCOIN_SCRIPT_INTERPRETER
+
+#include <vector>
+#include <stdint.h>
+#include <string>
+
+class CScript;
+class CTransaction;
+class uint256;
+
+/** Signature hash types/flags */
+enum
+{
+ SIGHASH_ALL = 1,
+ SIGHASH_NONE = 2,
+ SIGHASH_SINGLE = 3,
+ SIGHASH_ANYONECANPAY = 0x80,
+};
+
+/** Script verification flags */
+enum
+{
+ SCRIPT_VERIFY_NONE = 0,
+ SCRIPT_VERIFY_P2SH = (1U << 0), // evaluate P2SH (BIP16) subscripts
+ SCRIPT_VERIFY_STRICTENC = (1U << 1), // enforce strict conformance to DER and SEC2 for signatures and pubkeys
+ SCRIPT_VERIFY_LOW_S = (1U << 2), // enforce low S values (<n/2) in signatures (depends on STRICTENC)
+ SCRIPT_VERIFY_NOCACHE = (1U << 3), // do not store results in signature cache (but do query it)
+ SCRIPT_VERIFY_NULLDUMMY = (1U << 4), // verify dummy stack item consumed by CHECKMULTISIG is of zero-length
+};
+
+bool IsCanonicalPubKey(const std::vector<unsigned char> &vchPubKey, unsigned int flags);
+bool IsCanonicalSignature(const std::vector<unsigned char> &vchSig, unsigned int flags);
+
+uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
+bool CheckSig(std::vector<unsigned char> vchSig, const std::vector<unsigned char> &vchPubKey, const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, int flags);
+bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType);
+bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType);
+
+#endif // H_BITCOIN_SCRIPT_INTERPRETER
diff --git a/src/script/script.cpp b/src/script/script.cpp
new file mode 100644
index 0000000000..3c9f38dc8b
--- /dev/null
+++ b/src/script/script.cpp
@@ -0,0 +1,295 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "script.h"
+
+#include <boost/foreach.hpp>
+
+using namespace std;
+
+const char* GetOpName(opcodetype opcode)
+{
+ switch (opcode)
+ {
+ // push value
+ case OP_0 : return "0";
+ case OP_PUSHDATA1 : return "OP_PUSHDATA1";
+ case OP_PUSHDATA2 : return "OP_PUSHDATA2";
+ case OP_PUSHDATA4 : return "OP_PUSHDATA4";
+ case OP_1NEGATE : return "-1";
+ case OP_RESERVED : return "OP_RESERVED";
+ case OP_1 : return "1";
+ case OP_2 : return "2";
+ case OP_3 : return "3";
+ case OP_4 : return "4";
+ case OP_5 : return "5";
+ case OP_6 : return "6";
+ case OP_7 : return "7";
+ case OP_8 : return "8";
+ case OP_9 : return "9";
+ case OP_10 : return "10";
+ case OP_11 : return "11";
+ case OP_12 : return "12";
+ case OP_13 : return "13";
+ case OP_14 : return "14";
+ case OP_15 : return "15";
+ case OP_16 : return "16";
+
+ // control
+ case OP_NOP : return "OP_NOP";
+ case OP_VER : return "OP_VER";
+ case OP_IF : return "OP_IF";
+ case OP_NOTIF : return "OP_NOTIF";
+ case OP_VERIF : return "OP_VERIF";
+ case OP_VERNOTIF : return "OP_VERNOTIF";
+ case OP_ELSE : return "OP_ELSE";
+ case OP_ENDIF : return "OP_ENDIF";
+ case OP_VERIFY : return "OP_VERIFY";
+ case OP_RETURN : return "OP_RETURN";
+
+ // stack ops
+ case OP_TOALTSTACK : return "OP_TOALTSTACK";
+ case OP_FROMALTSTACK : return "OP_FROMALTSTACK";
+ case OP_2DROP : return "OP_2DROP";
+ case OP_2DUP : return "OP_2DUP";
+ case OP_3DUP : return "OP_3DUP";
+ case OP_2OVER : return "OP_2OVER";
+ case OP_2ROT : return "OP_2ROT";
+ case OP_2SWAP : return "OP_2SWAP";
+ case OP_IFDUP : return "OP_IFDUP";
+ case OP_DEPTH : return "OP_DEPTH";
+ case OP_DROP : return "OP_DROP";
+ case OP_DUP : return "OP_DUP";
+ case OP_NIP : return "OP_NIP";
+ case OP_OVER : return "OP_OVER";
+ case OP_PICK : return "OP_PICK";
+ case OP_ROLL : return "OP_ROLL";
+ case OP_ROT : return "OP_ROT";
+ case OP_SWAP : return "OP_SWAP";
+ case OP_TUCK : return "OP_TUCK";
+
+ // splice ops
+ case OP_CAT : return "OP_CAT";
+ case OP_SUBSTR : return "OP_SUBSTR";
+ case OP_LEFT : return "OP_LEFT";
+ case OP_RIGHT : return "OP_RIGHT";
+ case OP_SIZE : return "OP_SIZE";
+
+ // bit logic
+ case OP_INVERT : return "OP_INVERT";
+ case OP_AND : return "OP_AND";
+ case OP_OR : return "OP_OR";
+ case OP_XOR : return "OP_XOR";
+ case OP_EQUAL : return "OP_EQUAL";
+ case OP_EQUALVERIFY : return "OP_EQUALVERIFY";
+ case OP_RESERVED1 : return "OP_RESERVED1";
+ case OP_RESERVED2 : return "OP_RESERVED2";
+
+ // numeric
+ case OP_1ADD : return "OP_1ADD";
+ case OP_1SUB : return "OP_1SUB";
+ case OP_2MUL : return "OP_2MUL";
+ case OP_2DIV : return "OP_2DIV";
+ case OP_NEGATE : return "OP_NEGATE";
+ case OP_ABS : return "OP_ABS";
+ case OP_NOT : return "OP_NOT";
+ case OP_0NOTEQUAL : return "OP_0NOTEQUAL";
+ case OP_ADD : return "OP_ADD";
+ case OP_SUB : return "OP_SUB";
+ case OP_MUL : return "OP_MUL";
+ case OP_DIV : return "OP_DIV";
+ case OP_MOD : return "OP_MOD";
+ case OP_LSHIFT : return "OP_LSHIFT";
+ case OP_RSHIFT : return "OP_RSHIFT";
+ case OP_BOOLAND : return "OP_BOOLAND";
+ case OP_BOOLOR : return "OP_BOOLOR";
+ case OP_NUMEQUAL : return "OP_NUMEQUAL";
+ case OP_NUMEQUALVERIFY : return "OP_NUMEQUALVERIFY";
+ case OP_NUMNOTEQUAL : return "OP_NUMNOTEQUAL";
+ case OP_LESSTHAN : return "OP_LESSTHAN";
+ case OP_GREATERTHAN : return "OP_GREATERTHAN";
+ case OP_LESSTHANOREQUAL : return "OP_LESSTHANOREQUAL";
+ case OP_GREATERTHANOREQUAL : return "OP_GREATERTHANOREQUAL";
+ case OP_MIN : return "OP_MIN";
+ case OP_MAX : return "OP_MAX";
+ case OP_WITHIN : return "OP_WITHIN";
+
+ // crypto
+ case OP_RIPEMD160 : return "OP_RIPEMD160";
+ case OP_SHA1 : return "OP_SHA1";
+ case OP_SHA256 : return "OP_SHA256";
+ case OP_HASH160 : return "OP_HASH160";
+ case OP_HASH256 : return "OP_HASH256";
+ case OP_CODESEPARATOR : return "OP_CODESEPARATOR";
+ case OP_CHECKSIG : return "OP_CHECKSIG";
+ case OP_CHECKSIGVERIFY : return "OP_CHECKSIGVERIFY";
+ case OP_CHECKMULTISIG : return "OP_CHECKMULTISIG";
+ case OP_CHECKMULTISIGVERIFY : return "OP_CHECKMULTISIGVERIFY";
+
+ // expanson
+ case OP_NOP1 : return "OP_NOP1";
+ case OP_NOP2 : return "OP_NOP2";
+ case OP_NOP3 : return "OP_NOP3";
+ case OP_NOP4 : return "OP_NOP4";
+ case OP_NOP5 : return "OP_NOP5";
+ case OP_NOP6 : return "OP_NOP6";
+ case OP_NOP7 : return "OP_NOP7";
+ case OP_NOP8 : return "OP_NOP8";
+ case OP_NOP9 : return "OP_NOP9";
+ case OP_NOP10 : return "OP_NOP10";
+
+ case OP_INVALIDOPCODE : return "OP_INVALIDOPCODE";
+
+ // Note:
+ // The template matching params OP_SMALLDATA/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.
+
+ default:
+ return "OP_UNKNOWN";
+ }
+}
+
+unsigned int CScript::GetSigOpCount(bool fAccurate) const
+{
+ unsigned int n = 0;
+ const_iterator pc = begin();
+ opcodetype lastOpcode = OP_INVALIDOPCODE;
+ while (pc < end())
+ {
+ opcodetype opcode;
+ if (!GetOp(pc, opcode))
+ break;
+ if (opcode == OP_CHECKSIG || opcode == OP_CHECKSIGVERIFY)
+ n++;
+ else if (opcode == OP_CHECKMULTISIG || opcode == OP_CHECKMULTISIGVERIFY)
+ {
+ if (fAccurate && lastOpcode >= OP_1 && lastOpcode <= OP_16)
+ n += DecodeOP_N(lastOpcode);
+ else
+ n += 20;
+ }
+ lastOpcode = opcode;
+ }
+ return n;
+}
+
+unsigned int CScript::GetSigOpCount(const CScript& scriptSig) const
+{
+ if (!IsPayToScriptHash())
+ return GetSigOpCount(true);
+
+ // This is a pay-to-script-hash scriptPubKey;
+ // get the last item that the scriptSig
+ // pushes onto the stack:
+ const_iterator pc = scriptSig.begin();
+ vector<unsigned char> data;
+ while (pc < scriptSig.end())
+ {
+ opcodetype opcode;
+ if (!scriptSig.GetOp(pc, opcode, data))
+ return 0;
+ if (opcode > OP_16)
+ return 0;
+ }
+
+ /// ... and return its opcount:
+ CScript subscript(data.begin(), data.end());
+ return subscript.GetSigOpCount(true);
+}
+
+bool CScript::IsPayToScriptHash() const
+{
+ // Extra-fast test for pay-to-script-hash CScripts:
+ return (this->size() == 23 &&
+ this->at(0) == OP_HASH160 &&
+ this->at(1) == 0x14 &&
+ this->at(22) == OP_EQUAL);
+}
+
+bool CScript::IsPushOnly() const
+{
+ const_iterator pc = begin();
+ while (pc < end())
+ {
+ opcodetype opcode;
+ if (!GetOp(pc, opcode))
+ return false;
+ // Note that IsPushOnly() *does* consider OP_RESERVED to be a
+ // push-type opcode, however execution of OP_RESERVED fails, so
+ // it's not relevant to P2SH as the scriptSig would fail prior to
+ // the P2SH special validation code being executed.
+ if (opcode > OP_16)
+ return false;
+ }
+ return true;
+}
+
+bool CScript::HasCanonicalPushes() const
+{
+ const_iterator pc = begin();
+ while (pc < end())
+ {
+ opcodetype opcode;
+ std::vector<unsigned char> data;
+ if (!GetOp(pc, opcode, data))
+ return false;
+ if (opcode > OP_16)
+ continue;
+ if (opcode < OP_PUSHDATA1 && opcode > OP_0 && (data.size() == 1 && data[0] <= 16))
+ // Could have used an OP_n code, rather than a 1-byte push.
+ return false;
+ if (opcode == OP_PUSHDATA1 && data.size() < OP_PUSHDATA1)
+ // Could have used a normal n-byte push, rather than OP_PUSHDATA1.
+ return false;
+ if (opcode == OP_PUSHDATA2 && data.size() <= 0xFF)
+ // Could have used an OP_PUSHDATA1.
+ return false;
+ if (opcode == OP_PUSHDATA4 && data.size() <= 0xFFFF)
+ // Could have used an OP_PUSHDATA2.
+ return false;
+ }
+ return true;
+}
+
+class CScriptVisitor : public boost::static_visitor<bool>
+{
+private:
+ CScript *script;
+public:
+ CScriptVisitor(CScript *scriptin) { script = scriptin; }
+
+ bool operator()(const CNoDestination &dest) const {
+ script->clear();
+ return false;
+ }
+
+ bool operator()(const CKeyID &keyID) const {
+ script->clear();
+ *script << OP_DUP << OP_HASH160 << keyID << OP_EQUALVERIFY << OP_CHECKSIG;
+ return true;
+ }
+
+ bool operator()(const CScriptID &scriptID) const {
+ script->clear();
+ *script << OP_HASH160 << scriptID << OP_EQUAL;
+ return true;
+ }
+};
+
+void CScript::SetDestination(const CTxDestination& dest)
+{
+ boost::apply_visitor(CScriptVisitor(this), dest);
+}
+
+void CScript::SetMultisig(int nRequired, const std::vector<CPubKey>& keys)
+{
+ this->clear();
+
+ *this << EncodeOP_N(nRequired);
+ BOOST_FOREACH(const CPubKey& key, keys)
+ *this << key;
+ *this << EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
+}
diff --git a/src/script.h b/src/script/script.h
index d17cfe3fa4..2336cafd67 100644
--- a/src/script.h
+++ b/src/script/script.h
@@ -1,28 +1,168 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2013 The Bitcoin developers
-// Distributed under the MIT/X11 software license, see the accompanying
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef H_BITCOIN_SCRIPT
#define H_BITCOIN_SCRIPT
#include "key.h"
-#include "utilstrencodings.h"
#include "tinyformat.h"
+#include "utilstrencodings.h"
#include <stdexcept>
-#include <stdint.h>
-#include <string>
-#include <vector>
#include <boost/variant.hpp>
-class CKeyStore;
-class CTransaction;
-struct CMutableTransaction;
-
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes
-static const unsigned int MAX_OP_RETURN_RELAY = 40; // bytes
+
+/** Script opcodes */
+enum opcodetype
+{
+ // push value
+ OP_0 = 0x00,
+ OP_FALSE = OP_0,
+ OP_PUSHDATA1 = 0x4c,
+ OP_PUSHDATA2 = 0x4d,
+ OP_PUSHDATA4 = 0x4e,
+ OP_1NEGATE = 0x4f,
+ OP_RESERVED = 0x50,
+ OP_1 = 0x51,
+ OP_TRUE=OP_1,
+ OP_2 = 0x52,
+ OP_3 = 0x53,
+ OP_4 = 0x54,
+ OP_5 = 0x55,
+ OP_6 = 0x56,
+ OP_7 = 0x57,
+ OP_8 = 0x58,
+ OP_9 = 0x59,
+ OP_10 = 0x5a,
+ OP_11 = 0x5b,
+ OP_12 = 0x5c,
+ OP_13 = 0x5d,
+ OP_14 = 0x5e,
+ OP_15 = 0x5f,
+ OP_16 = 0x60,
+
+ // control
+ OP_NOP = 0x61,
+ OP_VER = 0x62,
+ OP_IF = 0x63,
+ OP_NOTIF = 0x64,
+ OP_VERIF = 0x65,
+ OP_VERNOTIF = 0x66,
+ OP_ELSE = 0x67,
+ OP_ENDIF = 0x68,
+ OP_VERIFY = 0x69,
+ OP_RETURN = 0x6a,
+
+ // stack ops
+ OP_TOALTSTACK = 0x6b,
+ OP_FROMALTSTACK = 0x6c,
+ OP_2DROP = 0x6d,
+ OP_2DUP = 0x6e,
+ OP_3DUP = 0x6f,
+ OP_2OVER = 0x70,
+ OP_2ROT = 0x71,
+ OP_2SWAP = 0x72,
+ OP_IFDUP = 0x73,
+ OP_DEPTH = 0x74,
+ OP_DROP = 0x75,
+ OP_DUP = 0x76,
+ OP_NIP = 0x77,
+ OP_OVER = 0x78,
+ OP_PICK = 0x79,
+ OP_ROLL = 0x7a,
+ OP_ROT = 0x7b,
+ OP_SWAP = 0x7c,
+ OP_TUCK = 0x7d,
+
+ // splice ops
+ OP_CAT = 0x7e,
+ OP_SUBSTR = 0x7f,
+ OP_LEFT = 0x80,
+ OP_RIGHT = 0x81,
+ OP_SIZE = 0x82,
+
+ // bit logic
+ OP_INVERT = 0x83,
+ OP_AND = 0x84,
+ OP_OR = 0x85,
+ OP_XOR = 0x86,
+ OP_EQUAL = 0x87,
+ OP_EQUALVERIFY = 0x88,
+ OP_RESERVED1 = 0x89,
+ OP_RESERVED2 = 0x8a,
+
+ // numeric
+ OP_1ADD = 0x8b,
+ OP_1SUB = 0x8c,
+ OP_2MUL = 0x8d,
+ OP_2DIV = 0x8e,
+ OP_NEGATE = 0x8f,
+ OP_ABS = 0x90,
+ OP_NOT = 0x91,
+ OP_0NOTEQUAL = 0x92,
+
+ OP_ADD = 0x93,
+ OP_SUB = 0x94,
+ OP_MUL = 0x95,
+ OP_DIV = 0x96,
+ OP_MOD = 0x97,
+ OP_LSHIFT = 0x98,
+ OP_RSHIFT = 0x99,
+
+ OP_BOOLAND = 0x9a,
+ OP_BOOLOR = 0x9b,
+ OP_NUMEQUAL = 0x9c,
+ OP_NUMEQUALVERIFY = 0x9d,
+ OP_NUMNOTEQUAL = 0x9e,
+ OP_LESSTHAN = 0x9f,
+ OP_GREATERTHAN = 0xa0,
+ OP_LESSTHANOREQUAL = 0xa1,
+ OP_GREATERTHANOREQUAL = 0xa2,
+ OP_MIN = 0xa3,
+ OP_MAX = 0xa4,
+
+ OP_WITHIN = 0xa5,
+
+ // crypto
+ OP_RIPEMD160 = 0xa6,
+ OP_SHA1 = 0xa7,
+ OP_SHA256 = 0xa8,
+ OP_HASH160 = 0xa9,
+ OP_HASH256 = 0xaa,
+ OP_CODESEPARATOR = 0xab,
+ OP_CHECKSIG = 0xac,
+ OP_CHECKSIGVERIFY = 0xad,
+ OP_CHECKMULTISIG = 0xae,
+ OP_CHECKMULTISIGVERIFY = 0xaf,
+
+ // expansion
+ OP_NOP1 = 0xb0,
+ OP_NOP2 = 0xb1,
+ OP_NOP3 = 0xb2,
+ OP_NOP4 = 0xb3,
+ OP_NOP5 = 0xb4,
+ OP_NOP6 = 0xb5,
+ OP_NOP7 = 0xb6,
+ OP_NOP8 = 0xb7,
+ OP_NOP9 = 0xb8,
+ OP_NOP10 = 0xb9,
+
+
+ // template matching params
+ OP_SMALLDATA = 0xf9,
+ OP_SMALLINTEGER = 0xfa,
+ OP_PUBKEYS = 0xfb,
+ OP_PUBKEYHASH = 0xfd,
+ OP_PUBKEY = 0xfe,
+
+ OP_INVALIDOPCODE = 0xff,
+};
+
+const char* GetOpName(opcodetype opcode);
class scriptnum_error : public std::runtime_error
{
@@ -131,7 +271,6 @@ public:
absvalue >>= 8;
}
-
// - If the most significant byte is >= 0x80 and the value is positive, push a
// new zero-byte to make the significant byte < 0x80 again.
@@ -173,66 +312,13 @@ private:
int64_t m_value;
};
-/** Signature hash types/flags */
-enum
-{
- SIGHASH_ALL = 1,
- SIGHASH_NONE = 2,
- SIGHASH_SINGLE = 3,
- SIGHASH_ANYONECANPAY = 0x80,
-};
-
-/** Script verification flags */
-enum
-{
- SCRIPT_VERIFY_NONE = 0,
- SCRIPT_VERIFY_P2SH = (1U << 0), // evaluate P2SH (BIP16) subscripts
- SCRIPT_VERIFY_STRICTENC = (1U << 1), // enforce strict conformance to DER and SEC2 for signatures and pubkeys
- SCRIPT_VERIFY_LOW_S = (1U << 2), // enforce low S values (<n/2) in signatures (depends on STRICTENC)
- SCRIPT_VERIFY_NOCACHE = (1U << 3), // do not store results in signature cache (but do query it)
- SCRIPT_VERIFY_NULLDUMMY = (1U << 4), // verify dummy stack item consumed by CHECKMULTISIG is of zero-length
-};
-
-/** IsMine() return codes */
-enum isminetype
-{
- ISMINE_NO = 0,
- ISMINE_WATCH_ONLY = 1,
- ISMINE_SPENDABLE = 2,
- ISMINE_ALL = ISMINE_WATCH_ONLY | ISMINE_SPENDABLE
-};
-/** used for bitflags of isminetype */
-typedef uint8_t isminefilter;
-
-// Mandatory script verification flags that all new blocks must comply with for
-// them to be valid. (but old blocks may not comply with) Currently just P2SH,
-// but in the future other flags may be added, such as a soft-fork to enforce
-// strict DER encoding.
-//
-// Failing one of these tests may trigger a DoS ban - see CheckInputs() for
-// details.
-static const unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH;
-
-// Standard script verification flags that standard transactions will comply
-// with. However scripts violating these flags may still be present in valid
-// blocks and we must accept those blocks.
-static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY_FLAGS |
- SCRIPT_VERIFY_STRICTENC |
- SCRIPT_VERIFY_NULLDUMMY;
-
-// For convenience, standard but not mandatory verify flags.
-static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS;
-
-enum txnouttype
+inline std::string ValueString(const std::vector<unsigned char>& vch)
{
- TX_NONSTANDARD,
- // 'standard' transaction types:
- TX_PUBKEY,
- TX_PUBKEYHASH,
- TX_SCRIPTHASH,
- TX_MULTISIG,
- TX_NULL_DATA,
-};
+ if (vch.size() <= 4)
+ return strprintf("%d", CScriptNum(vch).getint());
+ else
+ return HexStr(vch);
+}
class CNoDestination {
public:
@@ -248,167 +334,6 @@ public:
*/
typedef boost::variant<CNoDestination, CKeyID, CScriptID> CTxDestination;
-const char* GetTxnOutputType(txnouttype t);
-
-/** Script opcodes */
-enum opcodetype
-{
- // push value
- OP_0 = 0x00,
- OP_FALSE = OP_0,
- OP_PUSHDATA1 = 0x4c,
- OP_PUSHDATA2 = 0x4d,
- OP_PUSHDATA4 = 0x4e,
- OP_1NEGATE = 0x4f,
- OP_RESERVED = 0x50,
- OP_1 = 0x51,
- OP_TRUE=OP_1,
- OP_2 = 0x52,
- OP_3 = 0x53,
- OP_4 = 0x54,
- OP_5 = 0x55,
- OP_6 = 0x56,
- OP_7 = 0x57,
- OP_8 = 0x58,
- OP_9 = 0x59,
- OP_10 = 0x5a,
- OP_11 = 0x5b,
- OP_12 = 0x5c,
- OP_13 = 0x5d,
- OP_14 = 0x5e,
- OP_15 = 0x5f,
- OP_16 = 0x60,
-
- // control
- OP_NOP = 0x61,
- OP_VER = 0x62,
- OP_IF = 0x63,
- OP_NOTIF = 0x64,
- OP_VERIF = 0x65,
- OP_VERNOTIF = 0x66,
- OP_ELSE = 0x67,
- OP_ENDIF = 0x68,
- OP_VERIFY = 0x69,
- OP_RETURN = 0x6a,
-
- // stack ops
- OP_TOALTSTACK = 0x6b,
- OP_FROMALTSTACK = 0x6c,
- OP_2DROP = 0x6d,
- OP_2DUP = 0x6e,
- OP_3DUP = 0x6f,
- OP_2OVER = 0x70,
- OP_2ROT = 0x71,
- OP_2SWAP = 0x72,
- OP_IFDUP = 0x73,
- OP_DEPTH = 0x74,
- OP_DROP = 0x75,
- OP_DUP = 0x76,
- OP_NIP = 0x77,
- OP_OVER = 0x78,
- OP_PICK = 0x79,
- OP_ROLL = 0x7a,
- OP_ROT = 0x7b,
- OP_SWAP = 0x7c,
- OP_TUCK = 0x7d,
-
- // splice ops
- OP_CAT = 0x7e,
- OP_SUBSTR = 0x7f,
- OP_LEFT = 0x80,
- OP_RIGHT = 0x81,
- OP_SIZE = 0x82,
-
- // bit logic
- OP_INVERT = 0x83,
- OP_AND = 0x84,
- OP_OR = 0x85,
- OP_XOR = 0x86,
- OP_EQUAL = 0x87,
- OP_EQUALVERIFY = 0x88,
- OP_RESERVED1 = 0x89,
- OP_RESERVED2 = 0x8a,
-
- // numeric
- OP_1ADD = 0x8b,
- OP_1SUB = 0x8c,
- OP_2MUL = 0x8d,
- OP_2DIV = 0x8e,
- OP_NEGATE = 0x8f,
- OP_ABS = 0x90,
- OP_NOT = 0x91,
- OP_0NOTEQUAL = 0x92,
-
- OP_ADD = 0x93,
- OP_SUB = 0x94,
- OP_MUL = 0x95,
- OP_DIV = 0x96,
- OP_MOD = 0x97,
- OP_LSHIFT = 0x98,
- OP_RSHIFT = 0x99,
-
- OP_BOOLAND = 0x9a,
- OP_BOOLOR = 0x9b,
- OP_NUMEQUAL = 0x9c,
- OP_NUMEQUALVERIFY = 0x9d,
- OP_NUMNOTEQUAL = 0x9e,
- OP_LESSTHAN = 0x9f,
- OP_GREATERTHAN = 0xa0,
- OP_LESSTHANOREQUAL = 0xa1,
- OP_GREATERTHANOREQUAL = 0xa2,
- OP_MIN = 0xa3,
- OP_MAX = 0xa4,
-
- OP_WITHIN = 0xa5,
-
- // crypto
- OP_RIPEMD160 = 0xa6,
- OP_SHA1 = 0xa7,
- OP_SHA256 = 0xa8,
- OP_HASH160 = 0xa9,
- OP_HASH256 = 0xaa,
- OP_CODESEPARATOR = 0xab,
- OP_CHECKSIG = 0xac,
- OP_CHECKSIGVERIFY = 0xad,
- OP_CHECKMULTISIG = 0xae,
- OP_CHECKMULTISIGVERIFY = 0xaf,
-
- // expansion
- OP_NOP1 = 0xb0,
- OP_NOP2 = 0xb1,
- OP_NOP3 = 0xb2,
- OP_NOP4 = 0xb3,
- OP_NOP5 = 0xb4,
- OP_NOP6 = 0xb5,
- OP_NOP7 = 0xb6,
- OP_NOP8 = 0xb7,
- OP_NOP9 = 0xb8,
- OP_NOP10 = 0xb9,
-
-
-
- // template matching params
- OP_SMALLDATA = 0xf9,
- OP_SMALLINTEGER = 0xfa,
- OP_PUBKEYS = 0xfb,
- OP_PUBKEYHASH = 0xfd,
- OP_PUBKEY = 0xfe,
-
- OP_INVALIDOPCODE = 0xff,
-};
-
-const char* GetOpName(opcodetype opcode);
-
-
-
-inline std::string ValueString(const std::vector<unsigned char>& vch)
-{
- if (vch.size() <= 4)
- return strprintf("%d", CScriptNum(vch).getint());
- else
- return HexStr(vch);
-}
-
/** Serialized script, used inside transaction inputs and outputs */
class CScript : public std::vector<unsigned char>
{
@@ -446,7 +371,6 @@ public:
return ret;
}
-
CScript(int64_t b) { operator<<(b); }
explicit CScript(opcodetype b) { operator<<(b); }
@@ -718,98 +642,4 @@ public:
}
};
-/** Compact serializer for scripts.
- *
- * It detects common cases and encodes them much more efficiently.
- * 3 special cases are defined:
- * * Pay to pubkey hash (encoded as 21 bytes)
- * * Pay to script hash (encoded as 21 bytes)
- * * Pay to pubkey starting with 0x02, 0x03 or 0x04 (encoded as 33 bytes)
- *
- * Other scripts up to 121 bytes require 1 byte + script length. Above
- * that, scripts up to 16505 bytes require 2 bytes + script length.
- */
-class CScriptCompressor
-{
-private:
- // make this static for now (there are only 6 special scripts defined)
- // this can potentially be extended together with a new nVersion for
- // transactions, in which case this value becomes dependent on nVersion
- // and nHeight of the enclosing transaction.
- static const unsigned int nSpecialScripts = 6;
-
- CScript &script;
-protected:
- // These check for scripts for which a special case with a shorter encoding is defined.
- // They are implemented separately from the CScript test, as these test for exact byte
- // sequence correspondences, and are more strict. For example, IsToPubKey also verifies
- // whether the public key is valid (as invalid ones cannot be represented in compressed
- // form).
- bool IsToKeyID(CKeyID &hash) const;
- bool IsToScriptID(CScriptID &hash) const;
- bool IsToPubKey(CPubKey &pubkey) const;
-
- bool Compress(std::vector<unsigned char> &out) const;
- unsigned int GetSpecialSize(unsigned int nSize) const;
- bool Decompress(unsigned int nSize, const std::vector<unsigned char> &out);
-public:
- CScriptCompressor(CScript &scriptIn) : script(scriptIn) { }
-
- unsigned int GetSerializeSize(int nType, int nVersion) const {
- std::vector<unsigned char> compr;
- if (Compress(compr))
- return compr.size();
- unsigned int nSize = script.size() + nSpecialScripts;
- return script.size() + VARINT(nSize).GetSerializeSize(nType, nVersion);
- }
-
- template<typename Stream>
- void Serialize(Stream &s, int nType, int nVersion) const {
- std::vector<unsigned char> compr;
- if (Compress(compr)) {
- s << CFlatData(compr);
- return;
- }
- unsigned int nSize = script.size() + nSpecialScripts;
- s << VARINT(nSize);
- s << CFlatData(script);
- }
-
- template<typename Stream>
- void Unserialize(Stream &s, int nType, int nVersion) {
- unsigned int nSize = 0;
- s >> VARINT(nSize);
- if (nSize < nSpecialScripts) {
- std::vector<unsigned char> vch(GetSpecialSize(nSize), 0x00);
- s >> REF(CFlatData(vch));
- Decompress(nSize, vch);
- return;
- }
- nSize -= nSpecialScripts;
- script.resize(nSize);
- s >> REF(CFlatData(script));
- }
-};
-
-bool IsCanonicalPubKey(const std::vector<unsigned char> &vchPubKey, unsigned int flags);
-bool IsCanonicalSignature(const std::vector<unsigned char> &vchSig, unsigned int flags);
-
-bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType);
-uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
-bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet);
-int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions);
-bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType);
-isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
-isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest);
-void ExtractAffectedKeys(const CKeyStore &keystore, const CScript& scriptPubKey, std::vector<CKeyID> &vKeys);
-bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet);
-bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet);
-bool SignSignature(const CKeyStore& keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
-bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
-bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType);
-
-// Given two sets of signatures for scriptPubKey, possibly with OP_0 placeholders,
-// combine them intelligently and return the result.
-CScript CombineSignatures(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn, const CScript& scriptSig1, const CScript& scriptSig2);
-
#endif // H_BITCOIN_SCRIPT
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
new file mode 100644
index 0000000000..db9513db9f
--- /dev/null
+++ b/src/script/sign.cpp
@@ -0,0 +1,260 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "script/sign.h"
+
+#include "core.h"
+#include "key.h"
+#include "keystore.h"
+#include "script/standard.h"
+#include "uint256.h"
+
+#include <boost/foreach.hpp>
+
+using namespace std;
+
+typedef vector<unsigned char> valtype;
+
+bool Sign1(const CKeyID& address, const CKeyStore& keystore, uint256 hash, int nHashType, CScript& scriptSigRet)
+{
+ CKey key;
+ if (!keystore.GetKey(address, key))
+ return false;
+
+ vector<unsigned char> vchSig;
+ if (!key.Sign(hash, vchSig))
+ return false;
+ vchSig.push_back((unsigned char)nHashType);
+ scriptSigRet << vchSig;
+
+ return true;
+}
+
+bool SignN(const vector<valtype>& multisigdata, const CKeyStore& keystore, uint256 hash, int nHashType, CScript& scriptSigRet)
+{
+ int nSigned = 0;
+ int nRequired = multisigdata.front()[0];
+ for (unsigned int i = 1; i < multisigdata.size()-1 && nSigned < nRequired; i++)
+ {
+ const valtype& pubkey = multisigdata[i];
+ CKeyID keyID = CPubKey(pubkey).GetID();
+ if (Sign1(keyID, keystore, hash, nHashType, scriptSigRet))
+ ++nSigned;
+ }
+ return nSigned==nRequired;
+}
+
+//
+// Sign scriptPubKey with private keys stored in keystore, given transaction hash and hash type.
+// Signatures are returned in scriptSigRet (or returns false if scriptPubKey can't be signed),
+// unless whichTypeRet is TX_SCRIPTHASH, in which case scriptSigRet is the redemption script.
+// Returns false if scriptPubKey could not be completely satisfied.
+//
+bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, uint256 hash, int nHashType,
+ CScript& scriptSigRet, txnouttype& whichTypeRet)
+{
+ scriptSigRet.clear();
+
+ vector<valtype> vSolutions;
+ if (!Solver(scriptPubKey, whichTypeRet, vSolutions))
+ return false;
+
+ CKeyID keyID;
+ switch (whichTypeRet)
+ {
+ case TX_NONSTANDARD:
+ case TX_NULL_DATA:
+ return false;
+ case TX_PUBKEY:
+ keyID = CPubKey(vSolutions[0]).GetID();
+ return Sign1(keyID, keystore, hash, nHashType, scriptSigRet);
+ case TX_PUBKEYHASH:
+ keyID = CKeyID(uint160(vSolutions[0]));
+ if (!Sign1(keyID, keystore, hash, nHashType, scriptSigRet))
+ return false;
+ else
+ {
+ CPubKey vch;
+ keystore.GetPubKey(keyID, vch);
+ scriptSigRet << vch;
+ }
+ return true;
+ case TX_SCRIPTHASH:
+ return keystore.GetCScript(uint160(vSolutions[0]), scriptSigRet);
+
+ case TX_MULTISIG:
+ scriptSigRet << OP_0; // workaround CHECKMULTISIG bug
+ return (SignN(vSolutions, keystore, hash, nHashType, scriptSigRet));
+ }
+ return false;
+}
+
+bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
+{
+ assert(nIn < txTo.vin.size());
+ CTxIn& txin = txTo.vin[nIn];
+
+ // Leave out the signature from the hash, since a signature can't sign itself.
+ // The checksig op will also drop the signatures from its hash.
+ uint256 hash = SignatureHash(fromPubKey, txTo, nIn, nHashType);
+
+ txnouttype whichType;
+ if (!Solver(keystore, fromPubKey, hash, nHashType, txin.scriptSig, whichType))
+ return false;
+
+ if (whichType == TX_SCRIPTHASH)
+ {
+ // Solver returns the subscript that need to be evaluated;
+ // the final scriptSig is the signatures from that
+ // and then the serialized subscript:
+ CScript subscript = txin.scriptSig;
+
+ // Recompute txn hash using subscript in place of scriptPubKey:
+ uint256 hash2 = SignatureHash(subscript, txTo, nIn, nHashType);
+
+ txnouttype subType;
+ bool fSolved =
+ Solver(keystore, subscript, hash2, nHashType, txin.scriptSig, subType) && subType != TX_SCRIPTHASH;
+ // Append serialized subscript whether or not it is completely signed:
+ txin.scriptSig << static_cast<valtype>(subscript);
+ if (!fSolved) return false;
+ }
+
+ // Test solution
+ return VerifyScript(txin.scriptSig, fromPubKey, txTo, nIn, STANDARD_SCRIPT_VERIFY_FLAGS, 0);
+}
+
+bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
+{
+ assert(nIn < txTo.vin.size());
+ CTxIn& txin = txTo.vin[nIn];
+ assert(txin.prevout.n < txFrom.vout.size());
+ const CTxOut& txout = txFrom.vout[txin.prevout.n];
+
+ return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, nHashType);
+}
+
+static CScript PushAll(const vector<valtype>& values)
+{
+ CScript result;
+ BOOST_FOREACH(const valtype& v, values)
+ result << v;
+ return result;
+}
+
+static CScript CombineMultisig(CScript scriptPubKey, const CMutableTransaction& txTo, unsigned int nIn,
+ const vector<valtype>& vSolutions,
+ vector<valtype>& sigs1, vector<valtype>& sigs2)
+{
+ // Combine all the signatures we've got:
+ set<valtype> allsigs;
+ BOOST_FOREACH(const valtype& v, sigs1)
+ {
+ if (!v.empty())
+ allsigs.insert(v);
+ }
+ BOOST_FOREACH(const valtype& v, sigs2)
+ {
+ if (!v.empty())
+ allsigs.insert(v);
+ }
+
+ // Build a map of pubkey -> signature by matching sigs to pubkeys:
+ assert(vSolutions.size() > 1);
+ unsigned int nSigsRequired = vSolutions.front()[0];
+ unsigned int nPubKeys = vSolutions.size()-2;
+ map<valtype, valtype> sigs;
+ BOOST_FOREACH(const valtype& sig, allsigs)
+ {
+ for (unsigned int i = 0; i < nPubKeys; i++)
+ {
+ const valtype& pubkey = vSolutions[i+1];
+ if (sigs.count(pubkey))
+ continue; // Already got a sig for this pubkey
+
+ if (CheckSig(sig, pubkey, scriptPubKey, txTo, nIn, 0, 0))
+ {
+ sigs[pubkey] = sig;
+ break;
+ }
+ }
+ }
+ // Now build a merged CScript:
+ unsigned int nSigsHave = 0;
+ CScript result; result << OP_0; // pop-one-too-many workaround
+ for (unsigned int i = 0; i < nPubKeys && nSigsHave < nSigsRequired; i++)
+ {
+ if (sigs.count(vSolutions[i+1]))
+ {
+ result << sigs[vSolutions[i+1]];
+ ++nSigsHave;
+ }
+ }
+ // Fill any missing with OP_0:
+ for (unsigned int i = nSigsHave; i < nSigsRequired; i++)
+ result << OP_0;
+
+ return result;
+}
+
+static CScript CombineSignatures(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn,
+ const txnouttype txType, const vector<valtype>& vSolutions,
+ vector<valtype>& sigs1, vector<valtype>& sigs2)
+{
+ switch (txType)
+ {
+ case TX_NONSTANDARD:
+ case TX_NULL_DATA:
+ // Don't know anything about this, assume bigger one is correct:
+ if (sigs1.size() >= sigs2.size())
+ return PushAll(sigs1);
+ return PushAll(sigs2);
+ case TX_PUBKEY:
+ case TX_PUBKEYHASH:
+ // Signatures are bigger than placeholders or empty scripts:
+ if (sigs1.empty() || sigs1[0].empty())
+ return PushAll(sigs2);
+ return PushAll(sigs1);
+ case TX_SCRIPTHASH:
+ if (sigs1.empty() || sigs1.back().empty())
+ return PushAll(sigs2);
+ else if (sigs2.empty() || sigs2.back().empty())
+ return PushAll(sigs1);
+ else
+ {
+ // Recur to combine:
+ valtype spk = sigs1.back();
+ CScript pubKey2(spk.begin(), spk.end());
+
+ txnouttype txType2;
+ vector<vector<unsigned char> > vSolutions2;
+ Solver(pubKey2, txType2, vSolutions2);
+ sigs1.pop_back();
+ sigs2.pop_back();
+ CScript result = CombineSignatures(pubKey2, txTo, nIn, txType2, vSolutions2, sigs1, sigs2);
+ result << spk;
+ return result;
+ }
+ case TX_MULTISIG:
+ return CombineMultisig(scriptPubKey, txTo, nIn, vSolutions, sigs1, sigs2);
+ }
+
+ return CScript();
+}
+
+CScript CombineSignatures(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn,
+ const CScript& scriptSig1, const CScript& scriptSig2)
+{
+ txnouttype txType;
+ vector<vector<unsigned char> > vSolutions;
+ Solver(scriptPubKey, txType, vSolutions);
+
+ vector<valtype> stack1;
+ EvalScript(stack1, scriptSig1, CTransaction(), 0, SCRIPT_VERIFY_STRICTENC, 0);
+ vector<valtype> stack2;
+ EvalScript(stack2, scriptSig2, CTransaction(), 0, SCRIPT_VERIFY_STRICTENC, 0);
+
+ return CombineSignatures(scriptPubKey, txTo, nIn, txType, vSolutions, stack1, stack2);
+}
diff --git a/src/script/sign.h b/src/script/sign.h
new file mode 100644
index 0000000000..f218a64562
--- /dev/null
+++ b/src/script/sign.h
@@ -0,0 +1,24 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef H_BITCOIN_SCRIPT_SIGN
+#define H_BITCOIN_SCRIPT_SIGN
+
+#include "script/interpreter.h"
+
+class CKeyStore;
+class CScript;
+class CTransaction;
+
+struct CMutableTransaction;
+
+bool SignSignature(const CKeyStore& keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
+bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
+
+// Given two sets of signatures for scriptPubKey, possibly with OP_0 placeholders,
+// combine them intelligently and return the result.
+CScript CombineSignatures(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn, const CScript& scriptSig1, const CScript& scriptSig2);
+
+#endif // H_BITCOIN_SCRIPT_SIGN
diff --git a/src/script/standard.cpp b/src/script/standard.cpp
new file mode 100644
index 0000000000..bda4b8b0ae
--- /dev/null
+++ b/src/script/standard.cpp
@@ -0,0 +1,254 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "script/standard.h"
+
+#include "script/script.h"
+#include "util.h"
+
+#include <boost/foreach.hpp>
+
+using namespace std;
+
+typedef vector<unsigned char> valtype;
+
+const char* GetTxnOutputType(txnouttype t)
+{
+ switch (t)
+ {
+ case TX_NONSTANDARD: return "nonstandard";
+ case TX_PUBKEY: return "pubkey";
+ case TX_PUBKEYHASH: return "pubkeyhash";
+ case TX_SCRIPTHASH: return "scripthash";
+ case TX_MULTISIG: return "multisig";
+ case TX_NULL_DATA: return "nulldata";
+ }
+ return NULL;
+}
+
+//
+// Return public keys or hashes from scriptPubKey, for 'standard' transaction types.
+//
+bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsigned char> >& vSolutionsRet)
+{
+ // Templates
+ static multimap<txnouttype, CScript> mTemplates;
+ if (mTemplates.empty())
+ {
+ // Standard tx, sender provides pubkey, receiver adds signature
+ mTemplates.insert(make_pair(TX_PUBKEY, CScript() << OP_PUBKEY << OP_CHECKSIG));
+
+ // Bitcoin address tx, sender provides hash of pubkey, receiver provides signature and pubkey
+ mTemplates.insert(make_pair(TX_PUBKEYHASH, CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG));
+
+ // 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));
+ }
+
+ // 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())
+ {
+ typeRet = TX_SCRIPTHASH;
+ vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22);
+ vSolutionsRet.push_back(hashBytes);
+ return true;
+ }
+
+ // Scan templates
+ const CScript& script1 = scriptPubKey;
+ BOOST_FOREACH(const PAIRTYPE(txnouttype, CScript)& tplate, mTemplates)
+ {
+ const CScript& script2 = tplate.second;
+ vSolutionsRet.clear();
+
+ opcodetype opcode1, opcode2;
+ vector<unsigned char> vch1, vch2;
+
+ // Compare
+ CScript::const_iterator pc1 = script1.begin();
+ CScript::const_iterator pc2 = script2.begin();
+ while (true)
+ {
+ if (pc1 == script1.end() && pc2 == script2.end())
+ {
+ // Found a match
+ typeRet = tplate.first;
+ if (typeRet == TX_MULTISIG)
+ {
+ // Additional checks for TX_MULTISIG:
+ unsigned char m = vSolutionsRet.front()[0];
+ unsigned char n = vSolutionsRet.back()[0];
+ if (m < 1 || n < 1 || m > n || vSolutionsRet.size()-2 != n)
+ return false;
+ }
+ return true;
+ }
+ if (!script1.GetOp(pc1, opcode1, vch1))
+ break;
+ if (!script2.GetOp(pc2, opcode2, vch2))
+ break;
+
+ // Template matching opcodes:
+ if (opcode2 == OP_PUBKEYS)
+ {
+ while (vch1.size() >= 33 && vch1.size() <= 65)
+ {
+ vSolutionsRet.push_back(vch1);
+ if (!script1.GetOp(pc1, opcode1, vch1))
+ break;
+ }
+ if (!script2.GetOp(pc2, opcode2, vch2))
+ break;
+ // Normal situation is to fall through
+ // to other if/else statements
+ }
+
+ if (opcode2 == OP_PUBKEY)
+ {
+ if (vch1.size() < 33 || vch1.size() > 65)
+ break;
+ vSolutionsRet.push_back(vch1);
+ }
+ else if (opcode2 == OP_PUBKEYHASH)
+ {
+ if (vch1.size() != sizeof(uint160))
+ break;
+ vSolutionsRet.push_back(vch1);
+ }
+ else if (opcode2 == OP_SMALLINTEGER)
+ { // Single-byte small integer pushed onto vSolutions
+ if (opcode1 == OP_0 ||
+ (opcode1 >= OP_1 && opcode1 <= OP_16))
+ {
+ char n = (char)CScript::DecodeOP_N(opcode1);
+ vSolutionsRet.push_back(valtype(1, n));
+ }
+ else
+ break;
+ }
+ else if (opcode2 == OP_SMALLDATA)
+ {
+ // small pushdata, <= MAX_OP_RETURN_RELAY bytes
+ if (vch1.size() > MAX_OP_RETURN_RELAY)
+ break;
+ }
+ else if (opcode1 != opcode2 || vch1 != vch2)
+ {
+ // Others must match exactly
+ break;
+ }
+ }
+ }
+
+ vSolutionsRet.clear();
+ typeRet = TX_NONSTANDARD;
+ return false;
+}
+
+int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions)
+{
+ switch (t)
+ {
+ case TX_NONSTANDARD:
+ case TX_NULL_DATA:
+ return -1;
+ case TX_PUBKEY:
+ return 1;
+ case TX_PUBKEYHASH:
+ return 2;
+ case TX_MULTISIG:
+ if (vSolutions.size() < 1 || vSolutions[0].size() < 1)
+ return -1;
+ return vSolutions[0][0] + 1;
+ case TX_SCRIPTHASH:
+ return 1; // doesn't include args needed by the script
+ }
+ return -1;
+}
+
+bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
+{
+ vector<valtype> vSolutions;
+ if (!Solver(scriptPubKey, whichType, vSolutions))
+ return false;
+
+ if (whichType == TX_MULTISIG)
+ {
+ unsigned char m = vSolutions.front()[0];
+ unsigned char n = vSolutions.back()[0];
+ // Support up to x-of-3 multisig txns as standard
+ if (n < 1 || n > 3)
+ return false;
+ if (m < 1 || m > n)
+ return false;
+ }
+
+ return whichType != TX_NONSTANDARD;
+}
+
+bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
+{
+ vector<valtype> vSolutions;
+ txnouttype whichType;
+ if (!Solver(scriptPubKey, whichType, vSolutions))
+ return false;
+
+ if (whichType == TX_PUBKEY)
+ {
+ addressRet = CPubKey(vSolutions[0]).GetID();
+ return true;
+ }
+ else if (whichType == TX_PUBKEYHASH)
+ {
+ addressRet = CKeyID(uint160(vSolutions[0]));
+ return true;
+ }
+ else if (whichType == TX_SCRIPTHASH)
+ {
+ addressRet = CScriptID(uint160(vSolutions[0]));
+ return true;
+ }
+ // Multisig txns have more than one address...
+ return false;
+}
+
+bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vector<CTxDestination>& addressRet, int& nRequiredRet)
+{
+ addressRet.clear();
+ typeRet = TX_NONSTANDARD;
+ vector<valtype> vSolutions;
+ if (!Solver(scriptPubKey, typeRet, vSolutions))
+ return false;
+ if (typeRet == TX_NULL_DATA){
+ // This is data, not addresses
+ return false;
+ }
+
+ if (typeRet == TX_MULTISIG)
+ {
+ nRequiredRet = vSolutions.front()[0];
+ for (unsigned int i = 1; i < vSolutions.size()-1; i++)
+ {
+ CTxDestination address = CPubKey(vSolutions[i]).GetID();
+ addressRet.push_back(address);
+ }
+ }
+ else
+ {
+ nRequiredRet = 1;
+ CTxDestination address;
+ if (!ExtractDestination(scriptPubKey, address))
+ return false;
+ addressRet.push_back(address);
+ }
+
+ return true;
+}
diff --git a/src/script/standard.h b/src/script/standard.h
new file mode 100644
index 0000000000..6c17a9394e
--- /dev/null
+++ b/src/script/standard.h
@@ -0,0 +1,56 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef H_BITCOIN_SCRIPT_STANDARD
+#define H_BITCOIN_SCRIPT_STANDARD
+
+#include "script/script.h"
+#include "script/interpreter.h"
+
+#include <stdint.h>
+
+class CScript;
+
+static const unsigned int MAX_OP_RETURN_RELAY = 40; // bytes
+
+// Mandatory script verification flags that all new blocks must comply with for
+// them to be valid. (but old blocks may not comply with) Currently just P2SH,
+// but in the future other flags may be added, such as a soft-fork to enforce
+// strict DER encoding.
+//
+// Failing one of these tests may trigger a DoS ban - see CheckInputs() for
+// details.
+static const unsigned int MANDATORY_SCRIPT_VERIFY_FLAGS = SCRIPT_VERIFY_P2SH;
+
+// Standard script verification flags that standard transactions will comply
+// with. However scripts violating these flags may still be present in valid
+// blocks and we must accept those blocks.
+static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY_FLAGS |
+ SCRIPT_VERIFY_STRICTENC |
+ SCRIPT_VERIFY_NULLDUMMY;
+
+// For convenience, standard but not mandatory verify flags.
+static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS;
+
+enum txnouttype
+{
+ TX_NONSTANDARD,
+ // 'standard' transaction types:
+ TX_PUBKEY,
+ TX_PUBKEYHASH,
+ TX_SCRIPTHASH,
+ TX_MULTISIG,
+ TX_NULL_DATA,
+};
+
+const char* GetTxnOutputType(txnouttype t);
+
+bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet);
+int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions);
+bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType);
+bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet);
+bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet);
+
+#endif // H_BITCOIN_SCRIPT_STANDARD
diff --git a/src/serialize.h b/src/serialize.h
index 1440676a16..57f5fd069b 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -10,8 +10,8 @@
#include <algorithm>
#include <assert.h>
-#include <limits>
#include <ios>
+#include <limits>
#include <map>
#include <set>
#include <stdint.h>
@@ -91,9 +91,9 @@ enum
/* Implement three methods for serializable objects. These are actually wrappers over
* "SerializationOp" template, which implements the body of each class' serialization
- * code. Adding "IMPLEMENT_SERIALIZE" in the body of the class causes these wrappers to be
+ * code. Adding "ADD_SERIALIZE_METHODS" in the body of the class causes these wrappers to be
* added as members. */
-#define IMPLEMENT_SERIALIZE \
+#define ADD_SERIALIZE_METHODS \
size_t GetSerializeSize(int nType, int nVersion) const { \
CSizeComputer s(nType, nVersion); \
NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize(), nType, nVersion);\
@@ -807,7 +807,7 @@ void Unserialize(Stream& is, std::set<K, Pred, A>& m, int nType, int nVersion)
//
-// Support for IMPLEMENT_SERIALIZE and READWRITE macro
+// Support for ADD_SERIALIZE_METHODS and READWRITE macro
//
struct CSerActionSerialize
{
diff --git a/src/sync.cpp b/src/sync.cpp
index 066c1ca744..d424f7bc95 100644
--- a/src/sync.cpp
+++ b/src/sync.cpp
@@ -7,9 +7,10 @@
#include "util.h"
#include "utilstrencodings.h"
+#include <stdio.h>
+
#include <boost/foreach.hpp>
#include <boost/thread.hpp>
-#include <stdio.h>
#ifdef DEBUG_LOCKCONTENTION
void PrintLockContention(const char* pszName, const char* pszFile, int nLine)
diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp
index 8fa38c3605..e019674816 100644
--- a/src/test/DoS_tests.cpp
+++ b/src/test/DoS_tests.cpp
@@ -12,7 +12,7 @@
#include "main.h"
#include "net.h"
#include "pow.h"
-#include "script.h"
+#include "script/sign.h"
#include "serialize.h"
#include "util.h"
@@ -24,7 +24,8 @@
#include <boost/test/unit_test.hpp>
// Tests this internal-to-main.cpp method:
-extern bool AddOrphanTx(const CTransaction& tx);
+extern bool AddOrphanTx(const CTransaction& tx, NodeId peer);
+extern void EraseOrphansFor(NodeId peer);
extern unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans);
extern std::map<uint256, CTransaction> mapOrphanTransactions;
extern std::map<uint256, std::set<uint256> > mapOrphanTransactionsByPrev;
@@ -174,7 +175,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
tx.vout[0].nValue = 1*CENT;
tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
- AddOrphanTx(tx);
+ AddOrphanTx(tx, i);
}
// ... and 50 that depend on other orphans:
@@ -191,7 +192,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
SignSignature(keystore, txPrev, tx, 0);
- AddOrphanTx(tx);
+ AddOrphanTx(tx, i);
}
// This really-big orphan should be ignored:
@@ -215,7 +216,15 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
for (unsigned int j = 1; j < tx.vin.size(); j++)
tx.vin[j].scriptSig = tx.vin[0].scriptSig;
- BOOST_CHECK(!AddOrphanTx(tx));
+ BOOST_CHECK(!AddOrphanTx(tx, i));
+ }
+
+ // Test EraseOrphansFor:
+ for (NodeId i = 0; i < 3; i++)
+ {
+ size_t sizeBefore = mapOrphanTransactions.size();
+ EraseOrphansFor(i);
+ BOOST_CHECK(mapOrphanTransactions.size() < sizeBefore);
}
// Test LimitOrphanTxSize() function:
diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp
index 0ac3e9a363..fe68e9e974 100644
--- a/src/test/base58_tests.cpp
+++ b/src/test/base58_tests.cpp
@@ -9,7 +9,7 @@
#include "data/base58_keys_valid.json.h"
#include "key.h"
-#include "script.h"
+#include "script/script.h"
#include "uint256.h"
#include "util.h"
diff --git a/src/test/canonical_tests.cpp b/src/test/canonical_tests.cpp
index a9798623ea..a17099de72 100644
--- a/src/test/canonical_tests.cpp
+++ b/src/test/canonical_tests.cpp
@@ -8,9 +8,11 @@
#include "data/sig_noncanonical.json.h"
#include "data/sig_canonical.json.h"
+#include "key.h"
#include "random.h"
-#include "script.h"
+#include "script/interpreter.h"
#include "util.h"
+#include "utilstrencodings.h"
#include <boost/foreach.hpp>
#include <boost/test/unit_test.hpp>
diff --git a/src/test/data/bitcoin-util-test.json b/src/test/data/bitcoin-util-test.json
index 7db87d7c11..cb74d73ef2 100644
--- a/src/test/data/bitcoin-util-test.json
+++ b/src/test/data/bitcoin-util-test.json
@@ -34,5 +34,8 @@
"outaddr=0.18:13tuJJDR2RgArmgfv6JScSdreahzgc4T6o",
"outaddr=4:1P8yWvZW8jVihP1bzHeqfE4aoXNX8AVa46"],
"output_cmp": "txcreate1.hex"
+ },
+ { "exec": ["./bitcoin-tx", "-create", "outscript=0:"],
+ "output_cmp": "txcreate2.hex"
}
]
diff --git a/src/test/data/script_invalid.json b/src/test/data/script_invalid.json
index e3e1ccbf3c..75de4716f8 100644
--- a/src/test/data/script_invalid.json
+++ b/src/test/data/script_invalid.json
@@ -1,366 +1,377 @@
[
-["", "DEPTH", "Test the test: we should have an empty stack after scriptSig evaluation"],
-[" ", "DEPTH", "and multiple spaces should not change that."],
-[" ", "DEPTH"],
-[" ", "DEPTH"],
-
-["", ""],
-["", "NOP"],
-["", "NOP DEPTH"],
-["NOP", ""],
-["NOP", "DEPTH"],
-["NOP","NOP"],
-["NOP","NOP DEPTH"],
-
-["DEPTH", ""],
-
-["0x4c01","0x01 NOP", "PUSHDATA1 with not enough bytes"],
-["0x4d0200ff","0x01 NOP", "PUSHDATA2 with not enough bytes"],
-["0x4e03000000ffff","0x01 NOP", "PUSHDATA4 with not enough bytes"],
-
-["1", "IF 0x50 ENDIF 1", "0x50 is reserved"],
-["0x52", "0x5f ADD 0x60 EQUAL", "0x51 through 0x60 push 1 through 16 onto stack"],
-["0","NOP"],
-["1", "IF VER ELSE 1 ENDIF", "VER non-functional"],
-["0", "IF VERIF ELSE 1 ENDIF", "VERIF illegal everywhere"],
-["0", "IF ELSE 1 ELSE VERIF ENDIF", "VERIF illegal everywhere"],
-["0", "IF VERNOTIF ELSE 1 ENDIF", "VERNOTIF illegal everywhere"],
-["0", "IF ELSE 1 ELSE VERNOTIF ENDIF", "VERNOTIF illegal everywhere"],
-
-["1 IF", "1 ENDIF", "IF/ENDIF can't span scriptSig/scriptPubKey"],
-["1 IF 0 ENDIF", "1 ENDIF"],
-["1 ELSE 0 ENDIF", "1"],
-["0 NOTIF", "123"],
-
-["0", "DUP IF ENDIF"],
-["0", "IF 1 ENDIF"],
-["0", "DUP IF ELSE ENDIF"],
-["0", "IF 1 ELSE ENDIF"],
-["0", "NOTIF ELSE 1 ENDIF"],
-
-["0 1", "IF IF 1 ELSE 0 ENDIF ENDIF"],
-["0 0", "IF IF 1 ELSE 0 ENDIF ENDIF"],
-["1 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"],
-["0 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"],
-
-["0 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF"],
-["0 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF"],
-["1 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"],
-["0 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"],
-
-["1", "IF RETURN ELSE ELSE 1 ENDIF", "Multiple ELSEs"],
-["1", "IF 1 ELSE ELSE RETURN ENDIF"],
-
-["1", "ENDIF", "Malformed IF/ELSE/ENDIF sequence"],
-["1", "ELSE ENDIF"],
-["1", "ENDIF ELSE"],
-["1", "ENDIF ELSE IF"],
-["1", "IF ELSE ENDIF ELSE"],
-["1", "IF ELSE ENDIF ELSE ENDIF"],
-["1", "IF ENDIF ENDIF"],
-["1", "IF ELSE ELSE ENDIF ENDIF"],
-
-["1", "RETURN"],
-["1", "DUP IF RETURN ENDIF"],
-
-["1", "RETURN 'data'", "canonical prunable txout format"],
-["0 IF", "RETURN ENDIF 1", "still prunable because IF/ENDIF can't span scriptSig/scriptPubKey"],
-
-["0", "VERIFY 1"],
-["1", "VERIFY"],
-["1", "VERIFY 0"],
-
-["1 TOALTSTACK", "FROMALTSTACK 1", "alt stack not shared between sig/pubkey"],
-
-["IFDUP", "DEPTH 0 EQUAL"],
-["DROP", "DEPTH 0 EQUAL"],
-["DUP", "DEPTH 0 EQUAL"],
-["1", "DUP 1 ADD 2 EQUALVERIFY 0 EQUAL"],
-["NOP", "NIP"],
-["NOP", "1 NIP"],
-["NOP", "1 0 NIP"],
-["NOP", "OVER 1"],
-["1", "OVER"],
-["0 1", "OVER DEPTH 3 EQUALVERIFY"],
-["19 20 21", "PICK 19 EQUALVERIFY DEPTH 2 EQUAL"],
-["NOP", "0 PICK"],
-["1", "-1 PICK"],
-["19 20 21", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL"],
-["19 20 21", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL"],
-["19 20 21", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL"],
-["NOP", "0 ROLL"],
-["1", "-1 ROLL"],
-["19 20 21", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL"],
-["19 20 21", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL"],
-["19 20 21", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL"],
-["NOP", "ROT 1"],
-["NOP", "1 ROT 1"],
-["NOP", "1 2 ROT 1"],
-["NOP", "0 1 2 ROT"],
-["NOP", "SWAP 1"],
-["1", "SWAP 1"],
-["0 1", "SWAP 1 EQUALVERIFY"],
-["NOP", "TUCK 1"],
-["1", "TUCK 1"],
-["1 0", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP"],
-["NOP", "2DUP 1"],
-["1", "2DUP 1"],
-["NOP", "3DUP 1"],
-["1", "3DUP 1"],
-["1 2", "3DUP 1"],
-["NOP", "2OVER 1"],
-["1", "2 3 2OVER 1"],
-["NOP", "2SWAP 1"],
-["1", "2 3 2SWAP 1"],
-
-["'a' 'b'", "CAT", "CAT disabled"],
-["'a' 'b' 0", "IF CAT ELSE 1 ENDIF", "CAT disabled"],
-["'abc' 1 1", "SUBSTR", "SUBSTR disabled"],
-["'abc' 1 1 0", "IF SUBSTR ELSE 1 ENDIF", "SUBSTR disabled"],
-["'abc' 2 0", "IF LEFT ELSE 1 ENDIF", "LEFT disabled"],
-["'abc' 2 0", "IF RIGHT ELSE 1 ENDIF", "RIGHT disabled"],
-
-["NOP", "SIZE 1"],
-
-["'abc'", "IF INVERT ELSE 1 ENDIF", "INVERT disabled"],
-["1 2 0 IF AND ELSE 1 ENDIF", "NOP", "AND disabled"],
-["1 2 0 IF OR ELSE 1 ENDIF", "NOP", "OR disabled"],
-["1 2 0 IF XOR ELSE 1 ENDIF", "NOP", "XOR disabled"],
-["2 0 IF 2MUL ELSE 1 ENDIF", "NOP", "2MUL disabled"],
-["2 0 IF 2DIV ELSE 1 ENDIF", "NOP", "2DIV disabled"],
-["2 2 0 IF MUL ELSE 1 ENDIF", "NOP", "MUL disabled"],
-["2 2 0 IF DIV ELSE 1 ENDIF", "NOP", "DIV disabled"],
-["2 2 0 IF MOD ELSE 1 ENDIF", "NOP", "MOD disabled"],
-["2 2 0 IF LSHIFT ELSE 1 ENDIF", "NOP", "LSHIFT disabled"],
-["2 2 0 IF RSHIFT ELSE 1 ENDIF", "NOP", "RSHIFT disabled"],
-
-["0 1","EQUAL"],
-["1 1 ADD", "0 EQUAL"],
-["11 1 ADD 12 SUB", "11 EQUAL"],
-
-["2147483648 0 ADD", "NOP", "arithmetic operands must be in range [-2^31...2^31] "],
-["-2147483648 0 ADD", "NOP", "arithmetic operands must be in range [-2^31...2^31] "],
-["2147483647 DUP ADD", "4294967294 NUMEQUAL", "NUMEQUAL must be in numeric range"],
-["'abcdef' NOT", "0 EQUAL", "NOT is an arithmetic operand"],
-
-["2 DUP MUL", "4 EQUAL", "disabled"],
-["2 DUP DIV", "1 EQUAL", "disabled"],
-["2 2MUL", "4 EQUAL", "disabled"],
-["2 2DIV", "1 EQUAL", "disabled"],
-["7 3 MOD", "1 EQUAL", "disabled"],
-["2 2 LSHIFT", "8 EQUAL", "disabled"],
-["2 1 RSHIFT", "1 EQUAL", "disabled"],
-
-["1","NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL"],
-["'NOP_1_to_10' NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL"],
-
-["0x50","1", "opcode 0x50 is reserved"],
-["1", "IF 0xba ELSE 1 ENDIF", "opcodes above NOP10 invalid if executed"],
-["1", "IF 0xbb ELSE 1 ENDIF"],
-["1", "IF 0xbc ELSE 1 ENDIF"],
-["1", "IF 0xbd ELSE 1 ENDIF"],
-["1", "IF 0xbe ELSE 1 ENDIF"],
-["1", "IF 0xbf ELSE 1 ENDIF"],
-["1", "IF 0xc0 ELSE 1 ENDIF"],
-["1", "IF 0xc1 ELSE 1 ENDIF"],
-["1", "IF 0xc2 ELSE 1 ENDIF"],
-["1", "IF 0xc3 ELSE 1 ENDIF"],
-["1", "IF 0xc4 ELSE 1 ENDIF"],
-["1", "IF 0xc5 ELSE 1 ENDIF"],
-["1", "IF 0xc6 ELSE 1 ENDIF"],
-["1", "IF 0xc7 ELSE 1 ENDIF"],
-["1", "IF 0xc8 ELSE 1 ENDIF"],
-["1", "IF 0xc9 ELSE 1 ENDIF"],
-["1", "IF 0xca ELSE 1 ENDIF"],
-["1", "IF 0xcb ELSE 1 ENDIF"],
-["1", "IF 0xcc ELSE 1 ENDIF"],
-["1", "IF 0xcd ELSE 1 ENDIF"],
-["1", "IF 0xce ELSE 1 ENDIF"],
-["1", "IF 0xcf ELSE 1 ENDIF"],
-["1", "IF 0xd0 ELSE 1 ENDIF"],
-["1", "IF 0xd1 ELSE 1 ENDIF"],
-["1", "IF 0xd2 ELSE 1 ENDIF"],
-["1", "IF 0xd3 ELSE 1 ENDIF"],
-["1", "IF 0xd4 ELSE 1 ENDIF"],
-["1", "IF 0xd5 ELSE 1 ENDIF"],
-["1", "IF 0xd6 ELSE 1 ENDIF"],
-["1", "IF 0xd7 ELSE 1 ENDIF"],
-["1", "IF 0xd8 ELSE 1 ENDIF"],
-["1", "IF 0xd9 ELSE 1 ENDIF"],
-["1", "IF 0xda ELSE 1 ENDIF"],
-["1", "IF 0xdb ELSE 1 ENDIF"],
-["1", "IF 0xdc ELSE 1 ENDIF"],
-["1", "IF 0xdd ELSE 1 ENDIF"],
-["1", "IF 0xde ELSE 1 ENDIF"],
-["1", "IF 0xdf ELSE 1 ENDIF"],
-["1", "IF 0xe0 ELSE 1 ENDIF"],
-["1", "IF 0xe1 ELSE 1 ENDIF"],
-["1", "IF 0xe2 ELSE 1 ENDIF"],
-["1", "IF 0xe3 ELSE 1 ENDIF"],
-["1", "IF 0xe4 ELSE 1 ENDIF"],
-["1", "IF 0xe5 ELSE 1 ENDIF"],
-["1", "IF 0xe6 ELSE 1 ENDIF"],
-["1", "IF 0xe7 ELSE 1 ENDIF"],
-["1", "IF 0xe8 ELSE 1 ENDIF"],
-["1", "IF 0xe9 ELSE 1 ENDIF"],
-["1", "IF 0xea ELSE 1 ENDIF"],
-["1", "IF 0xeb ELSE 1 ENDIF"],
-["1", "IF 0xec ELSE 1 ENDIF"],
-["1", "IF 0xed ELSE 1 ENDIF"],
-["1", "IF 0xee ELSE 1 ENDIF"],
-["1", "IF 0xef ELSE 1 ENDIF"],
-["1", "IF 0xf0 ELSE 1 ENDIF"],
-["1", "IF 0xf1 ELSE 1 ENDIF"],
-["1", "IF 0xf2 ELSE 1 ENDIF"],
-["1", "IF 0xf3 ELSE 1 ENDIF"],
-["1", "IF 0xf4 ELSE 1 ENDIF"],
-["1", "IF 0xf5 ELSE 1 ENDIF"],
-["1", "IF 0xf6 ELSE 1 ENDIF"],
-["1", "IF 0xf7 ELSE 1 ENDIF"],
-["1", "IF 0xf8 ELSE 1 ENDIF"],
-["1", "IF 0xf9 ELSE 1 ENDIF"],
-["1", "IF 0xfa ELSE 1 ENDIF"],
-["1", "IF 0xfb ELSE 1 ENDIF"],
-["1", "IF 0xfc ELSE 1 ENDIF"],
-["1", "IF 0xfd ELSE 1 ENDIF"],
-["1", "IF 0xfe ELSE 1 ENDIF"],
-["1", "IF 0xff ELSE 1 ENDIF"],
-
-["1 IF 1 ELSE", "0xff ENDIF", "invalid because scriptSig and scriptPubKey are processed separately"],
-
-["NOP", "RIPEMD160"],
-["NOP", "SHA1"],
-["NOP", "SHA256"],
-["NOP", "HASH160"],
-["NOP", "HASH256"],
+["", "DEPTH", "P2SH,STRICTENC", "Test the test: we should have an empty stack after scriptSig evaluation"],
+[" ", "DEPTH", "P2SH,STRICTENC", "and multiple spaces should not change that."],
+[" ", "DEPTH", "P2SH,STRICTENC"],
+[" ", "DEPTH", "P2SH,STRICTENC"],
+
+["", "", "P2SH,STRICTENC"],
+["", "NOP", "P2SH,STRICTENC"],
+["", "NOP DEPTH", "P2SH,STRICTENC"],
+["NOP", "", "P2SH,STRICTENC"],
+["NOP", "DEPTH", "P2SH,STRICTENC"],
+["NOP","NOP", "P2SH,STRICTENC"],
+["NOP","NOP DEPTH", "P2SH,STRICTENC"],
+
+["DEPTH", "", "P2SH,STRICTENC"],
+
+["0x4c01","0x01 NOP", "P2SH,STRICTENC", "PUSHDATA1 with not enough bytes"],
+["0x4d0200ff","0x01 NOP", "P2SH,STRICTENC", "PUSHDATA2 with not enough bytes"],
+["0x4e03000000ffff","0x01 NOP", "P2SH,STRICTENC", "PUSHDATA4 with not enough bytes"],
+
+["1", "IF 0x50 ENDIF 1", "P2SH,STRICTENC", "0x50 is reserved"],
+["0x52", "0x5f ADD 0x60 EQUAL", "P2SH,STRICTENC", "0x51 through 0x60 push 1 through 16 onto stack"],
+["0","NOP", "P2SH,STRICTENC"],
+["1", "IF VER ELSE 1 ENDIF", "P2SH,STRICTENC", "VER non-functional"],
+["0", "IF VERIF ELSE 1 ENDIF", "P2SH,STRICTENC", "VERIF illegal everywhere"],
+["0", "IF ELSE 1 ELSE VERIF ENDIF", "P2SH,STRICTENC", "VERIF illegal everywhere"],
+["0", "IF VERNOTIF ELSE 1 ENDIF", "P2SH,STRICTENC", "VERNOTIF illegal everywhere"],
+["0", "IF ELSE 1 ELSE VERNOTIF ENDIF", "P2SH,STRICTENC", "VERNOTIF illegal everywhere"],
+
+["1 IF", "1 ENDIF", "P2SH,STRICTENC", "IF/ENDIF can't span scriptSig/scriptPubKey"],
+["1 IF 0 ENDIF", "1 ENDIF", "P2SH,STRICTENC"],
+["1 ELSE 0 ENDIF", "1", "P2SH,STRICTENC"],
+["0 NOTIF", "123", "P2SH,STRICTENC"],
+
+["0", "DUP IF ENDIF", "P2SH,STRICTENC"],
+["0", "IF 1 ENDIF", "P2SH,STRICTENC"],
+["0", "DUP IF ELSE ENDIF", "P2SH,STRICTENC"],
+["0", "IF 1 ELSE ENDIF", "P2SH,STRICTENC"],
+["0", "NOTIF ELSE 1 ENDIF", "P2SH,STRICTENC"],
+
+["0 1", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"],
+["0 0", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"],
+["1 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"],
+["0 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"],
+
+["0 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"],
+["0 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC"],
+["1 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"],
+["0 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC"],
+
+["1", "IF RETURN ELSE ELSE 1 ENDIF", "P2SH,STRICTENC", "Multiple ELSEs"],
+["1", "IF 1 ELSE ELSE RETURN ENDIF", "P2SH,STRICTENC"],
+
+["1", "ENDIF", "P2SH,STRICTENC", "Malformed IF/ELSE/ENDIF sequence"],
+["1", "ELSE ENDIF", "P2SH,STRICTENC"],
+["1", "ENDIF ELSE", "P2SH,STRICTENC"],
+["1", "ENDIF ELSE IF", "P2SH,STRICTENC"],
+["1", "IF ELSE ENDIF ELSE", "P2SH,STRICTENC"],
+["1", "IF ELSE ENDIF ELSE ENDIF", "P2SH,STRICTENC"],
+["1", "IF ENDIF ENDIF", "P2SH,STRICTENC"],
+["1", "IF ELSE ELSE ENDIF ENDIF", "P2SH,STRICTENC"],
+
+["1", "RETURN", "P2SH,STRICTENC"],
+["1", "DUP IF RETURN ENDIF", "P2SH,STRICTENC"],
+
+["1", "RETURN 'data'", "P2SH,STRICTENC", "canonical prunable txout format"],
+["0 IF", "RETURN ENDIF 1", "P2SH,STRICTENC", "still prunable because IF/ENDIF can't span scriptSig/scriptPubKey"],
+
+["0", "VERIFY 1", "P2SH,STRICTENC"],
+["1", "VERIFY", "P2SH,STRICTENC"],
+["1", "VERIFY 0", "P2SH,STRICTENC"],
+
+["1 TOALTSTACK", "FROMALTSTACK 1", "P2SH,STRICTENC", "alt stack not shared between sig/pubkey"],
+
+["IFDUP", "DEPTH 0 EQUAL", "P2SH,STRICTENC"],
+["DROP", "DEPTH 0 EQUAL", "P2SH,STRICTENC"],
+["DUP", "DEPTH 0 EQUAL", "P2SH,STRICTENC"],
+["1", "DUP 1 ADD 2 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC"],
+["NOP", "NIP", "P2SH,STRICTENC"],
+["NOP", "1 NIP", "P2SH,STRICTENC"],
+["NOP", "1 0 NIP", "P2SH,STRICTENC"],
+["NOP", "OVER 1", "P2SH,STRICTENC"],
+["1", "OVER", "P2SH,STRICTENC"],
+["0 1", "OVER DEPTH 3 EQUALVERIFY", "P2SH,STRICTENC"],
+["19 20 21", "PICK 19 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"],
+["NOP", "0 PICK", "P2SH,STRICTENC"],
+["1", "-1 PICK", "P2SH,STRICTENC"],
+["19 20 21", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC"],
+["19 20 21", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC"],
+["19 20 21", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC"],
+["NOP", "0 ROLL", "P2SH,STRICTENC"],
+["1", "-1 ROLL", "P2SH,STRICTENC"],
+["19 20 21", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"],
+["19 20 21", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"],
+["19 20 21", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC"],
+["NOP", "ROT 1", "P2SH,STRICTENC"],
+["NOP", "1 ROT 1", "P2SH,STRICTENC"],
+["NOP", "1 2 ROT 1", "P2SH,STRICTENC"],
+["NOP", "0 1 2 ROT", "P2SH,STRICTENC"],
+["NOP", "SWAP 1", "P2SH,STRICTENC"],
+["1", "SWAP 1", "P2SH,STRICTENC"],
+["0 1", "SWAP 1 EQUALVERIFY", "P2SH,STRICTENC"],
+["NOP", "TUCK 1", "P2SH,STRICTENC"],
+["1", "TUCK 1", "P2SH,STRICTENC"],
+["1 0", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP", "P2SH,STRICTENC"],
+["NOP", "2DUP 1", "P2SH,STRICTENC"],
+["1", "2DUP 1", "P2SH,STRICTENC"],
+["NOP", "3DUP 1", "P2SH,STRICTENC"],
+["1", "3DUP 1", "P2SH,STRICTENC"],
+["1 2", "3DUP 1", "P2SH,STRICTENC"],
+["NOP", "2OVER 1", "P2SH,STRICTENC"],
+["1", "2 3 2OVER 1", "P2SH,STRICTENC"],
+["NOP", "2SWAP 1", "P2SH,STRICTENC"],
+["1", "2 3 2SWAP 1", "P2SH,STRICTENC"],
+
+["'a' 'b'", "CAT", "P2SH,STRICTENC", "CAT disabled"],
+["'a' 'b' 0", "IF CAT ELSE 1 ENDIF", "P2SH,STRICTENC", "CAT disabled"],
+["'abc' 1 1", "SUBSTR", "P2SH,STRICTENC", "SUBSTR disabled"],
+["'abc' 1 1 0", "IF SUBSTR ELSE 1 ENDIF", "P2SH,STRICTENC", "SUBSTR disabled"],
+["'abc' 2 0", "IF LEFT ELSE 1 ENDIF", "P2SH,STRICTENC", "LEFT disabled"],
+["'abc' 2 0", "IF RIGHT ELSE 1 ENDIF", "P2SH,STRICTENC", "RIGHT disabled"],
+
+["NOP", "SIZE 1", "P2SH,STRICTENC"],
+
+["'abc'", "IF INVERT ELSE 1 ENDIF", "P2SH,STRICTENC", "INVERT disabled"],
+["1 2 0 IF AND ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "AND disabled"],
+["1 2 0 IF OR ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "OR disabled"],
+["1 2 0 IF XOR ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "XOR disabled"],
+["2 0 IF 2MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "2MUL disabled"],
+["2 0 IF 2DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "2DIV disabled"],
+["2 2 0 IF MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "MUL disabled"],
+["2 2 0 IF DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DIV disabled"],
+["2 2 0 IF MOD ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "MOD disabled"],
+["2 2 0 IF LSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "LSHIFT disabled"],
+["2 2 0 IF RSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "RSHIFT disabled"],
+
+["0 1","EQUAL", "P2SH,STRICTENC"],
+["1 1 ADD", "0 EQUAL", "P2SH,STRICTENC"],
+["11 1 ADD 12 SUB", "11 EQUAL", "P2SH,STRICTENC"],
+
+["2147483648 0 ADD", "NOP", "P2SH,STRICTENC", "arithmetic operands must be in range [-2^31...2^31] "],
+["-2147483648 0 ADD", "NOP", "P2SH,STRICTENC", "arithmetic operands must be in range [-2^31...2^31] "],
+["2147483647 DUP ADD", "4294967294 NUMEQUAL", "P2SH,STRICTENC", "NUMEQUAL must be in numeric range"],
+["'abcdef' NOT", "0 EQUAL", "P2SH,STRICTENC", "NOT is an arithmetic operand"],
+
+["2 DUP MUL", "4 EQUAL", "P2SH,STRICTENC", "disabled"],
+["2 DUP DIV", "1 EQUAL", "P2SH,STRICTENC", "disabled"],
+["2 2MUL", "4 EQUAL", "P2SH,STRICTENC", "disabled"],
+["2 2DIV", "1 EQUAL", "P2SH,STRICTENC", "disabled"],
+["7 3 MOD", "1 EQUAL", "P2SH,STRICTENC", "disabled"],
+["2 2 LSHIFT", "8 EQUAL", "P2SH,STRICTENC", "disabled"],
+["2 1 RSHIFT", "1 EQUAL", "P2SH,STRICTENC", "disabled"],
+
+["1","NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC"],
+["'NOP_1_to_10' NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC"],
+
+["0x50","1", "P2SH,STRICTENC", "opcode 0x50 is reserved"],
+["1", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "opcodes above NOP10 invalid if executed"],
+["1", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xc0 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xc4 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xc5 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xc6 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xc7 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xc8 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xc9 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xca ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xcb ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xcc ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xcd ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xce ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xcf ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xd0 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xd1 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xd2 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xd3 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xd4 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xd5 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xd6 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xd7 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xd8 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xd9 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xda ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xdb ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xdc ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xdd ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xde ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xdf ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xe0 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xe1 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xe2 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xe3 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xe4 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xe5 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xe6 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xe7 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xe8 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xe9 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xea ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xeb ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xec ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xed ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xee ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xef ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xf0 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xf1 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xf2 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xf3 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xf4 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xf5 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xf6 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xf7 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xf8 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xf9 ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xfa ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xfb ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xfc ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xfd ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xfe ELSE 1 ENDIF", "P2SH,STRICTENC"],
+["1", "IF 0xff ELSE 1 ENDIF", "P2SH,STRICTENC"],
+
+["1 IF 1 ELSE", "0xff ENDIF", "P2SH,STRICTENC", "invalid because scriptSig and scriptPubKey are processed separately"],
+
+["NOP", "RIPEMD160", "P2SH,STRICTENC"],
+["NOP", "SHA1", "P2SH,STRICTENC"],
+["NOP", "SHA256", "P2SH,STRICTENC"],
+["NOP", "HASH160", "P2SH,STRICTENC"],
+["NOP", "HASH256", "P2SH,STRICTENC"],
["NOP",
"'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'",
+"P2SH,STRICTENC",
">520 byte push"],
["0",
"IF 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' ENDIF 1",
+"P2SH,STRICTENC",
">520 byte push in non-executed IF branch"],
["1",
"0x61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161",
+"P2SH,STRICTENC",
">201 opcodes executed. 0x61 is NOP"],
["0",
"IF 0x6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161 ENDIF 1",
+"P2SH,STRICTENC",
">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",
">1,000 stack size (0x6f is 3DUP)"],
["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
"1 TOALTSTACK 2 TOALTSTACK 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"P2SH,STRICTENC",
">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",
"10,001-byte scriptPubKey"],
-["NOP1","NOP10"],
-
-["1","VER", "OP_VER is reserved"],
-["1","VERIF", "OP_VERIF is reserved"],
-["1","VERNOTIF", "OP_VERNOTIF is reserved"],
-["1","RESERVED", "OP_RESERVED is reserved"],
-["1","RESERVED1", "OP_RESERVED1 is reserved"],
-["1","RESERVED2", "OP_RESERVED2 is reserved"],
-["1","0xba", "0xba == OP_NOP10 + 1"],
-
-["2147483648", "1ADD 1", "We cannot do math on 5-byte integers"],
-["2147483648", "NEGATE 1", "We cannot do math on 5-byte integers"],
-["-2147483648", "1ADD 1", "Because we use a sign bit, -2147483648 is also 5 bytes"],
-["2147483647", "1ADD 1SUB 1", "We cannot do math on 5-byte integers, even if the result is 4-bytes"],
-["2147483648", "1SUB 1", "We cannot do math on 5-byte integers, even if the result is 4-bytes"],
-
-["2147483648 1", "BOOLOR 1", "We cannot do BOOLOR on 5-byte integers (but we can still do IF etc)"],
-["2147483648 1", "BOOLAND 1", "We cannot do BOOLAND on 5-byte integers"],
-
-["1", "1 ENDIF", "ENDIF without IF"],
-["1", "IF 1", "IF without ENDIF"],
-["1 IF 1", "ENDIF", "IFs don't carry over"],
-
-["NOP", "IF 1 ENDIF", "The following tests check the if(stack.size() < N) tests in each opcode"],
-["NOP", "NOTIF 1 ENDIF", "They are here to catch copy-and-paste errors"],
-["NOP", "VERIFY 1", "Most of them are duplicated elsewhere,"],
-
-["NOP", "TOALTSTACK 1", "but, hey, more is always better, right?"],
-["1", "FROMALTSTACK"],
-["1", "2DROP 1"],
-["1", "2DUP"],
-["1 1", "3DUP"],
-["1 1 1", "2OVER"],
-["1 1 1 1 1", "2ROT"],
-["1 1 1", "2SWAP"],
-["NOP", "IFDUP 1"],
-["NOP", "DROP 1"],
-["NOP", "DUP 1"],
-["1", "NIP"],
-["1", "OVER"],
-["1 1 1 3", "PICK"],
-["0", "PICK 1"],
-["1 1 1 3", "ROLL"],
-["0", "ROLL 1"],
-["1 1", "ROT"],
-["1", "SWAP"],
-["1", "TUCK"],
-
-["NOP", "SIZE 1"],
-
-["1", "EQUAL 1"],
-["1", "EQUALVERIFY 1"],
-
-["NOP", "1ADD 1"],
-["NOP", "1SUB 1"],
-["NOP", "NEGATE 1"],
-["NOP", "ABS 1"],
-["NOP", "NOT 1"],
-["NOP", "0NOTEQUAL 1"],
-
-["1", "ADD"],
-["1", "SUB"],
-["1", "BOOLAND"],
-["1", "BOOLOR"],
-["1", "NUMEQUAL"],
-["1", "NUMEQUALVERIFY 1"],
-["1", "NUMNOTEQUAL"],
-["1", "LESSTHAN"],
-["1", "GREATERTHAN"],
-["1", "LESSTHANOREQUAL"],
-["1", "GREATERTHANOREQUAL"],
-["1", "MIN"],
-["1", "MAX"],
-["1 1", "WITHIN"],
-
-["NOP", "RIPEMD160 1"],
-["NOP", "SHA1 1"],
-["NOP", "SHA256 1"],
-["NOP", "HASH160 1"],
-["NOP", "HASH256 1"],
+["NOP1","NOP10", "P2SH,STRICTENC"],
+
+["1","VER", "P2SH,STRICTENC", "OP_VER is reserved"],
+["1","VERIF", "P2SH,STRICTENC", "OP_VERIF is reserved"],
+["1","VERNOTIF", "P2SH,STRICTENC", "OP_VERNOTIF is reserved"],
+["1","RESERVED", "P2SH,STRICTENC", "OP_RESERVED is reserved"],
+["1","RESERVED1", "P2SH,STRICTENC", "OP_RESERVED1 is reserved"],
+["1","RESERVED2", "P2SH,STRICTENC", "OP_RESERVED2 is reserved"],
+["1","0xba", "P2SH,STRICTENC", "0xba == OP_NOP10 + 1"],
+
+["2147483648", "1ADD 1", "P2SH,STRICTENC", "We cannot do math on 5-byte integers"],
+["2147483648", "NEGATE 1", "P2SH,STRICTENC", "We cannot do math on 5-byte integers"],
+["-2147483648", "1ADD 1", "P2SH,STRICTENC", "Because we use a sign bit, -2147483648 is also 5 bytes"],
+["2147483647", "1ADD 1SUB 1", "P2SH,STRICTENC", "We cannot do math on 5-byte integers, even if the result is 4-bytes"],
+["2147483648", "1SUB 1", "P2SH,STRICTENC", "We cannot do math on 5-byte integers, even if the result is 4-bytes"],
+
+["2147483648 1", "BOOLOR 1", "P2SH,STRICTENC", "We cannot do BOOLOR on 5-byte integers (but we can still do IF etc)"],
+["2147483648 1", "BOOLAND 1", "P2SH,STRICTENC", "We cannot do BOOLAND on 5-byte integers"],
+
+["1", "1 ENDIF", "P2SH,STRICTENC", "ENDIF without IF"],
+["1", "IF 1", "P2SH,STRICTENC", "IF without ENDIF"],
+["1 IF 1", "ENDIF", "P2SH,STRICTENC", "IFs don't carry over"],
+
+["NOP", "IF 1 ENDIF", "P2SH,STRICTENC", "The following tests check the if(stack.size() < N) tests in each opcode"],
+["NOP", "NOTIF 1 ENDIF", "P2SH,STRICTENC", "They are here to catch copy-and-paste errors"],
+["NOP", "VERIFY 1", "P2SH,STRICTENC", "Most of them are duplicated elsewhere,"],
+
+["NOP", "TOALTSTACK 1", "P2SH,STRICTENC", "but, hey, more is always better, right?"],
+["1", "FROMALTSTACK", "P2SH,STRICTENC"],
+["1", "2DROP 1", "P2SH,STRICTENC"],
+["1", "2DUP", "P2SH,STRICTENC"],
+["1 1", "3DUP", "P2SH,STRICTENC"],
+["1 1 1", "2OVER", "P2SH,STRICTENC"],
+["1 1 1 1 1", "2ROT", "P2SH,STRICTENC"],
+["1 1 1", "2SWAP", "P2SH,STRICTENC"],
+["NOP", "IFDUP 1", "P2SH,STRICTENC"],
+["NOP", "DROP 1", "P2SH,STRICTENC"],
+["NOP", "DUP 1", "P2SH,STRICTENC"],
+["1", "NIP", "P2SH,STRICTENC"],
+["1", "OVER", "P2SH,STRICTENC"],
+["1 1 1 3", "PICK", "P2SH,STRICTENC"],
+["0", "PICK 1", "P2SH,STRICTENC"],
+["1 1 1 3", "ROLL", "P2SH,STRICTENC"],
+["0", "ROLL 1", "P2SH,STRICTENC"],
+["1 1", "ROT", "P2SH,STRICTENC"],
+["1", "SWAP", "P2SH,STRICTENC"],
+["1", "TUCK", "P2SH,STRICTENC"],
+
+["NOP", "SIZE 1", "P2SH,STRICTENC"],
+
+["1", "EQUAL 1", "P2SH,STRICTENC"],
+["1", "EQUALVERIFY 1", "P2SH,STRICTENC"],
+
+["NOP", "1ADD 1", "P2SH,STRICTENC"],
+["NOP", "1SUB 1", "P2SH,STRICTENC"],
+["NOP", "NEGATE 1", "P2SH,STRICTENC"],
+["NOP", "ABS 1", "P2SH,STRICTENC"],
+["NOP", "NOT 1", "P2SH,STRICTENC"],
+["NOP", "0NOTEQUAL 1", "P2SH,STRICTENC"],
+
+["1", "ADD", "P2SH,STRICTENC"],
+["1", "SUB", "P2SH,STRICTENC"],
+["1", "BOOLAND", "P2SH,STRICTENC"],
+["1", "BOOLOR", "P2SH,STRICTENC"],
+["1", "NUMEQUAL", "P2SH,STRICTENC"],
+["1", "NUMEQUALVERIFY 1", "P2SH,STRICTENC"],
+["1", "NUMNOTEQUAL", "P2SH,STRICTENC"],
+["1", "LESSTHAN", "P2SH,STRICTENC"],
+["1", "GREATERTHAN", "P2SH,STRICTENC"],
+["1", "LESSTHANOREQUAL", "P2SH,STRICTENC"],
+["1", "GREATERTHANOREQUAL", "P2SH,STRICTENC"],
+["1", "MIN", "P2SH,STRICTENC"],
+["1", "MAX", "P2SH,STRICTENC"],
+["1 1", "WITHIN", "P2SH,STRICTENC"],
+
+["NOP", "RIPEMD160 1", "P2SH,STRICTENC"],
+["NOP", "SHA1 1", "P2SH,STRICTENC"],
+["NOP", "SHA256 1", "P2SH,STRICTENC"],
+["NOP", "HASH160 1", "P2SH,STRICTENC"],
+["NOP", "HASH256 1", "P2SH,STRICTENC"],
["",
"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"],
["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"],
+"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"],
["",
"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"],
["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"],
+"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"],
-["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", "nPubKeys > 20"],
-["0 'sig' 1 0", "CHECKMULTISIG 1", "nSigs > nPubKeys"],
+["0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21", "21 CHECKMULTISIG 1", "P2SH,STRICTENC", "nPubKeys > 20"],
+["0 'sig' 1 0", "CHECKMULTISIG 1", "P2SH,STRICTENC", "nSigs > nPubKeys"],
-["NOP 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "Tests for Script.IsPushOnly()"],
-["NOP1 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL"],
+["NOP 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "Tests for Script.IsPushOnly()"],
+["NOP1 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC"],
-["0 0x01 0x50", "HASH160 0x14 0xece424a6bb6ddf4db592c0faed60685047a361b1 EQUAL", "OP_RESERVED in P2SH should fail"],
-["0 0x01 VER", "HASH160 0x14 0x0f4d7845db968f2a81b530b6f3c1d6246d4c7e01 EQUAL", "OP_VER in P2SH should fail"],
+["0 0x01 0x50", "HASH160 0x14 0xece424a6bb6ddf4db592c0faed60685047a361b1 EQUAL", "P2SH,STRICTENC", "OP_RESERVED in P2SH should fail"],
+["0 0x01 VER", "HASH160 0x14 0x0f4d7845db968f2a81b530b6f3c1d6246d4c7e01 EQUAL", "P2SH,STRICTENC", "OP_VER in P2SH should fail"],
-["0x00", "'00' EQUAL", "Basic OP_0 execution"]
+["0x00", "'00' EQUAL", "P2SH,STRICTENC", "Basic OP_0 execution"]
]
diff --git a/src/test/data/script_valid.json b/src/test/data/script_valid.json
index 082c65efed..c1db4c6061 100644
--- a/src/test/data/script_valid.json
+++ b/src/test/data/script_valid.json
@@ -1,510 +1,522 @@
[
-["", "DEPTH 0 EQUAL", "Test the test: we should have an empty stack after scriptSig evaluation"],
-[" ", "DEPTH 0 EQUAL", "and multiple spaces should not change that."],
-[" ", "DEPTH 0 EQUAL"],
-[" ", "DEPTH 0 EQUAL"],
-["1 2", "2 EQUALVERIFY 1 EQUAL", "Similarly whitespace around and between symbols"],
-["1 2", "2 EQUALVERIFY 1 EQUAL"],
-[" 1 2", "2 EQUALVERIFY 1 EQUAL"],
-["1 2 ", "2 EQUALVERIFY 1 EQUAL"],
-[" 1 2 ", "2 EQUALVERIFY 1 EQUAL"],
-
-["1", ""],
-["0x02 0x01 0x00", "", "all bytes are significant, not only the last one"],
-["0x09 0x00000000 0x00000000 0x10", "", "equals zero when cast to Int64"],
-
-["0x01 0x0b", "11 EQUAL", "push 1 byte"],
-["0x02 0x417a", "'Az' EQUAL"],
+["", "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", "push 75 bytes"],
-
-["0x4c 0x01 0x07","7 EQUAL", "0x4c is OP_PUSHDATA1"],
-["0x4d 0x0100 0x08","8 EQUAL", "0x4d is OP_PUSHDATA2"],
-["0x4e 0x01000000 0x09","9 EQUAL", "0x4e is OP_PUSHDATA4"],
-
-["0x4c 0x00","0 EQUAL"],
-["0x4d 0x0000","0 EQUAL"],
-["0x4e 0x00000000","0 EQUAL"],
-["0x4f 1000 ADD","999 EQUAL"],
-["0", "IF 0x50 ENDIF 1", "0x50 is reserved (ok if not executed)"],
-["0x51", "0x5f ADD 0x60 EQUAL", "0x51 through 0x60 push 1 through 16 onto stack"],
-["1","NOP"],
-["0", "IF VER ELSE 1 ENDIF", "VER non-functional (ok if not executed)"],
-["0", "IF RESERVED RESERVED1 RESERVED2 ELSE 1 ENDIF", "RESERVED ok in un-executed IF"],
-
-["1", "DUP IF ENDIF"],
-["1", "IF 1 ENDIF"],
-["1", "DUP IF ELSE ENDIF"],
-["1", "IF 1 ELSE ENDIF"],
-["0", "IF ELSE 1 ENDIF"],
-
-["1 1", "IF IF 1 ELSE 0 ENDIF ENDIF"],
-["1 0", "IF IF 1 ELSE 0 ENDIF ENDIF"],
-["1 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"],
-["0 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"],
-
-["1 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF"],
-["1 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF"],
-["1 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"],
-["0 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"],
-
-["0", "IF 0 ELSE 1 ELSE 0 ENDIF", "Multiple ELSE's are valid and executed inverts on each ELSE encountered"],
-["1", "IF 1 ELSE 0 ELSE ENDIF"],
-["1", "IF ELSE 0 ELSE 1 ENDIF"],
-["1", "IF 1 ELSE 0 ELSE 1 ENDIF ADD 2 EQUAL"],
-["'' 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"],
-
-["1", "NOTIF 0 ELSE 1 ELSE 0 ENDIF", "Multiple ELSE's are valid and execution inverts on each ELSE encountered"],
-["0", "NOTIF 1 ELSE 0 ELSE ENDIF"],
-["0", "NOTIF ELSE 0 ELSE 1 ENDIF"],
-["0", "NOTIF 1 ELSE 0 ELSE 1 ENDIF ADD 2 EQUAL"],
-["'' 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"],
-
-["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", "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"],
-
-["0", "IF RETURN ENDIF 1", "RETURN only works if executed"],
-
-["1 1", "VERIFY"],
-["1 0x05 0x01 0x00 0x00 0x00 0x00", "VERIFY", "values >4 bytes can be cast to boolean"],
-
-["10 0 11 TOALTSTACK DROP FROMALTSTACK", "ADD 21 EQUAL"],
-["'gavin_was_here' TOALTSTACK 11 FROMALTSTACK", "'gavin_was_here' EQUALVERIFY 11 EQUAL"],
-
-["0 IFDUP", "DEPTH 1 EQUALVERIFY 0 EQUAL"],
-["1 IFDUP", "DEPTH 2 EQUALVERIFY 1 EQUALVERIFY 1 EQUAL"],
-["0 DROP", "DEPTH 0 EQUAL"],
-["0", "DUP 1 ADD 1 EQUALVERIFY 0 EQUAL"],
-["0 1", "NIP"],
-["1 0", "OVER DEPTH 3 EQUALVERIFY"],
-["22 21 20", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL"],
-["22 21 20", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL"],
-["22 21 20", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL"],
-["22 21 20", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL"],
-["22 21 20", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL"],
-["22 21 20", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL"],
-["22 21 20", "ROT 22 EQUAL"],
-["22 21 20", "ROT DROP 20 EQUAL"],
-["22 21 20", "ROT DROP DROP 21 EQUAL"],
-["22 21 20", "ROT ROT 21 EQUAL"],
-["22 21 20", "ROT ROT ROT 20 EQUAL"],
-["25 24 23 22 21 20", "2ROT 24 EQUAL"],
-["25 24 23 22 21 20", "2ROT DROP 25 EQUAL"],
-["25 24 23 22 21 20", "2ROT 2DROP 20 EQUAL"],
-["25 24 23 22 21 20", "2ROT 2DROP DROP 21 EQUAL"],
-["25 24 23 22 21 20", "2ROT 2DROP 2DROP 22 EQUAL"],
-["25 24 23 22 21 20", "2ROT 2DROP 2DROP DROP 23 EQUAL"],
-["25 24 23 22 21 20", "2ROT 2ROT 22 EQUAL"],
-["25 24 23 22 21 20", "2ROT 2ROT 2ROT 20 EQUAL"],
-["1 0", "SWAP 1 EQUALVERIFY 0 EQUAL"],
-["0 1", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP"],
-["13 14", "2DUP ROT EQUALVERIFY EQUAL"],
-["-1 0 1 2", "3DUP DEPTH 7 EQUALVERIFY ADD ADD 3 EQUALVERIFY 2DROP 0 EQUALVERIFY"],
-["1 2 3 5", "2OVER ADD ADD 8 EQUALVERIFY ADD ADD 6 EQUAL"],
-["1 3 5 7", "2SWAP ADD 4 EQUALVERIFY ADD 12 EQUAL"],
-["0", "SIZE 0 EQUAL"],
-["1", "SIZE 1 EQUAL"],
-["127", "SIZE 1 EQUAL"],
-["128", "SIZE 2 EQUAL"],
-["32767", "SIZE 2 EQUAL"],
-["32768", "SIZE 3 EQUAL"],
-["8388607", "SIZE 3 EQUAL"],
-["8388608", "SIZE 4 EQUAL"],
-["2147483647", "SIZE 4 EQUAL"],
-["2147483648", "SIZE 5 EQUAL"],
-["549755813887", "SIZE 5 EQUAL"],
-["549755813888", "SIZE 6 EQUAL"],
-["9223372036854775807", "SIZE 8 EQUAL"],
-["-1", "SIZE 1 EQUAL"],
-["-127", "SIZE 1 EQUAL"],
-["-128", "SIZE 2 EQUAL"],
-["-32767", "SIZE 2 EQUAL"],
-["-32768", "SIZE 3 EQUAL"],
-["-8388607", "SIZE 3 EQUAL"],
-["-8388608", "SIZE 4 EQUAL"],
-["-2147483647", "SIZE 4 EQUAL"],
-["-2147483648", "SIZE 5 EQUAL"],
-["-549755813887", "SIZE 5 EQUAL"],
-["-549755813888", "SIZE 6 EQUAL"],
-["-9223372036854775807", "SIZE 8 EQUAL"],
-["'abcdefghijklmnopqrstuvwxyz'", "SIZE 26 EQUAL"],
-
-["42", "SIZE 1 EQUALVERIFY 42 EQUAL", "SIZE does not consume argument"],
-
-["2 -2 ADD", "0 EQUAL"],
-["2147483647 -2147483647 ADD", "0 EQUAL"],
-["-1 -1 ADD", "-2 EQUAL"],
-
-["0 0","EQUAL"],
-["1 1 ADD", "2 EQUAL"],
-["1 1ADD", "2 EQUAL"],
-["111 1SUB", "110 EQUAL"],
-["111 1 ADD 12 SUB", "100 EQUAL"],
-["0 ABS", "0 EQUAL"],
-["16 ABS", "16 EQUAL"],
-["-16 ABS", "-16 NEGATE EQUAL"],
-["0 NOT", "NOP"],
-["1 NOT", "0 EQUAL"],
-["11 NOT", "0 EQUAL"],
-["0 0NOTEQUAL", "0 EQUAL"],
-["1 0NOTEQUAL", "1 EQUAL"],
-["111 0NOTEQUAL", "1 EQUAL"],
-["-111 0NOTEQUAL", "1 EQUAL"],
-["1 1 BOOLAND", "NOP"],
-["1 0 BOOLAND", "NOT"],
-["0 1 BOOLAND", "NOT"],
-["0 0 BOOLAND", "NOT"],
-["16 17 BOOLAND", "NOP"],
-["1 1 BOOLOR", "NOP"],
-["1 0 BOOLOR", "NOP"],
-["0 1 BOOLOR", "NOP"],
-["0 0 BOOLOR", "NOT"],
-["16 17 BOOLOR", "NOP"],
-["11 10 1 ADD", "NUMEQUAL"],
-["11 10 1 ADD", "NUMEQUALVERIFY 1"],
-["11 10 1 ADD", "NUMNOTEQUAL NOT"],
-["111 10 1 ADD", "NUMNOTEQUAL"],
-["11 10", "LESSTHAN NOT"],
-["4 4", "LESSTHAN NOT"],
-["10 11", "LESSTHAN"],
-["-11 11", "LESSTHAN"],
-["-11 -10", "LESSTHAN"],
-["11 10", "GREATERTHAN"],
-["4 4", "GREATERTHAN NOT"],
-["10 11", "GREATERTHAN NOT"],
-["-11 11", "GREATERTHAN NOT"],
-["-11 -10", "GREATERTHAN NOT"],
-["11 10", "LESSTHANOREQUAL NOT"],
-["4 4", "LESSTHANOREQUAL"],
-["10 11", "LESSTHANOREQUAL"],
-["-11 11", "LESSTHANOREQUAL"],
-["-11 -10", "LESSTHANOREQUAL"],
-["11 10", "GREATERTHANOREQUAL"],
-["4 4", "GREATERTHANOREQUAL"],
-["10 11", "GREATERTHANOREQUAL NOT"],
-["-11 11", "GREATERTHANOREQUAL NOT"],
-["-11 -10", "GREATERTHANOREQUAL NOT"],
-["1 0 MIN", "0 NUMEQUAL"],
-["0 1 MIN", "0 NUMEQUAL"],
-["-1 0 MIN", "-1 NUMEQUAL"],
-["0 -2147483647 MIN", "-2147483647 NUMEQUAL"],
-["2147483647 0 MAX", "2147483647 NUMEQUAL"],
-["0 100 MAX", "100 NUMEQUAL"],
-["-100 0 MAX", "0 NUMEQUAL"],
-["0 -2147483647 MAX", "0 NUMEQUAL"],
-["0 0 1", "WITHIN"],
-["1 0 1", "WITHIN NOT"],
-["0 -2147483647 2147483647", "WITHIN"],
-["-1 -100 100", "WITHIN"],
-["11 -100 100", "WITHIN"],
-["-2147483647 -100 100", "WITHIN NOT"],
-["2147483647 -100 100", "WITHIN NOT"],
-
-["2147483647 2147483647 SUB", "0 EQUAL"],
-["2147483647 DUP ADD", "4294967294 EQUAL", ">32 bit EQUAL is valid"],
-["2147483647 NEGATE DUP ADD", "-4294967294 EQUAL"],
-
-["''", "RIPEMD160 0x14 0x9c1185a5c5e9fc54612808977ee8f548b2258d31 EQUAL"],
-["'a'", "RIPEMD160 0x14 0x0bdc9d2d256b3ee9daae347be6f4dc835a467ffe EQUAL"],
-["'abcdefghijklmnopqrstuvwxyz'", "RIPEMD160 0x14 0xf71c27109c692c1b56bbdceb5b9d2865b3708dbc EQUAL"],
-["''", "SHA1 0x14 0xda39a3ee5e6b4b0d3255bfef95601890afd80709 EQUAL"],
-["'a'", "SHA1 0x14 0x86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 EQUAL"],
-["'abcdefghijklmnopqrstuvwxyz'", "SHA1 0x14 0x32d10c7b8cf96570ca04ce37f2a19d84240d3a89 EQUAL"],
-["''", "SHA256 0x20 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 EQUAL"],
-["'a'", "SHA256 0x20 0xca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb EQUAL"],
-["'abcdefghijklmnopqrstuvwxyz'", "SHA256 0x20 0x71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73 EQUAL"],
-["''", "DUP HASH160 SWAP SHA256 RIPEMD160 EQUAL"],
-["''", "DUP HASH256 SWAP SHA256 SHA256 EQUAL"],
-["''", "NOP HASH160 0x14 0xb472a266d0bd89c13706a4132ccfb16f7c3b9fcb EQUAL"],
-["'a'", "HASH160 NOP 0x14 0x994355199e516ff76c4fa4aab39337b9d84cf12b EQUAL"],
-["'abcdefghijklmnopqrstuvwxyz'", "HASH160 0x4c 0x14 0xc286a1af0947f58d1ad787385b1c2c4a976f9e71 EQUAL"],
-["''", "HASH256 0x20 0x5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456 EQUAL"],
-["'a'", "HASH256 0x20 0xbf5d3affb73efd2ec6c36ad3112dd933efed63c4e1cbffcfa88e2759c144f2d8 EQUAL"],
-["'abcdefghijklmnopqrstuvwxyz'", "HASH256 0x4c 0x20 0xca139bc10c2f660da42666f72e89a225936fc60f193c161124a672050c434671 EQUAL"],
-
-
-["1","NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 1 EQUAL"],
-["'NOP_1_to_10' NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' EQUAL"],
-
-["0", "IF 0xba ELSE 1 ENDIF", "opcodes above NOP10 invalid if executed"],
-["0", "IF 0xbb ELSE 1 ENDIF"],
-["0", "IF 0xbc ELSE 1 ENDIF"],
-["0", "IF 0xbd ELSE 1 ENDIF"],
-["0", "IF 0xbe ELSE 1 ENDIF"],
-["0", "IF 0xbf ELSE 1 ENDIF"],
-["0", "IF 0xc0 ELSE 1 ENDIF"],
-["0", "IF 0xc1 ELSE 1 ENDIF"],
-["0", "IF 0xc2 ELSE 1 ENDIF"],
-["0", "IF 0xc3 ELSE 1 ENDIF"],
-["0", "IF 0xc4 ELSE 1 ENDIF"],
-["0", "IF 0xc5 ELSE 1 ENDIF"],
-["0", "IF 0xc6 ELSE 1 ENDIF"],
-["0", "IF 0xc7 ELSE 1 ENDIF"],
-["0", "IF 0xc8 ELSE 1 ENDIF"],
-["0", "IF 0xc9 ELSE 1 ENDIF"],
-["0", "IF 0xca ELSE 1 ENDIF"],
-["0", "IF 0xcb ELSE 1 ENDIF"],
-["0", "IF 0xcc ELSE 1 ENDIF"],
-["0", "IF 0xcd ELSE 1 ENDIF"],
-["0", "IF 0xce ELSE 1 ENDIF"],
-["0", "IF 0xcf ELSE 1 ENDIF"],
-["0", "IF 0xd0 ELSE 1 ENDIF"],
-["0", "IF 0xd1 ELSE 1 ENDIF"],
-["0", "IF 0xd2 ELSE 1 ENDIF"],
-["0", "IF 0xd3 ELSE 1 ENDIF"],
-["0", "IF 0xd4 ELSE 1 ENDIF"],
-["0", "IF 0xd5 ELSE 1 ENDIF"],
-["0", "IF 0xd6 ELSE 1 ENDIF"],
-["0", "IF 0xd7 ELSE 1 ENDIF"],
-["0", "IF 0xd8 ELSE 1 ENDIF"],
-["0", "IF 0xd9 ELSE 1 ENDIF"],
-["0", "IF 0xda ELSE 1 ENDIF"],
-["0", "IF 0xdb ELSE 1 ENDIF"],
-["0", "IF 0xdc ELSE 1 ENDIF"],
-["0", "IF 0xdd ELSE 1 ENDIF"],
-["0", "IF 0xde ELSE 1 ENDIF"],
-["0", "IF 0xdf ELSE 1 ENDIF"],
-["0", "IF 0xe0 ELSE 1 ENDIF"],
-["0", "IF 0xe1 ELSE 1 ENDIF"],
-["0", "IF 0xe2 ELSE 1 ENDIF"],
-["0", "IF 0xe3 ELSE 1 ENDIF"],
-["0", "IF 0xe4 ELSE 1 ENDIF"],
-["0", "IF 0xe5 ELSE 1 ENDIF"],
-["0", "IF 0xe6 ELSE 1 ENDIF"],
-["0", "IF 0xe7 ELSE 1 ENDIF"],
-["0", "IF 0xe8 ELSE 1 ENDIF"],
-["0", "IF 0xe9 ELSE 1 ENDIF"],
-["0", "IF 0xea ELSE 1 ENDIF"],
-["0", "IF 0xeb ELSE 1 ENDIF"],
-["0", "IF 0xec ELSE 1 ENDIF"],
-["0", "IF 0xed ELSE 1 ENDIF"],
-["0", "IF 0xee ELSE 1 ENDIF"],
-["0", "IF 0xef ELSE 1 ENDIF"],
-["0", "IF 0xf0 ELSE 1 ENDIF"],
-["0", "IF 0xf1 ELSE 1 ENDIF"],
-["0", "IF 0xf2 ELSE 1 ENDIF"],
-["0", "IF 0xf3 ELSE 1 ENDIF"],
-["0", "IF 0xf4 ELSE 1 ENDIF"],
-["0", "IF 0xf5 ELSE 1 ENDIF"],
-["0", "IF 0xf6 ELSE 1 ENDIF"],
-["0", "IF 0xf7 ELSE 1 ENDIF"],
-["0", "IF 0xf8 ELSE 1 ENDIF"],
-["0", "IF 0xf9 ELSE 1 ENDIF"],
-["0", "IF 0xfa ELSE 1 ENDIF"],
-["0", "IF 0xfb ELSE 1 ENDIF"],
-["0", "IF 0xfc ELSE 1 ENDIF"],
-["0", "IF 0xfd ELSE 1 ENDIF"],
-["0", "IF 0xfe ELSE 1 ENDIF"],
-["0", "IF 0xff ELSE 1 ENDIF"],
+ "'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"],
+
+["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"],
+["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 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 1 EQUAL", "P2SH,STRICTENC"],
+["'NOP_1_to_10' NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' EQUAL", "P2SH,STRICTENC"],
+
+["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"],
-
-["1", "0x01 0x01 EQUAL", "The following is useful for checking implementations of BN_bn2mpi"],
-["127", "0x01 0x7F EQUAL"],
-["128", "0x02 0x8000 EQUAL", "Leave room for the sign bit"],
-["32767", "0x02 0xFF7F EQUAL"],
-["32768", "0x03 0x008000 EQUAL"],
-["8388607", "0x03 0xFFFF7F EQUAL"],
-["8388608", "0x04 0x00008000 EQUAL"],
-["2147483647", "0x04 0xFFFFFF7F EQUAL"],
-["2147483648", "0x05 0x0000008000 EQUAL"],
-["549755813887", "0x05 0xFFFFFFFF7F EQUAL"],
-["549755813888", "0x06 0xFFFFFFFF7F EQUAL"],
-["9223372036854775807", "0x08 0xFFFFFFFFFFFFFF7F EQUAL"],
-["-1", "0x01 0x81 EQUAL", "Numbers are little-endian with the MSB being a sign bit"],
-["-127", "0x01 0xFF EQUAL"],
-["-128", "0x02 0x8080 EQUAL"],
-["-32767", "0x02 0xFFFF EQUAL"],
-["-32768", "0x03 0x008080 EQUAL"],
-["-8388607", "0x03 0xFFFFFF EQUAL"],
-["-8388608", "0x04 0x00008080 EQUAL"],
-["-2147483647", "0x04 0xFFFFFFFF EQUAL"],
-["-2147483648", "0x05 0x0000008080 EQUAL"],
-["-4294967295", "0x05 0xFFFFFFFF80 EQUAL"],
-["-549755813887", "0x05 0xFFFFFFFFFF EQUAL"],
-["-549755813888", "0x06 0x000000008080 EQUAL"],
-["-9223372036854775807", "0x08 0xFFFFFFFFFFFFFFFF EQUAL"],
-
-["2147483647", "1ADD 2147483648 EQUAL", "We can do math on 4-byte integers, and compare 5-byte ones"],
-["2147483647", "1ADD 1"],
-["-2147483647", "1ADD 1"],
-
-["1", "0x02 0x0100 EQUAL NOT", "Not the same byte array..."],
-["1", "0x02 0x0100 NUMEQUAL", "... but they are numerically equal"],
-["11", "0x4c 0x03 0x0b0000 NUMEQUAL"],
-["0", "0x01 0x80 EQUAL NOT"],
-["0", "0x01 0x80 NUMEQUAL", "Zero numerically equals negative zero"],
-["0", "0x02 0x0080 NUMEQUAL"],
-["0x03 0x000080", "0x04 0x00000080 NUMEQUAL"],
-["0x03 0x100080", "0x04 0x10000080 NUMEQUAL"],
-["0x03 0x100000", "0x04 0x10000000 NUMEQUAL"],
-
-["NOP", "NOP 1", "The following tests check the if(stack.size() < N) tests in each opcode"],
-["1", "IF 1 ENDIF", "They are here to catch copy-and-paste errors"],
-["0", "NOTIF 1 ENDIF", "Most of them are duplicated elsewhere,"],
-["1", "VERIFY 1", "but, hey, more is always better, right?"],
-
-["0", "TOALTSTACK 1"],
-["1", "TOALTSTACK FROMALTSTACK"],
-["0 0", "2DROP 1"],
-["0 1", "2DUP"],
-["0 0 1", "3DUP"],
-["0 1 0 0", "2OVER"],
-["0 1 0 0 0 0", "2ROT"],
-["0 1 0 0", "2SWAP"],
-["1", "IFDUP"],
-["NOP", "DEPTH 1"],
-["0", "DROP 1"],
-["1", "DUP"],
-["0 1", "NIP"],
-["1 0", "OVER"],
-["1 0 0 0 3", "PICK"],
-["1 0", "PICK"],
-["1 0 0 0 3", "ROLL"],
-["1 0", "ROLL"],
-["1 0 0", "ROT"],
-["1 0", "SWAP"],
-["0 1", "TUCK"],
-
-["1", "SIZE"],
-
-["0 0", "EQUAL"],
-["0 0", "EQUALVERIFY 1"],
-
-["0", "1ADD"],
-["2", "1SUB"],
-["-1", "NEGATE"],
-["-1", "ABS"],
-["0", "NOT"],
-["-1", "0NOTEQUAL"],
-
-["1 0", "ADD"],
-["1 0", "SUB"],
-["-1 -1", "BOOLAND"],
-["-1 0", "BOOLOR"],
-["0 0", "NUMEQUAL"],
-["0 0", "NUMEQUALVERIFY 1"],
-["-1 0", "NUMNOTEQUAL"],
-["-1 0", "LESSTHAN"],
-["1 0", "GREATERTHAN"],
-["0 0", "LESSTHANOREQUAL"],
-["0 0", "GREATERTHANOREQUAL"],
-["-1 0", "MIN"],
-["1 0", "MAX"],
-["-1 -1 0", "WITHIN"],
-
-["0", "RIPEMD160"],
-["0", "SHA1"],
-["0", "SHA256"],
-["0", "HASH160"],
-["0", "HASH256"],
-["NOP", "CODESEPARATOR 1"],
-
-["NOP", "NOP1 1"],
-["NOP", "NOP2 1"],
-["NOP", "NOP3 1"],
-["NOP", "NOP4 1"],
-["NOP", "NOP5 1"],
-["NOP", "NOP6 1"],
-["NOP", "NOP7 1"],
-["NOP", "NOP8 1"],
-["NOP", "NOP9 1"],
-["NOP", "NOP10 1"],
-
-["", "0 0 0 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "CHECKMULTISIG is allowed to have zero keys and/or sigs"],
-["", "0 0 0 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"],
-["", "0 0 0 1 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "Zero sigs means no sigs are checked"],
-["", "0 0 0 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"],
-
-["", "0 0 0 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "CHECKMULTISIG is allowed to have zero keys and/or sigs"],
-["", "0 0 0 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"],
-["", "0 0 0 1 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "Zero sigs means no sigs are checked"],
-["", "0 0 0 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"],
-
-["", "0 0 'a' 'b' 2 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "Test from up to 20 pubkeys, all not checked"],
-["", "0 0 'a' 'b' 'c' 3 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 4 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 5 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 6 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 7 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 8 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 9 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 10 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 11 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 12 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 13 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 14 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 15 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 16 CHECKMULTISIG VERIFY DEPTH 0 EQUAL"],
-["", "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"],
-["", "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"],
-["", "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"],
-["", "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"],
-["", "0 0 'a' 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 2 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 3 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 4 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 5 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 6 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 7 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 8 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 9 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 10 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 11 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 12 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 13 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 14 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 15 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 16 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"],
-["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 17 CHECKMULTISIGVERIFY DEPTH 0 EQUAL"],
-["", "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"],
-["", "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"],
-["", "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"],
+["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", "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", "NOP2 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"],
+"0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 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"],
+"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", "Very basic P2SH"],
-["0x4c 0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL"],
+["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"],
-["0x00", "SIZE 0 EQUAL", "Basic OP_0 execution"]
+["0x00", "SIZE 0 EQUAL", "P2SH,STRICTENC", "Basic OP_0 execution"]
]
diff --git a/src/test/data/txcreate2.hex b/src/test/data/txcreate2.hex
new file mode 100644
index 0000000000..5243c2d02e
--- /dev/null
+++ b/src/test/data/txcreate2.hex
@@ -0,0 +1 @@
+01000000000100000000000000000000000000
diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp
index 864d90128c..203c20731a 100644
--- a/src/test/key_tests.cpp
+++ b/src/test/key_tests.cpp
@@ -5,7 +5,7 @@
#include "key.h"
#include "base58.h"
-#include "script.h"
+#include "script/script.h"
#include "uint256.h"
#include "util.h"
diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp
index 02c6d095f2..91dfa39505 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -5,9 +5,15 @@
#include "key.h"
#include "keystore.h"
#include "main.h"
-#include "script.h"
+#include "script/script.h"
+#include "script/interpreter.h"
+#include "script/sign.h"
#include "uint256.h"
+#ifdef ENABLE_WALLET
+#include "wallet_ismine.h"
+#endif
+
#include <boost/assign/std/vector.hpp>
#include <boost/foreach.hpp>
#include <boost/test/unit_test.hpp>
@@ -192,8 +198,10 @@ 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;
@@ -205,8 +213,10 @@ 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;
@@ -217,9 +227,11 @@ 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;
@@ -234,9 +246,11 @@ 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/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp
index 51ff1ffbc9..f99002017f 100644
--- a/src/test/script_P2SH_tests.cpp
+++ b/src/test/script_P2SH_tests.cpp
@@ -2,12 +2,15 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "script.h"
-
#include "key.h"
#include "keystore.h"
#include "main.h"
-#include "script.h"
+#include "script/script.h"
+#include "script/sign.h"
+
+#ifdef ENABLE_WALLET
+#include "wallet_ismine.h"
+#endif
#include <vector>
@@ -95,7 +98,9 @@ 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++)
{
@@ -189,7 +194,9 @@ 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 77c44501ab..bc610778c4 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -2,15 +2,14 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "script.h"
-
#include "data/script_invalid.json.h"
#include "data/script_valid.json.h"
#include "key.h"
#include "keystore.h"
#include "main.h"
-#include "script.h"
+#include "script/script.h"
+#include "script/sign.h"
#include "core_io.h"
#include <fstream>
@@ -36,6 +35,8 @@ using namespace boost::algorithm;
static const unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
+unsigned int ParseScriptFlags(string strFlags);
+
Array
read_json(const std::string& jsondata)
{
@@ -55,7 +56,7 @@ BOOST_AUTO_TEST_CASE(script_valid)
{
// Read tests from test/data/script_valid.json
// Format is an array of arrays
- // Inner arrays are [ "scriptSig", "scriptPubKey" ]
+ // Inner arrays are [ "scriptSig", "scriptPubKey", "flags" ]
// ... where scriptSig and scriptPubKey are stringified
// scripts.
Array tests = read_json(std::string(json_tests::script_valid, json_tests::script_valid + sizeof(json_tests::script_valid)));
@@ -64,7 +65,7 @@ BOOST_AUTO_TEST_CASE(script_valid)
{
Array test = tv.get_array();
string strTest = write_string(tv, false);
- if (test.size() < 2) // Allow size > 2; extra stuff ignored (useful for comments)
+ if (test.size() < 3) // Allow size > 3; extra stuff ignored (useful for comments)
{
BOOST_ERROR("Bad test: " << strTest);
continue;
@@ -73,9 +74,10 @@ BOOST_AUTO_TEST_CASE(script_valid)
CScript scriptSig = ParseScript(scriptSigString);
string scriptPubKeyString = test[1].get_str();
CScript scriptPubKey = ParseScript(scriptPubKeyString);
+ unsigned int scriptflags = ParseScriptFlags(test[2].get_str());
CTransaction tx;
- BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, tx, 0, flags, SIGHASH_NONE), strTest);
+ BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, tx, 0, scriptflags, SIGHASH_NONE), strTest);
}
}
@@ -97,9 +99,10 @@ BOOST_AUTO_TEST_CASE(script_invalid)
CScript scriptSig = ParseScript(scriptSigString);
string scriptPubKeyString = test[1].get_str();
CScript scriptPubKey = ParseScript(scriptPubKeyString);
+ unsigned int scriptflags = ParseScriptFlags(test[2].get_str());
CTransaction tx;
- BOOST_CHECK_MESSAGE(!VerifyScript(scriptSig, scriptPubKey, tx, 0, flags, SIGHASH_NONE), strTest);
+ BOOST_CHECK_MESSAGE(!VerifyScript(scriptSig, scriptPubKey, tx, 0, scriptflags, SIGHASH_NONE), strTest);
}
}
diff --git a/src/test/scriptnum_tests.cpp b/src/test/scriptnum_tests.cpp
index cd194cc4d9..ac60fa426f 100644
--- a/src/test/scriptnum_tests.cpp
+++ b/src/test/scriptnum_tests.cpp
@@ -3,7 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "bignum.h"
-#include "script.h"
+#include "script/script.h"
#include <boost/test/unit_test.hpp>
#include <limits.h>
#include <stdint.h>
diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp
index bff151cdda..8abde887ce 100644
--- a/src/test/sighash_tests.cpp
+++ b/src/test/sighash_tests.cpp
@@ -6,7 +6,8 @@
#include "main.h"
#include "random.h"
#include "serialize.h"
-#include "script.h"
+#include "script/script.h"
+#include "script/interpreter.h"
#include "util.h"
#include "version.h"
diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp
index 722f14a989..2d10c356ac 100644
--- a/src/test/sigopcount_tests.cpp
+++ b/src/test/sigopcount_tests.cpp
@@ -3,7 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "key.h"
-#include "script.h"
+#include "script/script.h"
#include "uint256.h"
#include <vector>
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index 03919e7c7d..21377395cf 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -8,7 +8,7 @@
#include "key.h"
#include "keystore.h"
#include "main.h"
-#include "script.h"
+#include "script/script.h"
#include "core_io.h"
#include <map>
@@ -26,7 +26,7 @@ using namespace boost::algorithm;
// In script_tests.cpp
extern Array read_json(const std::string& jsondata);
-unsigned int ParseFlags(string strFlags){
+unsigned int ParseScriptFlags(string strFlags){
unsigned int flags = 0;
vector<string> words;
split(words, strFlags, is_any_of(","));
@@ -119,7 +119,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
break;
}
- unsigned int verify_flags = ParseFlags(test[2].get_str());
+ unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout],
tx, i, verify_flags, 0),
strTest);
@@ -192,7 +192,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
break;
}
- unsigned int verify_flags = ParseFlags(test[2].get_str());
+ unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout],
tx, i, verify_flags, 0);
}
diff --git a/src/timedata.h b/src/timedata.h
index 9cc47bec13..155f6872da 100644
--- a/src/timedata.h
+++ b/src/timedata.h
@@ -5,10 +5,10 @@
#ifndef BITCOIN_TIMEDATA_H
#define BITCOIN_TIMEDATA_H
-#include <stdint.h>
-#include <vector>
#include <algorithm>
#include <assert.h>
+#include <stdint.h>
+#include <vector>
class CNetAddr;
diff --git a/src/txdb.cpp b/src/txdb.cpp
index d4c6007558..79838b6116 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -9,9 +9,10 @@
#include "pow.h"
#include "uint256.h"
-#include <boost/thread.hpp>
#include <stdint.h>
+#include <boost/thread.hpp>
+
using namespace std;
void static BatchWriteCoins(CLevelDBBatch &batch, const uint256 &hash, const CCoins &coins) {
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index 238d5bab16..404cca2373 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -3,8 +3,9 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include "core.h"
#include "txmempool.h"
+
+#include "core.h"
#include "util.h"
#include <boost/circular_buffer.hpp>
@@ -23,6 +24,8 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, int64_t _nFee,
tx(_tx), nFee(_nFee), nTime(_nTime), dPriority(_dPriority), nHeight(_nHeight)
{
nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
+
+ nModSize = tx.CalculateModifiedSize(nTxSize);
}
CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry& other)
@@ -34,7 +37,7 @@ double
CTxMemPoolEntry::GetPriority(unsigned int currentHeight) const
{
int64_t nValueIn = tx.GetValueOut()+nFee;
- double deltaPriority = ((double)(currentHeight-nHeight)*nValueIn)/nTxSize;
+ double deltaPriority = ((double)(currentHeight-nHeight)*nValueIn)/nModSize;
double dResult = dPriority + deltaPriority;
return dResult;
}
@@ -509,8 +512,8 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
const CTransaction& tx2 = it2->second.GetTx();
assert(tx2.vout.size() > txin.prevout.n && !tx2.vout[txin.prevout.n].IsNull());
} else {
- const CCoins &coins = pcoins->GetCoins(txin.prevout.hash);
- assert(coins.IsAvailable(txin.prevout.n));
+ const CCoins* coins = pcoins->AccessCoins(txin.prevout.hash);
+ assert(coins && coins->IsAvailable(txin.prevout.n));
}
// Check whether its inputs are marked in mapNextTx.
std::map<COutPoint, CInPoint>::const_iterator it3 = mapNextTx.find(txin.prevout);
@@ -572,7 +575,7 @@ CTxMemPool::WriteFeeEstimates(CAutoFile& fileout) const
fileout << CLIENT_VERSION; // version that wrote the file
minerPolicyEstimator->Write(fileout);
}
- catch (std::exception &e) {
+ catch (const std::exception &) {
LogPrintf("CTxMemPool::WriteFeeEstimates() : unable to write policy estimator data (non-fatal)");
return false;
}
@@ -591,7 +594,7 @@ CTxMemPool::ReadFeeEstimates(CAutoFile& filein)
LOCK(cs);
minerPolicyEstimator->Read(filein, minRelayFee);
}
- catch (std::exception &e) {
+ catch (const std::exception &) {
LogPrintf("CTxMemPool::ReadFeeEstimates() : unable to read policy estimator data (non-fatal)");
return false;
}
@@ -606,7 +609,7 @@ void CTxMemPool::PrioritiseTransaction(const uint256 hash, const string strHash,
deltas.first += dPriorityDelta;
deltas.second += nFeeDelta;
}
- LogPrintf("PrioritiseTransaction: %s priority += %f, fee += %d\n", strHash.c_str(), dPriorityDelta, nFeeDelta);
+ LogPrintf("PrioritiseTransaction: %s priority += %f, fee += %d\n", strHash, dPriorityDelta, nFeeDelta);
}
void CTxMemPool::ApplyDeltas(const uint256 hash, double &dPriorityDelta, int64_t &nFeeDelta)
@@ -644,4 +647,3 @@ bool CCoinsViewMemPool::GetCoins(const uint256 &txid, CCoins &coins) const {
bool CCoinsViewMemPool::HaveCoins(const uint256 &txid) const {
return mempool.exists(txid) || base->HaveCoins(txid);
}
-
diff --git a/src/txmempool.h b/src/txmempool.h
index 360364d8b0..b9d50ee0bc 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -31,6 +31,7 @@ private:
CTransaction tx;
int64_t nFee; // Cached to avoid expensive parent-transaction lookups
size_t nTxSize; // ... and avoid recomputing tx size
+ size_t nModSize; // ... and modified size for priority
int64_t nTime; // Local time when entering the mempool
double dPriority; // Priority when entering the mempool
unsigned int nHeight; // Chain height when entering the mempool
diff --git a/src/uint256.h b/src/uint256.h
index d1a822af0d..28de540226 100644
--- a/src/uint256.h
+++ b/src/uint256.h
@@ -7,6 +7,7 @@
#define BITCOIN_UINT256_H
#include <assert.h>
+#include <cstring>
#include <stdexcept>
#include <stdint.h>
#include <string>
@@ -215,8 +216,8 @@ public:
friend inline const base_uint operator>>(const base_uint& a, int shift) { return base_uint(a) >>= shift; }
friend inline const base_uint operator<<(const base_uint& a, int shift) { return base_uint(a) <<= shift; }
friend inline const base_uint operator*(const base_uint& a, uint32_t b) { return base_uint(a) *= b; }
- friend inline bool operator==(const base_uint& a, const base_uint& b) { return a.CompareTo(b) == 0; }
- friend inline bool operator!=(const base_uint& a, const base_uint& b) { return a.CompareTo(b) != 0; }
+ friend inline bool operator==(const base_uint& a, const base_uint& b) { return memcmp(a.pn, b.pn, sizeof(a.pn)) == 0; }
+ friend inline bool operator!=(const base_uint& a, const base_uint& b) { return memcmp(a.pn, b.pn, sizeof(a.pn)) != 0; }
friend inline bool operator>(const base_uint& a, const base_uint& b) { return a.CompareTo(b) > 0; }
friend inline bool operator<(const base_uint& a, const base_uint& b) { return a.CompareTo(b) < 0; }
friend inline bool operator>=(const base_uint& a, const base_uint& b) { return a.CompareTo(b) >= 0; }
diff --git a/src/univalue/univalue_write.cpp b/src/univalue/univalue_write.cpp
index 042091a827..9565cfa11a 100644
--- a/src/univalue/univalue_write.cpp
+++ b/src/univalue/univalue_write.cpp
@@ -70,15 +70,9 @@ string UniValue::write(unsigned int prettyIndent,
return s;
}
-static string spaceStr;
-
-static string indentStr(unsigned int prettyIndent, unsigned int indentLevel)
+static void indentStr(unsigned int prettyIndent, unsigned int indentLevel, string& s)
{
- unsigned int spaces = prettyIndent * indentLevel;
- while (spaceStr.size() < spaces)
- spaceStr += " ";
-
- return spaceStr.substr(0, spaces);
+ s.append(prettyIndent * indentLevel, ' ');
}
void UniValue::writeArray(unsigned int prettyIndent, unsigned int indentLevel, string& s) const
@@ -89,7 +83,7 @@ void UniValue::writeArray(unsigned int prettyIndent, unsigned int indentLevel, s
for (unsigned int i = 0; i < values.size(); i++) {
if (prettyIndent)
- s += indentStr(prettyIndent, indentLevel);
+ indentStr(prettyIndent, indentLevel, s);
s += values[i].write(prettyIndent, indentLevel + 1);
if (i != (values.size() - 1)) {
s += ",";
@@ -101,7 +95,7 @@ void UniValue::writeArray(unsigned int prettyIndent, unsigned int indentLevel, s
}
if (prettyIndent)
- s += indentStr(prettyIndent, indentLevel - 1);
+ indentStr(prettyIndent, indentLevel - 1, s);
s += "]";
}
@@ -113,7 +107,7 @@ void UniValue::writeObject(unsigned int prettyIndent, unsigned int indentLevel,
for (unsigned int i = 0; i < keys.size(); i++) {
if (prettyIndent)
- s += indentStr(prettyIndent, indentLevel);
+ indentStr(prettyIndent, indentLevel, s);
s += "\"" + json_escape(keys[i]) + "\":";
if (prettyIndent)
s += " ";
@@ -125,7 +119,7 @@ void UniValue::writeObject(unsigned int prettyIndent, unsigned int indentLevel,
}
if (prettyIndent)
- s += indentStr(prettyIndent, indentLevel - 1);
+ indentStr(prettyIndent, indentLevel - 1, s);
s += "}";
}
diff --git a/src/util.cpp b/src/util.cpp
index 1a11d038ca..0ac0f70a79 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -211,6 +211,7 @@ int LogPrintStr(const std::string &str)
{
// print to console
ret = fwrite(str.data(), 1, str.size(), stdout);
+ fflush(stdout);
}
else if (fPrintToDebugLog && AreBaseParamsConfigured())
{
diff --git a/src/util.h b/src/util.h
index 6e1f439ff7..e72c99adc7 100644
--- a/src/util.h
+++ b/src/util.h
@@ -15,8 +15,8 @@
#endif
#include "compat.h"
-#include "utiltime.h"
#include "tinyformat.h"
+#include "utiltime.h"
#include <exception>
#include <map>
diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp
index ef13555104..6837e4e267 100644
--- a/src/utilstrencodings.cpp
+++ b/src/utilstrencodings.cpp
@@ -7,10 +7,11 @@
#include "tinyformat.h"
-#include <boost/foreach.hpp>
#include <errno.h>
#include <limits>
+#include <boost/foreach.hpp>
+
using namespace std;
// safeChars chosen to allow simple messages/URLs/email addresses, but avoid anything
diff --git a/src/version.cpp b/src/version.cpp
index 8311041ed2..e441cc463f 100644
--- a/src/version.cpp
+++ b/src/version.cpp
@@ -7,6 +7,7 @@
#include "tinyformat.h"
#include <string>
+
#include <boost/algorithm/string/join.hpp>
// Name of client reported in the 'version' message. Report the same name
diff --git a/src/wallet.cpp b/src/wallet.cpp
index 20ee0bbe84..611fb8bbcd 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -9,6 +9,8 @@
#include "checkpoints.h"
#include "coincontrol.h"
#include "net.h"
+#include "script/script.h"
+#include "script/sign.h"
#include "timedata.h"
#include "util.h"
#include "utilmoneystr.h"
@@ -42,7 +44,7 @@ struct CompareValueOnly
std::string COutput::ToString() const
{
- return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString(), i, nDepth, FormatMoney(tx->vout[i].nValue).c_str());
+ return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString(), i, nDepth, FormatMoney(tx->vout[i].nValue));
}
const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
@@ -2084,6 +2086,39 @@ void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts)
}
}
+
+class CAffectedKeysVisitor : public boost::static_visitor<void> {
+private:
+ const CKeyStore &keystore;
+ std::vector<CKeyID> &vKeys;
+
+public:
+ CAffectedKeysVisitor(const CKeyStore &keystoreIn, std::vector<CKeyID> &vKeysIn) : keystore(keystoreIn), vKeys(vKeysIn) {}
+
+ void Process(const CScript &script) {
+ txnouttype type;
+ std::vector<CTxDestination> vDest;
+ int nRequired;
+ if (ExtractDestinations(script, type, vDest, nRequired)) {
+ BOOST_FOREACH(const CTxDestination &dest, vDest)
+ boost::apply_visitor(*this, dest);
+ }
+ }
+
+ void operator()(const CKeyID &keyId) {
+ if (keystore.HaveKey(keyId))
+ vKeys.push_back(keyId);
+ }
+
+ void operator()(const CScriptID &scriptId) {
+ CScript script;
+ if (keystore.GetCScript(scriptId, script))
+ Process(script);
+ }
+
+ void operator()(const CNoDestination &none) {}
+};
+
void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const {
AssertLockHeld(cs_wallet); // mapKeyMetadata
mapKeyBirth.clear();
@@ -2113,13 +2148,13 @@ void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const {
for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); it++) {
// iterate over all wallet transactions...
const CWalletTx &wtx = (*it).second;
- std::map<uint256, CBlockIndex*>::const_iterator blit = mapBlockIndex.find(wtx.hashBlock);
+ BlockMap::const_iterator blit = mapBlockIndex.find(wtx.hashBlock);
if (blit != mapBlockIndex.end() && chainActive.Contains(blit->second)) {
// ... which are already in a block
int nHeight = blit->second->nHeight;
BOOST_FOREACH(const CTxOut &txout, wtx.vout) {
// iterate over all their outputs
- ::ExtractAffectedKeys(*this, txout.scriptPubKey, vAffected);
+ CAffectedKeysVisitor(*this, vAffected).Process(txout.scriptPubKey);
BOOST_FOREACH(const CKeyID &keyid, vAffected) {
// ... and all their affected keys
std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
@@ -2233,7 +2268,7 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
}
// Is the tx in a block that's in the main chain
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
+ BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
if (mi == mapBlockIndex.end())
return 0;
CBlockIndex* pindex = (*mi).second;
@@ -2250,7 +2285,7 @@ int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const
AssertLockHeld(cs_main);
// Find the block it claims to be in
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
+ BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
if (mi == mapBlockIndex.end())
return 0;
CBlockIndex* pindex = (*mi).second;
diff --git a/src/wallet.h b/src/wallet.h
index cea61afed3..3461446b8b 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -12,6 +12,7 @@
#include "keystore.h"
#include "main.h"
#include "ui_interface.h"
+#include "wallet_ismine.h"
#include "walletdb.h"
#include <algorithm>
@@ -64,7 +65,7 @@ public:
CKeyPool();
CKeyPool(const CPubKey& vchPubKeyIn);
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
@@ -492,7 +493,7 @@ public:
fMerkleVerified = false;
}
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
@@ -605,25 +606,22 @@ public:
nOrderPos = -1;
}
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- bool fRead = ser_action.ForRead();
-
- CWalletTx* pthis = const_cast<CWalletTx*>(this);
- if (fRead)
- pthis->Init(NULL);
+ if (ser_action.ForRead())
+ Init(NULL);
char fSpent = false;
- if (!fRead)
+ if (!ser_action.ForRead())
{
- pthis->mapValue["fromaccount"] = pthis->strFromAccount;
+ mapValue["fromaccount"] = strFromAccount;
- WriteOrderPos(pthis->nOrderPos, pthis->mapValue);
+ WriteOrderPos(nOrderPos, mapValue);
if (nTimeSmart)
- pthis->mapValue["timesmart"] = strprintf("%u", nTimeSmart);
+ mapValue["timesmart"] = strprintf("%u", nTimeSmart);
}
READWRITE(*(CMerkleTx*)this);
@@ -636,13 +634,13 @@ public:
READWRITE(fFromMe);
READWRITE(fSpent);
- if (fRead)
+ if (ser_action.ForRead())
{
- pthis->strFromAccount = pthis->mapValue["fromaccount"];
+ strFromAccount = mapValue["fromaccount"];
- ReadOrderPos(pthis->nOrderPos, pthis->mapValue);
+ ReadOrderPos(nOrderPos, mapValue);
- pthis->nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(pthis->mapValue["timesmart"]) : 0;
+ nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(mapValue["timesmart"]) : 0;
}
mapValue.erase("fromaccount");
@@ -896,7 +894,7 @@ public:
CWalletKey(int64_t nExpires=0);
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
@@ -932,7 +930,7 @@ public:
vchPubKey = CPubKey();
}
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
@@ -975,13 +973,10 @@ public:
nEntryNo = 0;
}
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
- bool fRead = ser_action.ForRead();
-
- CAccountingEntry& me = *const_cast<CAccountingEntry*>(this);
if (!(nType & SER_GETHASH))
READWRITE(nVersion);
// Note: strAccount is serialized as part of the key, not here.
@@ -989,9 +984,9 @@ public:
READWRITE(nTime);
READWRITE(LIMITED_STRING(strOtherAccount, 65536));
- if (!fRead)
+ if (!ser_action.ForRead())
{
- WriteOrderPos(nOrderPos, me.mapValue);
+ WriteOrderPos(nOrderPos, mapValue);
if (!(mapValue.empty() && _ssExtra.empty()))
{
@@ -999,26 +994,26 @@ public:
ss.insert(ss.begin(), '\0');
ss << mapValue;
ss.insert(ss.end(), _ssExtra.begin(), _ssExtra.end());
- me.strComment.append(ss.str());
+ strComment.append(ss.str());
}
}
READWRITE(LIMITED_STRING(strComment, 65536));
size_t nSepPos = strComment.find("\0", 0, 1);
- if (fRead)
+ if (ser_action.ForRead())
{
- me.mapValue.clear();
+ mapValue.clear();
if (std::string::npos != nSepPos)
{
CDataStream ss(std::vector<char>(strComment.begin() + nSepPos + 1, strComment.end()), nType, nVersion);
- ss >> me.mapValue;
- me._ssExtra = std::vector<char>(ss.begin(), ss.end());
+ ss >> mapValue;
+ _ssExtra = std::vector<char>(ss.begin(), ss.end());
}
- ReadOrderPos(me.nOrderPos, me.mapValue);
+ ReadOrderPos(nOrderPos, mapValue);
}
if (std::string::npos != nSepPos)
- me.strComment.erase(nSepPos);
+ strComment.erase(nSepPos);
mapValue.erase("n");
}
diff --git a/src/wallet_ismine.cpp b/src/wallet_ismine.cpp
new file mode 100644
index 0000000000..a3c221d3ab
--- /dev/null
+++ b/src/wallet_ismine.cpp
@@ -0,0 +1,91 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 The Bitcoin developers
+// 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 "key.h"
+#include "keystore.h"
+#include "script/standard.h"
+
+#include <boost/foreach.hpp>
+
+using namespace std;
+
+typedef vector<unsigned char> valtype;
+
+unsigned int HaveKeys(const vector<valtype>& pubkeys, const CKeyStore& keystore)
+{
+ unsigned int nResult = 0;
+ BOOST_FOREACH(const valtype& pubkey, pubkeys)
+ {
+ CKeyID keyID = CPubKey(pubkey).GetID();
+ if (keystore.HaveKey(keyID))
+ ++nResult;
+ }
+ return nResult;
+}
+
+isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest)
+{
+ CScript script;
+ script.SetDestination(dest);
+ return IsMine(keystore, script);
+}
+
+isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
+{
+ vector<valtype> vSolutions;
+ txnouttype whichType;
+ if (!Solver(scriptPubKey, whichType, vSolutions)) {
+ if (keystore.HaveWatchOnly(scriptPubKey))
+ return ISMINE_WATCH_ONLY;
+ return ISMINE_NO;
+ }
+
+ CKeyID keyID;
+ switch (whichType)
+ {
+ case TX_NONSTANDARD:
+ case TX_NULL_DATA:
+ break;
+ case TX_PUBKEY:
+ keyID = CPubKey(vSolutions[0]).GetID();
+ if (keystore.HaveKey(keyID))
+ return ISMINE_SPENDABLE;
+ break;
+ case TX_PUBKEYHASH:
+ keyID = CKeyID(uint160(vSolutions[0]));
+ if (keystore.HaveKey(keyID))
+ return ISMINE_SPENDABLE;
+ break;
+ case TX_SCRIPTHASH:
+ {
+ CScriptID scriptID = CScriptID(uint160(vSolutions[0]));
+ CScript subscript;
+ if (keystore.GetCScript(scriptID, subscript)) {
+ isminetype ret = IsMine(keystore, subscript);
+ if (ret == ISMINE_SPENDABLE)
+ return ret;
+ }
+ break;
+ }
+ case TX_MULTISIG:
+ {
+ // Only consider transactions "mine" if we own ALL the
+ // keys involved. multi-signature transactions that are
+ // partially owned (somebody else has a key that can spend
+ // them) enable spend-out-from-under-you attacks, especially
+ // in shared-wallet situations.
+ vector<valtype> keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1);
+ if (HaveKeys(keys, keystore) == keys.size())
+ return ISMINE_SPENDABLE;
+ break;
+ }
+ }
+
+ if (keystore.HaveWatchOnly(scriptPubKey))
+ return ISMINE_WATCH_ONLY;
+ return ISMINE_NO;
+}
diff --git a/src/wallet_ismine.h b/src/wallet_ismine.h
new file mode 100644
index 0000000000..29e13a94a6
--- /dev/null
+++ b/src/wallet_ismine.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2014 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef H_BITCOIN_WALLET_ISMINE
+#define H_BITCOIN_WALLET_ISMINE
+
+#include "key.h"
+#include "script/script.h"
+
+class CKeyStore;
+
+/** IsMine() return codes */
+enum isminetype
+{
+ ISMINE_NO = 0,
+ ISMINE_WATCH_ONLY = 1,
+ ISMINE_SPENDABLE = 2,
+ ISMINE_ALL = ISMINE_WATCH_ONLY | ISMINE_SPENDABLE
+};
+/** used for bitflags of isminetype */
+typedef uint8_t isminefilter;
+
+isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
+isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest);
+
+#endif // H_BITCOIN_WALLET_ISMINE
diff --git a/src/walletdb.cpp b/src/walletdb.cpp
index 2fa6071658..03161250db 100644
--- a/src/walletdb.cpp
+++ b/src/walletdb.cpp
@@ -9,8 +9,8 @@
#include "protocol.h"
#include "serialize.h"
#include "sync.h"
-#include "utiltime.h"
#include "util.h"
+#include "utiltime.h"
#include "wallet.h"
#include <boost/filesystem.hpp>
@@ -281,8 +281,12 @@ CWalletDB::ReorderTransactions(CWallet* pwallet)
nOrderPos = nOrderPosNext++;
nOrderPosOffsets.push_back(nOrderPos);
- if (pacentry)
- // Have to write accounting regardless, since we don't keep it in memory
+ if (pwtx)
+ {
+ if (!WriteTx(pwtx->GetHash(), *pwtx))
+ return DB_LOAD_FAIL;
+ }
+ else
if (!WriteAccountingEntry(pacentry->nEntryNo, *pacentry))
return DB_LOAD_FAIL;
}
@@ -311,6 +315,7 @@ CWalletDB::ReorderTransactions(CWallet* pwallet)
return DB_LOAD_FAIL;
}
}
+ WriteOrderPosNext(nOrderPosNext);
return DB_LOAD_OK;
}
diff --git a/src/walletdb.h b/src/walletdb.h
index cf1a66216e..ce63bb0b97 100644
--- a/src/walletdb.h
+++ b/src/walletdb.h
@@ -55,7 +55,7 @@ public:
nCreateTime = nCreateTime_;
}
- IMPLEMENT_SERIALIZE;
+ ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {