aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/Checkpoints_tests.cpp14
-rw-r--r--src/test/DoS_tests.cpp153
-rw-r--r--src/test/base32_tests.cpp20
-rw-r--r--src/test/base58_tests.cpp8
-rw-r--r--src/test/base64_tests.cpp2
-rw-r--r--src/test/bignum_tests.cpp125
-rw-r--r--src/test/data/script_invalid.json161
-rw-r--r--src/test/data/script_valid.json204
-rw-r--r--src/test/key_tests.cpp35
-rw-r--r--src/test/miner_tests.cpp3
-rw-r--r--src/test/mruset_tests.cpp2
-rw-r--r--src/test/multisig_tests.cpp24
-rw-r--r--src/test/netbase_tests.cpp102
-rw-r--r--src/test/rpc_tests.cpp15
-rw-r--r--src/test/script_P2SH_tests.cpp26
-rw-r--r--src/test/script_tests.cpp274
-rw-r--r--src/test/sigopcount_tests.cpp4
-rw-r--r--src/test/test_bitcoin.cpp10
-rw-r--r--src/test/transaction_tests.cpp6
-rw-r--r--src/test/util_tests.cpp20
-rw-r--r--src/test/wallet_tests.cpp295
21 files changed, 1408 insertions, 95 deletions
diff --git a/src/test/Checkpoints_tests.cpp b/src/test/Checkpoints_tests.cpp
index 0d8a366d7..b14e9f705 100644
--- a/src/test/Checkpoints_tests.cpp
+++ b/src/test/Checkpoints_tests.cpp
@@ -15,20 +15,20 @@ BOOST_AUTO_TEST_SUITE(Checkpoints_tests)
BOOST_AUTO_TEST_CASE(sanity)
{
uint256 p11111 = uint256("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d");
- uint256 p140700 = uint256("0x000000000000033b512028abb90e1626d8b346fd0ed598ac0a3c371138dce2bd");
+ uint256 p134444 = uint256("0x00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe");
BOOST_CHECK(Checkpoints::CheckBlock(11111, p11111));
- BOOST_CHECK(Checkpoints::CheckBlock(140700, p140700));
+ BOOST_CHECK(Checkpoints::CheckBlock(134444, p134444));
// Wrong hashes at checkpoints should fail:
- BOOST_CHECK(!Checkpoints::CheckBlock(11111, p140700));
- BOOST_CHECK(!Checkpoints::CheckBlock(140700, p11111));
+ BOOST_CHECK(!Checkpoints::CheckBlock(11111, p134444));
+ BOOST_CHECK(!Checkpoints::CheckBlock(134444, p11111));
// ... but any hash not at a checkpoint should succeed:
- BOOST_CHECK(Checkpoints::CheckBlock(11111+1, p140700));
- BOOST_CHECK(Checkpoints::CheckBlock(140700+1, p11111));
+ BOOST_CHECK(Checkpoints::CheckBlock(11111+1, p134444));
+ BOOST_CHECK(Checkpoints::CheckBlock(134444+1, p11111));
- BOOST_CHECK(Checkpoints::GetTotalBlocksEstimate() >= 140700);
+ BOOST_CHECK(Checkpoints::GetTotalBlocksEstimate() >= 134444);
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp
index 0b8941404..4a185b3cc 100644
--- a/src/test/DoS_tests.cpp
+++ b/src/test/DoS_tests.cpp
@@ -1,7 +1,10 @@
//
// Unit tests for denial-of-service detection/prevention code
//
+#include <algorithm>
+
#include <boost/assign/list_of.hpp> // for 'map_list_of()'
+#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/foreach.hpp>
@@ -13,10 +16,10 @@
#include <stdint.h>
// Tests this internal-to-main.cpp method:
-extern void AddOrphanTx(const CDataStream& vMsg);
-extern int LimitOrphanTxSize(int nMaxOrphans);
+extern bool AddOrphanTx(const CDataStream& vMsg);
+extern unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans);
extern std::map<uint256, CDataStream*> mapOrphanTransactions;
-extern std::multimap<uint256, CDataStream*> mapOrphanTransactionsByPrev;
+extern std::map<uint256, std::map<uint256, CDataStream*> > mapOrphanTransactionsByPrev;
CService ip(uint32_t i)
{
@@ -31,13 +34,13 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
{
CNode::ClearBanned();
CAddress addr1(ip(0xa0b0c001));
- CNode dummyNode1(INVALID_SOCKET, addr1, true);
+ CNode dummyNode1(INVALID_SOCKET, addr1, "", true);
dummyNode1.Misbehaving(100); // Should get banned
BOOST_CHECK(CNode::IsBanned(addr1));
BOOST_CHECK(!CNode::IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different ip, not banned
CAddress addr2(ip(0xa0b0c002));
- CNode dummyNode2(INVALID_SOCKET, addr2, true);
+ CNode dummyNode2(INVALID_SOCKET, addr2, "", true);
dummyNode2.Misbehaving(50);
BOOST_CHECK(!CNode::IsBanned(addr2)); // 2 not banned yet...
BOOST_CHECK(CNode::IsBanned(addr1)); // ... but 1 still should be
@@ -50,14 +53,14 @@ BOOST_AUTO_TEST_CASE(DoS_banscore)
CNode::ClearBanned();
mapArgs["-banscore"] = "111"; // because 11 is my favorite number
CAddress addr1(ip(0xa0b0c001));
- CNode dummyNode1(INVALID_SOCKET, addr1, true);
+ CNode dummyNode1(INVALID_SOCKET, addr1, "", true);
dummyNode1.Misbehaving(100);
BOOST_CHECK(!CNode::IsBanned(addr1));
dummyNode1.Misbehaving(10);
BOOST_CHECK(!CNode::IsBanned(addr1));
dummyNode1.Misbehaving(1);
BOOST_CHECK(CNode::IsBanned(addr1));
- mapArgs["-banscore"] = "100";
+ mapArgs.erase("-banscore");
}
BOOST_AUTO_TEST_CASE(DoS_bantime)
@@ -67,7 +70,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
SetMockTime(nStartTime); // Overrides future calls to GetTime()
CAddress addr(ip(0xa0b0c001));
- CNode dummyNode(INVALID_SOCKET, addr, true);
+ CNode dummyNode(INVALID_SOCKET, addr, "", true);
dummyNode.Misbehaving(100);
BOOST_CHECK(CNode::IsBanned(addr));
@@ -129,18 +132,10 @@ BOOST_AUTO_TEST_CASE(DoS_checknbits)
}
-static uint256 RandomHash()
-{
- std::vector<unsigned char> randbytes(32);
- RAND_bytes(&randbytes[0], 32);
- uint256 randomhash(randbytes);
- return randomhash;
-}
-
CTransaction RandomOrphan()
{
std::map<uint256, CDataStream*>::iterator it;
- it = mapOrphanTransactions.lower_bound(RandomHash());
+ it = mapOrphanTransactions.lower_bound(GetRandHash());
if (it == mapOrphanTransactions.end())
it = mapOrphanTransactions.begin();
const CDataStream* pvMsg = it->second;
@@ -162,13 +157,13 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
CTransaction tx;
tx.vin.resize(1);
tx.vin[0].prevout.n = 0;
- tx.vin[0].prevout.hash = RandomHash();
+ tx.vin[0].prevout.hash = GetRandHash();
tx.vin[0].scriptSig << OP_1;
tx.vout.resize(1);
tx.vout[0].nValue = 1*CENT;
- tx.vout[0].scriptPubKey.SetBitcoinAddress(key.GetPubKey());
+ tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
- CDataStream ds;
+ CDataStream ds(SER_DISK, CLIENT_VERSION);
ds << tx;
AddOrphanTx(ds);
}
@@ -184,14 +179,40 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
tx.vin[0].prevout.hash = txPrev.GetHash();
tx.vout.resize(1);
tx.vout[0].nValue = 1*CENT;
- tx.vout[0].scriptPubKey.SetBitcoinAddress(key.GetPubKey());
+ tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
SignSignature(keystore, txPrev, tx, 0);
- CDataStream ds;
+ CDataStream ds(SER_DISK, CLIENT_VERSION);
ds << tx;
AddOrphanTx(ds);
}
+ // This really-big orphan should be ignored:
+ for (int i = 0; i < 10; i++)
+ {
+ CTransaction txPrev = RandomOrphan();
+
+ CTransaction tx;
+ tx.vout.resize(1);
+ tx.vout[0].nValue = 1*CENT;
+ tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
+ tx.vin.resize(500);
+ for (unsigned int j = 0; j < tx.vin.size(); j++)
+ {
+ tx.vin[j].prevout.n = j;
+ tx.vin[j].prevout.hash = txPrev.GetHash();
+ }
+ SignSignature(keystore, txPrev, tx, 0);
+ // Re-use same signature for other inputs
+ // (they don't have to be valid for this test)
+ for (unsigned int j = 1; j < tx.vin.size(); j++)
+ tx.vin[j].scriptSig = tx.vin[0].scriptSig;
+
+ CDataStream ds(SER_DISK, CLIENT_VERSION);
+ ds << tx;
+ BOOST_CHECK(!AddOrphanTx(ds));
+ }
+
// Test LimitOrphanTxSize() function:
LimitOrphanTxSize(40);
BOOST_CHECK(mapOrphanTransactions.size() <= 40);
@@ -202,4 +223,92 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
BOOST_CHECK(mapOrphanTransactionsByPrev.empty());
}
+BOOST_AUTO_TEST_CASE(DoS_checkSig)
+{
+ // Test signature caching code (see key.cpp Verify() methods)
+
+ CKey key;
+ key.MakeNewKey(true);
+ CBasicKeyStore keystore;
+ keystore.AddKey(key);
+
+ // 100 orphan transactions:
+ static const int NPREV=100;
+ CTransaction orphans[NPREV];
+ for (int i = 0; i < NPREV; i++)
+ {
+ CTransaction& tx = orphans[i];
+ tx.vin.resize(1);
+ tx.vin[0].prevout.n = 0;
+ tx.vin[0].prevout.hash = GetRandHash();
+ tx.vin[0].scriptSig << OP_1;
+ tx.vout.resize(1);
+ tx.vout[0].nValue = 1*CENT;
+ tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
+
+ CDataStream ds(SER_DISK, CLIENT_VERSION);
+ ds << tx;
+ AddOrphanTx(ds);
+ }
+
+ // Create a transaction that depends on orphans:
+ CTransaction tx;
+ tx.vout.resize(1);
+ tx.vout[0].nValue = 1*CENT;
+ tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
+ tx.vin.resize(NPREV);
+ for (unsigned int j = 0; j < tx.vin.size(); j++)
+ {
+ tx.vin[j].prevout.n = 0;
+ tx.vin[j].prevout.hash = orphans[j].GetHash();
+ }
+ // Creating signatures primes the cache:
+ boost::posix_time::ptime mst1 = boost::posix_time::microsec_clock::local_time();
+ for (unsigned int j = 0; j < tx.vin.size(); j++)
+ BOOST_CHECK(SignSignature(keystore, orphans[j], tx, j));
+ boost::posix_time::ptime mst2 = boost::posix_time::microsec_clock::local_time();
+ boost::posix_time::time_duration msdiff = mst2 - mst1;
+ long nOneValidate = msdiff.total_milliseconds();
+ if (fDebug) printf("DoS_Checksig sign: %ld\n", nOneValidate);
+
+ // ... now validating repeatedly should be quick:
+ // 2.8GHz machine, -g build: Sign takes ~760ms,
+ // uncached Verify takes ~250ms, cached Verify takes ~50ms
+ // (for 100 single-signature inputs)
+ mst1 = boost::posix_time::microsec_clock::local_time();
+ for (unsigned int i = 0; i < 5; i++)
+ for (unsigned int j = 0; j < tx.vin.size(); j++)
+ BOOST_CHECK(VerifySignature(orphans[j], tx, j, true, SIGHASH_ALL));
+ mst2 = boost::posix_time::microsec_clock::local_time();
+ msdiff = mst2 - mst1;
+ long nManyValidate = msdiff.total_milliseconds();
+ if (fDebug) printf("DoS_Checksig five: %ld\n", nManyValidate);
+
+ BOOST_CHECK_MESSAGE(nManyValidate < nOneValidate, "Signature cache timing failed");
+
+ // Empty a signature, validation should fail:
+ CScript save = tx.vin[0].scriptSig;
+ tx.vin[0].scriptSig = CScript();
+ BOOST_CHECK(!VerifySignature(orphans[0], tx, 0, true, SIGHASH_ALL));
+ tx.vin[0].scriptSig = save;
+
+ // Swap signatures, validation should fail:
+ std::swap(tx.vin[0].scriptSig, tx.vin[1].scriptSig);
+ BOOST_CHECK(!VerifySignature(orphans[0], tx, 0, true, SIGHASH_ALL));
+ BOOST_CHECK(!VerifySignature(orphans[1], tx, 1, true, SIGHASH_ALL));
+ std::swap(tx.vin[0].scriptSig, tx.vin[1].scriptSig);
+
+ // Exercise -maxsigcachesize code:
+ mapArgs["-maxsigcachesize"] = "10";
+ // Generate a new, different signature for vin[0] to trigger cache clear:
+ CScript oldSig = tx.vin[0].scriptSig;
+ BOOST_CHECK(SignSignature(keystore, orphans[0], tx, 0));
+ BOOST_CHECK(tx.vin[0].scriptSig != oldSig);
+ for (unsigned int j = 0; j < tx.vin.size(); j++)
+ BOOST_CHECK(VerifySignature(orphans[j], tx, j, true, SIGHASH_ALL));
+ mapArgs.erase("-maxsigcachesize");
+
+ LimitOrphanTxSize(0);
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp
new file mode 100644
index 000000000..fdf328591
--- /dev/null
+++ b/src/test/base32_tests.cpp
@@ -0,0 +1,20 @@
+#include <boost/test/unit_test.hpp>
+
+#include "util.h"
+
+BOOST_AUTO_TEST_SUITE(base32_tests)
+
+BOOST_AUTO_TEST_CASE(base32_testvectors)
+{
+ static const std::string vstrIn[] = {"","f","fo","foo","foob","fooba","foobar"};
+ static const std::string vstrOut[] = {"","my======","mzxq====","mzxw6===","mzxw6yq=","mzxw6ytb","mzxw6ytboi======"};
+ for (unsigned int i=0; i<sizeof(vstrIn)/sizeof(vstrIn[0]); i++)
+ {
+ std::string strEnc = EncodeBase32(vstrIn[i]);
+ BOOST_CHECK(strEnc == vstrOut[i]);
+ std::string strDec = DecodeBase32(vstrOut[i]);
+ BOOST_CHECK(strDec == vstrIn[i]);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp
index d52ac7498..3f265f1fe 100644
--- a/src/test/base58_tests.cpp
+++ b/src/test/base58_tests.cpp
@@ -1,8 +1,6 @@
#include <boost/test/unit_test.hpp>
-#include "main.h"
-#include "wallet.h"
-#include "util.h"
+#include "base58.h"
BOOST_AUTO_TEST_SUITE(base58_tests)
@@ -67,7 +65,7 @@ const char *vstrOut[] = {
BOOST_AUTO_TEST_CASE(base58_EncodeBase58)
{
- for (int i=0; i<sizeof(vstrIn)/sizeof(vstrIn[0]); i++)
+ for (unsigned int i=0; i<sizeof(vstrIn)/sizeof(vstrIn[0]); i++)
{
BOOST_CHECK_EQUAL(EncodeBase58(vstrIn[i].data, vstrIn[i].data + vstrIn[i].size), vstrOut[i]);
}
@@ -76,7 +74,7 @@ BOOST_AUTO_TEST_CASE(base58_EncodeBase58)
BOOST_AUTO_TEST_CASE(base58_DecodeBase58)
{
std::vector<unsigned char> result;
- for (int i=0; i<sizeof(vstrIn)/sizeof(vstrIn[0]); i++)
+ for (unsigned int i=0; i<sizeof(vstrIn)/sizeof(vstrIn[0]); i++)
{
std::vector<unsigned char> expected(vstrIn[i].data, vstrIn[i].data + vstrIn[i].size);
BOOST_CHECK(DecodeBase58(vstrOut[i], result));
diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp
index fff30ef5e..c5a053e2e 100644
--- a/src/test/base64_tests.cpp
+++ b/src/test/base64_tests.cpp
@@ -10,7 +10,7 @@ BOOST_AUTO_TEST_CASE(base64_testvectors)
{
static const std::string vstrIn[] = {"","f","fo","foo","foob","fooba","foobar"};
static const std::string vstrOut[] = {"","Zg==","Zm8=","Zm9v","Zm9vYg==","Zm9vYmE=","Zm9vYmFy"};
- for (int i=0; i<sizeof(vstrIn)/sizeof(vstrIn[0]); i++)
+ for (unsigned int i=0; i<sizeof(vstrIn)/sizeof(vstrIn[0]); i++)
{
std::string strEnc = EncodeBase64(vstrIn[i]);
BOOST_CHECK(strEnc == vstrOut[i]);
diff --git a/src/test/bignum_tests.cpp b/src/test/bignum_tests.cpp
new file mode 100644
index 000000000..8620f81f1
--- /dev/null
+++ b/src/test/bignum_tests.cpp
@@ -0,0 +1,125 @@
+#include <boost/test/unit_test.hpp>
+#include <limits>
+
+#include "bignum.h"
+#include "util.h"
+
+BOOST_AUTO_TEST_SUITE(bignum_tests)
+
+// Unfortunately there's no standard way of preventing a function from being
+// inlined, so we define a macro for it.
+//
+// You should use it like this:
+// NOINLINE void function() {...}
+#if defined(__GNUC__)
+// This also works and will be defined for any compiler implementing gcc
+// extensions, such as clang and icc.
+#define NOINLINE __attribute__((noinline))
+#elif defined(_MSC_VER)
+#define NOINLINE __declspec(noinline)
+#else
+// We give out a warning because it impacts the correctness of one bignum test.
+#warning You should define NOINLINE for your compiler.
+#define NOINLINE
+#endif
+
+// For the following test case, it is useful to use additional tools.
+//
+// The simplest one to use is the compiler flag -ftrapv, which detects integer
+// overflows and similar errors. However, due to optimizations and compilers
+// taking advantage of undefined behavior sometimes it may not actually detect
+// anything.
+//
+// You can also use compiler-based stack protection to possibly detect possible
+// stack buffer overruns.
+//
+// For more accurate diagnostics, you can use an undefined arithmetic operation
+// detector such as the clang-based tool:
+//
+// "IOC: An Integer Overflow Checker for C/C++"
+//
+// Available at: http://embed.cs.utah.edu/ioc/
+//
+// It might also be useful to use Google's AddressSanitizer to detect
+// stack buffer overruns, which valgrind can't currently detect.
+
+// Let's force this code not to be inlined, in order to actually
+// test a generic version of the function. This increases the chance
+// that -ftrapv will detect overflows.
+NOINLINE void mysetint64(CBigNum& num, int64 n)
+{
+ num.setint64(n);
+}
+
+// For each number, we do 2 tests: one with inline code, then we reset the
+// value to 0, then the second one with a non-inlined function.
+BOOST_AUTO_TEST_CASE(bignum_setint64)
+{
+ int64 n;
+
+ {
+ n = 0;
+ CBigNum num(n);
+ BOOST_CHECK(num.ToString() == "0");
+ num.setulong(0);
+ BOOST_CHECK(num.ToString() == "0");
+ mysetint64(num, n);
+ BOOST_CHECK(num.ToString() == "0");
+ }
+ {
+ n = 1;
+ CBigNum num(n);
+ BOOST_CHECK(num.ToString() == "1");
+ num.setulong(0);
+ BOOST_CHECK(num.ToString() == "0");
+ mysetint64(num, n);
+ BOOST_CHECK(num.ToString() == "1");
+ }
+ {
+ n = -1;
+ CBigNum num(n);
+ BOOST_CHECK(num.ToString() == "-1");
+ num.setulong(0);
+ BOOST_CHECK(num.ToString() == "0");
+ mysetint64(num, n);
+ BOOST_CHECK(num.ToString() == "-1");
+ }
+ {
+ n = 5;
+ CBigNum num(n);
+ BOOST_CHECK(num.ToString() == "5");
+ num.setulong(0);
+ BOOST_CHECK(num.ToString() == "0");
+ mysetint64(num, n);
+ BOOST_CHECK(num.ToString() == "5");
+ }
+ {
+ n = -5;
+ CBigNum num(n);
+ BOOST_CHECK(num.ToString() == "-5");
+ num.setulong(0);
+ BOOST_CHECK(num.ToString() == "0");
+ mysetint64(num, n);
+ BOOST_CHECK(num.ToString() == "-5");
+ }
+ {
+ n = std::numeric_limits<int64>::min();
+ CBigNum num(n);
+ BOOST_CHECK(num.ToString() == "-9223372036854775808");
+ num.setulong(0);
+ BOOST_CHECK(num.ToString() == "0");
+ mysetint64(num, n);
+ BOOST_CHECK(num.ToString() == "-9223372036854775808");
+ }
+ {
+ n = std::numeric_limits<int64>::max();
+ CBigNum num(n);
+ BOOST_CHECK(num.ToString() == "9223372036854775807");
+ num.setulong(0);
+ BOOST_CHECK(num.ToString() == "0");
+ mysetint64(num, n);
+ BOOST_CHECK(num.ToString() == "9223372036854775807");
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/data/script_invalid.json b/src/test/data/script_invalid.json
new file mode 100644
index 000000000..0c2d7110d
--- /dev/null
+++ b/src/test/data/script_invalid.json
@@ -0,0 +1,161 @@
+[
+["", ""],
+["", "NOP"],
+["NOP", ""],
+["NOP","NOP"],
+
+["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 VERNOTIF ELSE 1 ENDIF", "VERNOT 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", "RETURN"],
+["1", "DUP IF RETURN ENDIF"],
+
+["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"],
+["1", "IF 0xc0 ELSE 1 ENDIF"],
+["1", "IF 0xd1 ELSE 1 ENDIF"],
+["1", "IF 0xee ELSE 1 ENDIF"],
+["1", "IF 0xfd ELSE 1 ENDIF"],
+["1", "IF 0xff ELSE 1 ENDIF"],
+
+["NOP", "RIPEMD160"],
+["NOP", "SHA1"],
+["NOP", "SHA256"],
+["NOP", "HASH160"],
+["NOP", "HASH256"],
+
+["NOP",
+"'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'",
+">520 byte push"],
+["1",
+"0x61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161",
+">201 opcodes executed. 0x61 is NOP"],
+["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"1 2 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+">1,000 stack size (0x6f is 3DUP)"],
+["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"1 TOALTSTACK 2 TOALTSTACK 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+">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",
+"10,001-byte scriptPubKey"],
+
+["NOP1","NOP10"]
+]
diff --git a/src/test/data/script_valid.json b/src/test/data/script_valid.json
new file mode 100644
index 000000000..6ef4d46a8
--- /dev/null
+++ b/src/test/data/script_valid.json
@@ -0,0 +1,204 @@
+[
+["0x01 0x0b", "11 EQUAL", "push 1 byte"],
+["0x02 0x417a", "'Az' EQUAL"],
+["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 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"],
+
+["1 1", "VERIFY"],
+
+["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 ROT 21 EQUAL"],
+["22 21 20", "ROT ROT ROT 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"],
+["-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"],
+["'abcdefghijklmnopqrstuvwxyz'", "SIZE 26 EQUAL"],
+
+
+["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 0xc0 ELSE 1 ENDIF"],
+["0", "IF 0xd1 ELSE 1 ENDIF"],
+["0", "IF 0xee ELSE 1 ENDIF"],
+["0", "IF 0xfd ELSE 1 ENDIF"],
+["0", "IF 0xff ELSE 1 ENDIF"],
+
+["NOP",
+"'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'",
+"520 byte push"],
+["1",
+"0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161",
+"201 opcodes executed. 0x61 is NOP"],
+["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"1,000 stack size (0x6f is 3DUP)"],
+["1 TOALTSTACK 2 TOALTSTACK 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"1 2 3 4 5 6 7 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"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",
+"Max-size (10,000-byte), max-push(520 bytes), max-opcodes(201), max stack size(1,000 items). 0x6f is 3DUP, 0x61 is NOP"],
+
+["NOP","1"]
+]
diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp
index bc8759b6f..0a6df88fe 100644
--- a/src/test/key_tests.cpp
+++ b/src/test/key_tests.cpp
@@ -10,10 +10,18 @@
using namespace std;
-static const string strSecret1 ("5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHfmFiWtmAbrj");
-static const string strSecret2 ("5KC4ejrDjv152FGwP386VD1i2NYc5KkfSMyv1nGy1VGDxGHqVY3");
-static const string strSecret1C("Kwr371tjA9u2rFSMZjTNun2PXXP3WPZu2afRHTcta6KxEUdm1vEw");
-static const string strSecret2C("L3Hq7a8FEQwJkW1M2GNKDW28546Vp5miewcCzSqUD9kCAXrJdS3g");
+static const string strSecret1 ("5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHfmFiWtmAbrj");
+static const string strSecret2 ("5KC4ejrDjv152FGwP386VD1i2NYc5KkfSMyv1nGy1VGDxGHqVY3");
+static const string strSecret1C ("Kwr371tjA9u2rFSMZjTNun2PXXP3WPZu2afRHTcta6KxEUdm1vEw");
+static const string strSecret2C ("L3Hq7a8FEQwJkW1M2GNKDW28546Vp5miewcCzSqUD9kCAXrJdS3g");
+static const CBitcoinAddress addr1 ("1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ");
+static const CBitcoinAddress addr2 ("1F5y5E5FMc5YzdJtB9hLaUe43GDxEKXENJ");
+static const CBitcoinAddress addr1C("1NoJrossxPBKfCHuJXT4HadJrXRE9Fxiqs");
+static const CBitcoinAddress addr2C("1CRj2HyM1CXWzHAXLQtiGLyggNT9WQqsDs");
+
+
+static const string strAddressBad("1HV9Lc3sNHZxwj4Zk6fB38tEmBryq2cBiF");
+
#ifdef KEY_TESTS_DUMPINFO
void dumpKeyInfo(uint256 privkey)
@@ -47,11 +55,12 @@ BOOST_AUTO_TEST_SUITE(key_tests)
BOOST_AUTO_TEST_CASE(key_test1)
{
- CBitcoinSecret bsecret1, bsecret2, bsecret1C, bsecret2C;
- bsecret1.SetString (strSecret1);
- bsecret2.SetString (strSecret2);
- bsecret1C.SetString(strSecret1C);
- bsecret2C.SetString(strSecret2C);
+ CBitcoinSecret bsecret1, bsecret2, bsecret1C, bsecret2C, baddress1;
+ BOOST_CHECK( bsecret1.SetString (strSecret1));
+ BOOST_CHECK( bsecret2.SetString (strSecret2));
+ BOOST_CHECK( bsecret1C.SetString(strSecret1C));
+ BOOST_CHECK( bsecret2C.SetString(strSecret2C));
+ BOOST_CHECK(!baddress1.SetString(strAddressBad));
bool fCompressed;
CSecret secret1 = bsecret1.GetSecret (fCompressed);
@@ -72,10 +81,10 @@ BOOST_AUTO_TEST_CASE(key_test1)
key1C.SetSecret(secret1, true);
key2C.SetSecret(secret2, true);
- BOOST_CHECK(CBitcoinAddress(key1.GetPubKey ()).ToString() == "1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ");
- BOOST_CHECK(CBitcoinAddress(key2.GetPubKey ()).ToString() == "1F5y5E5FMc5YzdJtB9hLaUe43GDxEKXENJ");
- BOOST_CHECK(CBitcoinAddress(key1C.GetPubKey()).ToString() == "1NoJrossxPBKfCHuJXT4HadJrXRE9Fxiqs");
- BOOST_CHECK(CBitcoinAddress(key2C.GetPubKey()).ToString() == "1CRj2HyM1CXWzHAXLQtiGLyggNT9WQqsDs");
+ BOOST_CHECK(addr1.Get() == CTxDestination(key1.GetPubKey().GetID()));
+ BOOST_CHECK(addr2.Get() == CTxDestination(key2.GetPubKey().GetID()));
+ BOOST_CHECK(addr1C.Get() == CTxDestination(key1C.GetPubKey().GetID()));
+ BOOST_CHECK(addr2C.Get() == CTxDestination(key2C.GetPubKey().GetID()));
for (int n=0; n<16; n++)
{
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index d4abd6d2a..5712b4a1b 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -1,6 +1,7 @@
#include <boost/test/unit_test.hpp>
#include "uint256.h"
+#include "util.h"
extern void SHA256Transform(void* pstate, void* pinput, const void* pinit);
@@ -11,7 +12,7 @@ BOOST_AUTO_TEST_CASE(sha256transform_equality)
unsigned int pSHA256InitState[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
- unsigned char pstate[32];
+ // unsigned char pstate[32];
unsigned char pinput[64];
int i;
diff --git a/src/test/mruset_tests.cpp b/src/test/mruset_tests.cpp
index ca5a1f1b1..64a6678a7 100644
--- a/src/test/mruset_tests.cpp
+++ b/src/test/mruset_tests.cpp
@@ -71,7 +71,7 @@ int static permute(int n)
return ret;
}
-// Test that an mruset acts like a moving window, if no duplcate elements are added
+// Test that an mruset acts like a moving window, if no duplicate elements are added
BOOST_AUTO_TEST_CASE(mruset_window)
{
mruset<int> mru(MAX_SIZE);
diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp
index 8ae9290fc..6bc5e3b99 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -175,12 +175,12 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
//
CBasicKeyStore keystore, emptykeystore, partialkeystore;
CKey key[3];
- CBitcoinAddress keyaddr[3];
+ CTxDestination keyaddr[3];
for (int i = 0; i < 3; i++)
{
key[i].MakeNewKey(true);
keystore.AddKey(key[i]);
- keyaddr[i].SetPubKey(key[i].GetPubKey());
+ keyaddr[i] = key[i].GetPubKey().GetID();
}
partialkeystore.AddKey(key[0]);
@@ -191,8 +191,8 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
s << key[0].GetPubKey() << OP_CHECKSIG;
BOOST_CHECK(Solver(s, whichType, solutions));
BOOST_CHECK(solutions.size() == 1);
- CBitcoinAddress addr;
- BOOST_CHECK(ExtractAddress(s, addr));
+ CTxDestination addr;
+ BOOST_CHECK(ExtractDestination(s, addr));
BOOST_CHECK(addr == keyaddr[0]);
BOOST_CHECK(IsMine(keystore, s));
BOOST_CHECK(!IsMine(emptykeystore, s));
@@ -201,11 +201,11 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
vector<valtype> solutions;
txnouttype whichType;
CScript s;
- s << OP_DUP << OP_HASH160 << Hash160(key[0].GetPubKey()) << OP_EQUALVERIFY << OP_CHECKSIG;
+ s << OP_DUP << OP_HASH160 << key[0].GetPubKey().GetID() << OP_EQUALVERIFY << OP_CHECKSIG;
BOOST_CHECK(Solver(s, whichType, solutions));
BOOST_CHECK(solutions.size() == 1);
- CBitcoinAddress addr;
- BOOST_CHECK(ExtractAddress(s, addr));
+ CTxDestination addr;
+ BOOST_CHECK(ExtractDestination(s, addr));
BOOST_CHECK(addr == keyaddr[0]);
BOOST_CHECK(IsMine(keystore, s));
BOOST_CHECK(!IsMine(emptykeystore, s));
@@ -217,8 +217,8 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
s << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
BOOST_CHECK(Solver(s, whichType, solutions));
BOOST_CHECK_EQUAL(solutions.size(), 4);
- CBitcoinAddress addr;
- BOOST_CHECK(!ExtractAddress(s, addr));
+ CTxDestination addr;
+ BOOST_CHECK(!ExtractDestination(s, addr));
BOOST_CHECK(IsMine(keystore, s));
BOOST_CHECK(!IsMine(emptykeystore, s));
BOOST_CHECK(!IsMine(partialkeystore, s));
@@ -230,12 +230,12 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
s << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
BOOST_CHECK(Solver(s, whichType, solutions));
BOOST_CHECK_EQUAL(solutions.size(), 4);
- vector<CBitcoinAddress> addrs;
+ vector<CTxDestination> addrs;
int nRequired;
- BOOST_CHECK(ExtractAddresses(s, whichType, addrs, nRequired));
+ BOOST_CHECK(ExtractDestinations(s, whichType, addrs, nRequired));
BOOST_CHECK(addrs[0] == keyaddr[0]);
BOOST_CHECK(addrs[1] == keyaddr[1]);
- BOOST_CHECK(nRequired = 1);
+ BOOST_CHECK(nRequired == 1);
BOOST_CHECK(IsMine(keystore, s));
BOOST_CHECK(!IsMine(emptykeystore, s));
BOOST_CHECK(!IsMine(partialkeystore, s));
diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp
new file mode 100644
index 000000000..e5a7562d9
--- /dev/null
+++ b/src/test/netbase_tests.cpp
@@ -0,0 +1,102 @@
+#include <boost/test/unit_test.hpp>
+
+#include <string>
+#include <vector>
+
+#include "netbase.h"
+
+using namespace std;
+
+BOOST_AUTO_TEST_SUITE(netbase_tests)
+
+BOOST_AUTO_TEST_CASE(netbase_networks)
+{
+ BOOST_CHECK(CNetAddr("127.0.0.1").GetNetwork() == NET_UNROUTABLE);
+ BOOST_CHECK(CNetAddr("::1").GetNetwork() == NET_UNROUTABLE);
+ BOOST_CHECK(CNetAddr("8.8.8.8").GetNetwork() == NET_IPV4);
+ BOOST_CHECK(CNetAddr("2001::8888").GetNetwork() == NET_IPV6);
+ BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetNetwork() == NET_TOR);
+}
+
+BOOST_AUTO_TEST_CASE(netbase_properties)
+{
+ BOOST_CHECK(CNetAddr("127.0.0.1").IsIPv4());
+ BOOST_CHECK(CNetAddr("::FFFF:192.168.1.1").IsIPv4());
+ BOOST_CHECK(CNetAddr("::1").IsIPv6());
+ BOOST_CHECK(CNetAddr("10.0.0.1").IsRFC1918());
+ BOOST_CHECK(CNetAddr("192.168.1.1").IsRFC1918());
+ BOOST_CHECK(CNetAddr("172.31.255.255").IsRFC1918());
+ BOOST_CHECK(CNetAddr("2001:0DB8::").IsRFC3849());
+ BOOST_CHECK(CNetAddr("169.254.1.1").IsRFC3927());
+ BOOST_CHECK(CNetAddr("2002::1").IsRFC3964());
+ BOOST_CHECK(CNetAddr("FC00::").IsRFC4193());
+ BOOST_CHECK(CNetAddr("2001::2").IsRFC4380());
+ BOOST_CHECK(CNetAddr("2001:10::").IsRFC4843());
+ BOOST_CHECK(CNetAddr("FE80::").IsRFC4862());
+ BOOST_CHECK(CNetAddr("64:FF9B::").IsRFC6052());
+ BOOST_CHECK(CNetAddr("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").IsTor());
+ BOOST_CHECK(CNetAddr("127.0.0.1").IsLocal());
+ BOOST_CHECK(CNetAddr("::1").IsLocal());
+ BOOST_CHECK(CNetAddr("8.8.8.8").IsRoutable());
+ BOOST_CHECK(CNetAddr("2001::1").IsRoutable());
+ BOOST_CHECK(CNetAddr("127.0.0.1").IsValid());
+}
+
+bool static TestSplitHost(string test, string host, int port)
+{
+ string hostOut;
+ int portOut = -1;
+ SplitHostPort(test, portOut, hostOut);
+ return hostOut == host && port == portOut;
+}
+
+BOOST_AUTO_TEST_CASE(netbase_splithost)
+{
+ BOOST_CHECK(TestSplitHost("www.bitcoin.org", "www.bitcoin.org", -1));
+ BOOST_CHECK(TestSplitHost("[www.bitcoin.org]", "www.bitcoin.org", -1));
+ BOOST_CHECK(TestSplitHost("www.bitcoin.org:80", "www.bitcoin.org", 80));
+ BOOST_CHECK(TestSplitHost("[www.bitcoin.org]:80", "www.bitcoin.org", 80));
+ BOOST_CHECK(TestSplitHost("127.0.0.1", "127.0.0.1", -1));
+ BOOST_CHECK(TestSplitHost("127.0.0.1:8333", "127.0.0.1", 8333));
+ BOOST_CHECK(TestSplitHost("[127.0.0.1]", "127.0.0.1", -1));
+ BOOST_CHECK(TestSplitHost("[127.0.0.1]:8333", "127.0.0.1", 8333));
+ BOOST_CHECK(TestSplitHost("::ffff:127.0.0.1", "::ffff:127.0.0.1", -1));
+ BOOST_CHECK(TestSplitHost("[::ffff:127.0.0.1]:8333", "::ffff:127.0.0.1", 8333));
+ BOOST_CHECK(TestSplitHost("[::]:8333", "::", 8333));
+ BOOST_CHECK(TestSplitHost("::8333", "::8333", -1));
+ BOOST_CHECK(TestSplitHost(":8333", "", 8333));
+ BOOST_CHECK(TestSplitHost("[]:8333", "", 8333));
+ BOOST_CHECK(TestSplitHost("", "", -1));
+}
+
+bool static TestParse(string src, string canon)
+{
+ CService addr;
+ if (!LookupNumeric(src.c_str(), addr, 65535))
+ return canon == "";
+ return canon == addr.ToString();
+}
+
+BOOST_AUTO_TEST_CASE(netbase_lookupnumeric)
+{
+ BOOST_CHECK(TestParse("127.0.0.1", "127.0.0.1:65535"));
+ BOOST_CHECK(TestParse("127.0.0.1:8333", "127.0.0.1:8333"));
+ BOOST_CHECK(TestParse("::ffff:127.0.0.1", "127.0.0.1:65535"));
+ BOOST_CHECK(TestParse("::", "[::]:65535"));
+ BOOST_CHECK(TestParse("[::]:8333", "[::]:8333"));
+ BOOST_CHECK(TestParse("[127.0.0.1]", "127.0.0.1:65535"));
+ BOOST_CHECK(TestParse(":::", ""));
+}
+
+BOOST_AUTO_TEST_CASE(onioncat_test)
+{
+ // values from http://www.cypherpunk.at/onioncat/wiki/OnionCat
+ CNetAddr addr1("5wyqrzbvrdsumnok.onion");
+ CNetAddr addr2("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca");
+ BOOST_CHECK(addr1 == addr2);
+ BOOST_CHECK(addr1.IsTor());
+ BOOST_CHECK(addr1.ToStringIP() == "5wyqrzbvrdsumnok.onion");
+ BOOST_CHECK(addr1.IsRoutable());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index 87462f765..e6c00e39d 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -3,16 +3,11 @@
#include "base58.h"
#include "util.h"
-#include "json/json_spirit_reader_template.h"
-#include "json/json_spirit_writer_template.h"
-#include "json/json_spirit_utils.h"
+#include "bitcoinrpc.h"
using namespace std;
using namespace json_spirit;
-typedef Value(*rpcfn_type)(const Array& params, bool fHelp);
-extern map<string, rpcfn_type> mapCallTable;
-
BOOST_AUTO_TEST_SUITE(rpc_tests)
static Array
@@ -36,12 +31,12 @@ struct TestNetFixture
BOOST_FIXTURE_TEST_CASE(rpc_addmultisig, TestNetFixture)
{
- rpcfn_type addmultisig = mapCallTable["addmultisigaddress"];
+ rpcfn_type addmultisig = tableRPC["addmultisigaddress"]->actor;
// old, 65-byte-long:
- const char* address1Hex = "0434e3e09f49ea168c5bbf53f877ff4206923858aab7c7e1df25bc263978107c95e35065a27ef6f1b27222db0ec97e0e895eaca603d3ee0d4c060ce3d8a00286c8";
+ const char address1Hex[] = "0434e3e09f49ea168c5bbf53f877ff4206923858aab7c7e1df25bc263978107c95e35065a27ef6f1b27222db0ec97e0e895eaca603d3ee0d4c060ce3d8a00286c8";
// new, compressed:
- const char* address2Hex = "0388c2037017c62240b6b72ac1a2a5f94da790596ebd06177c8572752922165cb4";
+ const char address2Hex[] = "0388c2037017c62240b6b72ac1a2a5f94da790596ebd06177c8572752922165cb4";
Value v;
CBitcoinAddress address;
@@ -67,7 +62,7 @@ BOOST_FIXTURE_TEST_CASE(rpc_addmultisig, TestNetFixture)
string short1(address1Hex, address1Hex+sizeof(address1Hex)-2); // last byte missing
BOOST_CHECK_THROW(addmultisig(createArgs(2, short1.c_str()), false), runtime_error);
- string short2(address1Hex+2, address1Hex+sizeof(address1Hex)); // first byte missing
+ string short2(address1Hex+1, address1Hex+sizeof(address1Hex)); // first byte missing
BOOST_CHECK_THROW(addmultisig(createArgs(2, short2.c_str()), false), runtime_error);
}
diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp
index aa72c0009..f7bf5dfbf 100644
--- a/src/test/script_P2SH_tests.cpp
+++ b/src/test/script_P2SH_tests.cpp
@@ -65,14 +65,14 @@ BOOST_AUTO_TEST_CASE(sign)
// different keys, straight/P2SH, pubkey/pubkeyhash
CScript standardScripts[4];
standardScripts[0] << key[0].GetPubKey() << OP_CHECKSIG;
- standardScripts[1].SetBitcoinAddress(key[1].GetPubKey());
+ standardScripts[1].SetDestination(key[1].GetPubKey().GetID());
standardScripts[2] << key[1].GetPubKey() << OP_CHECKSIG;
- standardScripts[3].SetBitcoinAddress(key[2].GetPubKey());
+ standardScripts[3].SetDestination(key[2].GetPubKey().GetID());
CScript evalScripts[4];
for (int i = 0; i < 4; i++)
{
keystore.AddCScript(standardScripts[i]);
- evalScripts[i].SetPayToScriptHash(standardScripts[i]);
+ evalScripts[i].SetDestination(standardScripts[i].GetID());
}
CTransaction txFrom; // Funding transaction:
@@ -122,7 +122,7 @@ BOOST_AUTO_TEST_CASE(norecurse)
invalidAsScript << OP_INVALIDOPCODE << OP_INVALIDOPCODE;
CScript p2sh;
- p2sh.SetPayToScriptHash(invalidAsScript);
+ p2sh.SetDestination(invalidAsScript.GetID());
CScript scriptSig;
scriptSig << Serialize(invalidAsScript);
@@ -133,7 +133,7 @@ BOOST_AUTO_TEST_CASE(norecurse)
// Try to recurse, and verification should succeed because
// the inner HASH160 <> EQUAL should only check the hash:
CScript p2sh2;
- p2sh2.SetPayToScriptHash(p2sh);
+ p2sh2.SetDestination(p2sh.GetID());
CScript scriptSig2;
scriptSig2 << Serialize(invalidAsScript) << Serialize(p2sh);
@@ -154,7 +154,7 @@ BOOST_AUTO_TEST_CASE(set)
}
CScript inner[4];
- inner[0].SetBitcoinAddress(key[0].GetPubKey());
+ inner[0].SetDestination(key[0].GetPubKey().GetID());
inner[1].SetMultisig(2, std::vector<CKey>(keys.begin(), keys.begin()+2));
inner[2].SetMultisig(1, std::vector<CKey>(keys.begin(), keys.begin()+2));
inner[3].SetMultisig(2, std::vector<CKey>(keys.begin(), keys.begin()+3));
@@ -162,7 +162,7 @@ BOOST_AUTO_TEST_CASE(set)
CScript outer[4];
for (int i = 0; i < 4; i++)
{
- outer[i].SetPayToScriptHash(inner[i]);
+ outer[i].SetDestination(inner[i].GetID());
keystore.AddCScript(inner[i]);
}
@@ -232,7 +232,7 @@ BOOST_AUTO_TEST_CASE(switchover)
scriptSig << Serialize(notValid);
CScript fund;
- fund.SetPayToScriptHash(notValid);
+ fund.SetDestination(notValid.GetID());
// Validation should succeed under old rules (hash is correct):
@@ -258,9 +258,9 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
txFrom.vout.resize(6);
// First three are standard:
- CScript pay1; pay1.SetBitcoinAddress(key[0].GetPubKey());
+ CScript pay1; pay1.SetDestination(key[0].GetPubKey().GetID());
keystore.AddCScript(pay1);
- CScript payScriptHash1; payScriptHash1.SetPayToScriptHash(pay1);
+ CScript payScriptHash1; payScriptHash1.SetDestination(pay1.GetID());
CScript pay1of3; pay1of3.SetMultisig(1, keys);
txFrom.vout[0].scriptPubKey = payScriptHash1;
@@ -278,13 +278,13 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
for (int i = 0; i < 11; i++)
oneOfEleven << key[0].GetPubKey();
oneOfEleven << OP_11 << OP_CHECKMULTISIG;
- txFrom.vout[5].scriptPubKey.SetPayToScriptHash(oneOfEleven);
+ txFrom.vout[5].scriptPubKey.SetDestination(oneOfEleven.GetID());
mapInputs[txFrom.GetHash()] = make_pair(CTxIndex(), txFrom);
CTransaction txTo;
txTo.vout.resize(1);
- txTo.vout[0].scriptPubKey.SetBitcoinAddress(key[1].GetPubKey());
+ txTo.vout[0].scriptPubKey.SetDestination(key[1].GetPubKey().GetID());
txTo.vin.resize(3);
txTo.vin[0].prevout.n = 0;
@@ -311,7 +311,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
CTransaction txToNonStd;
txToNonStd.vout.resize(1);
- txToNonStd.vout[0].scriptPubKey.SetBitcoinAddress(key[1].GetPubKey());
+ txToNonStd.vout[0].scriptPubKey.SetDestination(key[1].GetPubKey().GetID());
txToNonStd.vin.resize(2);
txToNonStd.vin[0].prevout.n = 4;
txToNonStd.vin[0].prevout.hash = txFrom.GetHash();
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 493ea69d9..61d9a64ee 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -1,17 +1,176 @@
+#include <iostream>
+#include <fstream>
#include <vector>
-#include <boost/test/unit_test.hpp>
+#include <boost/algorithm/string/classification.hpp>
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/algorithm/string/replace.hpp>
+#include <boost/algorithm/string/split.hpp>
#include <boost/foreach.hpp>
+#include <boost/preprocessor/stringize.hpp>
+#include <boost/test/unit_test.hpp>
+#include "json/json_spirit_reader_template.h"
+#include "json/json_spirit_writer_template.h"
+#include "json/json_spirit_utils.h"
#include "main.h"
#include "wallet.h"
using namespace std;
+using namespace json_spirit;
+using namespace boost::algorithm;
+
extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
extern bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn,
bool fValidatePayToScriptHash, int nHashType);
+CScript
+ParseScript(string s)
+{
+ CScript result;
+
+ static map<string, opcodetype> mapOpNames;
+
+ if (mapOpNames.size() == 0)
+ {
+ for (int op = OP_NOP; op <= OP_NOP10; op++)
+ {
+ const char* name = GetOpName((opcodetype)op);
+ if (strcmp(name, "OP_UNKNOWN") == 0)
+ continue;
+ string strName(name);
+ mapOpNames[strName] = (opcodetype)op;
+ // Convenience: OP_ADD and just ADD are both recognized:
+ replace_first(strName, "OP_", "");
+ mapOpNames[strName] = (opcodetype)op;
+ }
+ }
+
+ vector<string> words;
+ split(words, s, is_any_of(" \t\n"), token_compress_on);
+
+ BOOST_FOREACH(string w, words)
+ {
+ if (all(w, is_digit()) ||
+ (starts_with(w, "-") && all(string(w.begin()+1, w.end()), is_digit())))
+ {
+ // Number
+ int64 n = atoi64(w);
+ result << n;
+ }
+ else if (starts_with(w, "0x") && IsHex(string(w.begin()+2, w.end())))
+ {
+ // Raw hex data, inserted NOT pushed onto stack:
+ std::vector<unsigned char> raw = ParseHex(string(w.begin()+2, w.end()));
+ result.insert(result.end(), raw.begin(), raw.end());
+ }
+ else if (w.size() >= 2 && starts_with(w, "'") && ends_with(w, "'"))
+ {
+ // Single-quoted string, pushed as data. NOTE: this is poor-man's
+ // parsing, spaces/tabs/newlines in single-quoted strings won't work.
+ std::vector<unsigned char> value(w.begin()+1, w.end()-1);
+ result << value;
+ }
+ else if (mapOpNames.count(w))
+ {
+ // opcode, e.g. OP_ADD or OP_1:
+ result << mapOpNames[w];
+ }
+ else
+ {
+ BOOST_ERROR("Parse error: " << s);
+ return CScript();
+ }
+ }
+
+ return result;
+}
+
+Array
+read_json(const std::string& filename)
+{
+ namespace fs = boost::filesystem;
+ fs::path testFile = fs::current_path() / "test" / "data" / filename;
+
+#ifdef TEST_DATA_DIR
+ if (!fs::exists(testFile))
+ {
+ testFile = fs::path(BOOST_PP_STRINGIZE(TEST_DATA_DIR)) / filename;
+ }
+#endif
+
+ ifstream ifs(testFile.string().c_str(), ifstream::in);
+ Value v;
+ if (!read_stream(ifs, v))
+ {
+ if (ifs.fail())
+ BOOST_ERROR("Cound not find/open " << filename);
+ else
+ BOOST_ERROR("JSON syntax error in " << filename);
+ return Array();
+ }
+ if (v.type() != array_type)
+ {
+ BOOST_ERROR(filename << " does not contain a json array");
+ return Array();
+ }
+
+ return v.get_array();
+}
+
BOOST_AUTO_TEST_SUITE(script_tests)
+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" ]
+ // ... where scriptSig and scriptPubKey are stringified
+ // scripts.
+ Array tests = read_json("script_valid.json");
+
+ BOOST_FOREACH(Value& tv, tests)
+ {
+ Array test = tv.get_array();
+ string strTest = write_string(tv, false);
+ if (test.size() < 2) // Allow size > 2; extra stuff ignored (useful for comments)
+ {
+ BOOST_ERROR("Bad test: " << strTest);
+ continue;
+ }
+ string scriptSigString = test[0].get_str();
+ CScript scriptSig = ParseScript(scriptSigString);
+ string scriptPubKeyString = test[1].get_str();
+ CScript scriptPubKey = ParseScript(scriptPubKeyString);
+
+ CTransaction tx;
+ BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, tx, 0, true, SIGHASH_NONE), strTest);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(script_invalid)
+{
+ // Scripts that should evaluate as invalid
+ Array tests = read_json("script_invalid.json");
+
+ BOOST_FOREACH(Value& tv, tests)
+ {
+ Array test = tv.get_array();
+ string strTest = write_string(tv, false);
+ if (test.size() < 2) // Allow size > 2; extra stuff ignored (useful for comments)
+ {
+ BOOST_ERROR("Bad test: " << strTest);
+ continue;
+ }
+ string scriptSigString = test[0].get_str();
+ CScript scriptSig = ParseScript(scriptSigString);
+ string scriptPubKeyString = test[1].get_str();
+ CScript scriptPubKey = ParseScript(scriptPubKeyString);
+
+ CTransaction tx;
+ BOOST_CHECK_MESSAGE(!VerifyScript(scriptSig, scriptPubKey, tx, 0, true, SIGHASH_NONE), strTest);
+ }
+}
+
BOOST_AUTO_TEST_CASE(script_PushData)
{
// Check that PUSHDATA1, PUSHDATA2, and PUSHDATA4 create the same value on
@@ -169,5 +328,118 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, txTo23, 0, true, 0));
}
+BOOST_AUTO_TEST_CASE(script_combineSigs)
+{
+ // Test the CombineSignatures function
+ CBasicKeyStore keystore;
+ vector<CKey> keys;
+ for (int i = 0; i < 3; i++)
+ {
+ CKey key;
+ key.MakeNewKey(i%2 == 1);
+ keys.push_back(key);
+ keystore.AddKey(key);
+ }
+
+ CTransaction txFrom;
+ txFrom.vout.resize(1);
+ txFrom.vout[0].scriptPubKey.SetDestination(keys[0].GetPubKey().GetID());
+ CScript& scriptPubKey = txFrom.vout[0].scriptPubKey;
+ CTransaction txTo;
+ txTo.vin.resize(1);
+ txTo.vout.resize(1);
+ txTo.vin[0].prevout.n = 0;
+ txTo.vin[0].prevout.hash = txFrom.GetHash();
+ CScript& scriptSig = txTo.vin[0].scriptSig;
+ txTo.vout[0].nValue = 1;
+
+ CScript empty;
+ CScript combined = CombineSignatures(scriptPubKey, txTo, 0, empty, empty);
+ BOOST_CHECK(combined.empty());
+
+ // Single signature case:
+ SignSignature(keystore, txFrom, txTo, 0); // changes scriptSig
+ combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty);
+ BOOST_CHECK(combined == scriptSig);
+ combined = CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig);
+ BOOST_CHECK(combined == scriptSig);
+ CScript scriptSigCopy = scriptSig;
+ // Signing again will give a different, valid signature:
+ SignSignature(keystore, txFrom, txTo, 0);
+ combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig);
+ BOOST_CHECK(combined == scriptSigCopy || combined == scriptSig);
+
+ // P2SH, single-signature case:
+ CScript pkSingle; pkSingle << keys[0].GetPubKey() << OP_CHECKSIG;
+ keystore.AddCScript(pkSingle);
+ scriptPubKey.SetDestination(pkSingle.GetID());
+ SignSignature(keystore, txFrom, txTo, 0);
+ combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty);
+ BOOST_CHECK(combined == scriptSig);
+ combined = CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig);
+ BOOST_CHECK(combined == scriptSig);
+ scriptSigCopy = scriptSig;
+ SignSignature(keystore, txFrom, txTo, 0);
+ combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig);
+ BOOST_CHECK(combined == scriptSigCopy || combined == scriptSig);
+ // dummy scriptSigCopy with placeholder, should always choose non-placeholder:
+ scriptSigCopy = CScript() << OP_0 << static_cast<vector<unsigned char> >(pkSingle);
+ combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSigCopy, scriptSig);
+ BOOST_CHECK(combined == scriptSig);
+ combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, scriptSigCopy);
+ BOOST_CHECK(combined == scriptSig);
+
+ // Hardest case: Multisig 2-of-3
+ scriptPubKey.SetMultisig(2, keys);
+ keystore.AddCScript(scriptPubKey);
+ SignSignature(keystore, txFrom, txTo, 0);
+ combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty);
+ BOOST_CHECK(combined == scriptSig);
+ combined = CombineSignatures(scriptPubKey, txTo, 0, empty, scriptSig);
+ BOOST_CHECK(combined == scriptSig);
+
+ // A couple of partially-signed versions:
+ vector<unsigned char> sig1;
+ uint256 hash1 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_ALL);
+ BOOST_CHECK(keys[0].Sign(hash1, sig1));
+ sig1.push_back(SIGHASH_ALL);
+ vector<unsigned char> sig2;
+ uint256 hash2 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_NONE);
+ BOOST_CHECK(keys[1].Sign(hash2, sig2));
+ sig2.push_back(SIGHASH_NONE);
+ vector<unsigned char> sig3;
+ uint256 hash3 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_SINGLE);
+ BOOST_CHECK(keys[2].Sign(hash3, sig3));
+ sig3.push_back(SIGHASH_SINGLE);
+
+ // Not fussy about order (or even existence) of placeholders or signatures:
+ CScript partial1a = CScript() << OP_0 << sig1 << OP_0;
+ CScript partial1b = CScript() << OP_0 << OP_0 << sig1;
+ CScript partial2a = CScript() << OP_0 << sig2;
+ CScript partial2b = CScript() << sig2 << OP_0;
+ CScript partial3a = CScript() << sig3;
+ CScript partial3b = CScript() << OP_0 << OP_0 << sig3;
+ CScript partial3c = CScript() << OP_0 << sig3 << OP_0;
+ CScript complete12 = CScript() << OP_0 << sig1 << sig2;
+ CScript complete13 = CScript() << OP_0 << sig1 << sig3;
+ CScript complete23 = CScript() << OP_0 << sig2 << sig3;
+
+ combined = CombineSignatures(scriptPubKey, txTo, 0, partial1a, partial1b);
+ BOOST_CHECK(combined == partial1a);
+ combined = CombineSignatures(scriptPubKey, txTo, 0, partial1a, partial2a);
+ BOOST_CHECK(combined == complete12);
+ combined = CombineSignatures(scriptPubKey, txTo, 0, partial2a, partial1a);
+ BOOST_CHECK(combined == complete12);
+ combined = CombineSignatures(scriptPubKey, txTo, 0, partial1b, partial2b);
+ BOOST_CHECK(combined == complete12);
+ combined = CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial1b);
+ BOOST_CHECK(combined == complete13);
+ combined = CombineSignatures(scriptPubKey, txTo, 0, partial2a, partial3a);
+ BOOST_CHECK(combined == complete23);
+ combined = CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial2b);
+ BOOST_CHECK(combined == complete23);
+ combined = CombineSignatures(scriptPubKey, txTo, 0, partial3b, partial3a);
+ BOOST_CHECK(combined == partial3c);
+}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp
index d301313a9..59673f9b3 100644
--- a/src/test/sigopcount_tests.cpp
+++ b/src/test/sigopcount_tests.cpp
@@ -32,7 +32,7 @@ BOOST_AUTO_TEST_CASE(GetSigOpCount)
BOOST_CHECK_EQUAL(s1.GetSigOpCount(false), 21);
CScript p2sh;
- p2sh.SetPayToScriptHash(s1);
+ p2sh.SetDestination(s1.GetID());
CScript scriptSig;
scriptSig << OP_0 << Serialize(s1);
BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(scriptSig), 3);
@@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE(GetSigOpCount)
BOOST_CHECK_EQUAL(s2.GetSigOpCount(true), 3);
BOOST_CHECK_EQUAL(s2.GetSigOpCount(false), 20);
- p2sh.SetPayToScriptHash(s2);
+ p2sh.SetDestination(s2.GetID());
BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(true), 0);
BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(false), 0);
CScript scriptSig2;
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index 7ff7545ab..96d63bff9 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -5,11 +5,15 @@
#include "wallet.h"
CWallet* pwalletMain;
+CClientUIInterface uiInterface;
extern bool fPrintToConsole;
+extern void noui_connect();
+
struct TestingSetup {
TestingSetup() {
fPrintToConsole = true; // don't want to write to debug.log file
+ noui_connect();
pwalletMain = new CWallet();
RegisterWallet(pwalletMain);
}
@@ -26,3 +30,9 @@ void Shutdown(void* parg)
{
exit(0);
}
+
+void StartShutdown()
+{
+ exit(0);
+}
+
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index 99163e55f..be0d976d5 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -12,7 +12,7 @@ BOOST_AUTO_TEST_CASE(basic_transaction_tests)
// Random real transaction (e2769b09e784f32f62ef849763d4f45b98e07ba658647343b915ff832b110436)
unsigned char ch[] = {0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, 0xff, 0x7f, 0xcd, 0x4f, 0x85, 0x65, 0xef, 0x40, 0x6d, 0xd5, 0xd6, 0x3d, 0x4f, 0xf9, 0x4f, 0x31, 0x8f, 0xe8, 0x20, 0x27, 0xfd, 0x4d, 0xc4, 0x51, 0xb0, 0x44, 0x74, 0x01, 0x9f, 0x74, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x49, 0x30, 0x46, 0x02, 0x21, 0x00, 0xda, 0x0d, 0xc6, 0xae, 0xce, 0xfe, 0x1e, 0x06, 0xef, 0xdf, 0x05, 0x77, 0x37, 0x57, 0xde, 0xb1, 0x68, 0x82, 0x09, 0x30, 0xe3, 0xb0, 0xd0, 0x3f, 0x46, 0xf5, 0xfc, 0xf1, 0x50, 0xbf, 0x99, 0x0c, 0x02, 0x21, 0x00, 0xd2, 0x5b, 0x5c, 0x87, 0x04, 0x00, 0x76, 0xe4, 0xf2, 0x53, 0xf8, 0x26, 0x2e, 0x76, 0x3e, 0x2d, 0xd5, 0x1e, 0x7f, 0xf0, 0xbe, 0x15, 0x77, 0x27, 0xc4, 0xbc, 0x42, 0x80, 0x7f, 0x17, 0xbd, 0x39, 0x01, 0x41, 0x04, 0xe6, 0xc2, 0x6e, 0xf6, 0x7d, 0xc6, 0x10, 0xd2, 0xcd, 0x19, 0x24, 0x84, 0x78, 0x9a, 0x6c, 0xf9, 0xae, 0xa9, 0x93, 0x0b, 0x94, 0x4b, 0x7e, 0x2d, 0xb5, 0x34, 0x2b, 0x9d, 0x9e, 0x5b, 0x9f, 0xf7, 0x9a, 0xff, 0x9a, 0x2e, 0xe1, 0x97, 0x8d, 0xd7, 0xfd, 0x01, 0xdf, 0xc5, 0x22, 0xee, 0x02, 0x28, 0x3d, 0x3b, 0x06, 0xa9, 0xd0, 0x3a, 0xcf, 0x80, 0x96, 0x96, 0x8d, 0x7d, 0xbb, 0x0f, 0x91, 0x78, 0xff, 0xff, 0xff, 0xff, 0x02, 0x8b, 0xa7, 0x94, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xba, 0xde, 0xec, 0xfd, 0xef, 0x05, 0x07, 0x24, 0x7f, 0xc8, 0xf7, 0x42, 0x41, 0xd7, 0x3b, 0xc0, 0x39, 0x97, 0x2d, 0x7b, 0x88, 0xac, 0x40, 0x94, 0xa8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xc1, 0x09, 0x32, 0x48, 0x3f, 0xec, 0x93, 0xed, 0x51, 0xf5, 0xfe, 0x95, 0xe7, 0x25, 0x59, 0xf2, 0xcc, 0x70, 0x43, 0xf9, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00};
vector<unsigned char> vch(ch, ch + sizeof(ch) -1);
- CDataStream stream(vch);
+ CDataStream stream(vch, SER_DISK, CLIENT_VERSION);
CTransaction tx;
stream >> tx;
BOOST_CHECK_MESSAGE(tx.CheckTransaction(), "Simple deserialized transaction should be valid.");
@@ -52,9 +52,9 @@ SetupDummyInputs(CBasicKeyStore& keystoreRet, MapPrevTx& inputsRet)
dummyTransactions[1].vout.resize(2);
dummyTransactions[1].vout[0].nValue = 21*CENT;
- dummyTransactions[1].vout[0].scriptPubKey.SetBitcoinAddress(key[2].GetPubKey());
+ dummyTransactions[1].vout[0].scriptPubKey.SetDestination(key[2].GetPubKey().GetID());
dummyTransactions[1].vout[1].nValue = 22*CENT;
- dummyTransactions[1].vout[1].scriptPubKey.SetBitcoinAddress(key[3].GetPubKey());
+ dummyTransactions[1].vout[1].scriptPubKey.SetDestination(key[3].GetPubKey().GetID());
inputsRet[dummyTransactions[1].GetHash()] = make_pair(CTxIndex(), dummyTransactions[1]);
return dummyTransactions;
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 94c0c77a4..2bfda6167 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -15,14 +15,15 @@ BOOST_AUTO_TEST_CASE(util_criticalsection)
CCriticalSection cs;
do {
- CRITICAL_BLOCK(cs)
- break;
+ LOCK(cs);
+ break;
BOOST_ERROR("break was swallowed!");
} while(0);
do {
- TRY_CRITICAL_BLOCK(cs)
+ TRY_LOCK(cs, lockTest);
+ if (lockTest)
break;
BOOST_ERROR("break was swallowed!");
@@ -87,13 +88,24 @@ BOOST_AUTO_TEST_CASE(util_HexStr)
BOOST_CHECK_EQUAL(
HexStr(ParseHex_expected, ParseHex_expected + 5, true),
"04 67 8a fd b0");
+
+ BOOST_CHECK_EQUAL(
+ HexStr(ParseHex_expected, ParseHex_expected, true),
+ "");
+
+ std::vector<unsigned char> ParseHex_vec(ParseHex_expected, ParseHex_expected + 5);
+
+ BOOST_CHECK_EQUAL(
+ HexStr(ParseHex_vec, true),
+ "04 67 8a fd b0");
}
+
BOOST_AUTO_TEST_CASE(util_DateTimeStrFormat)
{
BOOST_CHECK_EQUAL(DateTimeStrFormat("%x %H:%M:%S", 0), "01/01/70 00:00:00");
BOOST_CHECK_EQUAL(DateTimeStrFormat("%x %H:%M:%S", 0x7FFFFFFF), "01/19/38 03:14:07");
- // Formats used within bitcoin
+ // Formats used within Bitcoin
BOOST_CHECK_EQUAL(DateTimeStrFormat("%x %H:%M:%S", 1317425777), "09/30/11 23:36:17");
BOOST_CHECK_EQUAL(DateTimeStrFormat("%x %H:%M", 1317425777), "09/30/11 23:36");
}
diff --git a/src/test/wallet_tests.cpp b/src/test/wallet_tests.cpp
new file mode 100644
index 000000000..2f6da932a
--- /dev/null
+++ b/src/test/wallet_tests.cpp
@@ -0,0 +1,295 @@
+#include <boost/test/unit_test.hpp>
+
+#include "main.h"
+#include "wallet.h"
+
+// how many times to run all the tests to have a chance to catch errors that only show up with particular random shuffles
+#define RUN_TESTS 100
+
+// some tests fail 1% of the time due to bad luck.
+// we repeat those tests this many times and only complain if all iterations of the test fail
+#define RANDOM_REPEATS 5
+
+using namespace std;
+
+typedef set<pair<const CWalletTx*,unsigned int> > CoinSet;
+
+BOOST_AUTO_TEST_SUITE(wallet_tests)
+
+static CWallet wallet;
+static vector<COutput> vCoins;
+
+static void add_coin(int64 nValue, int nAge = 6*24, bool fIsFromMe = false, int nInput=0)
+{
+ static int i;
+ CTransaction* tx = new CTransaction;
+ tx->nLockTime = i++; // so all transactions get different hashes
+ tx->vout.resize(nInput+1);
+ tx->vout[nInput].nValue = nValue;
+ CWalletTx* wtx = new CWalletTx(&wallet, *tx);
+ delete tx;
+ if (fIsFromMe)
+ {
+ // IsFromMe() returns (GetDebit() > 0), and GetDebit() is 0 if vin.empty(),
+ // so stop vin being empty, and cache a non-zero Debit to fake out IsFromMe()
+ wtx->vin.resize(1);
+ wtx->fDebitCached = true;
+ wtx->nDebitCached = 1;
+ }
+ COutput output(wtx, nInput, nAge);
+ vCoins.push_back(output);
+}
+
+static void empty_wallet(void)
+{
+ BOOST_FOREACH(COutput output, vCoins)
+ delete output.tx;
+ vCoins.clear();
+}
+
+static bool equal_sets(CoinSet a, CoinSet b)
+{
+ pair<CoinSet::iterator, CoinSet::iterator> ret = mismatch(a.begin(), a.end(), b.begin());
+ return ret.first == a.end() && ret.second == b.end();
+}
+
+BOOST_AUTO_TEST_CASE(coin_selection_tests)
+{
+ static CoinSet setCoinsRet, setCoinsRet2;
+ static int64 nValueRet;
+
+ // test multiple times to allow for differences in the shuffle order
+ for (int i = 0; i < RUN_TESTS; i++)
+ {
+ empty_wallet();
+
+ // with an empty wallet we can't even pay one cent
+ BOOST_CHECK(!wallet.SelectCoinsMinConf( 1 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet));
+
+ add_coin(1*CENT, 4); // add a new 1 cent coin
+
+ // with a new 1 cent coin, we still can't find a mature 1 cent
+ BOOST_CHECK(!wallet.SelectCoinsMinConf( 1 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet));
+
+ // but we can find a new 1 cent
+ BOOST_CHECK( wallet.SelectCoinsMinConf( 1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 1 * CENT);
+
+ add_coin(2*CENT); // add a mature 2 cent coin
+
+ // we can't make 3 cents of mature coins
+ BOOST_CHECK(!wallet.SelectCoinsMinConf( 3 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet));
+
+ // we can make 3 cents of new coins
+ BOOST_CHECK( wallet.SelectCoinsMinConf( 3 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 3 * CENT);
+
+ add_coin(5*CENT); // add a mature 5 cent coin,
+ add_coin(10*CENT, 3, true); // a new 10 cent coin sent from one of our own addresses
+ add_coin(20*CENT); // and a mature 20 cent coin
+
+ // now we have new: 1+10=11 (of which 10 was self-sent), and mature: 2+5+20=27. total = 38
+
+ // we can't make 38 cents only if we disallow new coins:
+ BOOST_CHECK(!wallet.SelectCoinsMinConf(38 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet));
+ // we can't even make 37 cents if we don't allow new coins even if they're from us
+ BOOST_CHECK(!wallet.SelectCoinsMinConf(38 * CENT, 6, 6, vCoins, setCoinsRet, nValueRet));
+ // but we can make 37 cents if we accept new coins from ourself
+ BOOST_CHECK( wallet.SelectCoinsMinConf(37 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 37 * CENT);
+ // and we can make 38 cents if we accept all new coins
+ BOOST_CHECK( wallet.SelectCoinsMinConf(38 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 38 * CENT);
+
+ // try making 34 cents from 1,2,5,10,20 - we can't do it exactly
+ BOOST_CHECK( wallet.SelectCoinsMinConf(34 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_GT(nValueRet, 34 * CENT); // but should get more than 34 cents
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 3); // the best should be 20+10+5. it's incredibly unlikely the 1 or 2 got included (but possible)
+
+ // when we try making 7 cents, the smaller coins (1,2,5) are enough. We should see just 2+5
+ BOOST_CHECK( wallet.SelectCoinsMinConf( 7 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 7 * CENT);
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 2);
+
+ // when we try making 8 cents, the smaller coins (1,2,5) are exactly enough.
+ BOOST_CHECK( wallet.SelectCoinsMinConf( 8 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK(nValueRet == 8 * CENT);
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 3);
+
+ // when we try making 9 cents, no subset of smaller coins is enough, and we get the next bigger coin (10)
+ BOOST_CHECK( wallet.SelectCoinsMinConf( 9 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 10 * CENT);
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 1);
+
+ // now clear out the wallet and start again to test choosing between subsets of smaller coins and the next biggest coin
+ empty_wallet();
+
+ add_coin( 6*CENT);
+ add_coin( 7*CENT);
+ add_coin( 8*CENT);
+ add_coin(20*CENT);
+ add_coin(30*CENT); // now we have 6+7+8+20+30 = 71 cents total
+
+ // check that we have 71 and not 72
+ BOOST_CHECK( wallet.SelectCoinsMinConf(71 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK(!wallet.SelectCoinsMinConf(72 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
+
+ // now try making 16 cents. the best smaller coins can do is 6+7+8 = 21; not as good at the next biggest coin, 20
+ BOOST_CHECK( wallet.SelectCoinsMinConf(16 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 20 * CENT); // we should get 20 in one coin
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 1);
+
+ add_coin( 5*CENT); // now we have 5+6+7+8+20+30 = 75 cents total
+
+ // now if we try making 16 cents again, the smaller coins can make 5+6+7 = 18 cents, better than the next biggest coin, 20
+ BOOST_CHECK( wallet.SelectCoinsMinConf(16 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 18 * CENT); // we should get 18 in 3 coins
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 3);
+
+ add_coin( 18*CENT); // now we have 5+6+7+8+18+20+30
+
+ // and now if we try making 16 cents again, the smaller coins can make 5+6+7 = 18 cents, the same as the next biggest coin, 18
+ BOOST_CHECK( wallet.SelectCoinsMinConf(16 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 18 * CENT); // we should get 18 in 1 coin
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 1); // because in the event of a tie, the biggest coin wins
+
+ // now try making 11 cents. we should get 5+6
+ BOOST_CHECK( wallet.SelectCoinsMinConf(11 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 11 * CENT);
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 2);
+
+ // check that the smallest bigger coin is used
+ add_coin( 1*COIN);
+ add_coin( 2*COIN);
+ add_coin( 3*COIN);
+ add_coin( 4*COIN); // now we have 5+6+7+8+18+20+30+100+200+300+400 = 1094 cents
+ BOOST_CHECK( wallet.SelectCoinsMinConf(95 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 1 * COIN); // we should get 1 bitcoin in 1 coin
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 1);
+
+ BOOST_CHECK( wallet.SelectCoinsMinConf(195 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 2 * COIN); // we should get 2 bitcoins in 1 coin
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 1);
+
+ // empty the wallet and start again, now with fractions of a cent, to test sub-cent change avoidance
+ empty_wallet();
+ add_coin(0.1*CENT);
+ add_coin(0.2*CENT);
+ add_coin(0.3*CENT);
+ add_coin(0.4*CENT);
+ add_coin(0.5*CENT);
+
+ // try making 1 cent from 0.1 + 0.2 + 0.3 + 0.4 + 0.5 = 1.5 cents
+ // we'll get sub-cent change whatever happens, so can expect 1.0 exactly
+ BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 1 * CENT);
+
+ // but if we add a bigger coin, making it possible to avoid sub-cent change, things change:
+ add_coin(1111*CENT);
+
+ // try making 1 cent from 0.1 + 0.2 + 0.3 + 0.4 + 0.5 + 1111 = 1112.5 cents
+ BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); // we should get the exact amount
+
+ // if we add more sub-cent coins:
+ add_coin(0.6*CENT);
+ add_coin(0.7*CENT);
+
+ // and try again to make 1.0 cents, we can still make 1.0 cents
+ BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); // we should get the exact amount
+
+ // run the 'mtgox' test (see http://blockexplorer.com/tx/29a3efd3ef04f9153d47a990bd7b048a4b2d213daaa5fb8ed670fb85f13bdbcf)
+ // they tried to consolidate 10 50k coins into one 500k coin, and ended up with 50k in change
+ empty_wallet();
+ for (int i = 0; i < 20; i++)
+ add_coin(50000 * COIN);
+
+ BOOST_CHECK( wallet.SelectCoinsMinConf(500000 * COIN, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 500000 * COIN); // we should get the exact amount
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 10); // in ten coins
+
+ // if there's not enough in the smaller coins to make at least 1 cent change (0.5+0.6+0.7 < 1.0+1.0),
+ // we need to try finding an exact subset anyway
+
+ // sometimes it will fail, and so we use the next biggest coin:
+ empty_wallet();
+ add_coin(0.5 * CENT);
+ add_coin(0.6 * CENT);
+ add_coin(0.7 * CENT);
+ add_coin(1111 * CENT);
+ BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 1111 * CENT); // we get the bigger coin
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 1);
+
+ // but sometimes it's possible, and we use an exact subset (0.4 + 0.6 = 1.0)
+ empty_wallet();
+ add_coin(0.4 * CENT);
+ add_coin(0.6 * CENT);
+ add_coin(0.8 * CENT);
+ add_coin(1111 * CENT);
+ BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); // we should get the exact amount
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 2); // in two coins 0.4+0.6
+
+ // test avoiding sub-cent change
+ empty_wallet();
+ add_coin(0.0005 * COIN);
+ add_coin(0.01 * COIN);
+ add_coin(1 * COIN);
+
+ // trying to make 1.0001 from these three coins
+ BOOST_CHECK( wallet.SelectCoinsMinConf(1.0001 * COIN, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 1.0105 * COIN); // we should get all coins
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 3);
+
+ // but if we try to make 0.999, we should take the bigger of the two small coins to avoid sub-cent change
+ BOOST_CHECK( wallet.SelectCoinsMinConf(0.999 * COIN, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 1.01 * COIN); // we should get 1 + 0.01
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 2);
+
+ // test randomness
+ {
+ empty_wallet();
+ for (int i2 = 0; i2 < 100; i2++)
+ add_coin(COIN);
+
+ // picking 50 from 100 coins doesn't depend on the shuffle,
+ // but does depend on randomness in the stochastic approximation code
+ BOOST_CHECK(wallet.SelectCoinsMinConf(50 * COIN, 1, 6, vCoins, setCoinsRet , nValueRet));
+ BOOST_CHECK(wallet.SelectCoinsMinConf(50 * COIN, 1, 6, vCoins, setCoinsRet2, nValueRet));
+ BOOST_CHECK(!equal_sets(setCoinsRet, setCoinsRet2));
+
+ int fails = 0;
+ for (int i = 0; i < RANDOM_REPEATS; i++)
+ {
+ // selecting 1 from 100 identical coins depends on the shuffle; this test will fail 1% of the time
+ // run the test RANDOM_REPEATS times and only complain if all of them fail
+ BOOST_CHECK(wallet.SelectCoinsMinConf(COIN, 1, 6, vCoins, setCoinsRet , nValueRet));
+ BOOST_CHECK(wallet.SelectCoinsMinConf(COIN, 1, 6, vCoins, setCoinsRet2, nValueRet));
+ if (equal_sets(setCoinsRet, setCoinsRet2))
+ fails++;
+ }
+ BOOST_CHECK_NE(fails, RANDOM_REPEATS);
+
+ // add 75 cents in small change. not enough to make 90 cents,
+ // then try making 90 cents. there are multiple competing "smallest bigger" coins,
+ // one of which should be picked at random
+ add_coin( 5*CENT); add_coin(10*CENT); add_coin(15*CENT); add_coin(20*CENT); add_coin(25*CENT);
+
+ fails = 0;
+ for (int i = 0; i < RANDOM_REPEATS; i++)
+ {
+ // selecting 1 from 100 identical coins depends on the shuffle; this test will fail 1% of the time
+ // run the test RANDOM_REPEATS times and only complain if all of them fail
+ BOOST_CHECK(wallet.SelectCoinsMinConf(90*CENT, 1, 6, vCoins, setCoinsRet , nValueRet));
+ BOOST_CHECK(wallet.SelectCoinsMinConf(90*CENT, 1, 6, vCoins, setCoinsRet2, nValueRet));
+ if (equal_sets(setCoinsRet, setCoinsRet2))
+ fails++;
+ }
+ BOOST_CHECK_NE(fails, RANDOM_REPEATS);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()