aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/Makefile6
-rw-r--r--src/test/README.md55
-rw-r--r--src/test/addrman_tests.cpp690
-rw-r--r--src/test/allocator_tests.cpp236
-rw-r--r--src/test/amount_tests.cpp108
-rw-r--r--src/test/arith_uint256_tests.cpp560
-rw-r--r--src/test/base32_tests.cpp25
-rw-r--r--src/test/base58_tests.cpp69
-rw-r--r--src/test/base64_tests.cpp25
-rw-r--r--src/test/bech32_tests.cpp69
-rw-r--r--src/test/bip32_tests.cpp154
-rw-r--r--src/test/blockchain_tests.cpp78
-rw-r--r--src/test/blockencodings_tests.cpp347
-rw-r--r--src/test/bloom_tests.cpp536
-rw-r--r--src/test/bswap_tests.cpp26
-rw-r--r--src/test/checkqueue_tests.cpp445
-rw-r--r--src/test/coins_tests.cpp858
-rw-r--r--src/test/compress_tests.cpp65
-rw-r--r--src/test/crypto_tests.cpp565
-rw-r--r--src/test/cuckoocache_tests.cpp380
-rw-r--r--src/test/data/README.md12
-rw-r--r--src/test/data/base58_encode_decode.json16
-rw-r--r--src/test/data/key_io_invalid.json182
-rw-r--r--src/test/data/key_io_valid.json533
-rw-r--r--src/test/data/script_tests.json2619
-rw-r--r--src/test/data/sighash.json503
-rw-r--r--src/test/data/tx_invalid.json392
-rw-r--r--src/test/data/tx_valid.json524
-rw-r--r--src/test/dbwrapper_tests.cpp322
-rw-r--r--src/test/denialofservice_tests.cpp415
-rw-r--r--src/test/descriptor_tests.cpp163
-rw-r--r--src/test/getarg_tests.cpp175
-rw-r--r--src/test/hash_tests.cpp150
-rw-r--r--src/test/key_io_tests.cpp149
-rw-r--r--src/test/key_tests.cpp155
-rw-r--r--src/test/limitedmap_tests.cpp101
-rw-r--r--src/test/main_tests.cpp77
-rw-r--r--src/test/mempool_tests.cpp752
-rw-r--r--src/test/merkle_tests.cpp252
-rw-r--r--src/test/merkleblock_tests.cpp78
-rw-r--r--src/test/miner_tests.cpp524
-rw-r--r--src/test/multisig_tests.cpp217
-rw-r--r--src/test/net_tests.cpp192
-rw-r--r--src/test/netbase_tests.cpp305
-rw-r--r--src/test/pmt_tests.cpp126
-rw-r--r--src/test/policyestimator_tests.cpp183
-rw-r--r--src/test/pow_tests.cpp86
-rw-r--r--src/test/prevector_tests.cpp267
-rw-r--r--src/test/raii_event_tests.cpp94
-rw-r--r--src/test/random_tests.cpp82
-rw-r--r--src/test/reverselock_tests.cpp60
-rw-r--r--src/test/rpc_tests.cpp339
-rw-r--r--src/test/sanity_tests.cpp20
-rw-r--r--src/test/scheduler_tests.cpp157
-rw-r--r--src/test/script_p2sh_tests.cpp369
-rw-r--r--src/test/script_standard_tests.cpp746
-rw-r--r--src/test/script_tests.cpp1640
-rw-r--r--src/test/scriptnum10.h183
-rw-r--r--src/test/scriptnum_tests.cpp200
-rw-r--r--src/test/serialize_tests.cpp373
-rw-r--r--src/test/sighash_tests.cpp211
-rw-r--r--src/test/sigopcount_tests.cpp232
-rw-r--r--src/test/skiplist_tests.cpp180
-rw-r--r--src/test/streams_tests.cpp126
-rw-r--r--src/test/test_bitcoin.cpp199
-rw-r--r--src/test/test_bitcoin.h130
-rw-r--r--src/test/test_bitcoin_fuzzy.cpp329
-rw-r--r--src/test/test_bitcoin_main.cpp28
-rw-r--r--src/test/timedata_tests.cpp37
-rw-r--r--src/test/torcontrol_tests.cpp207
-rw-r--r--src/test/transaction_tests.cpp771
-rw-r--r--src/test/txindex_tests.cpp66
-rw-r--r--src/test/txvalidation_tests.cpp61
-rw-r--r--src/test/txvalidationcache_tests.cpp371
-rw-r--r--src/test/uint256_tests.cpp282
-rw-r--r--src/test/util_tests.cpp1220
-rw-r--r--src/test/validation_block_tests.cpp184
-rw-r--r--src/test/versionbits_tests.cpp354
78 files changed, 24018 insertions, 0 deletions
diff --git a/src/test/Makefile b/src/test/Makefile
new file mode 100644
index 0000000000..87bf73fec9
--- /dev/null
+++ b/src/test/Makefile
@@ -0,0 +1,6 @@
+all:
+ $(MAKE) -C .. bitcoin_test
+clean:
+ $(MAKE) -C .. bitcoin_test_clean
+check:
+ $(MAKE) -C .. bitcoin_test_check
diff --git a/src/test/README.md b/src/test/README.md
new file mode 100644
index 0000000000..f2a4cb1818
--- /dev/null
+++ b/src/test/README.md
@@ -0,0 +1,55 @@
+### Compiling/running unit tests
+
+Unit tests will be automatically compiled if dependencies were met in `./configure`
+and tests weren't explicitly disabled.
+
+After configuring, they can be run with `make check`.
+
+To run the bitcoind tests manually, launch `src/test/test_bitcoin`. To recompile
+after a test file was modified, run `make` and then run the test again. If you
+modify a non-test file, use `make -C src/test` to recompile only what's needed
+to run the bitcoind tests.
+
+To add more bitcoind tests, add `BOOST_AUTO_TEST_CASE` functions to the existing
+.cpp files in the `test/` directory or add new .cpp files that
+implement new BOOST_AUTO_TEST_SUITE sections.
+
+To run the bitcoin-qt tests manually, launch `src/qt/test/test_bitcoin-qt`
+
+To add more bitcoin-qt tests, add them to the `src/qt/test/` directory and
+the `src/qt/test/test_main.cpp` file.
+
+### Running individual tests
+
+test_bitcoin has some built-in command-line arguments; for
+example, to run just the getarg_tests verbosely:
+
+ test_bitcoin --log_level=all --run_test=getarg_tests
+
+... or to run just the doubledash test:
+
+ test_bitcoin --run_test=getarg_tests/doubledash
+
+Run `test_bitcoin --help` for the full list.
+
+### Note on adding test cases
+
+The sources in this directory are unit test cases. Boost includes a
+unit testing framework, and since bitcoin already uses boost, it makes
+sense to simply use this framework rather than require developers to
+configure some other framework (we want as few impediments to creating
+unit tests as possible).
+
+The build system is setup to compile an executable called `test_bitcoin`
+that runs all of the unit tests. The main source file is called
+test_bitcoin.cpp. To add a new unit test file to our test suite you need
+to add the file to `src/Makefile.test.include`. The pattern is to create
+one test file for each class or source file for which you want to create
+unit tests. The file naming convention is `<source_filename>_tests.cpp`
+and such files should wrap their tests in a test suite
+called `<source_filename>_tests`. For an example of this pattern,
+examine `uint256_tests.cpp`.
+
+For further reading, I found the following website to be helpful in
+explaining how the boost unit test framework works:
+[http://www.alittlemadness.com/2009/03/31/c-unit-testing-with-boosttest/](http://archive.is/dRBGf).
diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp
new file mode 100644
index 0000000000..f57d0c6d79
--- /dev/null
+++ b/src/test/addrman_tests.cpp
@@ -0,0 +1,690 @@
+// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <addrman.h>
+#include <test/test_bitcoin.h>
+#include <string>
+#include <boost/test/unit_test.hpp>
+
+#include <hash.h>
+#include <netbase.h>
+#include <random.h>
+
+class CAddrManTest : public CAddrMan
+{
+ uint64_t state;
+
+public:
+ explicit CAddrManTest(bool makeDeterministic = true)
+ {
+ state = 1;
+
+ if (makeDeterministic) {
+ // Set addrman addr placement to be deterministic.
+ MakeDeterministic();
+ }
+ }
+
+ //! Ensure that bucket placement is always the same for testing purposes.
+ void MakeDeterministic()
+ {
+ nKey.SetNull();
+ insecure_rand = FastRandomContext(true);
+ }
+
+ int RandomInt(int nMax) override
+ {
+ state = (CHashWriter(SER_GETHASH, 0) << state).GetHash().GetCheapHash();
+ return (unsigned int)(state % nMax);
+ }
+
+ CAddrInfo* Find(const CNetAddr& addr, int* pnId = nullptr)
+ {
+ return CAddrMan::Find(addr, pnId);
+ }
+
+ CAddrInfo* Create(const CAddress& addr, const CNetAddr& addrSource, int* pnId = nullptr)
+ {
+ return CAddrMan::Create(addr, addrSource, pnId);
+ }
+
+ void Delete(int nId)
+ {
+ CAddrMan::Delete(nId);
+ }
+
+ // Simulates connection failure so that we can test eviction of offline nodes
+ void SimConnFail(CService& addr)
+ {
+ int64_t nLastSuccess = 1;
+ Good_(addr, true, nLastSuccess); // Set last good connection in the deep past.
+
+ bool count_failure = false;
+ int64_t nLastTry = GetAdjustedTime()-61;
+ Attempt(addr, count_failure, nLastTry);
+ }
+};
+
+static CNetAddr ResolveIP(const char* ip)
+{
+ CNetAddr addr;
+ BOOST_CHECK_MESSAGE(LookupHost(ip, addr, false), strprintf("failed to resolve: %s", ip));
+ return addr;
+}
+
+static CNetAddr ResolveIP(std::string ip)
+{
+ return ResolveIP(ip.c_str());
+}
+
+static CService ResolveService(const char* ip, int port = 0)
+{
+ CService serv;
+ BOOST_CHECK_MESSAGE(Lookup(ip, serv, port, false), strprintf("failed to resolve: %s:%i", ip, port));
+ return serv;
+}
+
+static CService ResolveService(std::string ip, int port = 0)
+{
+ return ResolveService(ip.c_str(), port);
+}
+
+BOOST_FIXTURE_TEST_SUITE(addrman_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(addrman_simple)
+{
+ CAddrManTest addrman;
+
+ CNetAddr source = ResolveIP("252.2.2.2");
+
+ // Test: Does Addrman respond correctly when empty.
+ BOOST_CHECK_EQUAL(addrman.size(), 0U);
+ CAddrInfo addr_null = addrman.Select();
+ BOOST_CHECK_EQUAL(addr_null.ToString(), "[::]:0");
+
+ // Test: Does Addrman::Add work as expected.
+ CService addr1 = ResolveService("250.1.1.1", 8333);
+ BOOST_CHECK(addrman.Add(CAddress(addr1, NODE_NONE), source));
+ BOOST_CHECK_EQUAL(addrman.size(), 1U);
+ CAddrInfo addr_ret1 = addrman.Select();
+ BOOST_CHECK_EQUAL(addr_ret1.ToString(), "250.1.1.1:8333");
+
+ // Test: Does IP address deduplication work correctly.
+ // Expected dup IP should not be added.
+ CService addr1_dup = ResolveService("250.1.1.1", 8333);
+ BOOST_CHECK(!addrman.Add(CAddress(addr1_dup, NODE_NONE), source));
+ BOOST_CHECK_EQUAL(addrman.size(), 1U);
+
+
+ // Test: New table has one addr and we add a diff addr we should
+ // have at least one addr.
+ // Note that addrman's size cannot be tested reliably after insertion, as
+ // hash collisions may occur. But we can always be sure of at least one
+ // success.
+
+ CService addr2 = ResolveService("250.1.1.2", 8333);
+ BOOST_CHECK(addrman.Add(CAddress(addr2, NODE_NONE), source));
+ BOOST_CHECK(addrman.size() >= 1);
+
+ // Test: AddrMan::Clear() should empty the new table.
+ addrman.Clear();
+ BOOST_CHECK_EQUAL(addrman.size(), 0U);
+ CAddrInfo addr_null2 = addrman.Select();
+ BOOST_CHECK_EQUAL(addr_null2.ToString(), "[::]:0");
+
+ // Test: AddrMan::Add multiple addresses works as expected
+ std::vector<CAddress> vAddr;
+ vAddr.push_back(CAddress(ResolveService("250.1.1.3", 8333), NODE_NONE));
+ vAddr.push_back(CAddress(ResolveService("250.1.1.4", 8333), NODE_NONE));
+ BOOST_CHECK(addrman.Add(vAddr, source));
+ BOOST_CHECK(addrman.size() >= 1);
+}
+
+BOOST_AUTO_TEST_CASE(addrman_ports)
+{
+ CAddrManTest addrman;
+
+ CNetAddr source = ResolveIP("252.2.2.2");
+
+ BOOST_CHECK_EQUAL(addrman.size(), 0U);
+
+ // Test 7; Addr with same IP but diff port does not replace existing addr.
+ CService addr1 = ResolveService("250.1.1.1", 8333);
+ addrman.Add(CAddress(addr1, NODE_NONE), source);
+ BOOST_CHECK_EQUAL(addrman.size(), 1U);
+
+ CService addr1_port = ResolveService("250.1.1.1", 8334);
+ addrman.Add(CAddress(addr1_port, NODE_NONE), source);
+ BOOST_CHECK_EQUAL(addrman.size(), 1U);
+ CAddrInfo addr_ret2 = addrman.Select();
+ BOOST_CHECK_EQUAL(addr_ret2.ToString(), "250.1.1.1:8333");
+
+ // Test: Add same IP but diff port to tried table, it doesn't get added.
+ // Perhaps this is not ideal behavior but it is the current behavior.
+ addrman.Good(CAddress(addr1_port, NODE_NONE));
+ BOOST_CHECK_EQUAL(addrman.size(), 1U);
+ bool newOnly = true;
+ CAddrInfo addr_ret3 = addrman.Select(newOnly);
+ BOOST_CHECK_EQUAL(addr_ret3.ToString(), "250.1.1.1:8333");
+}
+
+
+BOOST_AUTO_TEST_CASE(addrman_select)
+{
+ CAddrManTest addrman;
+
+ CNetAddr source = ResolveIP("252.2.2.2");
+
+ // Test: Select from new with 1 addr in new.
+ CService addr1 = ResolveService("250.1.1.1", 8333);
+ addrman.Add(CAddress(addr1, NODE_NONE), source);
+ BOOST_CHECK_EQUAL(addrman.size(), 1U);
+
+ bool newOnly = true;
+ CAddrInfo addr_ret1 = addrman.Select(newOnly);
+ BOOST_CHECK_EQUAL(addr_ret1.ToString(), "250.1.1.1:8333");
+
+ // Test: move addr to tried, select from new expected nothing returned.
+ addrman.Good(CAddress(addr1, NODE_NONE));
+ BOOST_CHECK_EQUAL(addrman.size(), 1U);
+ CAddrInfo addr_ret2 = addrman.Select(newOnly);
+ BOOST_CHECK_EQUAL(addr_ret2.ToString(), "[::]:0");
+
+ CAddrInfo addr_ret3 = addrman.Select();
+ BOOST_CHECK_EQUAL(addr_ret3.ToString(), "250.1.1.1:8333");
+
+ BOOST_CHECK_EQUAL(addrman.size(), 1U);
+
+
+ // Add three addresses to new table.
+ CService addr2 = ResolveService("250.3.1.1", 8333);
+ CService addr3 = ResolveService("250.3.2.2", 9999);
+ CService addr4 = ResolveService("250.3.3.3", 9999);
+
+ addrman.Add(CAddress(addr2, NODE_NONE), ResolveService("250.3.1.1", 8333));
+ addrman.Add(CAddress(addr3, NODE_NONE), ResolveService("250.3.1.1", 8333));
+ addrman.Add(CAddress(addr4, NODE_NONE), ResolveService("250.4.1.1", 8333));
+
+ // Add three addresses to tried table.
+ CService addr5 = ResolveService("250.4.4.4", 8333);
+ CService addr6 = ResolveService("250.4.5.5", 7777);
+ CService addr7 = ResolveService("250.4.6.6", 8333);
+
+ addrman.Add(CAddress(addr5, NODE_NONE), ResolveService("250.3.1.1", 8333));
+ addrman.Good(CAddress(addr5, NODE_NONE));
+ addrman.Add(CAddress(addr6, NODE_NONE), ResolveService("250.3.1.1", 8333));
+ addrman.Good(CAddress(addr6, NODE_NONE));
+ addrman.Add(CAddress(addr7, NODE_NONE), ResolveService("250.1.1.3", 8333));
+ addrman.Good(CAddress(addr7, NODE_NONE));
+
+ // Test: 6 addrs + 1 addr from last test = 7.
+ BOOST_CHECK_EQUAL(addrman.size(), 7U);
+
+ // Test: Select pulls from new and tried regardless of port number.
+ std::set<uint16_t> ports;
+ for (int i = 0; i < 20; ++i) {
+ ports.insert(addrman.Select().GetPort());
+ }
+ BOOST_CHECK_EQUAL(ports.size(), 3U);
+}
+
+BOOST_AUTO_TEST_CASE(addrman_new_collisions)
+{
+ CAddrManTest addrman;
+
+ CNetAddr source = ResolveIP("252.2.2.2");
+
+ BOOST_CHECK_EQUAL(addrman.size(), 0U);
+
+ for (unsigned int i = 1; i < 18; i++) {
+ CService addr = ResolveService("250.1.1." + std::to_string(i));
+ addrman.Add(CAddress(addr, NODE_NONE), source);
+
+ //Test: No collision in new table yet.
+ BOOST_CHECK_EQUAL(addrman.size(), i);
+ }
+
+ //Test: new table collision!
+ CService addr1 = ResolveService("250.1.1.18");
+ addrman.Add(CAddress(addr1, NODE_NONE), source);
+ BOOST_CHECK_EQUAL(addrman.size(), 17U);
+
+ CService addr2 = ResolveService("250.1.1.19");
+ addrman.Add(CAddress(addr2, NODE_NONE), source);
+ BOOST_CHECK_EQUAL(addrman.size(), 18U);
+}
+
+BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
+{
+ CAddrManTest addrman;
+
+ CNetAddr source = ResolveIP("252.2.2.2");
+
+ BOOST_CHECK_EQUAL(addrman.size(), 0U);
+
+ for (unsigned int i = 1; i < 80; i++) {
+ CService addr = ResolveService("250.1.1." + std::to_string(i));
+ addrman.Add(CAddress(addr, NODE_NONE), source);
+ addrman.Good(CAddress(addr, NODE_NONE));
+
+ //Test: No collision in tried table yet.
+ BOOST_CHECK_EQUAL(addrman.size(), i);
+ }
+
+ //Test: tried table collision!
+ CService addr1 = ResolveService("250.1.1.80");
+ addrman.Add(CAddress(addr1, NODE_NONE), source);
+ BOOST_CHECK_EQUAL(addrman.size(), 79U);
+
+ CService addr2 = ResolveService("250.1.1.81");
+ addrman.Add(CAddress(addr2, NODE_NONE), source);
+ BOOST_CHECK_EQUAL(addrman.size(), 80U);
+}
+
+BOOST_AUTO_TEST_CASE(addrman_find)
+{
+ CAddrManTest addrman;
+
+ BOOST_CHECK_EQUAL(addrman.size(), 0U);
+
+ CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
+ CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE);
+ CAddress addr3 = CAddress(ResolveService("251.255.2.1", 8333), NODE_NONE);
+
+ CNetAddr source1 = ResolveIP("250.1.2.1");
+ CNetAddr source2 = ResolveIP("250.1.2.2");
+
+ addrman.Add(addr1, source1);
+ addrman.Add(addr2, source2);
+ addrman.Add(addr3, source1);
+
+ // Test: ensure Find returns an IP matching what we searched on.
+ CAddrInfo* info1 = addrman.Find(addr1);
+ BOOST_REQUIRE(info1);
+ BOOST_CHECK_EQUAL(info1->ToString(), "250.1.2.1:8333");
+
+ // Test 18; Find does not discriminate by port number.
+ CAddrInfo* info2 = addrman.Find(addr2);
+ BOOST_REQUIRE(info2);
+ BOOST_CHECK_EQUAL(info2->ToString(), info1->ToString());
+
+ // Test: Find returns another IP matching what we searched on.
+ CAddrInfo* info3 = addrman.Find(addr3);
+ BOOST_REQUIRE(info3);
+ BOOST_CHECK_EQUAL(info3->ToString(), "251.255.2.1:8333");
+}
+
+BOOST_AUTO_TEST_CASE(addrman_create)
+{
+ CAddrManTest addrman;
+
+ BOOST_CHECK_EQUAL(addrman.size(), 0U);
+
+ CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
+ CNetAddr source1 = ResolveIP("250.1.2.1");
+
+ int nId;
+ CAddrInfo* pinfo = addrman.Create(addr1, source1, &nId);
+
+ // Test: The result should be the same as the input addr.
+ BOOST_CHECK_EQUAL(pinfo->ToString(), "250.1.2.1:8333");
+
+ CAddrInfo* info2 = addrman.Find(addr1);
+ BOOST_CHECK_EQUAL(info2->ToString(), "250.1.2.1:8333");
+}
+
+
+BOOST_AUTO_TEST_CASE(addrman_delete)
+{
+ CAddrManTest addrman;
+
+ BOOST_CHECK_EQUAL(addrman.size(), 0U);
+
+ CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
+ CNetAddr source1 = ResolveIP("250.1.2.1");
+
+ int nId;
+ addrman.Create(addr1, source1, &nId);
+
+ // Test: Delete should actually delete the addr.
+ BOOST_CHECK_EQUAL(addrman.size(), 1U);
+ addrman.Delete(nId);
+ BOOST_CHECK_EQUAL(addrman.size(), 0U);
+ CAddrInfo* info2 = addrman.Find(addr1);
+ BOOST_CHECK(info2 == nullptr);
+}
+
+BOOST_AUTO_TEST_CASE(addrman_getaddr)
+{
+ CAddrManTest addrman;
+
+ // Test: Sanity check, GetAddr should never return anything if addrman
+ // is empty.
+ BOOST_CHECK_EQUAL(addrman.size(), 0U);
+ std::vector<CAddress> vAddr1 = addrman.GetAddr();
+ BOOST_CHECK_EQUAL(vAddr1.size(), 0U);
+
+ CAddress addr1 = CAddress(ResolveService("250.250.2.1", 8333), NODE_NONE);
+ addr1.nTime = GetAdjustedTime(); // Set time so isTerrible = false
+ CAddress addr2 = CAddress(ResolveService("250.251.2.2", 9999), NODE_NONE);
+ addr2.nTime = GetAdjustedTime();
+ CAddress addr3 = CAddress(ResolveService("251.252.2.3", 8333), NODE_NONE);
+ addr3.nTime = GetAdjustedTime();
+ CAddress addr4 = CAddress(ResolveService("252.253.3.4", 8333), NODE_NONE);
+ addr4.nTime = GetAdjustedTime();
+ CAddress addr5 = CAddress(ResolveService("252.254.4.5", 8333), NODE_NONE);
+ addr5.nTime = GetAdjustedTime();
+ CNetAddr source1 = ResolveIP("250.1.2.1");
+ CNetAddr source2 = ResolveIP("250.2.3.3");
+
+ // Test: Ensure GetAddr works with new addresses.
+ addrman.Add(addr1, source1);
+ addrman.Add(addr2, source2);
+ addrman.Add(addr3, source1);
+ addrman.Add(addr4, source2);
+ addrman.Add(addr5, source1);
+
+ // GetAddr returns 23% of addresses, 23% of 5 is 1 rounded down.
+ BOOST_CHECK_EQUAL(addrman.GetAddr().size(), 1U);
+
+ // Test: Ensure GetAddr works with new and tried addresses.
+ addrman.Good(CAddress(addr1, NODE_NONE));
+ addrman.Good(CAddress(addr2, NODE_NONE));
+ BOOST_CHECK_EQUAL(addrman.GetAddr().size(), 1U);
+
+ // Test: Ensure GetAddr still returns 23% when addrman has many addrs.
+ for (unsigned int i = 1; i < (8 * 256); i++) {
+ int octet1 = i % 256;
+ int octet2 = i >> 8 % 256;
+ std::string strAddr = std::to_string(octet1) + "." + std::to_string(octet2) + ".1.23";
+ CAddress addr = CAddress(ResolveService(strAddr), NODE_NONE);
+
+ // Ensure that for all addrs in addrman, isTerrible == false.
+ addr.nTime = GetAdjustedTime();
+ addrman.Add(addr, ResolveIP(strAddr));
+ if (i % 8 == 0)
+ addrman.Good(addr);
+ }
+ std::vector<CAddress> vAddr = addrman.GetAddr();
+
+ size_t percent23 = (addrman.size() * 23) / 100;
+ BOOST_CHECK_EQUAL(vAddr.size(), percent23);
+ BOOST_CHECK_EQUAL(vAddr.size(), 461U);
+ // (Addrman.size() < number of addresses added) due to address collisions.
+ BOOST_CHECK_EQUAL(addrman.size(), 2006U);
+}
+
+
+BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket)
+{
+ CAddrManTest addrman;
+
+ CAddress addr1 = CAddress(ResolveService("250.1.1.1", 8333), NODE_NONE);
+ CAddress addr2 = CAddress(ResolveService("250.1.1.1", 9999), NODE_NONE);
+
+ CNetAddr source1 = ResolveIP("250.1.1.1");
+
+
+ CAddrInfo info1 = CAddrInfo(addr1, source1);
+
+ uint256 nKey1 = (uint256)(CHashWriter(SER_GETHASH, 0) << 1).GetHash();
+ uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash();
+
+
+ BOOST_CHECK_EQUAL(info1.GetTriedBucket(nKey1), 40);
+
+ // Test: Make sure key actually randomizes bucket placement. A fail on
+ // this test could be a security issue.
+ BOOST_CHECK(info1.GetTriedBucket(nKey1) != info1.GetTriedBucket(nKey2));
+
+ // Test: Two addresses with same IP but different ports can map to
+ // different buckets because they have different keys.
+ CAddrInfo info2 = CAddrInfo(addr2, source1);
+
+ BOOST_CHECK(info1.GetKey() != info2.GetKey());
+ BOOST_CHECK(info1.GetTriedBucket(nKey1) != info2.GetTriedBucket(nKey1));
+
+ std::set<int> buckets;
+ for (int i = 0; i < 255; i++) {
+ CAddrInfo infoi = CAddrInfo(
+ CAddress(ResolveService("250.1.1." + std::to_string(i)), NODE_NONE),
+ ResolveIP("250.1.1." + std::to_string(i)));
+ int bucket = infoi.GetTriedBucket(nKey1);
+ buckets.insert(bucket);
+ }
+ // Test: IP addresses in the same group (\16 prefix for IPv4) should
+ // never get more than 8 buckets
+ BOOST_CHECK_EQUAL(buckets.size(), 8U);
+
+ buckets.clear();
+ for (int j = 0; j < 255; j++) {
+ CAddrInfo infoj = CAddrInfo(
+ CAddress(ResolveService("250." + std::to_string(j) + ".1.1"), NODE_NONE),
+ ResolveIP("250." + std::to_string(j) + ".1.1"));
+ int bucket = infoj.GetTriedBucket(nKey1);
+ buckets.insert(bucket);
+ }
+ // Test: IP addresses in the different groups should map to more than
+ // 8 buckets.
+ BOOST_CHECK_EQUAL(buckets.size(), 160U);
+}
+
+BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
+{
+ CAddrManTest addrman;
+
+ CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
+ CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE);
+
+ CNetAddr source1 = ResolveIP("250.1.2.1");
+
+ CAddrInfo info1 = CAddrInfo(addr1, source1);
+
+ uint256 nKey1 = (uint256)(CHashWriter(SER_GETHASH, 0) << 1).GetHash();
+ uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash();
+
+ // Test: Make sure the buckets are what we expect
+ BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1), 786);
+ BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, source1), 786);
+
+ // Test: Make sure key actually randomizes bucket placement. A fail on
+ // this test could be a security issue.
+ BOOST_CHECK(info1.GetNewBucket(nKey1) != info1.GetNewBucket(nKey2));
+
+ // Test: Ports should not affect bucket placement in the addr
+ CAddrInfo info2 = CAddrInfo(addr2, source1);
+ BOOST_CHECK(info1.GetKey() != info2.GetKey());
+ BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1), info2.GetNewBucket(nKey1));
+
+ std::set<int> buckets;
+ for (int i = 0; i < 255; i++) {
+ CAddrInfo infoi = CAddrInfo(
+ CAddress(ResolveService("250.1.1." + std::to_string(i)), NODE_NONE),
+ ResolveIP("250.1.1." + std::to_string(i)));
+ int bucket = infoi.GetNewBucket(nKey1);
+ buckets.insert(bucket);
+ }
+ // Test: IP addresses in the same group (\16 prefix for IPv4) should
+ // always map to the same bucket.
+ BOOST_CHECK_EQUAL(buckets.size(), 1U);
+
+ buckets.clear();
+ for (int j = 0; j < 4 * 255; j++) {
+ CAddrInfo infoj = CAddrInfo(CAddress(
+ ResolveService(
+ std::to_string(250 + (j / 255)) + "." + std::to_string(j % 256) + ".1.1"), NODE_NONE),
+ ResolveIP("251.4.1.1"));
+ int bucket = infoj.GetNewBucket(nKey1);
+ buckets.insert(bucket);
+ }
+ // Test: IP addresses in the same source groups should map to no more
+ // than 64 buckets.
+ BOOST_CHECK(buckets.size() <= 64);
+
+ buckets.clear();
+ for (int p = 0; p < 255; p++) {
+ CAddrInfo infoj = CAddrInfo(
+ CAddress(ResolveService("250.1.1.1"), NODE_NONE),
+ ResolveIP("250." + std::to_string(p) + ".1.1"));
+ int bucket = infoj.GetNewBucket(nKey1);
+ buckets.insert(bucket);
+ }
+ // Test: IP addresses in the different source groups should map to more
+ // than 64 buckets.
+ BOOST_CHECK(buckets.size() > 64);
+}
+
+
+BOOST_AUTO_TEST_CASE(addrman_selecttriedcollision)
+{
+ CAddrManTest addrman;
+
+ // Set addrman addr placement to be deterministic.
+ addrman.MakeDeterministic();
+
+ BOOST_CHECK(addrman.size() == 0);
+
+ // Empty addrman should return blank addrman info.
+ BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
+
+ // Add twenty two addresses.
+ CNetAddr source = ResolveIP("252.2.2.2");
+ for (unsigned int i = 1; i < 23; i++) {
+ CService addr = ResolveService("250.1.1."+std::to_string(i));
+ addrman.Add(CAddress(addr, NODE_NONE), source);
+ addrman.Good(addr);
+
+ // No collisions yet.
+ BOOST_CHECK(addrman.size() == i);
+ BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
+ }
+
+ // Ensure Good handles duplicates well.
+ for (unsigned int i = 1; i < 23; i++) {
+ CService addr = ResolveService("250.1.1."+std::to_string(i));
+ addrman.Good(addr);
+
+ BOOST_CHECK(addrman.size() == 22);
+ BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
+ }
+
+}
+
+BOOST_AUTO_TEST_CASE(addrman_noevict)
+{
+ CAddrManTest addrman;
+
+ // Set addrman addr placement to be deterministic.
+ addrman.MakeDeterministic();
+
+ // Add twenty two addresses.
+ CNetAddr source = ResolveIP("252.2.2.2");
+ for (unsigned int i = 1; i < 23; i++) {
+ CService addr = ResolveService("250.1.1."+std::to_string(i));
+ addrman.Add(CAddress(addr, NODE_NONE), source);
+ addrman.Good(addr);
+
+ // No collision yet.
+ BOOST_CHECK(addrman.size() == i);
+ BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
+ }
+
+ // Collision between 23 and 19.
+ CService addr23 = ResolveService("250.1.1.23");
+ addrman.Add(CAddress(addr23, NODE_NONE), source);
+ addrman.Good(addr23);
+
+ BOOST_CHECK(addrman.size() == 23);
+ BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "250.1.1.19:0");
+
+ // 23 should be discarded and 19 not evicted.
+ addrman.ResolveCollisions();
+ BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
+
+ // Lets create two collisions.
+ for (unsigned int i = 24; i < 33; i++) {
+ CService addr = ResolveService("250.1.1."+std::to_string(i));
+ addrman.Add(CAddress(addr, NODE_NONE), source);
+ addrman.Good(addr);
+
+ BOOST_CHECK(addrman.size() == i);
+ BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
+ }
+
+ // Cause a collision.
+ CService addr33 = ResolveService("250.1.1.33");
+ addrman.Add(CAddress(addr33, NODE_NONE), source);
+ addrman.Good(addr33);
+ BOOST_CHECK(addrman.size() == 33);
+
+ BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "250.1.1.27:0");
+
+ // Cause a second collision.
+ addrman.Add(CAddress(addr23, NODE_NONE), source);
+ addrman.Good(addr23);
+ BOOST_CHECK(addrman.size() == 33);
+
+ BOOST_CHECK(addrman.SelectTriedCollision().ToString() != "[::]:0");
+ addrman.ResolveCollisions();
+ BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
+}
+
+BOOST_AUTO_TEST_CASE(addrman_evictionworks)
+{
+ CAddrManTest addrman;
+
+ // Set addrman addr placement to be deterministic.
+ addrman.MakeDeterministic();
+
+ BOOST_CHECK(addrman.size() == 0);
+
+ // Empty addrman should return blank addrman info.
+ BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
+
+ // Add twenty two addresses.
+ CNetAddr source = ResolveIP("252.2.2.2");
+ for (unsigned int i = 1; i < 23; i++) {
+ CService addr = ResolveService("250.1.1."+std::to_string(i));
+ addrman.Add(CAddress(addr, NODE_NONE), source);
+ addrman.Good(addr);
+
+ // No collision yet.
+ BOOST_CHECK(addrman.size() == i);
+ BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
+ }
+
+ // Collision between 23 and 19.
+ CService addr = ResolveService("250.1.1.23");
+ addrman.Add(CAddress(addr, NODE_NONE), source);
+ addrman.Good(addr);
+
+ BOOST_CHECK(addrman.size() == 23);
+ CAddrInfo info = addrman.SelectTriedCollision();
+ BOOST_CHECK(info.ToString() == "250.1.1.19:0");
+
+ // Ensure test of address fails, so that it is evicted.
+ addrman.SimConnFail(info);
+
+ // Should swap 23 for 19.
+ addrman.ResolveCollisions();
+ BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
+
+ // If 23 was swapped for 19, then this should cause no collisions.
+ addrman.Add(CAddress(addr, NODE_NONE), source);
+ addrman.Good(addr);
+
+ BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
+
+ // If we insert 19 is should collide with 23.
+ CService addr19 = ResolveService("250.1.1.19");
+ addrman.Add(CAddress(addr19, NODE_NONE), source);
+ addrman.Good(addr19);
+
+ BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "250.1.1.23:0");
+
+ addrman.ResolveCollisions();
+ BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
+}
+
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/allocator_tests.cpp b/src/test/allocator_tests.cpp
new file mode 100644
index 0000000000..1052ada232
--- /dev/null
+++ b/src/test/allocator_tests.cpp
@@ -0,0 +1,236 @@
+// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <util.h>
+
+#include <support/allocators/secure.h>
+#include <test/test_bitcoin.h>
+
+#include <memory>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(allocator_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(arena_tests)
+{
+ // Fake memory base address for testing
+ // without actually using memory.
+ void *synth_base = reinterpret_cast<void*>(0x08000000);
+ const size_t synth_size = 1024*1024;
+ Arena b(synth_base, synth_size, 16);
+ void *chunk = b.alloc(1000);
+#ifdef ARENA_DEBUG
+ b.walk();
+#endif
+ BOOST_CHECK(chunk != nullptr);
+ BOOST_CHECK(b.stats().used == 1008); // Aligned to 16
+ BOOST_CHECK(b.stats().total == synth_size); // Nothing has disappeared?
+ b.free(chunk);
+#ifdef ARENA_DEBUG
+ b.walk();
+#endif
+ BOOST_CHECK(b.stats().used == 0);
+ BOOST_CHECK(b.stats().free == synth_size);
+ try { // Test exception on double-free
+ b.free(chunk);
+ BOOST_CHECK(0);
+ } catch(std::runtime_error &)
+ {
+ }
+
+ void *a0 = b.alloc(128);
+ void *a1 = b.alloc(256);
+ void *a2 = b.alloc(512);
+ BOOST_CHECK(b.stats().used == 896);
+ BOOST_CHECK(b.stats().total == synth_size);
+#ifdef ARENA_DEBUG
+ b.walk();
+#endif
+ b.free(a0);
+#ifdef ARENA_DEBUG
+ b.walk();
+#endif
+ BOOST_CHECK(b.stats().used == 768);
+ b.free(a1);
+ BOOST_CHECK(b.stats().used == 512);
+ void *a3 = b.alloc(128);
+#ifdef ARENA_DEBUG
+ b.walk();
+#endif
+ BOOST_CHECK(b.stats().used == 640);
+ b.free(a2);
+ BOOST_CHECK(b.stats().used == 128);
+ b.free(a3);
+ BOOST_CHECK(b.stats().used == 0);
+ BOOST_CHECK_EQUAL(b.stats().chunks_used, 0U);
+ BOOST_CHECK(b.stats().total == synth_size);
+ BOOST_CHECK(b.stats().free == synth_size);
+ BOOST_CHECK_EQUAL(b.stats().chunks_free, 1U);
+
+ std::vector<void*> addr;
+ BOOST_CHECK(b.alloc(0) == nullptr); // allocating 0 always returns nullptr
+#ifdef ARENA_DEBUG
+ b.walk();
+#endif
+ // Sweeping allocate all memory
+ for (int x=0; x<1024; ++x)
+ addr.push_back(b.alloc(1024));
+ BOOST_CHECK(b.stats().free == 0);
+ BOOST_CHECK(b.alloc(1024) == nullptr); // memory is full, this must return nullptr
+ BOOST_CHECK(b.alloc(0) == nullptr);
+ for (int x=0; x<1024; ++x)
+ b.free(addr[x]);
+ addr.clear();
+ BOOST_CHECK(b.stats().total == synth_size);
+ BOOST_CHECK(b.stats().free == synth_size);
+
+ // Now in the other direction...
+ for (int x=0; x<1024; ++x)
+ addr.push_back(b.alloc(1024));
+ for (int x=0; x<1024; ++x)
+ b.free(addr[1023-x]);
+ addr.clear();
+
+ // Now allocate in smaller unequal chunks, then deallocate haphazardly
+ // Not all the chunks will succeed allocating, but freeing nullptr is
+ // allowed so that is no problem.
+ for (int x=0; x<2048; ++x)
+ addr.push_back(b.alloc(x+1));
+ for (int x=0; x<2048; ++x)
+ b.free(addr[((x*23)%2048)^242]);
+ addr.clear();
+
+ // Go entirely wild: free and alloc interleaved,
+ // generate targets and sizes using pseudo-randomness.
+ for (int x=0; x<2048; ++x)
+ addr.push_back(0);
+ uint32_t s = 0x12345678;
+ for (int x=0; x<5000; ++x) {
+ int idx = s & (addr.size()-1);
+ if (s & 0x80000000) {
+ b.free(addr[idx]);
+ addr[idx] = 0;
+ } else if(!addr[idx]) {
+ addr[idx] = b.alloc((s >> 16) & 2047);
+ }
+ bool lsb = s & 1;
+ s >>= 1;
+ if (lsb)
+ s ^= 0xf00f00f0; // LFSR period 0xf7ffffe0
+ }
+ for (void *ptr: addr)
+ b.free(ptr);
+ addr.clear();
+
+ BOOST_CHECK(b.stats().total == synth_size);
+ BOOST_CHECK(b.stats().free == synth_size);
+}
+
+/** Mock LockedPageAllocator for testing */
+class TestLockedPageAllocator: public LockedPageAllocator
+{
+public:
+ TestLockedPageAllocator(int count_in, int lockedcount_in): count(count_in), lockedcount(lockedcount_in) {}
+ void* AllocateLocked(size_t len, bool *lockingSuccess) override
+ {
+ *lockingSuccess = false;
+ if (count > 0) {
+ --count;
+
+ if (lockedcount > 0) {
+ --lockedcount;
+ *lockingSuccess = true;
+ }
+
+ return reinterpret_cast<void*>(0x08000000 + (count<<24)); // Fake address, do not actually use this memory
+ }
+ return 0;
+ }
+ void FreeLocked(void* addr, size_t len) override
+ {
+ }
+ size_t GetLimit() override
+ {
+ return std::numeric_limits<size_t>::max();
+ }
+private:
+ int count;
+ int lockedcount;
+};
+
+BOOST_AUTO_TEST_CASE(lockedpool_tests_mock)
+{
+ // Test over three virtual arenas, of which one will succeed being locked
+ std::unique_ptr<LockedPageAllocator> x(new TestLockedPageAllocator(3, 1));
+ LockedPool pool(std::move(x));
+ BOOST_CHECK(pool.stats().total == 0);
+ BOOST_CHECK(pool.stats().locked == 0);
+
+ // Ensure unreasonable requests are refused without allocating anything
+ void *invalid_toosmall = pool.alloc(0);
+ BOOST_CHECK(invalid_toosmall == nullptr);
+ BOOST_CHECK(pool.stats().used == 0);
+ BOOST_CHECK(pool.stats().free == 0);
+ void *invalid_toobig = pool.alloc(LockedPool::ARENA_SIZE+1);
+ BOOST_CHECK(invalid_toobig == nullptr);
+ BOOST_CHECK(pool.stats().used == 0);
+ BOOST_CHECK(pool.stats().free == 0);
+
+ void *a0 = pool.alloc(LockedPool::ARENA_SIZE / 2);
+ BOOST_CHECK(a0);
+ BOOST_CHECK(pool.stats().locked == LockedPool::ARENA_SIZE);
+ void *a1 = pool.alloc(LockedPool::ARENA_SIZE / 2);
+ BOOST_CHECK(a1);
+ void *a2 = pool.alloc(LockedPool::ARENA_SIZE / 2);
+ BOOST_CHECK(a2);
+ void *a3 = pool.alloc(LockedPool::ARENA_SIZE / 2);
+ BOOST_CHECK(a3);
+ void *a4 = pool.alloc(LockedPool::ARENA_SIZE / 2);
+ BOOST_CHECK(a4);
+ void *a5 = pool.alloc(LockedPool::ARENA_SIZE / 2);
+ BOOST_CHECK(a5);
+ // We've passed a count of three arenas, so this allocation should fail
+ void *a6 = pool.alloc(16);
+ BOOST_CHECK(!a6);
+
+ pool.free(a0);
+ pool.free(a2);
+ pool.free(a4);
+ pool.free(a1);
+ pool.free(a3);
+ pool.free(a5);
+ BOOST_CHECK(pool.stats().total == 3*LockedPool::ARENA_SIZE);
+ BOOST_CHECK(pool.stats().locked == LockedPool::ARENA_SIZE);
+ BOOST_CHECK(pool.stats().used == 0);
+}
+
+// These tests used the live LockedPoolManager object, this is also used
+// by other tests so the conditions are somewhat less controllable and thus the
+// tests are somewhat more error-prone.
+BOOST_AUTO_TEST_CASE(lockedpool_tests_live)
+{
+ LockedPoolManager &pool = LockedPoolManager::Instance();
+ LockedPool::Stats initial = pool.stats();
+
+ void *a0 = pool.alloc(16);
+ BOOST_CHECK(a0);
+ // Test reading and writing the allocated memory
+ *((uint32_t*)a0) = 0x1234;
+ BOOST_CHECK(*((uint32_t*)a0) == 0x1234);
+
+ pool.free(a0);
+ try { // Test exception on double-free
+ pool.free(a0);
+ BOOST_CHECK(0);
+ } catch(std::runtime_error &)
+ {
+ }
+ // If more than one new arena was allocated for the above tests, something is wrong
+ BOOST_CHECK(pool.stats().total <= (initial.total + LockedPool::ARENA_SIZE));
+ // Usage must be back to where it started
+ BOOST_CHECK(pool.stats().used == initial.used);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp
new file mode 100644
index 0000000000..adffcfeef5
--- /dev/null
+++ b/src/test/amount_tests.cpp
@@ -0,0 +1,108 @@
+// Copyright (c) 2016-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <amount.h>
+#include <policy/feerate.h>
+#include <test/test_bitcoin.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(amount_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(MoneyRangeTest)
+{
+ BOOST_CHECK_EQUAL(MoneyRange(CAmount(-1)), false);
+ BOOST_CHECK_EQUAL(MoneyRange(MAX_MONEY + CAmount(1)), false);
+ BOOST_CHECK_EQUAL(MoneyRange(CAmount(1)), true);
+}
+
+BOOST_AUTO_TEST_CASE(GetFeeTest)
+{
+ CFeeRate feeRate, altFeeRate;
+
+ feeRate = CFeeRate(0);
+ // Must always return 0
+ BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(1e5), 0);
+
+ feeRate = CFeeRate(1000);
+ // Must always just return the arg
+ BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(1), 1);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(121), 121);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(999), 999);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), 1e3);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), 9e3);
+
+ feeRate = CFeeRate(-1000);
+ // Must always just return -1 * arg
+ BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(1), -1);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(121), -121);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(999), -999);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), -1e3);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), -9e3);
+
+ feeRate = CFeeRate(123);
+ // Truncates the result, if not integer
+ BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(8), 1); // Special case: returns 1 instead of 0
+ BOOST_CHECK_EQUAL(feeRate.GetFee(9), 1);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(121), 14);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(122), 15);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(999), 122);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(1e3), 123);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(9e3), 1107);
+
+ feeRate = CFeeRate(-123);
+ // Truncates the result, if not integer
+ BOOST_CHECK_EQUAL(feeRate.GetFee(0), 0);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(8), -1); // Special case: returns -1 instead of 0
+ BOOST_CHECK_EQUAL(feeRate.GetFee(9), -1);
+
+ // check alternate constructor
+ feeRate = CFeeRate(1000);
+ altFeeRate = CFeeRate(feeRate);
+ BOOST_CHECK_EQUAL(feeRate.GetFee(100), altFeeRate.GetFee(100));
+
+ // Check full constructor
+ // default value
+ BOOST_CHECK(CFeeRate(CAmount(-1), 1000) == CFeeRate(-1));
+ BOOST_CHECK(CFeeRate(CAmount(0), 1000) == CFeeRate(0));
+ BOOST_CHECK(CFeeRate(CAmount(1), 1000) == CFeeRate(1));
+ // lost precision (can only resolve satoshis per kB)
+ BOOST_CHECK(CFeeRate(CAmount(1), 1001) == CFeeRate(0));
+ BOOST_CHECK(CFeeRate(CAmount(2), 1001) == CFeeRate(1));
+ // some more integer checks
+ BOOST_CHECK(CFeeRate(CAmount(26), 789) == CFeeRate(32));
+ BOOST_CHECK(CFeeRate(CAmount(27), 789) == CFeeRate(34));
+ // Maximum size in bytes, should not crash
+ CFeeRate(MAX_MONEY, std::numeric_limits<size_t>::max() >> 1).GetFeePerK();
+}
+
+BOOST_AUTO_TEST_CASE(BinaryOperatorTest)
+{
+ CFeeRate a, b;
+ a = CFeeRate(1);
+ b = CFeeRate(2);
+ BOOST_CHECK(a < b);
+ BOOST_CHECK(b > a);
+ BOOST_CHECK(a == a);
+ BOOST_CHECK(a <= b);
+ BOOST_CHECK(a <= a);
+ BOOST_CHECK(b >= a);
+ BOOST_CHECK(b >= b);
+ // a should be 0.00000002 BTC/kB now
+ a += a;
+ BOOST_CHECK(a == b);
+}
+
+BOOST_AUTO_TEST_CASE(ToStringTest)
+{
+ CFeeRate feeRate;
+ feeRate = CFeeRate(1);
+ BOOST_CHECK_EQUAL(feeRate.ToString(), "0.00000001 BTC/kB");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/arith_uint256_tests.cpp b/src/test/arith_uint256_tests.cpp
new file mode 100644
index 0000000000..77b6008fd0
--- /dev/null
+++ b/src/test/arith_uint256_tests.cpp
@@ -0,0 +1,560 @@
+// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <boost/test/unit_test.hpp>
+#include <stdint.h>
+#include <sstream>
+#include <iomanip>
+#include <limits>
+#include <cmath>
+#include <uint256.h>
+#include <arith_uint256.h>
+#include <string>
+#include <version.h>
+#include <test/test_bitcoin.h>
+
+BOOST_FIXTURE_TEST_SUITE(arith_uint256_tests, BasicTestingSetup)
+
+/// Convert vector to arith_uint256, via uint256 blob
+static inline arith_uint256 arith_uint256V(const std::vector<unsigned char>& vch)
+{
+ return UintToArith256(uint256(vch));
+}
+
+const unsigned char R1Array[] =
+ "\x9c\x52\x4a\xdb\xcf\x56\x11\x12\x2b\x29\x12\x5e\x5d\x35\xd2\xd2"
+ "\x22\x81\xaa\xb5\x33\xf0\x08\x32\xd5\x56\xb1\xf9\xea\xe5\x1d\x7d";
+const char R1ArrayHex[] = "7D1DE5EAF9B156D53208F033B5AA8122D2d2355d5e12292b121156cfdb4a529c";
+const double R1Ldouble = 0.4887374590559308955; // R1L equals roughly R1Ldouble * 2^256
+const arith_uint256 R1L = arith_uint256V(std::vector<unsigned char>(R1Array,R1Array+32));
+const uint64_t R1LLow64 = 0x121156cfdb4a529cULL;
+
+const unsigned char R2Array[] =
+ "\x70\x32\x1d\x7c\x47\xa5\x6b\x40\x26\x7e\x0a\xc3\xa6\x9c\xb6\xbf"
+ "\x13\x30\x47\xa3\x19\x2d\xda\x71\x49\x13\x72\xf0\xb4\xca\x81\xd7";
+const arith_uint256 R2L = arith_uint256V(std::vector<unsigned char>(R2Array,R2Array+32));
+
+const char R1LplusR2L[] = "549FB09FEA236A1EA3E31D4D58F1B1369288D204211CA751527CFC175767850C";
+
+const unsigned char ZeroArray[] =
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
+const arith_uint256 ZeroL = arith_uint256V(std::vector<unsigned char>(ZeroArray,ZeroArray+32));
+
+const unsigned char OneArray[] =
+ "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
+const arith_uint256 OneL = arith_uint256V(std::vector<unsigned char>(OneArray,OneArray+32));
+
+const unsigned char MaxArray[] =
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
+const arith_uint256 MaxL = arith_uint256V(std::vector<unsigned char>(MaxArray,MaxArray+32));
+
+const arith_uint256 HalfL = (OneL << 255);
+static std::string ArrayToString(const unsigned char A[], unsigned int width)
+{
+ std::stringstream Stream;
+ Stream << std::hex;
+ for (unsigned int i = 0; i < width; ++i)
+ {
+ Stream<<std::setw(2)<<std::setfill('0')<<(unsigned int)A[width-i-1];
+ }
+ return Stream.str();
+}
+
+BOOST_AUTO_TEST_CASE( basics ) // constructors, equality, inequality
+{
+ BOOST_CHECK(1 == 0+1);
+ // constructor arith_uint256(vector<char>):
+ BOOST_CHECK(R1L.ToString() == ArrayToString(R1Array,32));
+ BOOST_CHECK(R2L.ToString() == ArrayToString(R2Array,32));
+ BOOST_CHECK(ZeroL.ToString() == ArrayToString(ZeroArray,32));
+ BOOST_CHECK(OneL.ToString() == ArrayToString(OneArray,32));
+ BOOST_CHECK(MaxL.ToString() == ArrayToString(MaxArray,32));
+ BOOST_CHECK(OneL.ToString() != ArrayToString(ZeroArray,32));
+
+ // == and !=
+ BOOST_CHECK(R1L != R2L);
+ BOOST_CHECK(ZeroL != OneL);
+ BOOST_CHECK(OneL != ZeroL);
+ BOOST_CHECK(MaxL != ZeroL);
+ BOOST_CHECK(~MaxL == ZeroL);
+ BOOST_CHECK( ((R1L ^ R2L) ^ R1L) == R2L);
+
+ uint64_t Tmp64 = 0xc4dab720d9c7acaaULL;
+ for (unsigned int i = 0; i < 256; ++i)
+ {
+ BOOST_CHECK(ZeroL != (OneL << i));
+ BOOST_CHECK((OneL << i) != ZeroL);
+ BOOST_CHECK(R1L != (R1L ^ (OneL << i)));
+ BOOST_CHECK(((arith_uint256(Tmp64) ^ (OneL << i) ) != Tmp64 ));
+ }
+ BOOST_CHECK(ZeroL == (OneL << 256));
+
+ // String Constructor and Copy Constructor
+ BOOST_CHECK(arith_uint256("0x"+R1L.ToString()) == R1L);
+ BOOST_CHECK(arith_uint256("0x"+R2L.ToString()) == R2L);
+ BOOST_CHECK(arith_uint256("0x"+ZeroL.ToString()) == ZeroL);
+ BOOST_CHECK(arith_uint256("0x"+OneL.ToString()) == OneL);
+ BOOST_CHECK(arith_uint256("0x"+MaxL.ToString()) == MaxL);
+ BOOST_CHECK(arith_uint256(R1L.ToString()) == R1L);
+ BOOST_CHECK(arith_uint256(" 0x"+R1L.ToString()+" ") == R1L);
+ BOOST_CHECK(arith_uint256("") == ZeroL);
+ BOOST_CHECK(R1L == arith_uint256(R1ArrayHex));
+ BOOST_CHECK(arith_uint256(R1L) == R1L);
+ BOOST_CHECK((arith_uint256(R1L^R2L)^R2L) == R1L);
+ BOOST_CHECK(arith_uint256(ZeroL) == ZeroL);
+ BOOST_CHECK(arith_uint256(OneL) == OneL);
+
+ // uint64_t constructor
+ BOOST_CHECK( (R1L & arith_uint256("0xffffffffffffffff")) == arith_uint256(R1LLow64));
+ BOOST_CHECK(ZeroL == arith_uint256(0));
+ BOOST_CHECK(OneL == arith_uint256(1));
+ BOOST_CHECK(arith_uint256("0xffffffffffffffff") == arith_uint256(0xffffffffffffffffULL));
+
+ // Assignment (from base_uint)
+ arith_uint256 tmpL = ~ZeroL; BOOST_CHECK(tmpL == ~ZeroL);
+ tmpL = ~OneL; BOOST_CHECK(tmpL == ~OneL);
+ tmpL = ~R1L; BOOST_CHECK(tmpL == ~R1L);
+ tmpL = ~R2L; BOOST_CHECK(tmpL == ~R2L);
+ tmpL = ~MaxL; BOOST_CHECK(tmpL == ~MaxL);
+}
+
+static void shiftArrayRight(unsigned char* to, const unsigned char* from, unsigned int arrayLength, unsigned int bitsToShift)
+{
+ for (unsigned int T=0; T < arrayLength; ++T)
+ {
+ unsigned int F = (T+bitsToShift/8);
+ if (F < arrayLength)
+ to[T] = from[F] >> (bitsToShift%8);
+ else
+ to[T] = 0;
+ if (F + 1 < arrayLength)
+ to[T] |= from[(F+1)] << (8-bitsToShift%8);
+ }
+}
+
+static void shiftArrayLeft(unsigned char* to, const unsigned char* from, unsigned int arrayLength, unsigned int bitsToShift)
+{
+ for (unsigned int T=0; T < arrayLength; ++T)
+ {
+ if (T >= bitsToShift/8)
+ {
+ unsigned int F = T-bitsToShift/8;
+ to[T] = from[F] << (bitsToShift%8);
+ if (T >= bitsToShift/8+1)
+ to[T] |= from[F-1] >> (8-bitsToShift%8);
+ }
+ else {
+ to[T] = 0;
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE( shifts ) { // "<<" ">>" "<<=" ">>="
+ unsigned char TmpArray[32];
+ arith_uint256 TmpL;
+ for (unsigned int i = 0; i < 256; ++i)
+ {
+ shiftArrayLeft(TmpArray, OneArray, 32, i);
+ BOOST_CHECK(arith_uint256V(std::vector<unsigned char>(TmpArray,TmpArray+32)) == (OneL << i));
+ TmpL = OneL; TmpL <<= i;
+ BOOST_CHECK(TmpL == (OneL << i));
+ BOOST_CHECK((HalfL >> (255-i)) == (OneL << i));
+ TmpL = HalfL; TmpL >>= (255-i);
+ BOOST_CHECK(TmpL == (OneL << i));
+
+ shiftArrayLeft(TmpArray, R1Array, 32, i);
+ BOOST_CHECK(arith_uint256V(std::vector<unsigned char>(TmpArray,TmpArray+32)) == (R1L << i));
+ TmpL = R1L; TmpL <<= i;
+ BOOST_CHECK(TmpL == (R1L << i));
+
+ shiftArrayRight(TmpArray, R1Array, 32, i);
+ BOOST_CHECK(arith_uint256V(std::vector<unsigned char>(TmpArray,TmpArray+32)) == (R1L >> i));
+ TmpL = R1L; TmpL >>= i;
+ BOOST_CHECK(TmpL == (R1L >> i));
+
+ shiftArrayLeft(TmpArray, MaxArray, 32, i);
+ BOOST_CHECK(arith_uint256V(std::vector<unsigned char>(TmpArray,TmpArray+32)) == (MaxL << i));
+ TmpL = MaxL; TmpL <<= i;
+ BOOST_CHECK(TmpL == (MaxL << i));
+
+ shiftArrayRight(TmpArray, MaxArray, 32, i);
+ BOOST_CHECK(arith_uint256V(std::vector<unsigned char>(TmpArray,TmpArray+32)) == (MaxL >> i));
+ TmpL = MaxL; TmpL >>= i;
+ BOOST_CHECK(TmpL == (MaxL >> i));
+ }
+ arith_uint256 c1L = arith_uint256(0x0123456789abcdefULL);
+ arith_uint256 c2L = c1L << 128;
+ for (unsigned int i = 0; i < 128; ++i) {
+ BOOST_CHECK((c1L << i) == (c2L >> (128-i)));
+ }
+ for (unsigned int i = 128; i < 256; ++i) {
+ BOOST_CHECK((c1L << i) == (c2L << (i-128)));
+ }
+}
+
+BOOST_AUTO_TEST_CASE( unaryOperators ) // ! ~ -
+{
+ BOOST_CHECK(~ZeroL == MaxL);
+
+ unsigned char TmpArray[32];
+ for (unsigned int i = 0; i < 32; ++i) { TmpArray[i] = ~R1Array[i]; }
+ BOOST_CHECK(arith_uint256V(std::vector<unsigned char>(TmpArray,TmpArray+32)) == (~R1L));
+
+ BOOST_CHECK(-ZeroL == ZeroL);
+ BOOST_CHECK(-R1L == (~R1L)+1);
+ for (unsigned int i = 0; i < 256; ++i)
+ BOOST_CHECK(-(OneL<<i) == (MaxL << i));
+}
+
+
+// Check if doing _A_ _OP_ _B_ results in the same as applying _OP_ onto each
+// element of Aarray and Barray, and then converting the result into an arith_uint256.
+#define CHECKBITWISEOPERATOR(_A_,_B_,_OP_) \
+ for (unsigned int i = 0; i < 32; ++i) { TmpArray[i] = _A_##Array[i] _OP_ _B_##Array[i]; } \
+ BOOST_CHECK(arith_uint256V(std::vector<unsigned char>(TmpArray,TmpArray+32)) == (_A_##L _OP_ _B_##L));
+
+#define CHECKASSIGNMENTOPERATOR(_A_,_B_,_OP_) \
+ TmpL = _A_##L; TmpL _OP_##= _B_##L; BOOST_CHECK(TmpL == (_A_##L _OP_ _B_##L));
+
+BOOST_AUTO_TEST_CASE( bitwiseOperators )
+{
+ unsigned char TmpArray[32];
+
+ CHECKBITWISEOPERATOR(R1,R2,|)
+ CHECKBITWISEOPERATOR(R1,R2,^)
+ CHECKBITWISEOPERATOR(R1,R2,&)
+ CHECKBITWISEOPERATOR(R1,Zero,|)
+ CHECKBITWISEOPERATOR(R1,Zero,^)
+ CHECKBITWISEOPERATOR(R1,Zero,&)
+ CHECKBITWISEOPERATOR(R1,Max,|)
+ CHECKBITWISEOPERATOR(R1,Max,^)
+ CHECKBITWISEOPERATOR(R1,Max,&)
+ CHECKBITWISEOPERATOR(Zero,R1,|)
+ CHECKBITWISEOPERATOR(Zero,R1,^)
+ CHECKBITWISEOPERATOR(Zero,R1,&)
+ CHECKBITWISEOPERATOR(Max,R1,|)
+ CHECKBITWISEOPERATOR(Max,R1,^)
+ CHECKBITWISEOPERATOR(Max,R1,&)
+
+ arith_uint256 TmpL;
+ CHECKASSIGNMENTOPERATOR(R1,R2,|)
+ CHECKASSIGNMENTOPERATOR(R1,R2,^)
+ CHECKASSIGNMENTOPERATOR(R1,R2,&)
+ CHECKASSIGNMENTOPERATOR(R1,Zero,|)
+ CHECKASSIGNMENTOPERATOR(R1,Zero,^)
+ CHECKASSIGNMENTOPERATOR(R1,Zero,&)
+ CHECKASSIGNMENTOPERATOR(R1,Max,|)
+ CHECKASSIGNMENTOPERATOR(R1,Max,^)
+ CHECKASSIGNMENTOPERATOR(R1,Max,&)
+ CHECKASSIGNMENTOPERATOR(Zero,R1,|)
+ CHECKASSIGNMENTOPERATOR(Zero,R1,^)
+ CHECKASSIGNMENTOPERATOR(Zero,R1,&)
+ CHECKASSIGNMENTOPERATOR(Max,R1,|)
+ CHECKASSIGNMENTOPERATOR(Max,R1,^)
+ CHECKASSIGNMENTOPERATOR(Max,R1,&)
+
+ uint64_t Tmp64 = 0xe1db685c9a0b47a2ULL;
+ TmpL = R1L; TmpL |= Tmp64; BOOST_CHECK(TmpL == (R1L | arith_uint256(Tmp64)));
+ TmpL = R1L; TmpL |= 0; BOOST_CHECK(TmpL == R1L);
+ TmpL ^= 0; BOOST_CHECK(TmpL == R1L);
+ TmpL ^= Tmp64; BOOST_CHECK(TmpL == (R1L ^ arith_uint256(Tmp64)));
+}
+
+BOOST_AUTO_TEST_CASE( comparison ) // <= >= < >
+{
+ arith_uint256 TmpL;
+ for (unsigned int i = 0; i < 256; ++i) {
+ TmpL= OneL<< i;
+ BOOST_CHECK( TmpL >= ZeroL && TmpL > ZeroL && ZeroL < TmpL && ZeroL <= TmpL);
+ BOOST_CHECK( TmpL >= 0 && TmpL > 0 && 0 < TmpL && 0 <= TmpL);
+ TmpL |= R1L;
+ BOOST_CHECK( TmpL >= R1L ); BOOST_CHECK( (TmpL == R1L) != (TmpL > R1L)); BOOST_CHECK( (TmpL == R1L) || !( TmpL <= R1L));
+ BOOST_CHECK( R1L <= TmpL ); BOOST_CHECK( (R1L == TmpL) != (R1L < TmpL)); BOOST_CHECK( (TmpL == R1L) || !( R1L >= TmpL));
+ BOOST_CHECK(! (TmpL < R1L)); BOOST_CHECK(! (R1L > TmpL));
+ }
+}
+
+BOOST_AUTO_TEST_CASE( plusMinus )
+{
+ arith_uint256 TmpL = 0;
+ BOOST_CHECK(R1L+R2L == arith_uint256(R1LplusR2L));
+ TmpL += R1L;
+ BOOST_CHECK(TmpL == R1L);
+ TmpL += R2L;
+ BOOST_CHECK(TmpL == R1L + R2L);
+ BOOST_CHECK(OneL+MaxL == ZeroL);
+ BOOST_CHECK(MaxL+OneL == ZeroL);
+ for (unsigned int i = 1; i < 256; ++i) {
+ BOOST_CHECK( (MaxL >> i) + OneL == (HalfL >> (i-1)) );
+ BOOST_CHECK( OneL + (MaxL >> i) == (HalfL >> (i-1)) );
+ TmpL = (MaxL>>i); TmpL += OneL;
+ BOOST_CHECK( TmpL == (HalfL >> (i-1)) );
+ TmpL = (MaxL>>i); TmpL += 1;
+ BOOST_CHECK( TmpL == (HalfL >> (i-1)) );
+ TmpL = (MaxL>>i);
+ BOOST_CHECK( TmpL++ == (MaxL>>i) );
+ BOOST_CHECK( TmpL == (HalfL >> (i-1)));
+ }
+ BOOST_CHECK(arith_uint256(0xbedc77e27940a7ULL) + 0xee8d836fce66fbULL == arith_uint256(0xbedc77e27940a7ULL + 0xee8d836fce66fbULL));
+ TmpL = arith_uint256(0xbedc77e27940a7ULL); TmpL += 0xee8d836fce66fbULL;
+ BOOST_CHECK(TmpL == arith_uint256(0xbedc77e27940a7ULL+0xee8d836fce66fbULL));
+ TmpL -= 0xee8d836fce66fbULL; BOOST_CHECK(TmpL == 0xbedc77e27940a7ULL);
+ TmpL = R1L;
+ BOOST_CHECK(++TmpL == R1L+1);
+
+ BOOST_CHECK(R1L -(-R2L) == R1L+R2L);
+ BOOST_CHECK(R1L -(-OneL) == R1L+OneL);
+ BOOST_CHECK(R1L - OneL == R1L+(-OneL));
+ for (unsigned int i = 1; i < 256; ++i) {
+ BOOST_CHECK((MaxL>>i) - (-OneL) == (HalfL >> (i-1)));
+ BOOST_CHECK((HalfL >> (i-1)) - OneL == (MaxL>>i));
+ TmpL = (HalfL >> (i-1));
+ BOOST_CHECK(TmpL-- == (HalfL >> (i-1)));
+ BOOST_CHECK(TmpL == (MaxL >> i));
+ TmpL = (HalfL >> (i-1));
+ BOOST_CHECK(--TmpL == (MaxL >> i));
+ }
+ TmpL = R1L;
+ BOOST_CHECK(--TmpL == R1L-1);
+}
+
+BOOST_AUTO_TEST_CASE( multiply )
+{
+ BOOST_CHECK((R1L * R1L).ToString() == "62a38c0486f01e45879d7910a7761bf30d5237e9873f9bff3642a732c4d84f10");
+ BOOST_CHECK((R1L * R2L).ToString() == "de37805e9986996cfba76ff6ba51c008df851987d9dd323f0e5de07760529c40");
+ BOOST_CHECK((R1L * ZeroL) == ZeroL);
+ BOOST_CHECK((R1L * OneL) == R1L);
+ BOOST_CHECK((R1L * MaxL) == -R1L);
+ BOOST_CHECK((R2L * R1L) == (R1L * R2L));
+ BOOST_CHECK((R2L * R2L).ToString() == "ac8c010096767d3cae5005dec28bb2b45a1d85ab7996ccd3e102a650f74ff100");
+ BOOST_CHECK((R2L * ZeroL) == ZeroL);
+ BOOST_CHECK((R2L * OneL) == R2L);
+ BOOST_CHECK((R2L * MaxL) == -R2L);
+
+ BOOST_CHECK(MaxL * MaxL == OneL);
+
+ BOOST_CHECK((R1L * 0) == 0);
+ BOOST_CHECK((R1L * 1) == R1L);
+ BOOST_CHECK((R1L * 3).ToString() == "7759b1c0ed14047f961ad09b20ff83687876a0181a367b813634046f91def7d4");
+ BOOST_CHECK((R2L * 0x87654321UL).ToString() == "23f7816e30c4ae2017257b7a0fa64d60402f5234d46e746b61c960d09a26d070");
+}
+
+BOOST_AUTO_TEST_CASE( divide )
+{
+ arith_uint256 D1L("AD7133AC1977FA2B7");
+ arith_uint256 D2L("ECD751716");
+ BOOST_CHECK((R1L / D1L).ToString() == "00000000000000000b8ac01106981635d9ed112290f8895545a7654dde28fb3a");
+ BOOST_CHECK((R1L / D2L).ToString() == "000000000873ce8efec5b67150bad3aa8c5fcb70e947586153bf2cec7c37c57a");
+ BOOST_CHECK(R1L / OneL == R1L);
+ BOOST_CHECK(R1L / MaxL == ZeroL);
+ BOOST_CHECK(MaxL / R1L == 2);
+ BOOST_CHECK_THROW(R1L / ZeroL, uint_error);
+ BOOST_CHECK((R2L / D1L).ToString() == "000000000000000013e1665895a1cc981de6d93670105a6b3ec3b73141b3a3c5");
+ BOOST_CHECK((R2L / D2L).ToString() == "000000000e8f0abe753bb0afe2e9437ee85d280be60882cf0bd1aaf7fa3cc2c4");
+ BOOST_CHECK(R2L / OneL == R2L);
+ BOOST_CHECK(R2L / MaxL == ZeroL);
+ BOOST_CHECK(MaxL / R2L == 1);
+ BOOST_CHECK_THROW(R2L / ZeroL, uint_error);
+}
+
+
+static bool almostEqual(double d1, double d2)
+{
+ return fabs(d1-d2) <= 4*fabs(d1)*std::numeric_limits<double>::epsilon();
+}
+
+BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex size() GetLow64 GetSerializeSize, Serialize, Unserialize
+{
+ BOOST_CHECK(R1L.GetHex() == R1L.ToString());
+ BOOST_CHECK(R2L.GetHex() == R2L.ToString());
+ BOOST_CHECK(OneL.GetHex() == OneL.ToString());
+ BOOST_CHECK(MaxL.GetHex() == MaxL.ToString());
+ arith_uint256 TmpL(R1L);
+ BOOST_CHECK(TmpL == R1L);
+ TmpL.SetHex(R2L.ToString()); BOOST_CHECK(TmpL == R2L);
+ TmpL.SetHex(ZeroL.ToString()); BOOST_CHECK(TmpL == 0);
+ TmpL.SetHex(HalfL.ToString()); BOOST_CHECK(TmpL == HalfL);
+
+ TmpL.SetHex(R1L.ToString());
+ BOOST_CHECK(R1L.size() == 32);
+ BOOST_CHECK(R2L.size() == 32);
+ BOOST_CHECK(ZeroL.size() == 32);
+ BOOST_CHECK(MaxL.size() == 32);
+ BOOST_CHECK(R1L.GetLow64() == R1LLow64);
+ BOOST_CHECK(HalfL.GetLow64() ==0x0000000000000000ULL);
+ BOOST_CHECK(OneL.GetLow64() ==0x0000000000000001ULL);
+
+ for (unsigned int i = 0; i < 255; ++i)
+ {
+ BOOST_CHECK((OneL << i).getdouble() == ldexp(1.0,i));
+ }
+ BOOST_CHECK(ZeroL.getdouble() == 0.0);
+ for (int i = 256; i > 53; --i)
+ BOOST_CHECK(almostEqual((R1L>>(256-i)).getdouble(), ldexp(R1Ldouble,i)));
+ uint64_t R1L64part = (R1L>>192).GetLow64();
+ for (int i = 53; i > 0; --i) // doubles can store all integers in {0,...,2^54-1} exactly
+ {
+ BOOST_CHECK((R1L>>(256-i)).getdouble() == (double)(R1L64part >> (64-i)));
+ }
+}
+
+BOOST_AUTO_TEST_CASE(bignum_SetCompact)
+{
+ arith_uint256 num;
+ bool fNegative;
+ bool fOverflow;
+ num.SetCompact(0, &fNegative, &fOverflow);
+ BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0U);
+ BOOST_CHECK_EQUAL(fNegative, false);
+ BOOST_CHECK_EQUAL(fOverflow, false);
+
+ num.SetCompact(0x00123456, &fNegative, &fOverflow);
+ BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0U);
+ BOOST_CHECK_EQUAL(fNegative, false);
+ BOOST_CHECK_EQUAL(fOverflow, false);
+
+ num.SetCompact(0x01003456, &fNegative, &fOverflow);
+ BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0U);
+ BOOST_CHECK_EQUAL(fNegative, false);
+ BOOST_CHECK_EQUAL(fOverflow, false);
+
+ num.SetCompact(0x02000056, &fNegative, &fOverflow);
+ BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0U);
+ BOOST_CHECK_EQUAL(fNegative, false);
+ BOOST_CHECK_EQUAL(fOverflow, false);
+
+ num.SetCompact(0x03000000, &fNegative, &fOverflow);
+ BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0U);
+ BOOST_CHECK_EQUAL(fNegative, false);
+ BOOST_CHECK_EQUAL(fOverflow, false);
+
+ num.SetCompact(0x04000000, &fNegative, &fOverflow);
+ BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0U);
+ BOOST_CHECK_EQUAL(fNegative, false);
+ BOOST_CHECK_EQUAL(fOverflow, false);
+
+ num.SetCompact(0x00923456, &fNegative, &fOverflow);
+ BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0U);
+ BOOST_CHECK_EQUAL(fNegative, false);
+ BOOST_CHECK_EQUAL(fOverflow, false);
+
+ num.SetCompact(0x01803456, &fNegative, &fOverflow);
+ BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0U);
+ BOOST_CHECK_EQUAL(fNegative, false);
+ BOOST_CHECK_EQUAL(fOverflow, false);
+
+ num.SetCompact(0x02800056, &fNegative, &fOverflow);
+ BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0U);
+ BOOST_CHECK_EQUAL(fNegative, false);
+ BOOST_CHECK_EQUAL(fOverflow, false);
+
+ num.SetCompact(0x03800000, &fNegative, &fOverflow);
+ BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0U);
+ BOOST_CHECK_EQUAL(fNegative, false);
+ BOOST_CHECK_EQUAL(fOverflow, false);
+
+ num.SetCompact(0x04800000, &fNegative, &fOverflow);
+ BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0U);
+ BOOST_CHECK_EQUAL(fNegative, false);
+ BOOST_CHECK_EQUAL(fOverflow, false);
+
+ num.SetCompact(0x01123456, &fNegative, &fOverflow);
+ BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000012");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x01120000U);
+ BOOST_CHECK_EQUAL(fNegative, false);
+ BOOST_CHECK_EQUAL(fOverflow, false);
+
+ // Make sure that we don't generate compacts with the 0x00800000 bit set
+ num = 0x80;
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x02008000U);
+
+ num.SetCompact(0x01fedcba, &fNegative, &fOverflow);
+ BOOST_CHECK_EQUAL(num.GetHex(), "000000000000000000000000000000000000000000000000000000000000007e");
+ BOOST_CHECK_EQUAL(num.GetCompact(true), 0x01fe0000U);
+ BOOST_CHECK_EQUAL(fNegative, true);
+ BOOST_CHECK_EQUAL(fOverflow, false);
+
+ num.SetCompact(0x02123456, &fNegative, &fOverflow);
+ BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000001234");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x02123400U);
+ BOOST_CHECK_EQUAL(fNegative, false);
+ BOOST_CHECK_EQUAL(fOverflow, false);
+
+ num.SetCompact(0x03123456, &fNegative, &fOverflow);
+ BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000123456");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x03123456U);
+ BOOST_CHECK_EQUAL(fNegative, false);
+ BOOST_CHECK_EQUAL(fOverflow, false);
+
+ num.SetCompact(0x04123456, &fNegative, &fOverflow);
+ BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000012345600");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x04123456U);
+ BOOST_CHECK_EQUAL(fNegative, false);
+ BOOST_CHECK_EQUAL(fOverflow, false);
+
+ num.SetCompact(0x04923456, &fNegative, &fOverflow);
+ BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000012345600");
+ BOOST_CHECK_EQUAL(num.GetCompact(true), 0x04923456U);
+ BOOST_CHECK_EQUAL(fNegative, true);
+ BOOST_CHECK_EQUAL(fOverflow, false);
+
+ num.SetCompact(0x05009234, &fNegative, &fOverflow);
+ BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000092340000");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x05009234U);
+ BOOST_CHECK_EQUAL(fNegative, false);
+ BOOST_CHECK_EQUAL(fOverflow, false);
+
+ num.SetCompact(0x20123456, &fNegative, &fOverflow);
+ BOOST_CHECK_EQUAL(num.GetHex(), "1234560000000000000000000000000000000000000000000000000000000000");
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x20123456U);
+ BOOST_CHECK_EQUAL(fNegative, false);
+ BOOST_CHECK_EQUAL(fOverflow, false);
+
+ num.SetCompact(0xff123456, &fNegative, &fOverflow);
+ BOOST_CHECK_EQUAL(fNegative, false);
+ BOOST_CHECK_EQUAL(fOverflow, true);
+}
+
+
+BOOST_AUTO_TEST_CASE( getmaxcoverage ) // some more tests just to get 100% coverage
+{
+ // ~R1L give a base_uint<256>
+ BOOST_CHECK((~~R1L >> 10) == (R1L >> 10));
+ BOOST_CHECK((~~R1L << 10) == (R1L << 10));
+ BOOST_CHECK(!(~~R1L < R1L));
+ BOOST_CHECK(~~R1L <= R1L);
+ BOOST_CHECK(!(~~R1L > R1L));
+ BOOST_CHECK(~~R1L >= R1L);
+ BOOST_CHECK(!(R1L < ~~R1L));
+ BOOST_CHECK(R1L <= ~~R1L);
+ BOOST_CHECK(!(R1L > ~~R1L));
+ BOOST_CHECK(R1L >= ~~R1L);
+
+ BOOST_CHECK(~~R1L + R2L == R1L + ~~R2L);
+ BOOST_CHECK(~~R1L - R2L == R1L - ~~R2L);
+ BOOST_CHECK(~R1L != R1L); BOOST_CHECK(R1L != ~R1L);
+ unsigned char TmpArray[32];
+ CHECKBITWISEOPERATOR(~R1,R2,|)
+ CHECKBITWISEOPERATOR(~R1,R2,^)
+ CHECKBITWISEOPERATOR(~R1,R2,&)
+ CHECKBITWISEOPERATOR(R1,~R2,|)
+ CHECKBITWISEOPERATOR(R1,~R2,^)
+ CHECKBITWISEOPERATOR(R1,~R2,&)
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp
new file mode 100644
index 0000000000..6b06d2e1b6
--- /dev/null
+++ b/src/test/base32_tests.cpp
@@ -0,0 +1,25 @@
+// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <utilstrencodings.h>
+#include <test/test_bitcoin.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(base32_tests, BasicTestingSetup)
+
+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_EQUAL(strEnc, vstrOut[i]);
+ std::string strDec = DecodeBase32(vstrOut[i]);
+ BOOST_CHECK_EQUAL(strDec, vstrIn[i]);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp
new file mode 100644
index 0000000000..5fc4abaf3d
--- /dev/null
+++ b/src/test/base58_tests.cpp
@@ -0,0 +1,69 @@
+// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <test/data/base58_encode_decode.json.h>
+
+#include <base58.h>
+#include <test/test_bitcoin.h>
+#include <utilstrencodings.h>
+
+#include <univalue.h>
+
+#include <boost/test/unit_test.hpp>
+
+
+extern UniValue read_json(const std::string& jsondata);
+
+BOOST_FIXTURE_TEST_SUITE(base58_tests, BasicTestingSetup)
+
+// Goal: test low-level base58 encoding functionality
+BOOST_AUTO_TEST_CASE(base58_EncodeBase58)
+{
+ UniValue tests = read_json(std::string(json_tests::base58_encode_decode, json_tests::base58_encode_decode + sizeof(json_tests::base58_encode_decode)));
+ for (unsigned int idx = 0; idx < tests.size(); idx++) {
+ UniValue test = tests[idx];
+ std::string strTest = test.write();
+ if (test.size() < 2) // Allow for extra stuff (useful for comments)
+ {
+ BOOST_ERROR("Bad test: " << strTest);
+ continue;
+ }
+ std::vector<unsigned char> sourcedata = ParseHex(test[0].get_str());
+ std::string base58string = test[1].get_str();
+ BOOST_CHECK_MESSAGE(
+ EncodeBase58(sourcedata.data(), sourcedata.data() + sourcedata.size()) == base58string,
+ strTest);
+ }
+}
+
+// Goal: test low-level base58 decoding functionality
+BOOST_AUTO_TEST_CASE(base58_DecodeBase58)
+{
+ UniValue tests = read_json(std::string(json_tests::base58_encode_decode, json_tests::base58_encode_decode + sizeof(json_tests::base58_encode_decode)));
+ std::vector<unsigned char> result;
+
+ for (unsigned int idx = 0; idx < tests.size(); idx++) {
+ UniValue test = tests[idx];
+ std::string strTest = test.write();
+ if (test.size() < 2) // Allow for extra stuff (useful for comments)
+ {
+ BOOST_ERROR("Bad test: " << strTest);
+ continue;
+ }
+ std::vector<unsigned char> expected = ParseHex(test[0].get_str());
+ std::string base58string = test[1].get_str();
+ BOOST_CHECK_MESSAGE(DecodeBase58(base58string, result), strTest);
+ BOOST_CHECK_MESSAGE(result.size() == expected.size() && std::equal(result.begin(), result.end(), expected.begin()), strTest);
+ }
+
+ BOOST_CHECK(!DecodeBase58("invalid", result));
+
+ // check that DecodeBase58 skips whitespace, but still fails with unexpected non-whitespace at the end.
+ BOOST_CHECK(!DecodeBase58(" \t\n\v\f\r skip \r\f\v\n\t a", result));
+ BOOST_CHECK( DecodeBase58(" \t\n\v\f\r skip \r\f\v\n\t ", result));
+ std::vector<unsigned char> expected = ParseHex("971a55");
+ BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp
new file mode 100644
index 0000000000..daceea262c
--- /dev/null
+++ b/src/test/base64_tests.cpp
@@ -0,0 +1,25 @@
+// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <utilstrencodings.h>
+#include <test/test_bitcoin.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(base64_tests, BasicTestingSetup)
+
+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 (unsigned int i=0; i<sizeof(vstrIn)/sizeof(vstrIn[0]); i++)
+ {
+ std::string strEnc = EncodeBase64(vstrIn[i]);
+ BOOST_CHECK_EQUAL(strEnc, vstrOut[i]);
+ std::string strDec = DecodeBase64(strEnc);
+ BOOST_CHECK_EQUAL(strDec, vstrIn[i]);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/bech32_tests.cpp b/src/test/bech32_tests.cpp
new file mode 100644
index 0000000000..6ecc9ac705
--- /dev/null
+++ b/src/test/bech32_tests.cpp
@@ -0,0 +1,69 @@
+// Copyright (c) 2017 Pieter Wuille
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <bech32.h>
+#include <test/test_bitcoin.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(bech32_tests, BasicTestingSetup)
+
+static bool CaseInsensitiveEqual(const std::string &s1, const std::string &s2)
+{
+ if (s1.size() != s2.size()) return false;
+ for (size_t i = 0; i < s1.size(); ++i) {
+ char c1 = s1[i];
+ if (c1 >= 'A' && c1 <= 'Z') c1 -= ('A' - 'a');
+ char c2 = s2[i];
+ if (c2 >= 'A' && c2 <= 'Z') c2 -= ('A' - 'a');
+ if (c1 != c2) return false;
+ }
+ return true;
+}
+
+BOOST_AUTO_TEST_CASE(bip173_testvectors_valid)
+{
+ static const std::string CASES[] = {
+ "A12UEL5L",
+ "a12uel5l",
+ "an83characterlonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1tt5tgs",
+ "abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw",
+ "11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqc8247j",
+ "split1checkupstagehandshakeupstreamerranterredcaperred2y9e3w",
+ "?1ezyfcl",
+ };
+ for (const std::string& str : CASES) {
+ auto ret = bech32::Decode(str);
+ BOOST_CHECK(!ret.first.empty());
+ std::string recode = bech32::Encode(ret.first, ret.second);
+ BOOST_CHECK(!recode.empty());
+ BOOST_CHECK(CaseInsensitiveEqual(str, recode));
+ }
+}
+
+BOOST_AUTO_TEST_CASE(bip173_testvectors_invalid)
+{
+ static const std::string CASES[] = {
+ " 1nwldj5",
+ "\x7f""1axkwrx",
+ "\x80""1eym55h",
+ "an84characterslonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1569pvx",
+ "pzry9x0s0muk",
+ "1pzry9x0s0muk",
+ "x1b4n0q5v",
+ "li1dgmt3",
+ "de1lg7wt\xff",
+ "A1G7SGD8",
+ "10a06t8",
+ "1qzzfhee",
+ "a12UEL5L",
+ "A12uEL5L",
+ };
+ for (const std::string& str : CASES) {
+ auto ret = bech32::Decode(str);
+ BOOST_CHECK(ret.first.empty());
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp
new file mode 100644
index 0000000000..2cdbaca7ba
--- /dev/null
+++ b/src/test/bip32_tests.cpp
@@ -0,0 +1,154 @@
+// Copyright (c) 2013-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <boost/test/unit_test.hpp>
+
+#include <key.h>
+#include <key_io.h>
+#include <uint256.h>
+#include <util.h>
+#include <utilstrencodings.h>
+#include <test/test_bitcoin.h>
+
+#include <string>
+#include <vector>
+
+struct TestDerivation {
+ std::string pub;
+ std::string prv;
+ unsigned int nChild;
+};
+
+struct TestVector {
+ std::string strHexMaster;
+ std::vector<TestDerivation> vDerive;
+
+ explicit TestVector(std::string strHexMasterIn) : strHexMaster(strHexMasterIn) {}
+
+ TestVector& operator()(std::string pub, std::string prv, unsigned int nChild) {
+ vDerive.push_back(TestDerivation());
+ TestDerivation &der = vDerive.back();
+ der.pub = pub;
+ der.prv = prv;
+ der.nChild = nChild;
+ return *this;
+ }
+};
+
+TestVector test1 =
+ TestVector("000102030405060708090a0b0c0d0e0f")
+ ("xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8",
+ "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi",
+ 0x80000000)
+ ("xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw",
+ "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7",
+ 1)
+ ("xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ",
+ "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs",
+ 0x80000002)
+ ("xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5",
+ "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM",
+ 2)
+ ("xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV",
+ "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334",
+ 1000000000)
+ ("xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy",
+ "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76",
+ 0);
+
+TestVector test2 =
+ TestVector("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542")
+ ("xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB",
+ "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U",
+ 0)
+ ("xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH",
+ "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt",
+ 0xFFFFFFFF)
+ ("xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a",
+ "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9",
+ 1)
+ ("xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon",
+ "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef",
+ 0xFFFFFFFE)
+ ("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL",
+ "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc",
+ 2)
+ ("xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt",
+ "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j",
+ 0);
+
+TestVector test3 =
+ TestVector("4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be")
+ ("xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13",
+ "xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6",
+ 0x80000000)
+ ("xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y",
+ "xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L",
+ 0);
+
+static void RunTest(const TestVector &test) {
+ std::vector<unsigned char> seed = ParseHex(test.strHexMaster);
+ CExtKey key;
+ CExtPubKey pubkey;
+ key.SetSeed(seed.data(), seed.size());
+ pubkey = key.Neuter();
+ for (const TestDerivation &derive : test.vDerive) {
+ unsigned char data[74];
+ key.Encode(data);
+ pubkey.Encode(data);
+
+ // Test private key
+ BOOST_CHECK(EncodeExtKey(key) == derive.prv);
+ BOOST_CHECK(DecodeExtKey(derive.prv) == key); //ensure a base58 decoded key also matches
+
+ // Test public key
+ BOOST_CHECK(EncodeExtPubKey(pubkey) == derive.pub);
+ BOOST_CHECK(DecodeExtPubKey(derive.pub) == pubkey); //ensure a base58 decoded pubkey also matches
+
+ // Derive new keys
+ CExtKey keyNew;
+ BOOST_CHECK(key.Derive(keyNew, derive.nChild));
+ CExtPubKey pubkeyNew = keyNew.Neuter();
+ if (!(derive.nChild & 0x80000000)) {
+ // Compare with public derivation
+ CExtPubKey pubkeyNew2;
+ BOOST_CHECK(pubkey.Derive(pubkeyNew2, derive.nChild));
+ BOOST_CHECK(pubkeyNew == pubkeyNew2);
+ }
+ key = keyNew;
+ pubkey = pubkeyNew;
+
+ CDataStream ssPub(SER_DISK, CLIENT_VERSION);
+ ssPub << pubkeyNew;
+ BOOST_CHECK(ssPub.size() == 75);
+
+ CDataStream ssPriv(SER_DISK, CLIENT_VERSION);
+ ssPriv << keyNew;
+ BOOST_CHECK(ssPriv.size() == 75);
+
+ CExtPubKey pubCheck;
+ CExtKey privCheck;
+ ssPub >> pubCheck;
+ ssPriv >> privCheck;
+
+ BOOST_CHECK(pubCheck == pubkeyNew);
+ BOOST_CHECK(privCheck == keyNew);
+ }
+}
+
+BOOST_FIXTURE_TEST_SUITE(bip32_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(bip32_test1) {
+ RunTest(test1);
+}
+
+BOOST_AUTO_TEST_CASE(bip32_test2) {
+ RunTest(test2);
+}
+
+BOOST_AUTO_TEST_CASE(bip32_test3) {
+ RunTest(test3);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/blockchain_tests.cpp b/src/test/blockchain_tests.cpp
new file mode 100644
index 0000000000..7d8ae46fb8
--- /dev/null
+++ b/src/test/blockchain_tests.cpp
@@ -0,0 +1,78 @@
+#include <boost/test/unit_test.hpp>
+
+#include <stdlib.h>
+
+#include <rpc/blockchain.h>
+#include <test/test_bitcoin.h>
+
+/* Equality between doubles is imprecise. Comparison should be done
+ * with a small threshold of tolerance, rather than exact equality.
+ */
+static bool DoubleEquals(double a, double b, double epsilon)
+{
+ return std::abs(a - b) < epsilon;
+}
+
+static CBlockIndex* CreateBlockIndexWithNbits(uint32_t nbits)
+{
+ CBlockIndex* block_index = new CBlockIndex();
+ block_index->nHeight = 46367;
+ block_index->nTime = 1269211443;
+ block_index->nBits = nbits;
+ return block_index;
+}
+
+static void RejectDifficultyMismatch(double difficulty, double expected_difficulty) {
+ BOOST_CHECK_MESSAGE(
+ DoubleEquals(difficulty, expected_difficulty, 0.00001),
+ "Difficulty was " + std::to_string(difficulty)
+ + " but was expected to be " + std::to_string(expected_difficulty));
+}
+
+/* Given a BlockIndex with the provided nbits,
+ * verify that the expected difficulty results.
+ */
+static void TestDifficulty(uint32_t nbits, double expected_difficulty)
+{
+ CBlockIndex* block_index = CreateBlockIndexWithNbits(nbits);
+ double difficulty = GetDifficulty(block_index);
+ delete block_index;
+
+ RejectDifficultyMismatch(difficulty, expected_difficulty);
+}
+
+BOOST_FIXTURE_TEST_SUITE(blockchain_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(get_difficulty_for_very_low_target)
+{
+ TestDifficulty(0x1f111111, 0.000001);
+}
+
+BOOST_AUTO_TEST_CASE(get_difficulty_for_low_target)
+{
+ TestDifficulty(0x1ef88f6f, 0.000016);
+}
+
+BOOST_AUTO_TEST_CASE(get_difficulty_for_mid_target)
+{
+ TestDifficulty(0x1df88f6f, 0.004023);
+}
+
+BOOST_AUTO_TEST_CASE(get_difficulty_for_high_target)
+{
+ TestDifficulty(0x1cf88f6f, 1.029916);
+}
+
+BOOST_AUTO_TEST_CASE(get_difficulty_for_very_high_target)
+{
+ TestDifficulty(0x12345678, 5913134931067755359633408.0);
+}
+
+// Verify that difficulty is 1.0 for an empty chain.
+BOOST_AUTO_TEST_CASE(get_difficulty_for_null_tip)
+{
+ double difficulty = GetDifficulty(nullptr);
+ RejectDifficultyMismatch(difficulty, 1.0);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp
new file mode 100644
index 0000000000..d2c7c8cb1d
--- /dev/null
+++ b/src/test/blockencodings_tests.cpp
@@ -0,0 +1,347 @@
+// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <blockencodings.h>
+#include <consensus/merkle.h>
+#include <chainparams.h>
+#include <pow.h>
+#include <random.h>
+
+#include <test/test_bitcoin.h>
+
+#include <boost/test/unit_test.hpp>
+
+std::vector<std::pair<uint256, CTransactionRef>> extra_txn;
+
+struct RegtestingSetup : public TestingSetup {
+ RegtestingSetup() : TestingSetup(CBaseChainParams::REGTEST) {}
+};
+
+BOOST_FIXTURE_TEST_SUITE(blockencodings_tests, RegtestingSetup)
+
+static CBlock BuildBlockTestCase() {
+ CBlock block;
+ CMutableTransaction tx;
+ tx.vin.resize(1);
+ tx.vin[0].scriptSig.resize(10);
+ tx.vout.resize(1);
+ tx.vout[0].nValue = 42;
+
+ block.vtx.resize(3);
+ block.vtx[0] = MakeTransactionRef(tx);
+ block.nVersion = 42;
+ block.hashPrevBlock = InsecureRand256();
+ block.nBits = 0x207fffff;
+
+ tx.vin[0].prevout.hash = InsecureRand256();
+ tx.vin[0].prevout.n = 0;
+ block.vtx[1] = MakeTransactionRef(tx);
+
+ tx.vin.resize(10);
+ for (size_t i = 0; i < tx.vin.size(); i++) {
+ tx.vin[i].prevout.hash = InsecureRand256();
+ tx.vin[i].prevout.n = 0;
+ }
+ block.vtx[2] = MakeTransactionRef(tx);
+
+ bool mutated;
+ block.hashMerkleRoot = BlockMerkleRoot(block, &mutated);
+ assert(!mutated);
+ while (!CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) ++block.nNonce;
+ return block;
+}
+
+// Number of shared use_counts we expect for a tx we haven't touched
+// (block + mempool + our copy from the GetSharedTx call)
+constexpr long SHARED_TX_OFFSET{3};
+
+BOOST_AUTO_TEST_CASE(SimpleRoundTripTest)
+{
+ CTxMemPool pool;
+ TestMemPoolEntryHelper entry;
+ CBlock block(BuildBlockTestCase());
+
+ LOCK(pool.cs);
+ pool.addUnchecked(block.vtx[2]->GetHash(), entry.FromTx(block.vtx[2]));
+ BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
+
+ // Do a simple ShortTxIDs RT
+ {
+ CBlockHeaderAndShortTxIDs shortIDs(block, true);
+
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << shortIDs;
+
+ CBlockHeaderAndShortTxIDs shortIDs2;
+ stream >> shortIDs2;
+
+ PartiallyDownloadedBlock partialBlock(&pool);
+ BOOST_CHECK(partialBlock.InitData(shortIDs2, extra_txn) == READ_STATUS_OK);
+ BOOST_CHECK( partialBlock.IsTxAvailable(0));
+ BOOST_CHECK(!partialBlock.IsTxAvailable(1));
+ BOOST_CHECK( partialBlock.IsTxAvailable(2));
+
+ BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1);
+
+ size_t poolSize = pool.size();
+ pool.removeRecursive(*block.vtx[2]);
+ BOOST_CHECK_EQUAL(pool.size(), poolSize - 1);
+
+ CBlock block2;
+ {
+ PartiallyDownloadedBlock tmp = partialBlock;
+ BOOST_CHECK(partialBlock.FillBlock(block2, {}) == READ_STATUS_INVALID); // No transactions
+ partialBlock = tmp;
+ }
+
+ // Wrong transaction
+ {
+ PartiallyDownloadedBlock tmp = partialBlock;
+ partialBlock.FillBlock(block2, {block.vtx[2]}); // Current implementation doesn't check txn here, but don't require that
+ partialBlock = tmp;
+ }
+ bool mutated;
+ BOOST_CHECK(block.hashMerkleRoot != BlockMerkleRoot(block2, &mutated));
+
+ CBlock block3;
+ BOOST_CHECK(partialBlock.FillBlock(block3, {block.vtx[1]}) == READ_STATUS_OK);
+ BOOST_CHECK_EQUAL(block.GetHash().ToString(), block3.GetHash().ToString());
+ BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block3, &mutated).ToString());
+ BOOST_CHECK(!mutated);
+ }
+}
+
+class TestHeaderAndShortIDs {
+ // Utility to encode custom CBlockHeaderAndShortTxIDs
+public:
+ CBlockHeader header;
+ uint64_t nonce;
+ std::vector<uint64_t> shorttxids;
+ std::vector<PrefilledTransaction> prefilledtxn;
+
+ explicit TestHeaderAndShortIDs(const CBlockHeaderAndShortTxIDs& orig) {
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << orig;
+ stream >> *this;
+ }
+ explicit TestHeaderAndShortIDs(const CBlock& block) :
+ TestHeaderAndShortIDs(CBlockHeaderAndShortTxIDs(block, true)) {}
+
+ uint64_t GetShortID(const uint256& txhash) const {
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << *this;
+ CBlockHeaderAndShortTxIDs base;
+ stream >> base;
+ return base.GetShortID(txhash);
+ }
+
+ ADD_SERIALIZE_METHODS;
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream& s, Operation ser_action) {
+ READWRITE(header);
+ READWRITE(nonce);
+ size_t shorttxids_size = shorttxids.size();
+ READWRITE(VARINT(shorttxids_size));
+ shorttxids.resize(shorttxids_size);
+ for (size_t i = 0; i < shorttxids.size(); i++) {
+ uint32_t lsb = shorttxids[i] & 0xffffffff;
+ uint16_t msb = (shorttxids[i] >> 32) & 0xffff;
+ READWRITE(lsb);
+ READWRITE(msb);
+ shorttxids[i] = (uint64_t(msb) << 32) | uint64_t(lsb);
+ }
+ READWRITE(prefilledtxn);
+ }
+};
+
+BOOST_AUTO_TEST_CASE(NonCoinbasePreforwardRTTest)
+{
+ CTxMemPool pool;
+ TestMemPoolEntryHelper entry;
+ CBlock block(BuildBlockTestCase());
+
+ LOCK(pool.cs);
+ pool.addUnchecked(block.vtx[2]->GetHash(), entry.FromTx(block.vtx[2]));
+ BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
+
+ uint256 txhash;
+
+ // Test with pre-forwarding tx 1, but not coinbase
+ {
+ TestHeaderAndShortIDs shortIDs(block);
+ shortIDs.prefilledtxn.resize(1);
+ shortIDs.prefilledtxn[0] = {1, block.vtx[1]};
+ shortIDs.shorttxids.resize(2);
+ shortIDs.shorttxids[0] = shortIDs.GetShortID(block.vtx[0]->GetHash());
+ shortIDs.shorttxids[1] = shortIDs.GetShortID(block.vtx[2]->GetHash());
+
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << shortIDs;
+
+ CBlockHeaderAndShortTxIDs shortIDs2;
+ stream >> shortIDs2;
+
+ PartiallyDownloadedBlock partialBlock(&pool);
+ BOOST_CHECK(partialBlock.InitData(shortIDs2, extra_txn) == READ_STATUS_OK);
+ BOOST_CHECK(!partialBlock.IsTxAvailable(0));
+ BOOST_CHECK( partialBlock.IsTxAvailable(1));
+ BOOST_CHECK( partialBlock.IsTxAvailable(2));
+
+ BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1); // +1 because of partialBlock
+
+ CBlock block2;
+ {
+ PartiallyDownloadedBlock tmp = partialBlock;
+ BOOST_CHECK(partialBlock.FillBlock(block2, {}) == READ_STATUS_INVALID); // No transactions
+ partialBlock = tmp;
+ }
+
+ // Wrong transaction
+ {
+ PartiallyDownloadedBlock tmp = partialBlock;
+ partialBlock.FillBlock(block2, {block.vtx[1]}); // Current implementation doesn't check txn here, but don't require that
+ partialBlock = tmp;
+ }
+ BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 2); // +2 because of partialBlock and block2
+ bool mutated;
+ BOOST_CHECK(block.hashMerkleRoot != BlockMerkleRoot(block2, &mutated));
+
+ CBlock block3;
+ PartiallyDownloadedBlock partialBlockCopy = partialBlock;
+ BOOST_CHECK(partialBlock.FillBlock(block3, {block.vtx[0]}) == READ_STATUS_OK);
+ BOOST_CHECK_EQUAL(block.GetHash().ToString(), block3.GetHash().ToString());
+ BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block3, &mutated).ToString());
+ BOOST_CHECK(!mutated);
+
+ BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[2]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 3); // +2 because of partialBlock and block2 and block3
+
+ txhash = block.vtx[2]->GetHash();
+ block.vtx.clear();
+ block2.vtx.clear();
+ block3.vtx.clear();
+ BOOST_CHECK_EQUAL(pool.mapTx.find(txhash)->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1 - 1); // + 1 because of partialBlock; -1 because of block.
+ }
+ BOOST_CHECK_EQUAL(pool.mapTx.find(txhash)->GetSharedTx().use_count(), SHARED_TX_OFFSET - 1); // -1 because of block
+}
+
+BOOST_AUTO_TEST_CASE(SufficientPreforwardRTTest)
+{
+ CTxMemPool pool;
+ TestMemPoolEntryHelper entry;
+ CBlock block(BuildBlockTestCase());
+
+ LOCK(pool.cs);
+ pool.addUnchecked(block.vtx[1]->GetHash(), entry.FromTx(block.vtx[1]));
+ BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[1]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 0);
+
+ uint256 txhash;
+
+ // Test with pre-forwarding coinbase + tx 2 with tx 1 in mempool
+ {
+ TestHeaderAndShortIDs shortIDs(block);
+ shortIDs.prefilledtxn.resize(2);
+ shortIDs.prefilledtxn[0] = {0, block.vtx[0]};
+ shortIDs.prefilledtxn[1] = {1, block.vtx[2]}; // id == 1 as it is 1 after index 1
+ shortIDs.shorttxids.resize(1);
+ shortIDs.shorttxids[0] = shortIDs.GetShortID(block.vtx[1]->GetHash());
+
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << shortIDs;
+
+ CBlockHeaderAndShortTxIDs shortIDs2;
+ stream >> shortIDs2;
+
+ PartiallyDownloadedBlock partialBlock(&pool);
+ BOOST_CHECK(partialBlock.InitData(shortIDs2, extra_txn) == READ_STATUS_OK);
+ BOOST_CHECK( partialBlock.IsTxAvailable(0));
+ BOOST_CHECK( partialBlock.IsTxAvailable(1));
+ BOOST_CHECK( partialBlock.IsTxAvailable(2));
+
+ BOOST_CHECK_EQUAL(pool.mapTx.find(block.vtx[1]->GetHash())->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1);
+
+ CBlock block2;
+ PartiallyDownloadedBlock partialBlockCopy = partialBlock;
+ BOOST_CHECK(partialBlock.FillBlock(block2, {}) == READ_STATUS_OK);
+ BOOST_CHECK_EQUAL(block.GetHash().ToString(), block2.GetHash().ToString());
+ bool mutated;
+ BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block2, &mutated).ToString());
+ BOOST_CHECK(!mutated);
+
+ txhash = block.vtx[1]->GetHash();
+ block.vtx.clear();
+ block2.vtx.clear();
+ BOOST_CHECK_EQUAL(pool.mapTx.find(txhash)->GetSharedTx().use_count(), SHARED_TX_OFFSET + 1 - 1); // + 1 because of partialBlock; -1 because of block.
+ }
+ BOOST_CHECK_EQUAL(pool.mapTx.find(txhash)->GetSharedTx().use_count(), SHARED_TX_OFFSET - 1); // -1 because of block
+}
+
+BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest)
+{
+ CTxMemPool pool;
+ CMutableTransaction coinbase;
+ coinbase.vin.resize(1);
+ coinbase.vin[0].scriptSig.resize(10);
+ coinbase.vout.resize(1);
+ coinbase.vout[0].nValue = 42;
+
+ CBlock block;
+ block.vtx.resize(1);
+ block.vtx[0] = MakeTransactionRef(std::move(coinbase));
+ block.nVersion = 42;
+ block.hashPrevBlock = InsecureRand256();
+ block.nBits = 0x207fffff;
+
+ bool mutated;
+ block.hashMerkleRoot = BlockMerkleRoot(block, &mutated);
+ assert(!mutated);
+ while (!CheckProofOfWork(block.GetHash(), block.nBits, Params().GetConsensus())) ++block.nNonce;
+
+ // Test simple header round-trip with only coinbase
+ {
+ CBlockHeaderAndShortTxIDs shortIDs(block, false);
+
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << shortIDs;
+
+ CBlockHeaderAndShortTxIDs shortIDs2;
+ stream >> shortIDs2;
+
+ PartiallyDownloadedBlock partialBlock(&pool);
+ BOOST_CHECK(partialBlock.InitData(shortIDs2, extra_txn) == READ_STATUS_OK);
+ BOOST_CHECK(partialBlock.IsTxAvailable(0));
+
+ CBlock block2;
+ std::vector<CTransactionRef> vtx_missing;
+ BOOST_CHECK(partialBlock.FillBlock(block2, vtx_missing) == READ_STATUS_OK);
+ BOOST_CHECK_EQUAL(block.GetHash().ToString(), block2.GetHash().ToString());
+ BOOST_CHECK_EQUAL(block.hashMerkleRoot.ToString(), BlockMerkleRoot(block2, &mutated).ToString());
+ BOOST_CHECK(!mutated);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(TransactionsRequestSerializationTest) {
+ BlockTransactionsRequest req1;
+ req1.blockhash = InsecureRand256();
+ req1.indexes.resize(4);
+ req1.indexes[0] = 0;
+ req1.indexes[1] = 1;
+ req1.indexes[2] = 3;
+ req1.indexes[3] = 4;
+
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << req1;
+
+ BlockTransactionsRequest req2;
+ stream >> req2;
+
+ BOOST_CHECK_EQUAL(req1.blockhash.ToString(), req2.blockhash.ToString());
+ BOOST_CHECK_EQUAL(req1.indexes.size(), req2.indexes.size());
+ BOOST_CHECK_EQUAL(req1.indexes[0], req2.indexes[0]);
+ BOOST_CHECK_EQUAL(req1.indexes[1], req2.indexes[1]);
+ BOOST_CHECK_EQUAL(req1.indexes[2], req2.indexes[2]);
+ BOOST_CHECK_EQUAL(req1.indexes[3], req2.indexes[3]);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp
new file mode 100644
index 0000000000..8a8e8bfdc3
--- /dev/null
+++ b/src/test/bloom_tests.cpp
@@ -0,0 +1,536 @@
+// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <bloom.h>
+
+#include <clientversion.h>
+#include <key.h>
+#include <key_io.h>
+#include <merkleblock.h>
+#include <primitives/block.h>
+#include <random.h>
+#include <serialize.h>
+#include <streams.h>
+#include <uint256.h>
+#include <util.h>
+#include <utilstrencodings.h>
+#include <test/test_bitcoin.h>
+
+#include <vector>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(bloom_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize)
+{
+ CBloomFilter filter(3, 0.01, 0, BLOOM_UPDATE_ALL);
+
+ filter.insert(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8"));
+ BOOST_CHECK_MESSAGE( filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "Bloom filter doesn't contain just-inserted object!");
+ // One bit different in first byte
+ BOOST_CHECK_MESSAGE(!filter.contains(ParseHex("19108ad8ed9bb6274d3980bab5a85c048f0950c8")), "Bloom filter contains something it shouldn't!");
+
+ filter.insert(ParseHex("b5a2c786d9ef4658287ced5914b37a1b4aa32eee"));
+ BOOST_CHECK_MESSAGE(filter.contains(ParseHex("b5a2c786d9ef4658287ced5914b37a1b4aa32eee")), "Bloom filter doesn't contain just-inserted object (2)!");
+
+ filter.insert(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5"));
+ BOOST_CHECK_MESSAGE(filter.contains(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5")), "Bloom filter doesn't contain just-inserted object (3)!");
+
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << filter;
+
+ std::vector<unsigned char> vch = ParseHex("03614e9b050000000000000001");
+ std::vector<char> expected(vch.size());
+
+ for (unsigned int i = 0; i < vch.size(); i++)
+ expected[i] = (char)vch[i];
+
+ BOOST_CHECK_EQUAL_COLLECTIONS(stream.begin(), stream.end(), expected.begin(), expected.end());
+
+ BOOST_CHECK_MESSAGE( filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "Bloom filter doesn't contain just-inserted object!");
+ filter.clear();
+ BOOST_CHECK_MESSAGE( !filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "Bloom filter should be empty!");
+}
+
+BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize_with_tweak)
+{
+ // Same test as bloom_create_insert_serialize, but we add a nTweak of 100
+ CBloomFilter filter(3, 0.01, 2147483649UL, BLOOM_UPDATE_ALL);
+
+ filter.insert(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8"));
+ BOOST_CHECK_MESSAGE( filter.contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "Bloom filter doesn't contain just-inserted object!");
+ // One bit different in first byte
+ BOOST_CHECK_MESSAGE(!filter.contains(ParseHex("19108ad8ed9bb6274d3980bab5a85c048f0950c8")), "Bloom filter contains something it shouldn't!");
+
+ filter.insert(ParseHex("b5a2c786d9ef4658287ced5914b37a1b4aa32eee"));
+ BOOST_CHECK_MESSAGE(filter.contains(ParseHex("b5a2c786d9ef4658287ced5914b37a1b4aa32eee")), "Bloom filter doesn't contain just-inserted object (2)!");
+
+ filter.insert(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5"));
+ BOOST_CHECK_MESSAGE(filter.contains(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5")), "Bloom filter doesn't contain just-inserted object (3)!");
+
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << filter;
+
+ std::vector<unsigned char> vch = ParseHex("03ce4299050000000100008001");
+ std::vector<char> expected(vch.size());
+
+ for (unsigned int i = 0; i < vch.size(); i++)
+ expected[i] = (char)vch[i];
+
+ BOOST_CHECK_EQUAL_COLLECTIONS(stream.begin(), stream.end(), expected.begin(), expected.end());
+}
+
+BOOST_AUTO_TEST_CASE(bloom_create_insert_key)
+{
+ std::string strSecret = std::string("5Kg1gnAjaLfKiwhhPpGS3QfRg2m6awQvaj98JCZBZQ5SuS2F15C");
+ CKey key = DecodeSecret(strSecret);
+ CPubKey pubkey = key.GetPubKey();
+ std::vector<unsigned char> vchPubKey(pubkey.begin(), pubkey.end());
+
+ CBloomFilter filter(2, 0.001, 0, BLOOM_UPDATE_ALL);
+ filter.insert(vchPubKey);
+ uint160 hash = pubkey.GetID();
+ filter.insert(std::vector<unsigned char>(hash.begin(), hash.end()));
+
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << filter;
+
+ std::vector<unsigned char> vch = ParseHex("038fc16b080000000000000001");
+ std::vector<char> expected(vch.size());
+
+ for (unsigned int i = 0; i < vch.size(); i++)
+ expected[i] = (char)vch[i];
+
+ BOOST_CHECK_EQUAL_COLLECTIONS(stream.begin(), stream.end(), expected.begin(), expected.end());
+}
+
+BOOST_AUTO_TEST_CASE(bloom_match)
+{
+ // Random real transaction (b4749f017444b051c44dfd2720e88f314ff94f3dd6d56d40ef65854fcd7fff6b)
+ CDataStream stream(ParseHex("01000000010b26e9b7735eb6aabdf358bab62f9816a21ba9ebdb719d5299e88607d722c190000000008b4830450220070aca44506c5cef3a16ed519d7c3c39f8aab192c4e1c90d065f37b8a4af6141022100a8e160b856c2d43d27d8fba71e5aef6405b8643ac4cb7cb3c462aced7f14711a0141046d11fee51b0e60666d5049a9101a72741df480b96ee26488a4d3466b95c9a40ac5eeef87e10a5cd336c19a84565f80fa6c547957b7700ff4dfbdefe76036c339ffffffff021bff3d11000000001976a91404943fdd508053c75000106d3bc6e2754dbcff1988ac2f15de00000000001976a914a266436d2965547608b9e15d9032a7b9d64fa43188ac00000000"), SER_DISK, CLIENT_VERSION);
+ CTransaction tx(deserialize, stream);
+
+ // and one which spends it (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};
+ std::vector<unsigned char> vch(ch, ch + sizeof(ch) -1);
+ CDataStream spendStream(vch, SER_DISK, CLIENT_VERSION);
+ CTransaction spendingTx(deserialize, spendStream);
+
+ CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ filter.insert(uint256S("0xb4749f017444b051c44dfd2720e88f314ff94f3dd6d56d40ef65854fcd7fff6b"));
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match tx hash");
+
+ filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ // byte-reversed tx hash
+ filter.insert(ParseHex("6bff7fcd4f8565ef406dd5d63d4ff94f318fe82027fd4dc451b04474019f74b4"));
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match manually serialized tx hash");
+
+ filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ filter.insert(ParseHex("30450220070aca44506c5cef3a16ed519d7c3c39f8aab192c4e1c90d065f37b8a4af6141022100a8e160b856c2d43d27d8fba71e5aef6405b8643ac4cb7cb3c462aced7f14711a01"));
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match input signature");
+
+ filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ filter.insert(ParseHex("046d11fee51b0e60666d5049a9101a72741df480b96ee26488a4d3466b95c9a40ac5eeef87e10a5cd336c19a84565f80fa6c547957b7700ff4dfbdefe76036c339"));
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match input pub key");
+
+ filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ filter.insert(ParseHex("04943fdd508053c75000106d3bc6e2754dbcff19"));
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match output address");
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(spendingTx), "Simple Bloom filter didn't add output");
+
+ filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ filter.insert(ParseHex("a266436d2965547608b9e15d9032a7b9d64fa431"));
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match output address");
+
+ filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ filter.insert(COutPoint(uint256S("0x90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 0));
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match COutPoint");
+
+ filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ COutPoint prevOutPoint(uint256S("0x90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 0);
+ {
+ std::vector<unsigned char> data(32 + sizeof(unsigned int));
+ memcpy(data.data(), prevOutPoint.hash.begin(), 32);
+ memcpy(data.data()+32, &prevOutPoint.n, sizeof(unsigned int));
+ filter.insert(data);
+ }
+ BOOST_CHECK_MESSAGE(filter.IsRelevantAndUpdate(tx), "Simple Bloom filter didn't match manually serialized COutPoint");
+
+ filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ filter.insert(uint256S("00000009e784f32f62ef849763d4f45b98e07ba658647343b915ff832b110436"));
+ BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx), "Simple Bloom filter matched random tx hash");
+
+ filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ filter.insert(ParseHex("0000006d2965547608b9e15d9032a7b9d64fa431"));
+ BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx), "Simple Bloom filter matched random address");
+
+ filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ filter.insert(COutPoint(uint256S("0x90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 1));
+ BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx), "Simple Bloom filter matched COutPoint for an output we didn't care about");
+
+ filter = CBloomFilter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ filter.insert(COutPoint(uint256S("0x000000d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b"), 0));
+ BOOST_CHECK_MESSAGE(!filter.IsRelevantAndUpdate(tx), "Simple Bloom filter matched COutPoint for an output we didn't care about");
+}
+
+BOOST_AUTO_TEST_CASE(merkle_block_1)
+{
+ CBlock block = getBlock13b8a();
+ CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ // Match the last transaction
+ filter.insert(uint256S("0x74d681e0e03bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20"));
+
+ CMerkleBlock merkleBlock(block, filter);
+ BOOST_CHECK_EQUAL(merkleBlock.header.GetHash().GetHex(), block.GetHash().GetHex());
+
+ BOOST_CHECK_EQUAL(merkleBlock.vMatchedTxn.size(), 1U);
+ std::pair<unsigned int, uint256> pair = merkleBlock.vMatchedTxn[0];
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256S("0x74d681e0e03bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20"));
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 8);
+
+ std::vector<uint256> vMatched;
+ std::vector<unsigned int> vIndex;
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot);
+ BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
+ for (unsigned int i = 0; i < vMatched.size(); i++)
+ BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
+
+ // Also match the 8th transaction
+ filter.insert(uint256S("0xdd1fd2a6fc16404faf339881a90adbde7f4f728691ac62e8f168809cdfae1053"));
+ merkleBlock = CMerkleBlock(block, filter);
+ BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash());
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 2);
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[1] == pair);
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256S("0xdd1fd2a6fc16404faf339881a90adbde7f4f728691ac62e8f168809cdfae1053"));
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 7);
+
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot);
+ BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
+ for (unsigned int i = 0; i < vMatched.size(); i++)
+ BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
+}
+
+BOOST_AUTO_TEST_CASE(merkle_block_2)
+{
+ // Random real block (000000005a4ded781e667e06ceefafb71410b511fe0d5adc3e5a27ecbec34ae6)
+ // With 4 txes
+ CBlock block;
+ CDataStream stream(ParseHex("0100000075616236cc2126035fadb38deb65b9102cc2c41c09cdf29fc051906800000000fe7d5e12ef0ff901f6050211249919b1c0653771832b3a80c66cea42847f0ae1d4d26e49ffff001d00f0a4410401000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d029105ffffffff0100f2052a010000004341046d8709a041d34357697dfcb30a9d05900a6294078012bf3bb09c6f9b525f1d16d5503d7905db1ada9501446ea00728668fc5719aa80be2fdfc8a858a4dbdd4fbac00000000010000000255605dc6f5c3dc148b6da58442b0b2cd422be385eab2ebea4119ee9c268d28350000000049483045022100aa46504baa86df8a33b1192b1b9367b4d729dc41e389f2c04f3e5c7f0559aae702205e82253a54bf5c4f65b7428551554b2045167d6d206dfe6a2e198127d3f7df1501ffffffff55605dc6f5c3dc148b6da58442b0b2cd422be385eab2ebea4119ee9c268d2835010000004847304402202329484c35fa9d6bb32a55a70c0982f606ce0e3634b69006138683bcd12cbb6602200c28feb1e2555c3210f1dddb299738b4ff8bbe9667b68cb8764b5ac17b7adf0001ffffffff0200e1f505000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00180d8f000000004341044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cfc617c0ea45afac0000000001000000025f9a06d3acdceb56be1bfeaa3e8a25e62d182fa24fefe899d1c17f1dad4c2028000000004847304402205d6058484157235b06028c30736c15613a28bdb768ee628094ca8b0030d4d6eb0220328789c9a2ec27ddaec0ad5ef58efded42e6ea17c2e1ce838f3d6913f5e95db601ffffffff5f9a06d3acdceb56be1bfeaa3e8a25e62d182fa24fefe899d1c17f1dad4c2028010000004a493046022100c45af050d3cea806cedd0ab22520c53ebe63b987b8954146cdca42487b84bdd6022100b9b027716a6b59e640da50a864d6dd8a0ef24c76ce62391fa3eabaf4d2886d2d01ffffffff0200e1f505000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00180d8f000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac000000000100000002e2274e5fea1bf29d963914bd301aa63b64daaf8a3e88f119b5046ca5738a0f6b0000000048473044022016e7a727a061ea2254a6c358376aaa617ac537eb836c77d646ebda4c748aac8b0220192ce28bf9f2c06a6467e6531e27648d2b3e2e2bae85159c9242939840295ba501ffffffffe2274e5fea1bf29d963914bd301aa63b64daaf8a3e88f119b5046ca5738a0f6b010000004a493046022100b7a1a755588d4190118936e15cd217d133b0e4a53c3c15924010d5648d8925c9022100aaef031874db2114f2d869ac2de4ae53908fbfea5b2b1862e181626bb9005c9f01ffffffff0200e1f505000000004341044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cfc617c0ea45afac00180d8f000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00000000"), SER_NETWORK, PROTOCOL_VERSION);
+ stream >> block;
+
+ CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ // Match the first transaction
+ filter.insert(uint256S("0xe980fe9f792d014e73b95203dc1335c5f9ce19ac537a419e6df5b47aecb93b70"));
+
+ CMerkleBlock merkleBlock(block, filter);
+ BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash());
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 1);
+ std::pair<unsigned int, uint256> pair = merkleBlock.vMatchedTxn[0];
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256S("0xe980fe9f792d014e73b95203dc1335c5f9ce19ac537a419e6df5b47aecb93b70"));
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 0);
+
+ std::vector<uint256> vMatched;
+ std::vector<unsigned int> vIndex;
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot);
+ BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
+ for (unsigned int i = 0; i < vMatched.size(); i++)
+ BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
+
+ // Match an output from the second transaction (the pubkey for address 1DZTzaBHUDM7T3QvUKBz4qXMRpkg8jsfB5)
+ // This should match the third transaction because it spends the output matched
+ // It also matches the fourth transaction, which spends to the pubkey again
+ filter.insert(ParseHex("044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cfc617c0ea45af"));
+
+ merkleBlock = CMerkleBlock(block, filter);
+ BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash());
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 4);
+
+ BOOST_CHECK(pair == merkleBlock.vMatchedTxn[0]);
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[1].second == uint256S("0x28204cad1d7fc1d199e8ef4fa22f182de6258a3eaafe1bbe56ebdcacd3069a5f"));
+ BOOST_CHECK(merkleBlock.vMatchedTxn[1].first == 1);
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[2].second == uint256S("0x6b0f8a73a56c04b519f1883e8aafda643ba61a30bd1439969df21bea5f4e27e2"));
+ BOOST_CHECK(merkleBlock.vMatchedTxn[2].first == 2);
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[3].second == uint256S("0x3c1d7e82342158e4109df2e0b6348b6e84e403d8b4046d7007663ace63cddb23"));
+ BOOST_CHECK(merkleBlock.vMatchedTxn[3].first == 3);
+
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot);
+ BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
+ for (unsigned int i = 0; i < vMatched.size(); i++)
+ BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
+}
+
+BOOST_AUTO_TEST_CASE(merkle_block_2_with_update_none)
+{
+ // Random real block (000000005a4ded781e667e06ceefafb71410b511fe0d5adc3e5a27ecbec34ae6)
+ // With 4 txes
+ CBlock block;
+ CDataStream stream(ParseHex("0100000075616236cc2126035fadb38deb65b9102cc2c41c09cdf29fc051906800000000fe7d5e12ef0ff901f6050211249919b1c0653771832b3a80c66cea42847f0ae1d4d26e49ffff001d00f0a4410401000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d029105ffffffff0100f2052a010000004341046d8709a041d34357697dfcb30a9d05900a6294078012bf3bb09c6f9b525f1d16d5503d7905db1ada9501446ea00728668fc5719aa80be2fdfc8a858a4dbdd4fbac00000000010000000255605dc6f5c3dc148b6da58442b0b2cd422be385eab2ebea4119ee9c268d28350000000049483045022100aa46504baa86df8a33b1192b1b9367b4d729dc41e389f2c04f3e5c7f0559aae702205e82253a54bf5c4f65b7428551554b2045167d6d206dfe6a2e198127d3f7df1501ffffffff55605dc6f5c3dc148b6da58442b0b2cd422be385eab2ebea4119ee9c268d2835010000004847304402202329484c35fa9d6bb32a55a70c0982f606ce0e3634b69006138683bcd12cbb6602200c28feb1e2555c3210f1dddb299738b4ff8bbe9667b68cb8764b5ac17b7adf0001ffffffff0200e1f505000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00180d8f000000004341044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cfc617c0ea45afac0000000001000000025f9a06d3acdceb56be1bfeaa3e8a25e62d182fa24fefe899d1c17f1dad4c2028000000004847304402205d6058484157235b06028c30736c15613a28bdb768ee628094ca8b0030d4d6eb0220328789c9a2ec27ddaec0ad5ef58efded42e6ea17c2e1ce838f3d6913f5e95db601ffffffff5f9a06d3acdceb56be1bfeaa3e8a25e62d182fa24fefe899d1c17f1dad4c2028010000004a493046022100c45af050d3cea806cedd0ab22520c53ebe63b987b8954146cdca42487b84bdd6022100b9b027716a6b59e640da50a864d6dd8a0ef24c76ce62391fa3eabaf4d2886d2d01ffffffff0200e1f505000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00180d8f000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac000000000100000002e2274e5fea1bf29d963914bd301aa63b64daaf8a3e88f119b5046ca5738a0f6b0000000048473044022016e7a727a061ea2254a6c358376aaa617ac537eb836c77d646ebda4c748aac8b0220192ce28bf9f2c06a6467e6531e27648d2b3e2e2bae85159c9242939840295ba501ffffffffe2274e5fea1bf29d963914bd301aa63b64daaf8a3e88f119b5046ca5738a0f6b010000004a493046022100b7a1a755588d4190118936e15cd217d133b0e4a53c3c15924010d5648d8925c9022100aaef031874db2114f2d869ac2de4ae53908fbfea5b2b1862e181626bb9005c9f01ffffffff0200e1f505000000004341044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cfc617c0ea45afac00180d8f000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00000000"), SER_NETWORK, PROTOCOL_VERSION);
+ stream >> block;
+
+ CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_NONE);
+ // Match the first transaction
+ filter.insert(uint256S("0xe980fe9f792d014e73b95203dc1335c5f9ce19ac537a419e6df5b47aecb93b70"));
+
+ CMerkleBlock merkleBlock(block, filter);
+ BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash());
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 1);
+ std::pair<unsigned int, uint256> pair = merkleBlock.vMatchedTxn[0];
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256S("0xe980fe9f792d014e73b95203dc1335c5f9ce19ac537a419e6df5b47aecb93b70"));
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 0);
+
+ std::vector<uint256> vMatched;
+ std::vector<unsigned int> vIndex;
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot);
+ BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
+ for (unsigned int i = 0; i < vMatched.size(); i++)
+ BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
+
+ // Match an output from the second transaction (the pubkey for address 1DZTzaBHUDM7T3QvUKBz4qXMRpkg8jsfB5)
+ // This should not match the third transaction though it spends the output matched
+ // It will match the fourth transaction, which has another pay-to-pubkey output to the same address
+ filter.insert(ParseHex("044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cfc617c0ea45af"));
+
+ merkleBlock = CMerkleBlock(block, filter);
+ BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash());
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 3);
+
+ BOOST_CHECK(pair == merkleBlock.vMatchedTxn[0]);
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[1].second == uint256S("0x28204cad1d7fc1d199e8ef4fa22f182de6258a3eaafe1bbe56ebdcacd3069a5f"));
+ BOOST_CHECK(merkleBlock.vMatchedTxn[1].first == 1);
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[2].second == uint256S("0x3c1d7e82342158e4109df2e0b6348b6e84e403d8b4046d7007663ace63cddb23"));
+ BOOST_CHECK(merkleBlock.vMatchedTxn[2].first == 3);
+
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot);
+ BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
+ for (unsigned int i = 0; i < vMatched.size(); i++)
+ BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
+}
+
+BOOST_AUTO_TEST_CASE(merkle_block_3_and_serialize)
+{
+ // Random real block (000000000000dab0130bbcc991d3d7ae6b81aa6f50a798888dfe62337458dc45)
+ // With one tx
+ CBlock block;
+ CDataStream stream(ParseHex("0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b4b8b0000000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f196367291b4d4c86041b8fa45d630101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff08044c86041b020a02ffffffff0100f2052a01000000434104ecd3229b0571c3be876feaac0442a9f13c5a572742927af1dc623353ecf8c202225f64868137a18cdd85cbbb4c74fbccfd4f49639cf1bdc94a5672bb15ad5d4cac00000000"), SER_NETWORK, PROTOCOL_VERSION);
+ stream >> block;
+
+ CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ // Match the only transaction
+ filter.insert(uint256S("0x63194f18be0af63f2c6bc9dc0f777cbefed3d9415c4af83f3ee3a3d669c00cb5"));
+
+ CMerkleBlock merkleBlock(block, filter);
+ BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash());
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 1);
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256S("0x63194f18be0af63f2c6bc9dc0f777cbefed3d9415c4af83f3ee3a3d669c00cb5"));
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 0);
+
+ std::vector<uint256> vMatched;
+ std::vector<unsigned int> vIndex;
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot);
+ BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
+ for (unsigned int i = 0; i < vMatched.size(); i++)
+ BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
+
+ CDataStream merkleStream(SER_NETWORK, PROTOCOL_VERSION);
+ merkleStream << merkleBlock;
+
+ std::vector<unsigned char> vch = ParseHex("0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b4b8b0000000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f196367291b4d4c86041b8fa45d630100000001b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f19630101");
+ std::vector<char> expected(vch.size());
+
+ for (unsigned int i = 0; i < vch.size(); i++)
+ expected[i] = (char)vch[i];
+
+ BOOST_CHECK_EQUAL_COLLECTIONS(expected.begin(), expected.end(), merkleStream.begin(), merkleStream.end());
+}
+
+BOOST_AUTO_TEST_CASE(merkle_block_4)
+{
+ // Random real block (000000000000b731f2eef9e8c63173adfb07e41bd53eb0ef0a6b720d6cb6dea4)
+ // With 7 txes
+ CBlock block;
+ CDataStream stream(ParseHex("0100000082bb869cf3a793432a66e826e05a6fc37469f8efb7421dc880670100000000007f16c5962e8bd963659c793ce370d95f093bc7e367117b3c30c1f8fdd0d9728776381b4d4c86041b554b85290701000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07044c86041b0136ffffffff0100f2052a01000000434104eaafc2314def4ca98ac970241bcab022b9c1e1f4ea423a20f134c876f2c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce13ad1357231a2252247d97a46a91ac000000000100000001bcad20a6a29827d1424f08989255120bf7f3e9e3cdaaa6bb31b0737fe048724300000000494830450220356e834b046cadc0f8ebb5a8a017b02de59c86305403dad52cd77b55af062ea10221009253cd6c119d4729b77c978e1e2aa19f5ea6e0e52b3f16e32fa608cd5bab753901ffffffff02008d380c010000001976a9142b4b8072ecbba129b6453c63e129e643207249ca88ac0065cd1d000000001976a9141b8dd13b994bcfc787b32aeadf58ccb3615cbd5488ac000000000100000003fdacf9b3eb077412e7a968d2e4f11b9a9dee312d666187ed77ee7d26af16cb0b000000008c493046022100ea1608e70911ca0de5af51ba57ad23b9a51db8d28f82c53563c56a05c20f5a87022100a8bdc8b4a8acc8634c6b420410150775eb7f2474f5615f7fccd65af30f310fbf01410465fdf49e29b06b9a1582287b6279014f834edc317695d125ef623c1cc3aaece245bd69fcad7508666e9c74a49dc9056d5fc14338ef38118dc4afae5fe2c585caffffffff309e1913634ecb50f3c4f83e96e70b2df071b497b8973a3e75429df397b5af83000000004948304502202bdb79c596a9ffc24e96f4386199aba386e9bc7b6071516e2b51dda942b3a1ed022100c53a857e76b724fc14d45311eac5019650d415c3abb5428f3aae16d8e69bec2301ffffffff2089e33491695080c9edc18a428f7d834db5b6d372df13ce2b1b0e0cbcb1e6c10000000049483045022100d4ce67c5896ee251c810ac1ff9ceccd328b497c8f553ab6e08431e7d40bad6b5022033119c0c2b7d792d31f1187779c7bd95aefd93d90a715586d73801d9b47471c601ffffffff0100714460030000001976a914c7b55141d097ea5df7a0ed330cf794376e53ec8d88ac0000000001000000045bf0e214aa4069a3e792ecee1e1bf0c1d397cde8dd08138f4b72a00681743447000000008b48304502200c45de8c4f3e2c1821f2fc878cba97b1e6f8807d94930713aa1c86a67b9bf1e40221008581abfef2e30f957815fc89978423746b2086375ca8ecf359c85c2a5b7c88ad01410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffffffffd669f7d7958d40fc59d2253d88e0f248e29b599c80bbcec344a83dda5f9aa72c000000008a473044022078124c8beeaa825f9e0b30bff96e564dd859432f2d0cb3b72d3d5d93d38d7e930220691d233b6c0f995be5acb03d70a7f7a65b6bc9bdd426260f38a1346669507a3601410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95fffffffff878af0d93f5229a68166cf051fd372bb7a537232946e0a46f53636b4dafdaa4000000008c493046022100c717d1714551663f69c3c5759bdbb3a0fcd3fab023abc0e522fe6440de35d8290221008d9cbe25bffc44af2b18e81c58eb37293fd7fe1c2e7b46fc37ee8c96c50ab1e201410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffffffff27f2b668859cd7f2f894aa0fd2d9e60963bcd07c88973f425f999b8cbfd7a1e2000000008c493046022100e00847147cbf517bcc2f502f3ddc6d284358d102ed20d47a8aa788a62f0db780022100d17b2d6fa84dcaf1c95d88d7e7c30385aecf415588d749afd3ec81f6022cecd701410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffffffff0100c817a8040000001976a914b6efd80d99179f4f4ff6f4dd0a007d018c385d2188ac000000000100000001834537b2f1ce8ef9373a258e10545ce5a50b758df616cd4356e0032554ebd3c4000000008b483045022100e68f422dd7c34fdce11eeb4509ddae38201773dd62f284e8aa9d96f85099d0b002202243bd399ff96b649a0fad05fa759d6a882f0af8c90cf7632c2840c29070aec20141045e58067e815c2f464c6a2a15f987758374203895710c2d452442e28496ff38ba8f5fd901dc20e29e88477167fe4fc299bf818fd0d9e1632d467b2a3d9503b1aaffffffff0280d7e636030000001976a914f34c3e10eb387efe872acb614c89e78bfca7815d88ac404b4c00000000001976a914a84e272933aaf87e1715d7786c51dfaeb5b65a6f88ac00000000010000000143ac81c8e6f6ef307dfe17f3d906d999e23e0189fda838c5510d850927e03ae7000000008c4930460221009c87c344760a64cb8ae6685a3eec2c1ac1bed5b88c87de51acd0e124f266c16602210082d07c037359c3a257b5c63ebd90f5a5edf97b2ac1c434b08ca998839f346dd40141040ba7e521fa7946d12edbb1d1e95a15c34bd4398195e86433c92b431cd315f455fe30032ede69cad9d1e1ed6c3c4ec0dbfced53438c625462afb792dcb098544bffffffff0240420f00000000001976a9144676d1b820d63ec272f1900d59d43bc6463d96f888ac40420f00000000001976a914648d04341d00d7968b3405c034adc38d4d8fb9bd88ac00000000010000000248cc917501ea5c55f4a8d2009c0567c40cfe037c2e71af017d0a452ff705e3f1000000008b483045022100bf5fdc86dc5f08a5d5c8e43a8c9d5b1ed8c65562e280007b52b133021acd9acc02205e325d613e555f772802bf413d36ba807892ed1a690a77811d3033b3de226e0a01410429fa713b124484cb2bd7b5557b2c0b9df7b2b1fee61825eadc5ae6c37a9920d38bfccdc7dc3cb0c47d7b173dbc9db8d37db0a33ae487982c59c6f8606e9d1791ffffffff41ed70551dd7e841883ab8f0b16bf04176b7d1480e4f0af9f3d4c3595768d068000000008b4830450221008513ad65187b903aed1102d1d0c47688127658c51106753fed0151ce9c16b80902201432b9ebcb87bd04ceb2de66035fbbaf4bf8b00d1cfe41f1a1f7338f9ad79d210141049d4cf80125bf50be1709f718c07ad15d0fc612b7da1f5570dddc35f2a352f0f27c978b06820edca9ef982c35fda2d255afba340068c5035552368bc7200c1488ffffffff0100093d00000000001976a9148edb68822f1ad580b043c7b3df2e400f8699eb4888ac00000000"), SER_NETWORK, PROTOCOL_VERSION);
+ stream >> block;
+
+ CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
+ // Match the last transaction
+ filter.insert(uint256S("0x0a2a92f0bda4727d0a13eaddf4dd9ac6b5c61a1429e6b2b818f19b15df0ac154"));
+
+ CMerkleBlock merkleBlock(block, filter);
+ BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash());
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 1);
+ std::pair<unsigned int, uint256> pair = merkleBlock.vMatchedTxn[0];
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256S("0x0a2a92f0bda4727d0a13eaddf4dd9ac6b5c61a1429e6b2b818f19b15df0ac154"));
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 6);
+
+ std::vector<uint256> vMatched;
+ std::vector<unsigned int> vIndex;
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot);
+ BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
+ for (unsigned int i = 0; i < vMatched.size(); i++)
+ BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
+
+ // Also match the 4th transaction
+ filter.insert(uint256S("0x02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041"));
+ merkleBlock = CMerkleBlock(block, filter);
+ BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash());
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn.size() == 2);
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].second == uint256S("0x02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041"));
+ BOOST_CHECK(merkleBlock.vMatchedTxn[0].first == 3);
+
+ BOOST_CHECK(merkleBlock.vMatchedTxn[1] == pair);
+
+ BOOST_CHECK(merkleBlock.txn.ExtractMatches(vMatched, vIndex) == block.hashMerkleRoot);
+ BOOST_CHECK(vMatched.size() == merkleBlock.vMatchedTxn.size());
+ for (unsigned int i = 0; i < vMatched.size(); i++)
+ BOOST_CHECK(vMatched[i] == merkleBlock.vMatchedTxn[i].second);
+}
+
+BOOST_AUTO_TEST_CASE(merkle_block_4_test_p2pubkey_only)
+{
+ // Random real block (000000000000b731f2eef9e8c63173adfb07e41bd53eb0ef0a6b720d6cb6dea4)
+ // With 7 txes
+ CBlock block;
+ CDataStream stream(ParseHex("0100000082bb869cf3a793432a66e826e05a6fc37469f8efb7421dc880670100000000007f16c5962e8bd963659c793ce370d95f093bc7e367117b3c30c1f8fdd0d9728776381b4d4c86041b554b85290701000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07044c86041b0136ffffffff0100f2052a01000000434104eaafc2314def4ca98ac970241bcab022b9c1e1f4ea423a20f134c876f2c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce13ad1357231a2252247d97a46a91ac000000000100000001bcad20a6a29827d1424f08989255120bf7f3e9e3cdaaa6bb31b0737fe048724300000000494830450220356e834b046cadc0f8ebb5a8a017b02de59c86305403dad52cd77b55af062ea10221009253cd6c119d4729b77c978e1e2aa19f5ea6e0e52b3f16e32fa608cd5bab753901ffffffff02008d380c010000001976a9142b4b8072ecbba129b6453c63e129e643207249ca88ac0065cd1d000000001976a9141b8dd13b994bcfc787b32aeadf58ccb3615cbd5488ac000000000100000003fdacf9b3eb077412e7a968d2e4f11b9a9dee312d666187ed77ee7d26af16cb0b000000008c493046022100ea1608e70911ca0de5af51ba57ad23b9a51db8d28f82c53563c56a05c20f5a87022100a8bdc8b4a8acc8634c6b420410150775eb7f2474f5615f7fccd65af30f310fbf01410465fdf49e29b06b9a1582287b6279014f834edc317695d125ef623c1cc3aaece245bd69fcad7508666e9c74a49dc9056d5fc14338ef38118dc4afae5fe2c585caffffffff309e1913634ecb50f3c4f83e96e70b2df071b497b8973a3e75429df397b5af83000000004948304502202bdb79c596a9ffc24e96f4386199aba386e9bc7b6071516e2b51dda942b3a1ed022100c53a857e76b724fc14d45311eac5019650d415c3abb5428f3aae16d8e69bec2301ffffffff2089e33491695080c9edc18a428f7d834db5b6d372df13ce2b1b0e0cbcb1e6c10000000049483045022100d4ce67c5896ee251c810ac1ff9ceccd328b497c8f553ab6e08431e7d40bad6b5022033119c0c2b7d792d31f1187779c7bd95aefd93d90a715586d73801d9b47471c601ffffffff0100714460030000001976a914c7b55141d097ea5df7a0ed330cf794376e53ec8d88ac0000000001000000045bf0e214aa4069a3e792ecee1e1bf0c1d397cde8dd08138f4b72a00681743447000000008b48304502200c45de8c4f3e2c1821f2fc878cba97b1e6f8807d94930713aa1c86a67b9bf1e40221008581abfef2e30f957815fc89978423746b2086375ca8ecf359c85c2a5b7c88ad01410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffffffffd669f7d7958d40fc59d2253d88e0f248e29b599c80bbcec344a83dda5f9aa72c000000008a473044022078124c8beeaa825f9e0b30bff96e564dd859432f2d0cb3b72d3d5d93d38d7e930220691d233b6c0f995be5acb03d70a7f7a65b6bc9bdd426260f38a1346669507a3601410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95fffffffff878af0d93f5229a68166cf051fd372bb7a537232946e0a46f53636b4dafdaa4000000008c493046022100c717d1714551663f69c3c5759bdbb3a0fcd3fab023abc0e522fe6440de35d8290221008d9cbe25bffc44af2b18e81c58eb37293fd7fe1c2e7b46fc37ee8c96c50ab1e201410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffffffff27f2b668859cd7f2f894aa0fd2d9e60963bcd07c88973f425f999b8cbfd7a1e2000000008c493046022100e00847147cbf517bcc2f502f3ddc6d284358d102ed20d47a8aa788a62f0db780022100d17b2d6fa84dcaf1c95d88d7e7c30385aecf415588d749afd3ec81f6022cecd701410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffffffff0100c817a8040000001976a914b6efd80d99179f4f4ff6f4dd0a007d018c385d2188ac000000000100000001834537b2f1ce8ef9373a258e10545ce5a50b758df616cd4356e0032554ebd3c4000000008b483045022100e68f422dd7c34fdce11eeb4509ddae38201773dd62f284e8aa9d96f85099d0b002202243bd399ff96b649a0fad05fa759d6a882f0af8c90cf7632c2840c29070aec20141045e58067e815c2f464c6a2a15f987758374203895710c2d452442e28496ff38ba8f5fd901dc20e29e88477167fe4fc299bf818fd0d9e1632d467b2a3d9503b1aaffffffff0280d7e636030000001976a914f34c3e10eb387efe872acb614c89e78bfca7815d88ac404b4c00000000001976a914a84e272933aaf87e1715d7786c51dfaeb5b65a6f88ac00000000010000000143ac81c8e6f6ef307dfe17f3d906d999e23e0189fda838c5510d850927e03ae7000000008c4930460221009c87c344760a64cb8ae6685a3eec2c1ac1bed5b88c87de51acd0e124f266c16602210082d07c037359c3a257b5c63ebd90f5a5edf97b2ac1c434b08ca998839f346dd40141040ba7e521fa7946d12edbb1d1e95a15c34bd4398195e86433c92b431cd315f455fe30032ede69cad9d1e1ed6c3c4ec0dbfced53438c625462afb792dcb098544bffffffff0240420f00000000001976a9144676d1b820d63ec272f1900d59d43bc6463d96f888ac40420f00000000001976a914648d04341d00d7968b3405c034adc38d4d8fb9bd88ac00000000010000000248cc917501ea5c55f4a8d2009c0567c40cfe037c2e71af017d0a452ff705e3f1000000008b483045022100bf5fdc86dc5f08a5d5c8e43a8c9d5b1ed8c65562e280007b52b133021acd9acc02205e325d613e555f772802bf413d36ba807892ed1a690a77811d3033b3de226e0a01410429fa713b124484cb2bd7b5557b2c0b9df7b2b1fee61825eadc5ae6c37a9920d38bfccdc7dc3cb0c47d7b173dbc9db8d37db0a33ae487982c59c6f8606e9d1791ffffffff41ed70551dd7e841883ab8f0b16bf04176b7d1480e4f0af9f3d4c3595768d068000000008b4830450221008513ad65187b903aed1102d1d0c47688127658c51106753fed0151ce9c16b80902201432b9ebcb87bd04ceb2de66035fbbaf4bf8b00d1cfe41f1a1f7338f9ad79d210141049d4cf80125bf50be1709f718c07ad15d0fc612b7da1f5570dddc35f2a352f0f27c978b06820edca9ef982c35fda2d255afba340068c5035552368bc7200c1488ffffffff0100093d00000000001976a9148edb68822f1ad580b043c7b3df2e400f8699eb4888ac00000000"), SER_NETWORK, PROTOCOL_VERSION);
+ stream >> block;
+
+ CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_P2PUBKEY_ONLY);
+ // Match the generation pubkey
+ filter.insert(ParseHex("04eaafc2314def4ca98ac970241bcab022b9c1e1f4ea423a20f134c876f2c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce13ad1357231a2252247d97a46a91"));
+ // ...and the output address of the 4th transaction
+ filter.insert(ParseHex("b6efd80d99179f4f4ff6f4dd0a007d018c385d21"));
+
+ CMerkleBlock merkleBlock(block, filter);
+ BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash());
+
+ // We should match the generation outpoint
+ BOOST_CHECK(filter.contains(COutPoint(uint256S("0x147caa76786596590baa4e98f5d9f48b86c7765e489f7a6ff3360fe5c674360b"), 0)));
+ // ... but not the 4th transaction's output (its not pay-2-pubkey)
+ BOOST_CHECK(!filter.contains(COutPoint(uint256S("0x02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041"), 0)));
+}
+
+BOOST_AUTO_TEST_CASE(merkle_block_4_test_update_none)
+{
+ // Random real block (000000000000b731f2eef9e8c63173adfb07e41bd53eb0ef0a6b720d6cb6dea4)
+ // With 7 txes
+ CBlock block;
+ CDataStream stream(ParseHex("0100000082bb869cf3a793432a66e826e05a6fc37469f8efb7421dc880670100000000007f16c5962e8bd963659c793ce370d95f093bc7e367117b3c30c1f8fdd0d9728776381b4d4c86041b554b85290701000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07044c86041b0136ffffffff0100f2052a01000000434104eaafc2314def4ca98ac970241bcab022b9c1e1f4ea423a20f134c876f2c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce13ad1357231a2252247d97a46a91ac000000000100000001bcad20a6a29827d1424f08989255120bf7f3e9e3cdaaa6bb31b0737fe048724300000000494830450220356e834b046cadc0f8ebb5a8a017b02de59c86305403dad52cd77b55af062ea10221009253cd6c119d4729b77c978e1e2aa19f5ea6e0e52b3f16e32fa608cd5bab753901ffffffff02008d380c010000001976a9142b4b8072ecbba129b6453c63e129e643207249ca88ac0065cd1d000000001976a9141b8dd13b994bcfc787b32aeadf58ccb3615cbd5488ac000000000100000003fdacf9b3eb077412e7a968d2e4f11b9a9dee312d666187ed77ee7d26af16cb0b000000008c493046022100ea1608e70911ca0de5af51ba57ad23b9a51db8d28f82c53563c56a05c20f5a87022100a8bdc8b4a8acc8634c6b420410150775eb7f2474f5615f7fccd65af30f310fbf01410465fdf49e29b06b9a1582287b6279014f834edc317695d125ef623c1cc3aaece245bd69fcad7508666e9c74a49dc9056d5fc14338ef38118dc4afae5fe2c585caffffffff309e1913634ecb50f3c4f83e96e70b2df071b497b8973a3e75429df397b5af83000000004948304502202bdb79c596a9ffc24e96f4386199aba386e9bc7b6071516e2b51dda942b3a1ed022100c53a857e76b724fc14d45311eac5019650d415c3abb5428f3aae16d8e69bec2301ffffffff2089e33491695080c9edc18a428f7d834db5b6d372df13ce2b1b0e0cbcb1e6c10000000049483045022100d4ce67c5896ee251c810ac1ff9ceccd328b497c8f553ab6e08431e7d40bad6b5022033119c0c2b7d792d31f1187779c7bd95aefd93d90a715586d73801d9b47471c601ffffffff0100714460030000001976a914c7b55141d097ea5df7a0ed330cf794376e53ec8d88ac0000000001000000045bf0e214aa4069a3e792ecee1e1bf0c1d397cde8dd08138f4b72a00681743447000000008b48304502200c45de8c4f3e2c1821f2fc878cba97b1e6f8807d94930713aa1c86a67b9bf1e40221008581abfef2e30f957815fc89978423746b2086375ca8ecf359c85c2a5b7c88ad01410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffffffffd669f7d7958d40fc59d2253d88e0f248e29b599c80bbcec344a83dda5f9aa72c000000008a473044022078124c8beeaa825f9e0b30bff96e564dd859432f2d0cb3b72d3d5d93d38d7e930220691d233b6c0f995be5acb03d70a7f7a65b6bc9bdd426260f38a1346669507a3601410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95fffffffff878af0d93f5229a68166cf051fd372bb7a537232946e0a46f53636b4dafdaa4000000008c493046022100c717d1714551663f69c3c5759bdbb3a0fcd3fab023abc0e522fe6440de35d8290221008d9cbe25bffc44af2b18e81c58eb37293fd7fe1c2e7b46fc37ee8c96c50ab1e201410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffffffff27f2b668859cd7f2f894aa0fd2d9e60963bcd07c88973f425f999b8cbfd7a1e2000000008c493046022100e00847147cbf517bcc2f502f3ddc6d284358d102ed20d47a8aa788a62f0db780022100d17b2d6fa84dcaf1c95d88d7e7c30385aecf415588d749afd3ec81f6022cecd701410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffffffff0100c817a8040000001976a914b6efd80d99179f4f4ff6f4dd0a007d018c385d2188ac000000000100000001834537b2f1ce8ef9373a258e10545ce5a50b758df616cd4356e0032554ebd3c4000000008b483045022100e68f422dd7c34fdce11eeb4509ddae38201773dd62f284e8aa9d96f85099d0b002202243bd399ff96b649a0fad05fa759d6a882f0af8c90cf7632c2840c29070aec20141045e58067e815c2f464c6a2a15f987758374203895710c2d452442e28496ff38ba8f5fd901dc20e29e88477167fe4fc299bf818fd0d9e1632d467b2a3d9503b1aaffffffff0280d7e636030000001976a914f34c3e10eb387efe872acb614c89e78bfca7815d88ac404b4c00000000001976a914a84e272933aaf87e1715d7786c51dfaeb5b65a6f88ac00000000010000000143ac81c8e6f6ef307dfe17f3d906d999e23e0189fda838c5510d850927e03ae7000000008c4930460221009c87c344760a64cb8ae6685a3eec2c1ac1bed5b88c87de51acd0e124f266c16602210082d07c037359c3a257b5c63ebd90f5a5edf97b2ac1c434b08ca998839f346dd40141040ba7e521fa7946d12edbb1d1e95a15c34bd4398195e86433c92b431cd315f455fe30032ede69cad9d1e1ed6c3c4ec0dbfced53438c625462afb792dcb098544bffffffff0240420f00000000001976a9144676d1b820d63ec272f1900d59d43bc6463d96f888ac40420f00000000001976a914648d04341d00d7968b3405c034adc38d4d8fb9bd88ac00000000010000000248cc917501ea5c55f4a8d2009c0567c40cfe037c2e71af017d0a452ff705e3f1000000008b483045022100bf5fdc86dc5f08a5d5c8e43a8c9d5b1ed8c65562e280007b52b133021acd9acc02205e325d613e555f772802bf413d36ba807892ed1a690a77811d3033b3de226e0a01410429fa713b124484cb2bd7b5557b2c0b9df7b2b1fee61825eadc5ae6c37a9920d38bfccdc7dc3cb0c47d7b173dbc9db8d37db0a33ae487982c59c6f8606e9d1791ffffffff41ed70551dd7e841883ab8f0b16bf04176b7d1480e4f0af9f3d4c3595768d068000000008b4830450221008513ad65187b903aed1102d1d0c47688127658c51106753fed0151ce9c16b80902201432b9ebcb87bd04ceb2de66035fbbaf4bf8b00d1cfe41f1a1f7338f9ad79d210141049d4cf80125bf50be1709f718c07ad15d0fc612b7da1f5570dddc35f2a352f0f27c978b06820edca9ef982c35fda2d255afba340068c5035552368bc7200c1488ffffffff0100093d00000000001976a9148edb68822f1ad580b043c7b3df2e400f8699eb4888ac00000000"), SER_NETWORK, PROTOCOL_VERSION);
+ stream >> block;
+
+ CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_NONE);
+ // Match the generation pubkey
+ filter.insert(ParseHex("04eaafc2314def4ca98ac970241bcab022b9c1e1f4ea423a20f134c876f2c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce13ad1357231a2252247d97a46a91"));
+ // ...and the output address of the 4th transaction
+ filter.insert(ParseHex("b6efd80d99179f4f4ff6f4dd0a007d018c385d21"));
+
+ CMerkleBlock merkleBlock(block, filter);
+ BOOST_CHECK(merkleBlock.header.GetHash() == block.GetHash());
+
+ // We shouldn't match any outpoints (UPDATE_NONE)
+ BOOST_CHECK(!filter.contains(COutPoint(uint256S("0x147caa76786596590baa4e98f5d9f48b86c7765e489f7a6ff3360fe5c674360b"), 0)));
+ BOOST_CHECK(!filter.contains(COutPoint(uint256S("0x02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041"), 0)));
+}
+
+static std::vector<unsigned char> RandomData()
+{
+ uint256 r = InsecureRand256();
+ return std::vector<unsigned char>(r.begin(), r.end());
+}
+
+BOOST_AUTO_TEST_CASE(rolling_bloom)
+{
+ // last-100-entry, 1% false positive:
+ CRollingBloomFilter rb1(100, 0.01);
+
+ // Overfill:
+ static const int DATASIZE=399;
+ std::vector<unsigned char> data[DATASIZE];
+ for (int i = 0; i < DATASIZE; i++) {
+ data[i] = RandomData();
+ rb1.insert(data[i]);
+ }
+ // Last 100 guaranteed to be remembered:
+ for (int i = 299; i < DATASIZE; i++) {
+ BOOST_CHECK(rb1.contains(data[i]));
+ }
+
+ // false positive rate is 1%, so we should get about 100 hits if
+ // testing 10,000 random keys. We get worst-case false positive
+ // behavior when the filter is as full as possible, which is
+ // when we've inserted one minus an integer multiple of nElement*2.
+ unsigned int nHits = 0;
+ for (int i = 0; i < 10000; i++) {
+ if (rb1.contains(RandomData()))
+ ++nHits;
+ }
+ // Run test_bitcoin with --log_level=message to see BOOST_TEST_MESSAGEs:
+ BOOST_TEST_MESSAGE("RollingBloomFilter got " << nHits << " false positives (~100 expected)");
+
+ // Insanely unlikely to get a fp count outside this range:
+ BOOST_CHECK(nHits > 25);
+ BOOST_CHECK(nHits < 175);
+
+ BOOST_CHECK(rb1.contains(data[DATASIZE-1]));
+ rb1.reset();
+ BOOST_CHECK(!rb1.contains(data[DATASIZE-1]));
+
+ // Now roll through data, make sure last 100 entries
+ // are always remembered:
+ for (int i = 0; i < DATASIZE; i++) {
+ if (i >= 100)
+ BOOST_CHECK(rb1.contains(data[i-100]));
+ rb1.insert(data[i]);
+ BOOST_CHECK(rb1.contains(data[i]));
+ }
+
+ // Insert 999 more random entries:
+ for (int i = 0; i < 999; i++) {
+ std::vector<unsigned char> d = RandomData();
+ rb1.insert(d);
+ BOOST_CHECK(rb1.contains(d));
+ }
+ // Sanity check to make sure the filter isn't just filling up:
+ nHits = 0;
+ for (int i = 0; i < DATASIZE; i++) {
+ if (rb1.contains(data[i]))
+ ++nHits;
+ }
+ // Expect about 5 false positives, more than 100 means
+ // something is definitely broken.
+ BOOST_TEST_MESSAGE("RollingBloomFilter got " << nHits << " false positives (~5 expected)");
+ BOOST_CHECK(nHits < 100);
+
+ // last-1000-entry, 0.01% false positive:
+ CRollingBloomFilter rb2(1000, 0.001);
+ for (int i = 0; i < DATASIZE; i++) {
+ rb2.insert(data[i]);
+ }
+ // ... room for all of them:
+ for (int i = 0; i < DATASIZE; i++) {
+ BOOST_CHECK(rb2.contains(data[i]));
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/bswap_tests.cpp b/src/test/bswap_tests.cpp
new file mode 100644
index 0000000000..8572926193
--- /dev/null
+++ b/src/test/bswap_tests.cpp
@@ -0,0 +1,26 @@
+// Copyright (c) 2016-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <compat/byteswap.h>
+#include <test/test_bitcoin.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(bswap_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(bswap_tests)
+{
+ // Sibling in bitcoin/src/qt/test/compattests.cpp
+ uint16_t u1 = 0x1234;
+ uint32_t u2 = 0x56789abc;
+ uint64_t u3 = 0xdef0123456789abc;
+ uint16_t e1 = 0x3412;
+ uint32_t e2 = 0xbc9a7856;
+ uint64_t e3 = 0xbc9a78563412f0de;
+ BOOST_CHECK(bswap_16(u1) == e1);
+ BOOST_CHECK(bswap_32(u2) == e2);
+ BOOST_CHECK(bswap_64(u3) == e3);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp
new file mode 100644
index 0000000000..39d0061c1c
--- /dev/null
+++ b/src/test/checkqueue_tests.cpp
@@ -0,0 +1,445 @@
+// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <util.h>
+#include <utiltime.h>
+#include <validation.h>
+
+#include <test/test_bitcoin.h>
+#include <checkqueue.h>
+#include <boost/test/unit_test.hpp>
+#include <boost/thread.hpp>
+#include <atomic>
+#include <thread>
+#include <vector>
+#include <mutex>
+#include <condition_variable>
+
+#include <unordered_set>
+#include <memory>
+#include <random.h>
+
+// BasicTestingSetup not sufficient because nScriptCheckThreads is not set
+// otherwise.
+BOOST_FIXTURE_TEST_SUITE(checkqueue_tests, TestingSetup)
+
+static const unsigned int QUEUE_BATCH_SIZE = 128;
+
+struct FakeCheck {
+ bool operator()()
+ {
+ return true;
+ }
+ void swap(FakeCheck& x){};
+};
+
+struct FakeCheckCheckCompletion {
+ static std::atomic<size_t> n_calls;
+ bool operator()()
+ {
+ n_calls.fetch_add(1, std::memory_order_relaxed);
+ return true;
+ }
+ void swap(FakeCheckCheckCompletion& x){};
+};
+
+struct FailingCheck {
+ bool fails;
+ FailingCheck(bool _fails) : fails(_fails){};
+ FailingCheck() : fails(true){};
+ bool operator()()
+ {
+ return !fails;
+ }
+ void swap(FailingCheck& x)
+ {
+ std::swap(fails, x.fails);
+ };
+};
+
+struct UniqueCheck {
+ static std::mutex m;
+ static std::unordered_multiset<size_t> results;
+ size_t check_id;
+ UniqueCheck(size_t check_id_in) : check_id(check_id_in){};
+ UniqueCheck() : check_id(0){};
+ bool operator()()
+ {
+ std::lock_guard<std::mutex> l(m);
+ results.insert(check_id);
+ return true;
+ }
+ void swap(UniqueCheck& x) { std::swap(x.check_id, check_id); };
+};
+
+
+struct MemoryCheck {
+ static std::atomic<size_t> fake_allocated_memory;
+ bool b {false};
+ bool operator()()
+ {
+ return true;
+ }
+ MemoryCheck(){};
+ MemoryCheck(const MemoryCheck& x)
+ {
+ // We have to do this to make sure that destructor calls are paired
+ //
+ // Really, copy constructor should be deletable, but CCheckQueue breaks
+ // if it is deleted because of internal push_back.
+ fake_allocated_memory.fetch_add(b, std::memory_order_relaxed);
+ };
+ MemoryCheck(bool b_) : b(b_)
+ {
+ fake_allocated_memory.fetch_add(b, std::memory_order_relaxed);
+ };
+ ~MemoryCheck()
+ {
+ fake_allocated_memory.fetch_sub(b, std::memory_order_relaxed);
+ };
+ void swap(MemoryCheck& x) { std::swap(b, x.b); };
+};
+
+struct FrozenCleanupCheck {
+ static std::atomic<uint64_t> nFrozen;
+ static std::condition_variable cv;
+ static std::mutex m;
+ // Freezing can't be the default initialized behavior given how the queue
+ // swaps in default initialized Checks.
+ bool should_freeze {false};
+ bool operator()()
+ {
+ return true;
+ }
+ FrozenCleanupCheck() {}
+ ~FrozenCleanupCheck()
+ {
+ if (should_freeze) {
+ std::unique_lock<std::mutex> l(m);
+ nFrozen.store(1, std::memory_order_relaxed);
+ cv.notify_one();
+ cv.wait(l, []{ return nFrozen.load(std::memory_order_relaxed) == 0;});
+ }
+ }
+ void swap(FrozenCleanupCheck& x){std::swap(should_freeze, x.should_freeze);};
+};
+
+// Static Allocations
+std::mutex FrozenCleanupCheck::m{};
+std::atomic<uint64_t> FrozenCleanupCheck::nFrozen{0};
+std::condition_variable FrozenCleanupCheck::cv{};
+std::mutex UniqueCheck::m;
+std::unordered_multiset<size_t> UniqueCheck::results;
+std::atomic<size_t> FakeCheckCheckCompletion::n_calls{0};
+std::atomic<size_t> MemoryCheck::fake_allocated_memory{0};
+
+// Queue Typedefs
+typedef CCheckQueue<FakeCheckCheckCompletion> Correct_Queue;
+typedef CCheckQueue<FakeCheck> Standard_Queue;
+typedef CCheckQueue<FailingCheck> Failing_Queue;
+typedef CCheckQueue<UniqueCheck> Unique_Queue;
+typedef CCheckQueue<MemoryCheck> Memory_Queue;
+typedef CCheckQueue<FrozenCleanupCheck> FrozenCleanup_Queue;
+
+
+/** This test case checks that the CCheckQueue works properly
+ * with each specified size_t Checks pushed.
+ */
+static void Correct_Queue_range(std::vector<size_t> range)
+{
+ auto small_queue = std::unique_ptr<Correct_Queue>(new Correct_Queue {QUEUE_BATCH_SIZE});
+ boost::thread_group tg;
+ for (auto x = 0; x < nScriptCheckThreads; ++x) {
+ tg.create_thread([&]{small_queue->Thread();});
+ }
+ // Make vChecks here to save on malloc (this test can be slow...)
+ std::vector<FakeCheckCheckCompletion> vChecks;
+ for (auto i : range) {
+ size_t total = i;
+ FakeCheckCheckCompletion::n_calls = 0;
+ CCheckQueueControl<FakeCheckCheckCompletion> control(small_queue.get());
+ while (total) {
+ vChecks.resize(std::min(total, (size_t) InsecureRandRange(10)));
+ total -= vChecks.size();
+ control.Add(vChecks);
+ }
+ BOOST_REQUIRE(control.Wait());
+ if (FakeCheckCheckCompletion::n_calls != i) {
+ BOOST_REQUIRE_EQUAL(FakeCheckCheckCompletion::n_calls, i);
+ BOOST_TEST_MESSAGE("Failure on trial " << i << " expected, got " << FakeCheckCheckCompletion::n_calls);
+ }
+ }
+ tg.interrupt_all();
+ tg.join_all();
+}
+
+/** Test that 0 checks is correct
+ */
+BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_Zero)
+{
+ std::vector<size_t> range;
+ range.push_back((size_t)0);
+ Correct_Queue_range(range);
+}
+/** Test that 1 check is correct
+ */
+BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_One)
+{
+ std::vector<size_t> range;
+ range.push_back((size_t)1);
+ Correct_Queue_range(range);
+}
+/** Test that MAX check is correct
+ */
+BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_Max)
+{
+ std::vector<size_t> range;
+ range.push_back(100000);
+ Correct_Queue_range(range);
+}
+/** Test that random numbers of checks are correct
+ */
+BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_Random)
+{
+ std::vector<size_t> range;
+ range.reserve(100000/1000);
+ for (size_t i = 2; i < 100000; i += std::max((size_t)1, (size_t)InsecureRandRange(std::min((size_t)1000, ((size_t)100000) - i))))
+ range.push_back(i);
+ Correct_Queue_range(range);
+}
+
+
+/** Test that failing checks are caught */
+BOOST_AUTO_TEST_CASE(test_CheckQueue_Catches_Failure)
+{
+ auto fail_queue = std::unique_ptr<Failing_Queue>(new Failing_Queue {QUEUE_BATCH_SIZE});
+
+ boost::thread_group tg;
+ for (auto x = 0; x < nScriptCheckThreads; ++x) {
+ tg.create_thread([&]{fail_queue->Thread();});
+ }
+
+ for (size_t i = 0; i < 1001; ++i) {
+ CCheckQueueControl<FailingCheck> control(fail_queue.get());
+ size_t remaining = i;
+ while (remaining) {
+ size_t r = InsecureRandRange(10);
+
+ std::vector<FailingCheck> vChecks;
+ vChecks.reserve(r);
+ for (size_t k = 0; k < r && remaining; k++, remaining--)
+ vChecks.emplace_back(remaining == 1);
+ control.Add(vChecks);
+ }
+ bool success = control.Wait();
+ if (i > 0) {
+ BOOST_REQUIRE(!success);
+ } else if (i == 0) {
+ BOOST_REQUIRE(success);
+ }
+ }
+ tg.interrupt_all();
+ tg.join_all();
+}
+// Test that a block validation which fails does not interfere with
+// future blocks, ie, the bad state is cleared.
+BOOST_AUTO_TEST_CASE(test_CheckQueue_Recovers_From_Failure)
+{
+ auto fail_queue = std::unique_ptr<Failing_Queue>(new Failing_Queue {QUEUE_BATCH_SIZE});
+ boost::thread_group tg;
+ for (auto x = 0; x < nScriptCheckThreads; ++x) {
+ tg.create_thread([&]{fail_queue->Thread();});
+ }
+
+ for (auto times = 0; times < 10; ++times) {
+ for (bool end_fails : {true, false}) {
+ CCheckQueueControl<FailingCheck> control(fail_queue.get());
+ {
+ std::vector<FailingCheck> vChecks;
+ vChecks.resize(100, false);
+ vChecks[99] = end_fails;
+ control.Add(vChecks);
+ }
+ bool r =control.Wait();
+ BOOST_REQUIRE(r != end_fails);
+ }
+ }
+ tg.interrupt_all();
+ tg.join_all();
+}
+
+// Test that unique checks are actually all called individually, rather than
+// just one check being called repeatedly. Test that checks are not called
+// more than once as well
+BOOST_AUTO_TEST_CASE(test_CheckQueue_UniqueCheck)
+{
+ auto queue = std::unique_ptr<Unique_Queue>(new Unique_Queue {QUEUE_BATCH_SIZE});
+ boost::thread_group tg;
+ for (auto x = 0; x < nScriptCheckThreads; ++x) {
+ tg.create_thread([&]{queue->Thread();});
+
+ }
+
+ size_t COUNT = 100000;
+ size_t total = COUNT;
+ {
+ CCheckQueueControl<UniqueCheck> control(queue.get());
+ while (total) {
+ size_t r = InsecureRandRange(10);
+ std::vector<UniqueCheck> vChecks;
+ for (size_t k = 0; k < r && total; k++)
+ vChecks.emplace_back(--total);
+ control.Add(vChecks);
+ }
+ }
+ bool r = true;
+ BOOST_REQUIRE_EQUAL(UniqueCheck::results.size(), COUNT);
+ for (size_t i = 0; i < COUNT; ++i)
+ r = r && UniqueCheck::results.count(i) == 1;
+ BOOST_REQUIRE(r);
+ tg.interrupt_all();
+ tg.join_all();
+}
+
+
+// Test that blocks which might allocate lots of memory free their memory aggressively.
+//
+// This test attempts to catch a pathological case where by lazily freeing
+// checks might mean leaving a check un-swapped out, and decreasing by 1 each
+// time could leave the data hanging across a sequence of blocks.
+BOOST_AUTO_TEST_CASE(test_CheckQueue_Memory)
+{
+ auto queue = std::unique_ptr<Memory_Queue>(new Memory_Queue {QUEUE_BATCH_SIZE});
+ boost::thread_group tg;
+ for (auto x = 0; x < nScriptCheckThreads; ++x) {
+ tg.create_thread([&]{queue->Thread();});
+ }
+ for (size_t i = 0; i < 1000; ++i) {
+ size_t total = i;
+ {
+ CCheckQueueControl<MemoryCheck> control(queue.get());
+ while (total) {
+ size_t r = InsecureRandRange(10);
+ std::vector<MemoryCheck> vChecks;
+ for (size_t k = 0; k < r && total; k++) {
+ total--;
+ // Each iteration leaves data at the front, back, and middle
+ // to catch any sort of deallocation failure
+ vChecks.emplace_back(total == 0 || total == i || total == i/2);
+ }
+ control.Add(vChecks);
+ }
+ }
+ BOOST_REQUIRE_EQUAL(MemoryCheck::fake_allocated_memory, 0U);
+ }
+ tg.interrupt_all();
+ tg.join_all();
+}
+
+// Test that a new verification cannot occur until all checks
+// have been destructed
+BOOST_AUTO_TEST_CASE(test_CheckQueue_FrozenCleanup)
+{
+ auto queue = std::unique_ptr<FrozenCleanup_Queue>(new FrozenCleanup_Queue {QUEUE_BATCH_SIZE});
+ boost::thread_group tg;
+ bool fails = false;
+ for (auto x = 0; x < nScriptCheckThreads; ++x) {
+ tg.create_thread([&]{queue->Thread();});
+ }
+ std::thread t0([&]() {
+ CCheckQueueControl<FrozenCleanupCheck> control(queue.get());
+ std::vector<FrozenCleanupCheck> vChecks(1);
+ // Freezing can't be the default initialized behavior given how the queue
+ // swaps in default initialized Checks (otherwise freezing destructor
+ // would get called twice).
+ vChecks[0].should_freeze = true;
+ control.Add(vChecks);
+ control.Wait(); // Hangs here
+ });
+ {
+ std::unique_lock<std::mutex> l(FrozenCleanupCheck::m);
+ // Wait until the queue has finished all jobs and frozen
+ FrozenCleanupCheck::cv.wait(l, [](){return FrozenCleanupCheck::nFrozen == 1;});
+ }
+ // Try to get control of the queue a bunch of times
+ for (auto x = 0; x < 100 && !fails; ++x) {
+ fails = queue->ControlMutex.try_lock();
+ }
+ {
+ // Unfreeze (we need lock n case of spurious wakeup)
+ std::unique_lock<std::mutex> l(FrozenCleanupCheck::m);
+ FrozenCleanupCheck::nFrozen = 0;
+ }
+ // Awaken frozen destructor
+ FrozenCleanupCheck::cv.notify_one();
+ // Wait for control to finish
+ t0.join();
+ tg.interrupt_all();
+ tg.join_all();
+ BOOST_REQUIRE(!fails);
+}
+
+
+/** Test that CCheckQueueControl is threadsafe */
+BOOST_AUTO_TEST_CASE(test_CheckQueueControl_Locks)
+{
+ auto queue = std::unique_ptr<Standard_Queue>(new Standard_Queue{QUEUE_BATCH_SIZE});
+ {
+ boost::thread_group tg;
+ std::atomic<int> nThreads {0};
+ std::atomic<int> fails {0};
+ for (size_t i = 0; i < 3; ++i) {
+ tg.create_thread(
+ [&]{
+ CCheckQueueControl<FakeCheck> control(queue.get());
+ // While sleeping, no other thread should execute to this point
+ auto observed = ++nThreads;
+ MilliSleep(10);
+ fails += observed != nThreads;
+ });
+ }
+ tg.join_all();
+ BOOST_REQUIRE_EQUAL(fails, 0);
+ }
+ {
+ boost::thread_group tg;
+ std::mutex m;
+ std::condition_variable cv;
+ bool has_lock{false};
+ bool has_tried{false};
+ bool done{false};
+ bool done_ack{false};
+ {
+ std::unique_lock<std::mutex> l(m);
+ tg.create_thread([&]{
+ CCheckQueueControl<FakeCheck> control(queue.get());
+ std::unique_lock<std::mutex> ll(m);
+ has_lock = true;
+ cv.notify_one();
+ cv.wait(ll, [&]{return has_tried;});
+ done = true;
+ cv.notify_one();
+ // Wait until the done is acknowledged
+ //
+ cv.wait(ll, [&]{return done_ack;});
+ });
+ // Wait for thread to get the lock
+ cv.wait(l, [&](){return has_lock;});
+ bool fails = false;
+ for (auto x = 0; x < 100 && !fails; ++x) {
+ fails = queue->ControlMutex.try_lock();
+ }
+ has_tried = true;
+ cv.notify_one();
+ cv.wait(l, [&](){return done;});
+ // Acknowledge the done
+ done_ack = true;
+ cv.notify_one();
+ BOOST_REQUIRE(!fails);
+ }
+ tg.join_all();
+ }
+}
+BOOST_AUTO_TEST_SUITE_END()
+
diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp
new file mode 100644
index 0000000000..63b91b74c0
--- /dev/null
+++ b/src/test/coins_tests.cpp
@@ -0,0 +1,858 @@
+// Copyright (c) 2014-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <coins.h>
+#include <script/standard.h>
+#include <uint256.h>
+#include <undo.h>
+#include <utilstrencodings.h>
+#include <test/test_bitcoin.h>
+#include <validation.h>
+#include <consensus/validation.h>
+
+#include <vector>
+#include <map>
+
+#include <boost/test/unit_test.hpp>
+
+int ApplyTxInUndo(Coin&& undo, CCoinsViewCache& view, const COutPoint& out);
+void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txundo, int nHeight);
+
+namespace
+{
+//! equality test
+bool operator==(const Coin &a, const Coin &b) {
+ // Empty Coin objects are always equal.
+ if (a.IsSpent() && b.IsSpent()) return true;
+ return a.fCoinBase == b.fCoinBase &&
+ a.nHeight == b.nHeight &&
+ a.out == b.out;
+}
+
+class CCoinsViewTest : public CCoinsView
+{
+ uint256 hashBestBlock_;
+ std::map<COutPoint, Coin> map_;
+
+public:
+ bool GetCoin(const COutPoint& outpoint, Coin& coin) const override
+ {
+ std::map<COutPoint, Coin>::const_iterator it = map_.find(outpoint);
+ if (it == map_.end()) {
+ return false;
+ }
+ coin = it->second;
+ if (coin.IsSpent() && InsecureRandBool() == 0) {
+ // Randomly return false in case of an empty entry.
+ return false;
+ }
+ return true;
+ }
+
+ uint256 GetBestBlock() const override { return hashBestBlock_; }
+
+ bool BatchWrite(CCoinsMap& mapCoins, const uint256& hashBlock) override
+ {
+ for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end(); ) {
+ if (it->second.flags & CCoinsCacheEntry::DIRTY) {
+ // Same optimization used in CCoinsViewDB is to only write dirty entries.
+ map_[it->first] = it->second.coin;
+ if (it->second.coin.IsSpent() && InsecureRandRange(3) == 0) {
+ // Randomly delete empty entries on write.
+ map_.erase(it->first);
+ }
+ }
+ mapCoins.erase(it++);
+ }
+ if (!hashBlock.IsNull())
+ hashBestBlock_ = hashBlock;
+ return true;
+ }
+};
+
+class CCoinsViewCacheTest : public CCoinsViewCache
+{
+public:
+ explicit CCoinsViewCacheTest(CCoinsView* _base) : CCoinsViewCache(_base) {}
+
+ void SelfTest() const
+ {
+ // Manually recompute the dynamic usage of the whole data, and compare it.
+ size_t ret = memusage::DynamicUsage(cacheCoins);
+ size_t count = 0;
+ for (const auto& entry : cacheCoins) {
+ ret += entry.second.coin.DynamicMemoryUsage();
+ ++count;
+ }
+ BOOST_CHECK_EQUAL(GetCacheSize(), count);
+ BOOST_CHECK_EQUAL(DynamicMemoryUsage(), ret);
+ }
+
+ CCoinsMap& map() const { return cacheCoins; }
+ size_t& usage() const { return cachedCoinsUsage; }
+};
+
+} // namespace
+
+BOOST_FIXTURE_TEST_SUITE(coins_tests, BasicTestingSetup)
+
+static const unsigned int NUM_SIMULATION_ITERATIONS = 40000;
+
+// This is a large randomized insert/remove simulation test on a variable-size
+// stack of caches on top of CCoinsViewTest.
+//
+// It will randomly create/update/delete Coin entries to a tip of caches, with
+// txids picked from a limited list of random 256-bit hashes. Occasionally, a
+// new tip is added to the stack of caches, or the tip is flushed and removed.
+//
+// During the process, booleans are kept to make sure that the randomized
+// operation hits all branches.
+BOOST_AUTO_TEST_CASE(coins_cache_simulation_test)
+{
+ // Various coverage trackers.
+ bool removed_all_caches = false;
+ bool reached_4_caches = false;
+ bool added_an_entry = false;
+ bool added_an_unspendable_entry = false;
+ bool removed_an_entry = false;
+ bool updated_an_entry = false;
+ bool found_an_entry = false;
+ bool missed_an_entry = false;
+ bool uncached_an_entry = false;
+
+ // A simple map to track what we expect the cache stack to represent.
+ std::map<COutPoint, Coin> result;
+
+ // The cache stack.
+ CCoinsViewTest base; // A CCoinsViewTest at the bottom.
+ std::vector<CCoinsViewCacheTest*> stack; // A stack of CCoinsViewCaches on top.
+ stack.push_back(new CCoinsViewCacheTest(&base)); // Start with one cache.
+
+ // Use a limited set of random transaction ids, so we do test overwriting entries.
+ std::vector<uint256> txids;
+ txids.resize(NUM_SIMULATION_ITERATIONS / 8);
+ for (unsigned int i = 0; i < txids.size(); i++) {
+ txids[i] = InsecureRand256();
+ }
+
+ for (unsigned int i = 0; i < NUM_SIMULATION_ITERATIONS; i++) {
+ // Do a random modification.
+ {
+ uint256 txid = txids[InsecureRandRange(txids.size())]; // txid we're going to modify in this iteration.
+ Coin& coin = result[COutPoint(txid, 0)];
+
+ // Determine whether to test HaveCoin before or after Access* (or both). As these functions
+ // can influence each other's behaviour by pulling things into the cache, all combinations
+ // are tested.
+ bool test_havecoin_before = InsecureRandBits(2) == 0;
+ bool test_havecoin_after = InsecureRandBits(2) == 0;
+
+ bool result_havecoin = test_havecoin_before ? stack.back()->HaveCoin(COutPoint(txid, 0)) : false;
+ const Coin& entry = (InsecureRandRange(500) == 0) ? AccessByTxid(*stack.back(), txid) : stack.back()->AccessCoin(COutPoint(txid, 0));
+ BOOST_CHECK(coin == entry);
+ BOOST_CHECK(!test_havecoin_before || result_havecoin == !entry.IsSpent());
+
+ if (test_havecoin_after) {
+ bool ret = stack.back()->HaveCoin(COutPoint(txid, 0));
+ BOOST_CHECK(ret == !entry.IsSpent());
+ }
+
+ if (InsecureRandRange(5) == 0 || coin.IsSpent()) {
+ Coin newcoin;
+ newcoin.out.nValue = InsecureRand32();
+ newcoin.nHeight = 1;
+ if (InsecureRandRange(16) == 0 && coin.IsSpent()) {
+ newcoin.out.scriptPubKey.assign(1 + InsecureRandBits(6), OP_RETURN);
+ BOOST_CHECK(newcoin.out.scriptPubKey.IsUnspendable());
+ added_an_unspendable_entry = true;
+ } else {
+ newcoin.out.scriptPubKey.assign(InsecureRandBits(6), 0); // Random sizes so we can test memory usage accounting
+ (coin.IsSpent() ? added_an_entry : updated_an_entry) = true;
+ coin = newcoin;
+ }
+ stack.back()->AddCoin(COutPoint(txid, 0), std::move(newcoin), !coin.IsSpent() || InsecureRand32() & 1);
+ } else {
+ removed_an_entry = true;
+ coin.Clear();
+ stack.back()->SpendCoin(COutPoint(txid, 0));
+ }
+ }
+
+ // One every 10 iterations, remove a random entry from the cache
+ if (InsecureRandRange(10) == 0) {
+ COutPoint out(txids[InsecureRand32() % txids.size()], 0);
+ int cacheid = InsecureRand32() % stack.size();
+ stack[cacheid]->Uncache(out);
+ uncached_an_entry |= !stack[cacheid]->HaveCoinInCache(out);
+ }
+
+ // Once every 1000 iterations and at the end, verify the full cache.
+ if (InsecureRandRange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) {
+ for (const auto& entry : result) {
+ bool have = stack.back()->HaveCoin(entry.first);
+ const Coin& coin = stack.back()->AccessCoin(entry.first);
+ BOOST_CHECK(have == !coin.IsSpent());
+ BOOST_CHECK(coin == entry.second);
+ if (coin.IsSpent()) {
+ missed_an_entry = true;
+ } else {
+ BOOST_CHECK(stack.back()->HaveCoinInCache(entry.first));
+ found_an_entry = true;
+ }
+ }
+ for (const CCoinsViewCacheTest *test : stack) {
+ test->SelfTest();
+ }
+ }
+
+ if (InsecureRandRange(100) == 0) {
+ // Every 100 iterations, flush an intermediate cache
+ if (stack.size() > 1 && InsecureRandBool() == 0) {
+ unsigned int flushIndex = InsecureRandRange(stack.size() - 1);
+ stack[flushIndex]->Flush();
+ }
+ }
+ if (InsecureRandRange(100) == 0) {
+ // Every 100 iterations, change the cache stack.
+ if (stack.size() > 0 && InsecureRandBool() == 0) {
+ //Remove the top cache
+ stack.back()->Flush();
+ delete stack.back();
+ stack.pop_back();
+ }
+ if (stack.size() == 0 || (stack.size() < 4 && InsecureRandBool())) {
+ //Add a new cache
+ CCoinsView* tip = &base;
+ if (stack.size() > 0) {
+ tip = stack.back();
+ } else {
+ removed_all_caches = true;
+ }
+ stack.push_back(new CCoinsViewCacheTest(tip));
+ if (stack.size() == 4) {
+ reached_4_caches = true;
+ }
+ }
+ }
+ }
+
+ // Clean up the stack.
+ while (stack.size() > 0) {
+ delete stack.back();
+ stack.pop_back();
+ }
+
+ // Verify coverage.
+ BOOST_CHECK(removed_all_caches);
+ BOOST_CHECK(reached_4_caches);
+ BOOST_CHECK(added_an_entry);
+ BOOST_CHECK(added_an_unspendable_entry);
+ BOOST_CHECK(removed_an_entry);
+ BOOST_CHECK(updated_an_entry);
+ BOOST_CHECK(found_an_entry);
+ BOOST_CHECK(missed_an_entry);
+ BOOST_CHECK(uncached_an_entry);
+}
+
+// Store of all necessary tx and undo data for next test
+typedef std::map<COutPoint, std::tuple<CTransaction,CTxUndo,Coin>> UtxoData;
+UtxoData utxoData;
+
+UtxoData::iterator FindRandomFrom(const std::set<COutPoint> &utxoSet) {
+ assert(utxoSet.size());
+ auto utxoSetIt = utxoSet.lower_bound(COutPoint(InsecureRand256(), 0));
+ if (utxoSetIt == utxoSet.end()) {
+ utxoSetIt = utxoSet.begin();
+ }
+ auto utxoDataIt = utxoData.find(*utxoSetIt);
+ assert(utxoDataIt != utxoData.end());
+ return utxoDataIt;
+}
+
+
+// This test is similar to the previous test
+// except the emphasis is on testing the functionality of UpdateCoins
+// random txs are created and UpdateCoins is used to update the cache stack
+// In particular it is tested that spending a duplicate coinbase tx
+// has the expected effect (the other duplicate is overwritten at all cache levels)
+BOOST_AUTO_TEST_CASE(updatecoins_simulation_test)
+{
+ bool spent_a_duplicate_coinbase = false;
+ // A simple map to track what we expect the cache stack to represent.
+ std::map<COutPoint, Coin> result;
+
+ // The cache stack.
+ CCoinsViewTest base; // A CCoinsViewTest at the bottom.
+ std::vector<CCoinsViewCacheTest*> stack; // A stack of CCoinsViewCaches on top.
+ stack.push_back(new CCoinsViewCacheTest(&base)); // Start with one cache.
+
+ // Track the txids we've used in various sets
+ std::set<COutPoint> coinbase_coins;
+ std::set<COutPoint> disconnected_coins;
+ std::set<COutPoint> duplicate_coins;
+ std::set<COutPoint> utxoset;
+
+ for (unsigned int i = 0; i < NUM_SIMULATION_ITERATIONS; i++) {
+ uint32_t randiter = InsecureRand32();
+
+ // 19/20 txs add a new transaction
+ if (randiter % 20 < 19) {
+ CMutableTransaction tx;
+ tx.vin.resize(1);
+ tx.vout.resize(1);
+ tx.vout[0].nValue = i; //Keep txs unique unless intended to duplicate
+ tx.vout[0].scriptPubKey.assign(InsecureRand32() & 0x3F, 0); // Random sizes so we can test memory usage accounting
+ unsigned int height = InsecureRand32();
+ Coin old_coin;
+
+ // 2/20 times create a new coinbase
+ if (randiter % 20 < 2 || coinbase_coins.size() < 10) {
+ // 1/10 of those times create a duplicate coinbase
+ if (InsecureRandRange(10) == 0 && coinbase_coins.size()) {
+ auto utxod = FindRandomFrom(coinbase_coins);
+ // Reuse the exact same coinbase
+ tx = CMutableTransaction{std::get<0>(utxod->second)};
+ // shouldn't be available for reconnection if it's been duplicated
+ disconnected_coins.erase(utxod->first);
+
+ duplicate_coins.insert(utxod->first);
+ }
+ else {
+ coinbase_coins.insert(COutPoint(tx.GetHash(), 0));
+ }
+ assert(CTransaction(tx).IsCoinBase());
+ }
+
+ // 17/20 times reconnect previous or add a regular tx
+ else {
+
+ COutPoint prevout;
+ // 1/20 times reconnect a previously disconnected tx
+ if (randiter % 20 == 2 && disconnected_coins.size()) {
+ auto utxod = FindRandomFrom(disconnected_coins);
+ tx = CMutableTransaction{std::get<0>(utxod->second)};
+ prevout = tx.vin[0].prevout;
+ if (!CTransaction(tx).IsCoinBase() && !utxoset.count(prevout)) {
+ disconnected_coins.erase(utxod->first);
+ continue;
+ }
+
+ // If this tx is already IN the UTXO, then it must be a coinbase, and it must be a duplicate
+ if (utxoset.count(utxod->first)) {
+ assert(CTransaction(tx).IsCoinBase());
+ assert(duplicate_coins.count(utxod->first));
+ }
+ disconnected_coins.erase(utxod->first);
+ }
+
+ // 16/20 times create a regular tx
+ else {
+ auto utxod = FindRandomFrom(utxoset);
+ prevout = utxod->first;
+
+ // Construct the tx to spend the coins of prevouthash
+ tx.vin[0].prevout = prevout;
+ assert(!CTransaction(tx).IsCoinBase());
+ }
+ // In this simple test coins only have two states, spent or unspent, save the unspent state to restore
+ old_coin = result[prevout];
+ // Update the expected result of prevouthash to know these coins are spent
+ result[prevout].Clear();
+
+ utxoset.erase(prevout);
+
+ // The test is designed to ensure spending a duplicate coinbase will work properly
+ // if that ever happens and not resurrect the previously overwritten coinbase
+ if (duplicate_coins.count(prevout)) {
+ spent_a_duplicate_coinbase = true;
+ }
+
+ }
+ // Update the expected result to know about the new output coins
+ assert(tx.vout.size() == 1);
+ const COutPoint outpoint(tx.GetHash(), 0);
+ result[outpoint] = Coin(tx.vout[0], height, CTransaction(tx).IsCoinBase());
+
+ // Call UpdateCoins on the top cache
+ CTxUndo undo;
+ UpdateCoins(tx, *(stack.back()), undo, height);
+
+ // Update the utxo set for future spends
+ utxoset.insert(outpoint);
+
+ // Track this tx and undo info to use later
+ utxoData.emplace(outpoint, std::make_tuple(tx,undo,old_coin));
+ } else if (utxoset.size()) {
+ //1/20 times undo a previous transaction
+ auto utxod = FindRandomFrom(utxoset);
+
+ CTransaction &tx = std::get<0>(utxod->second);
+ CTxUndo &undo = std::get<1>(utxod->second);
+ Coin &orig_coin = std::get<2>(utxod->second);
+
+ // Update the expected result
+ // Remove new outputs
+ result[utxod->first].Clear();
+ // If not coinbase restore prevout
+ if (!tx.IsCoinBase()) {
+ result[tx.vin[0].prevout] = orig_coin;
+ }
+
+ // Disconnect the tx from the current UTXO
+ // See code in DisconnectBlock
+ // remove outputs
+ stack.back()->SpendCoin(utxod->first);
+ // restore inputs
+ if (!tx.IsCoinBase()) {
+ const COutPoint &out = tx.vin[0].prevout;
+ Coin coin = undo.vprevout[0];
+ ApplyTxInUndo(std::move(coin), *(stack.back()), out);
+ }
+ // Store as a candidate for reconnection
+ disconnected_coins.insert(utxod->first);
+
+ // Update the utxoset
+ utxoset.erase(utxod->first);
+ if (!tx.IsCoinBase())
+ utxoset.insert(tx.vin[0].prevout);
+ }
+
+ // Once every 1000 iterations and at the end, verify the full cache.
+ if (InsecureRandRange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) {
+ for (const auto& entry : result) {
+ bool have = stack.back()->HaveCoin(entry.first);
+ const Coin& coin = stack.back()->AccessCoin(entry.first);
+ BOOST_CHECK(have == !coin.IsSpent());
+ BOOST_CHECK(coin == entry.second);
+ }
+ }
+
+ // One every 10 iterations, remove a random entry from the cache
+ if (utxoset.size() > 1 && InsecureRandRange(30) == 0) {
+ stack[InsecureRand32() % stack.size()]->Uncache(FindRandomFrom(utxoset)->first);
+ }
+ if (disconnected_coins.size() > 1 && InsecureRandRange(30) == 0) {
+ stack[InsecureRand32() % stack.size()]->Uncache(FindRandomFrom(disconnected_coins)->first);
+ }
+ if (duplicate_coins.size() > 1 && InsecureRandRange(30) == 0) {
+ stack[InsecureRand32() % stack.size()]->Uncache(FindRandomFrom(duplicate_coins)->first);
+ }
+
+ if (InsecureRandRange(100) == 0) {
+ // Every 100 iterations, flush an intermediate cache
+ if (stack.size() > 1 && InsecureRandBool() == 0) {
+ unsigned int flushIndex = InsecureRandRange(stack.size() - 1);
+ stack[flushIndex]->Flush();
+ }
+ }
+ if (InsecureRandRange(100) == 0) {
+ // Every 100 iterations, change the cache stack.
+ if (stack.size() > 0 && InsecureRandBool() == 0) {
+ stack.back()->Flush();
+ delete stack.back();
+ stack.pop_back();
+ }
+ if (stack.size() == 0 || (stack.size() < 4 && InsecureRandBool())) {
+ CCoinsView* tip = &base;
+ if (stack.size() > 0) {
+ tip = stack.back();
+ }
+ stack.push_back(new CCoinsViewCacheTest(tip));
+ }
+ }
+ }
+
+ // Clean up the stack.
+ while (stack.size() > 0) {
+ delete stack.back();
+ stack.pop_back();
+ }
+
+ // Verify coverage.
+ BOOST_CHECK(spent_a_duplicate_coinbase);
+}
+
+BOOST_AUTO_TEST_CASE(ccoins_serialization)
+{
+ // Good example
+ CDataStream ss1(ParseHex("97f23c835800816115944e077fe7c803cfa57f29b36bf87c1d35"), SER_DISK, CLIENT_VERSION);
+ Coin cc1;
+ ss1 >> cc1;
+ BOOST_CHECK_EQUAL(cc1.fCoinBase, false);
+ BOOST_CHECK_EQUAL(cc1.nHeight, 203998U);
+ BOOST_CHECK_EQUAL(cc1.out.nValue, CAmount{60000000000});
+ BOOST_CHECK_EQUAL(HexStr(cc1.out.scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("816115944e077fe7c803cfa57f29b36bf87c1d35"))))));
+
+ // Good example
+ CDataStream ss2(ParseHex("8ddf77bbd123008c988f1a4a4de2161e0f50aac7f17e7f9555caa4"), SER_DISK, CLIENT_VERSION);
+ Coin cc2;
+ ss2 >> cc2;
+ BOOST_CHECK_EQUAL(cc2.fCoinBase, true);
+ BOOST_CHECK_EQUAL(cc2.nHeight, 120891U);
+ BOOST_CHECK_EQUAL(cc2.out.nValue, 110397);
+ BOOST_CHECK_EQUAL(HexStr(cc2.out.scriptPubKey), HexStr(GetScriptForDestination(CKeyID(uint160(ParseHex("8c988f1a4a4de2161e0f50aac7f17e7f9555caa4"))))));
+
+ // Smallest possible example
+ CDataStream ss3(ParseHex("000006"), SER_DISK, CLIENT_VERSION);
+ Coin cc3;
+ ss3 >> cc3;
+ BOOST_CHECK_EQUAL(cc3.fCoinBase, false);
+ BOOST_CHECK_EQUAL(cc3.nHeight, 0U);
+ BOOST_CHECK_EQUAL(cc3.out.nValue, 0);
+ BOOST_CHECK_EQUAL(cc3.out.scriptPubKey.size(), 0U);
+
+ // scriptPubKey that ends beyond the end of the stream
+ CDataStream ss4(ParseHex("000007"), SER_DISK, CLIENT_VERSION);
+ try {
+ Coin cc4;
+ ss4 >> cc4;
+ BOOST_CHECK_MESSAGE(false, "We should have thrown");
+ } catch (const std::ios_base::failure& e) {
+ }
+
+ // Very large scriptPubKey (3*10^9 bytes) past the end of the stream
+ CDataStream tmp(SER_DISK, CLIENT_VERSION);
+ uint64_t x = 3000000000ULL;
+ tmp << VARINT(x);
+ BOOST_CHECK_EQUAL(HexStr(tmp.begin(), tmp.end()), "8a95c0bb00");
+ CDataStream ss5(ParseHex("00008a95c0bb00"), SER_DISK, CLIENT_VERSION);
+ try {
+ Coin cc5;
+ ss5 >> cc5;
+ BOOST_CHECK_MESSAGE(false, "We should have thrown");
+ } catch (const std::ios_base::failure& e) {
+ }
+}
+
+const static COutPoint OUTPOINT;
+const static CAmount PRUNED = -1;
+const static CAmount ABSENT = -2;
+const static CAmount FAIL = -3;
+const static CAmount VALUE1 = 100;
+const static CAmount VALUE2 = 200;
+const static CAmount VALUE3 = 300;
+const static char DIRTY = CCoinsCacheEntry::DIRTY;
+const static char FRESH = CCoinsCacheEntry::FRESH;
+const static char NO_ENTRY = -1;
+
+const static auto FLAGS = {char(0), FRESH, DIRTY, char(DIRTY | FRESH)};
+const static auto CLEAN_FLAGS = {char(0), FRESH};
+const static auto ABSENT_FLAGS = {NO_ENTRY};
+
+static void SetCoinsValue(CAmount value, Coin& coin)
+{
+ assert(value != ABSENT);
+ coin.Clear();
+ assert(coin.IsSpent());
+ if (value != PRUNED) {
+ coin.out.nValue = value;
+ coin.nHeight = 1;
+ assert(!coin.IsSpent());
+ }
+}
+
+static size_t InsertCoinsMapEntry(CCoinsMap& map, CAmount value, char flags)
+{
+ if (value == ABSENT) {
+ assert(flags == NO_ENTRY);
+ return 0;
+ }
+ assert(flags != NO_ENTRY);
+ CCoinsCacheEntry entry;
+ entry.flags = flags;
+ SetCoinsValue(value, entry.coin);
+ auto inserted = map.emplace(OUTPOINT, std::move(entry));
+ assert(inserted.second);
+ return inserted.first->second.coin.DynamicMemoryUsage();
+}
+
+void GetCoinsMapEntry(const CCoinsMap& map, CAmount& value, char& flags)
+{
+ auto it = map.find(OUTPOINT);
+ if (it == map.end()) {
+ value = ABSENT;
+ flags = NO_ENTRY;
+ } else {
+ if (it->second.coin.IsSpent()) {
+ value = PRUNED;
+ } else {
+ value = it->second.coin.out.nValue;
+ }
+ flags = it->second.flags;
+ assert(flags != NO_ENTRY);
+ }
+}
+
+void WriteCoinsViewEntry(CCoinsView& view, CAmount value, char flags)
+{
+ CCoinsMap map;
+ InsertCoinsMapEntry(map, value, flags);
+ view.BatchWrite(map, {});
+}
+
+class SingleEntryCacheTest
+{
+public:
+ SingleEntryCacheTest(CAmount base_value, CAmount cache_value, char cache_flags)
+ {
+ WriteCoinsViewEntry(base, base_value, base_value == ABSENT ? NO_ENTRY : DIRTY);
+ cache.usage() += InsertCoinsMapEntry(cache.map(), cache_value, cache_flags);
+ }
+
+ CCoinsView root;
+ CCoinsViewCacheTest base{&root};
+ CCoinsViewCacheTest cache{&base};
+};
+
+static void CheckAccessCoin(CAmount base_value, CAmount cache_value, CAmount expected_value, char cache_flags, char expected_flags)
+{
+ SingleEntryCacheTest test(base_value, cache_value, cache_flags);
+ test.cache.AccessCoin(OUTPOINT);
+ test.cache.SelfTest();
+
+ CAmount result_value;
+ char result_flags;
+ GetCoinsMapEntry(test.cache.map(), result_value, result_flags);
+ BOOST_CHECK_EQUAL(result_value, expected_value);
+ BOOST_CHECK_EQUAL(result_flags, expected_flags);
+}
+
+BOOST_AUTO_TEST_CASE(ccoins_access)
+{
+ /* Check AccessCoin behavior, requesting a coin from a cache view layered on
+ * top of a base view, and checking the resulting entry in the cache after
+ * the access.
+ *
+ * Base Cache Result Cache Result
+ * Value Value Value Flags Flags
+ */
+ CheckAccessCoin(ABSENT, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY );
+ CheckAccessCoin(ABSENT, PRUNED, PRUNED, 0 , 0 );
+ CheckAccessCoin(ABSENT, PRUNED, PRUNED, FRESH , FRESH );
+ CheckAccessCoin(ABSENT, PRUNED, PRUNED, DIRTY , DIRTY );
+ CheckAccessCoin(ABSENT, PRUNED, PRUNED, DIRTY|FRESH, DIRTY|FRESH);
+ CheckAccessCoin(ABSENT, VALUE2, VALUE2, 0 , 0 );
+ CheckAccessCoin(ABSENT, VALUE2, VALUE2, FRESH , FRESH );
+ CheckAccessCoin(ABSENT, VALUE2, VALUE2, DIRTY , DIRTY );
+ CheckAccessCoin(ABSENT, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH);
+ CheckAccessCoin(PRUNED, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY );
+ CheckAccessCoin(PRUNED, PRUNED, PRUNED, 0 , 0 );
+ CheckAccessCoin(PRUNED, PRUNED, PRUNED, FRESH , FRESH );
+ CheckAccessCoin(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY );
+ CheckAccessCoin(PRUNED, PRUNED, PRUNED, DIRTY|FRESH, DIRTY|FRESH);
+ CheckAccessCoin(PRUNED, VALUE2, VALUE2, 0 , 0 );
+ CheckAccessCoin(PRUNED, VALUE2, VALUE2, FRESH , FRESH );
+ CheckAccessCoin(PRUNED, VALUE2, VALUE2, DIRTY , DIRTY );
+ CheckAccessCoin(PRUNED, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH);
+ CheckAccessCoin(VALUE1, ABSENT, VALUE1, NO_ENTRY , 0 );
+ CheckAccessCoin(VALUE1, PRUNED, PRUNED, 0 , 0 );
+ CheckAccessCoin(VALUE1, PRUNED, PRUNED, FRESH , FRESH );
+ CheckAccessCoin(VALUE1, PRUNED, PRUNED, DIRTY , DIRTY );
+ CheckAccessCoin(VALUE1, PRUNED, PRUNED, DIRTY|FRESH, DIRTY|FRESH);
+ CheckAccessCoin(VALUE1, VALUE2, VALUE2, 0 , 0 );
+ CheckAccessCoin(VALUE1, VALUE2, VALUE2, FRESH , FRESH );
+ CheckAccessCoin(VALUE1, VALUE2, VALUE2, DIRTY , DIRTY );
+ CheckAccessCoin(VALUE1, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH);
+}
+
+static void CheckSpendCoins(CAmount base_value, CAmount cache_value, CAmount expected_value, char cache_flags, char expected_flags)
+{
+ SingleEntryCacheTest test(base_value, cache_value, cache_flags);
+ test.cache.SpendCoin(OUTPOINT);
+ test.cache.SelfTest();
+
+ CAmount result_value;
+ char result_flags;
+ GetCoinsMapEntry(test.cache.map(), result_value, result_flags);
+ BOOST_CHECK_EQUAL(result_value, expected_value);
+ BOOST_CHECK_EQUAL(result_flags, expected_flags);
+};
+
+BOOST_AUTO_TEST_CASE(ccoins_spend)
+{
+ /* Check SpendCoin behavior, requesting a coin from a cache view layered on
+ * top of a base view, spending, and then checking
+ * the resulting entry in the cache after the modification.
+ *
+ * Base Cache Result Cache Result
+ * Value Value Value Flags Flags
+ */
+ CheckSpendCoins(ABSENT, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY );
+ CheckSpendCoins(ABSENT, PRUNED, PRUNED, 0 , DIRTY );
+ CheckSpendCoins(ABSENT, PRUNED, ABSENT, FRESH , NO_ENTRY );
+ CheckSpendCoins(ABSENT, PRUNED, PRUNED, DIRTY , DIRTY );
+ CheckSpendCoins(ABSENT, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY );
+ CheckSpendCoins(ABSENT, VALUE2, PRUNED, 0 , DIRTY );
+ CheckSpendCoins(ABSENT, VALUE2, ABSENT, FRESH , NO_ENTRY );
+ CheckSpendCoins(ABSENT, VALUE2, PRUNED, DIRTY , DIRTY );
+ CheckSpendCoins(ABSENT, VALUE2, ABSENT, DIRTY|FRESH, NO_ENTRY );
+ CheckSpendCoins(PRUNED, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY );
+ CheckSpendCoins(PRUNED, PRUNED, PRUNED, 0 , DIRTY );
+ CheckSpendCoins(PRUNED, PRUNED, ABSENT, FRESH , NO_ENTRY );
+ CheckSpendCoins(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY );
+ CheckSpendCoins(PRUNED, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY );
+ CheckSpendCoins(PRUNED, VALUE2, PRUNED, 0 , DIRTY );
+ CheckSpendCoins(PRUNED, VALUE2, ABSENT, FRESH , NO_ENTRY );
+ CheckSpendCoins(PRUNED, VALUE2, PRUNED, DIRTY , DIRTY );
+ CheckSpendCoins(PRUNED, VALUE2, ABSENT, DIRTY|FRESH, NO_ENTRY );
+ CheckSpendCoins(VALUE1, ABSENT, PRUNED, NO_ENTRY , DIRTY );
+ CheckSpendCoins(VALUE1, PRUNED, PRUNED, 0 , DIRTY );
+ CheckSpendCoins(VALUE1, PRUNED, ABSENT, FRESH , NO_ENTRY );
+ CheckSpendCoins(VALUE1, PRUNED, PRUNED, DIRTY , DIRTY );
+ CheckSpendCoins(VALUE1, PRUNED, ABSENT, DIRTY|FRESH, NO_ENTRY );
+ CheckSpendCoins(VALUE1, VALUE2, PRUNED, 0 , DIRTY );
+ CheckSpendCoins(VALUE1, VALUE2, ABSENT, FRESH , NO_ENTRY );
+ CheckSpendCoins(VALUE1, VALUE2, PRUNED, DIRTY , DIRTY );
+ CheckSpendCoins(VALUE1, VALUE2, ABSENT, DIRTY|FRESH, NO_ENTRY );
+}
+
+static void CheckAddCoinBase(CAmount base_value, CAmount cache_value, CAmount modify_value, CAmount expected_value, char cache_flags, char expected_flags, bool coinbase)
+{
+ SingleEntryCacheTest test(base_value, cache_value, cache_flags);
+
+ CAmount result_value;
+ char result_flags;
+ try {
+ CTxOut output;
+ output.nValue = modify_value;
+ test.cache.AddCoin(OUTPOINT, Coin(std::move(output), 1, coinbase), coinbase);
+ test.cache.SelfTest();
+ GetCoinsMapEntry(test.cache.map(), result_value, result_flags);
+ } catch (std::logic_error& e) {
+ result_value = FAIL;
+ result_flags = NO_ENTRY;
+ }
+
+ BOOST_CHECK_EQUAL(result_value, expected_value);
+ BOOST_CHECK_EQUAL(result_flags, expected_flags);
+}
+
+// Simple wrapper for CheckAddCoinBase function above that loops through
+// different possible base_values, making sure each one gives the same results.
+// This wrapper lets the coins_add test below be shorter and less repetitive,
+// while still verifying that the CoinsViewCache::AddCoin implementation
+// ignores base values.
+template <typename... Args>
+static void CheckAddCoin(Args&&... args)
+{
+ for (CAmount base_value : {ABSENT, PRUNED, VALUE1})
+ CheckAddCoinBase(base_value, std::forward<Args>(args)...);
+}
+
+BOOST_AUTO_TEST_CASE(ccoins_add)
+{
+ /* Check AddCoin behavior, requesting a new coin from a cache view,
+ * writing a modification to the coin, and then checking the resulting
+ * entry in the cache after the modification. Verify behavior with the
+ * with the AddCoin potential_overwrite argument set to false, and to true.
+ *
+ * Cache Write Result Cache Result potential_overwrite
+ * Value Value Value Flags Flags
+ */
+ CheckAddCoin(ABSENT, VALUE3, VALUE3, NO_ENTRY , DIRTY|FRESH, false);
+ CheckAddCoin(ABSENT, VALUE3, VALUE3, NO_ENTRY , DIRTY , true );
+ CheckAddCoin(PRUNED, VALUE3, VALUE3, 0 , DIRTY|FRESH, false);
+ CheckAddCoin(PRUNED, VALUE3, VALUE3, 0 , DIRTY , true );
+ CheckAddCoin(PRUNED, VALUE3, VALUE3, FRESH , DIRTY|FRESH, false);
+ CheckAddCoin(PRUNED, VALUE3, VALUE3, FRESH , DIRTY|FRESH, true );
+ CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY , DIRTY , false);
+ CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY , DIRTY , true );
+ CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, false);
+ CheckAddCoin(PRUNED, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, true );
+ CheckAddCoin(VALUE2, VALUE3, FAIL , 0 , NO_ENTRY , false);
+ CheckAddCoin(VALUE2, VALUE3, VALUE3, 0 , DIRTY , true );
+ CheckAddCoin(VALUE2, VALUE3, FAIL , FRESH , NO_ENTRY , false);
+ CheckAddCoin(VALUE2, VALUE3, VALUE3, FRESH , DIRTY|FRESH, true );
+ CheckAddCoin(VALUE2, VALUE3, FAIL , DIRTY , NO_ENTRY , false);
+ CheckAddCoin(VALUE2, VALUE3, VALUE3, DIRTY , DIRTY , true );
+ CheckAddCoin(VALUE2, VALUE3, FAIL , DIRTY|FRESH, NO_ENTRY , false);
+ CheckAddCoin(VALUE2, VALUE3, VALUE3, DIRTY|FRESH, DIRTY|FRESH, true );
+}
+
+void CheckWriteCoins(CAmount parent_value, CAmount child_value, CAmount expected_value, char parent_flags, char child_flags, char expected_flags)
+{
+ SingleEntryCacheTest test(ABSENT, parent_value, parent_flags);
+
+ CAmount result_value;
+ char result_flags;
+ try {
+ WriteCoinsViewEntry(test.cache, child_value, child_flags);
+ test.cache.SelfTest();
+ GetCoinsMapEntry(test.cache.map(), result_value, result_flags);
+ } catch (std::logic_error& e) {
+ result_value = FAIL;
+ result_flags = NO_ENTRY;
+ }
+
+ BOOST_CHECK_EQUAL(result_value, expected_value);
+ BOOST_CHECK_EQUAL(result_flags, expected_flags);
+}
+
+BOOST_AUTO_TEST_CASE(ccoins_write)
+{
+ /* Check BatchWrite behavior, flushing one entry from a child cache to a
+ * parent cache, and checking the resulting entry in the parent cache
+ * after the write.
+ *
+ * Parent Child Result Parent Child Result
+ * Value Value Value Flags Flags Flags
+ */
+ CheckWriteCoins(ABSENT, ABSENT, ABSENT, NO_ENTRY , NO_ENTRY , NO_ENTRY );
+ CheckWriteCoins(ABSENT, PRUNED, PRUNED, NO_ENTRY , DIRTY , DIRTY );
+ CheckWriteCoins(ABSENT, PRUNED, ABSENT, NO_ENTRY , DIRTY|FRESH, NO_ENTRY );
+ CheckWriteCoins(ABSENT, VALUE2, VALUE2, NO_ENTRY , DIRTY , DIRTY );
+ CheckWriteCoins(ABSENT, VALUE2, VALUE2, NO_ENTRY , DIRTY|FRESH, DIRTY|FRESH);
+ CheckWriteCoins(PRUNED, ABSENT, PRUNED, 0 , NO_ENTRY , 0 );
+ CheckWriteCoins(PRUNED, ABSENT, PRUNED, FRESH , NO_ENTRY , FRESH );
+ CheckWriteCoins(PRUNED, ABSENT, PRUNED, DIRTY , NO_ENTRY , DIRTY );
+ CheckWriteCoins(PRUNED, ABSENT, PRUNED, DIRTY|FRESH, NO_ENTRY , DIRTY|FRESH);
+ CheckWriteCoins(PRUNED, PRUNED, PRUNED, 0 , DIRTY , DIRTY );
+ CheckWriteCoins(PRUNED, PRUNED, PRUNED, 0 , DIRTY|FRESH, DIRTY );
+ CheckWriteCoins(PRUNED, PRUNED, ABSENT, FRESH , DIRTY , NO_ENTRY );
+ CheckWriteCoins(PRUNED, PRUNED, ABSENT, FRESH , DIRTY|FRESH, NO_ENTRY );
+ CheckWriteCoins(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY , DIRTY );
+ CheckWriteCoins(PRUNED, PRUNED, PRUNED, DIRTY , DIRTY|FRESH, DIRTY );
+ CheckWriteCoins(PRUNED, PRUNED, ABSENT, DIRTY|FRESH, DIRTY , NO_ENTRY );
+ CheckWriteCoins(PRUNED, PRUNED, ABSENT, DIRTY|FRESH, DIRTY|FRESH, NO_ENTRY );
+ CheckWriteCoins(PRUNED, VALUE2, VALUE2, 0 , DIRTY , DIRTY );
+ CheckWriteCoins(PRUNED, VALUE2, VALUE2, 0 , DIRTY|FRESH, DIRTY );
+ CheckWriteCoins(PRUNED, VALUE2, VALUE2, FRESH , DIRTY , DIRTY|FRESH);
+ CheckWriteCoins(PRUNED, VALUE2, VALUE2, FRESH , DIRTY|FRESH, DIRTY|FRESH);
+ CheckWriteCoins(PRUNED, VALUE2, VALUE2, DIRTY , DIRTY , DIRTY );
+ CheckWriteCoins(PRUNED, VALUE2, VALUE2, DIRTY , DIRTY|FRESH, DIRTY );
+ CheckWriteCoins(PRUNED, VALUE2, VALUE2, DIRTY|FRESH, DIRTY , DIRTY|FRESH);
+ CheckWriteCoins(PRUNED, VALUE2, VALUE2, DIRTY|FRESH, DIRTY|FRESH, DIRTY|FRESH);
+ CheckWriteCoins(VALUE1, ABSENT, VALUE1, 0 , NO_ENTRY , 0 );
+ CheckWriteCoins(VALUE1, ABSENT, VALUE1, FRESH , NO_ENTRY , FRESH );
+ CheckWriteCoins(VALUE1, ABSENT, VALUE1, DIRTY , NO_ENTRY , DIRTY );
+ CheckWriteCoins(VALUE1, ABSENT, VALUE1, DIRTY|FRESH, NO_ENTRY , DIRTY|FRESH);
+ CheckWriteCoins(VALUE1, PRUNED, PRUNED, 0 , DIRTY , DIRTY );
+ CheckWriteCoins(VALUE1, PRUNED, FAIL , 0 , DIRTY|FRESH, NO_ENTRY );
+ CheckWriteCoins(VALUE1, PRUNED, ABSENT, FRESH , DIRTY , NO_ENTRY );
+ CheckWriteCoins(VALUE1, PRUNED, FAIL , FRESH , DIRTY|FRESH, NO_ENTRY );
+ CheckWriteCoins(VALUE1, PRUNED, PRUNED, DIRTY , DIRTY , DIRTY );
+ CheckWriteCoins(VALUE1, PRUNED, FAIL , DIRTY , DIRTY|FRESH, NO_ENTRY );
+ CheckWriteCoins(VALUE1, PRUNED, ABSENT, DIRTY|FRESH, DIRTY , NO_ENTRY );
+ CheckWriteCoins(VALUE1, PRUNED, FAIL , DIRTY|FRESH, DIRTY|FRESH, NO_ENTRY );
+ CheckWriteCoins(VALUE1, VALUE2, VALUE2, 0 , DIRTY , DIRTY );
+ CheckWriteCoins(VALUE1, VALUE2, FAIL , 0 , DIRTY|FRESH, NO_ENTRY );
+ CheckWriteCoins(VALUE1, VALUE2, VALUE2, FRESH , DIRTY , DIRTY|FRESH);
+ CheckWriteCoins(VALUE1, VALUE2, FAIL , FRESH , DIRTY|FRESH, NO_ENTRY );
+ CheckWriteCoins(VALUE1, VALUE2, VALUE2, DIRTY , DIRTY , DIRTY );
+ CheckWriteCoins(VALUE1, VALUE2, FAIL , DIRTY , DIRTY|FRESH, NO_ENTRY );
+ CheckWriteCoins(VALUE1, VALUE2, VALUE2, DIRTY|FRESH, DIRTY , DIRTY|FRESH);
+ CheckWriteCoins(VALUE1, VALUE2, FAIL , DIRTY|FRESH, DIRTY|FRESH, NO_ENTRY );
+
+ // The checks above omit cases where the child flags are not DIRTY, since
+ // they would be too repetitive (the parent cache is never updated in these
+ // cases). The loop below covers these cases and makes sure the parent cache
+ // is always left unchanged.
+ for (CAmount parent_value : {ABSENT, PRUNED, VALUE1})
+ for (CAmount child_value : {ABSENT, PRUNED, VALUE2})
+ for (char parent_flags : parent_value == ABSENT ? ABSENT_FLAGS : FLAGS)
+ for (char child_flags : child_value == ABSENT ? ABSENT_FLAGS : CLEAN_FLAGS)
+ CheckWriteCoins(parent_value, child_value, parent_value, parent_flags, child_flags, parent_flags);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/compress_tests.cpp b/src/test/compress_tests.cpp
new file mode 100644
index 0000000000..a4e99d438f
--- /dev/null
+++ b/src/test/compress_tests.cpp
@@ -0,0 +1,65 @@
+// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <compressor.h>
+#include <util.h>
+#include <test/test_bitcoin.h>
+
+#include <stdint.h>
+
+#include <boost/test/unit_test.hpp>
+
+// amounts 0.00000001 .. 0.00100000
+#define NUM_MULTIPLES_UNIT 100000
+
+// amounts 0.01 .. 100.00
+#define NUM_MULTIPLES_CENT 10000
+
+// amounts 1 .. 10000
+#define NUM_MULTIPLES_1BTC 10000
+
+// amounts 50 .. 21000000
+#define NUM_MULTIPLES_50BTC 420000
+
+BOOST_FIXTURE_TEST_SUITE(compress_tests, BasicTestingSetup)
+
+bool static TestEncode(uint64_t in) {
+ return in == DecompressAmount(CompressAmount(in));
+}
+
+bool static TestDecode(uint64_t in) {
+ return in == CompressAmount(DecompressAmount(in));
+}
+
+bool static TestPair(uint64_t dec, uint64_t enc) {
+ return CompressAmount(dec) == enc &&
+ DecompressAmount(enc) == dec;
+}
+
+BOOST_AUTO_TEST_CASE(compress_amounts)
+{
+ BOOST_CHECK(TestPair( 0, 0x0));
+ BOOST_CHECK(TestPair( 1, 0x1));
+ BOOST_CHECK(TestPair( CENT, 0x7));
+ BOOST_CHECK(TestPair( COIN, 0x9));
+ BOOST_CHECK(TestPair( 50*COIN, 0x32));
+ BOOST_CHECK(TestPair(21000000*COIN, 0x1406f40));
+
+ for (uint64_t i = 1; i <= NUM_MULTIPLES_UNIT; i++)
+ BOOST_CHECK(TestEncode(i));
+
+ for (uint64_t i = 1; i <= NUM_MULTIPLES_CENT; i++)
+ BOOST_CHECK(TestEncode(i * CENT));
+
+ for (uint64_t i = 1; i <= NUM_MULTIPLES_1BTC; i++)
+ BOOST_CHECK(TestEncode(i * COIN));
+
+ for (uint64_t i = 1; i <= NUM_MULTIPLES_50BTC; i++)
+ BOOST_CHECK(TestEncode(i * 50 * COIN));
+
+ for (uint64_t i = 0; i < 100000; i++)
+ BOOST_CHECK(TestDecode(i));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp
new file mode 100644
index 0000000000..19521027a9
--- /dev/null
+++ b/src/test/crypto_tests.cpp
@@ -0,0 +1,565 @@
+// Copyright (c) 2014-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <crypto/aes.h>
+#include <crypto/chacha20.h>
+#include <crypto/ripemd160.h>
+#include <crypto/sha1.h>
+#include <crypto/sha256.h>
+#include <crypto/sha512.h>
+#include <crypto/hmac_sha256.h>
+#include <crypto/hmac_sha512.h>
+#include <random.h>
+#include <utilstrencodings.h>
+#include <test/test_bitcoin.h>
+
+#include <vector>
+
+#include <boost/test/unit_test.hpp>
+#include <openssl/aes.h>
+#include <openssl/evp.h>
+
+BOOST_FIXTURE_TEST_SUITE(crypto_tests, BasicTestingSetup)
+
+template<typename Hasher, typename In, typename Out>
+static void TestVector(const Hasher &h, const In &in, const Out &out) {
+ Out hash;
+ BOOST_CHECK(out.size() == h.OUTPUT_SIZE);
+ hash.resize(out.size());
+ {
+ // Test that writing the whole input string at once works.
+ Hasher(h).Write((unsigned char*)&in[0], in.size()).Finalize(&hash[0]);
+ BOOST_CHECK(hash == out);
+ }
+ for (int i=0; i<32; i++) {
+ // Test that writing the string broken up in random pieces works.
+ Hasher hasher(h);
+ size_t pos = 0;
+ while (pos < in.size()) {
+ size_t len = InsecureRandRange((in.size() - pos + 1) / 2 + 1);
+ hasher.Write((unsigned char*)&in[pos], len);
+ pos += len;
+ if (pos > 0 && pos + 2 * out.size() > in.size() && pos < in.size()) {
+ // Test that writing the rest at once to a copy of a hasher works.
+ Hasher(hasher).Write((unsigned char*)&in[pos], in.size() - pos).Finalize(&hash[0]);
+ BOOST_CHECK(hash == out);
+ }
+ }
+ hasher.Finalize(&hash[0]);
+ BOOST_CHECK(hash == out);
+ }
+}
+
+static void TestSHA1(const std::string &in, const std::string &hexout) { TestVector(CSHA1(), in, ParseHex(hexout));}
+static void TestSHA256(const std::string &in, const std::string &hexout) { TestVector(CSHA256(), in, ParseHex(hexout));}
+static void TestSHA512(const std::string &in, const std::string &hexout) { TestVector(CSHA512(), in, ParseHex(hexout));}
+static void TestRIPEMD160(const std::string &in, const std::string &hexout) { TestVector(CRIPEMD160(), in, ParseHex(hexout));}
+
+static void TestHMACSHA256(const std::string &hexkey, const std::string &hexin, const std::string &hexout) {
+ std::vector<unsigned char> key = ParseHex(hexkey);
+ TestVector(CHMAC_SHA256(key.data(), key.size()), ParseHex(hexin), ParseHex(hexout));
+}
+
+static void TestHMACSHA512(const std::string &hexkey, const std::string &hexin, const std::string &hexout) {
+ std::vector<unsigned char> key = ParseHex(hexkey);
+ TestVector(CHMAC_SHA512(key.data(), key.size()), ParseHex(hexin), ParseHex(hexout));
+}
+
+static void TestAES128(const std::string &hexkey, const std::string &hexin, const std::string &hexout)
+{
+ std::vector<unsigned char> key = ParseHex(hexkey);
+ std::vector<unsigned char> in = ParseHex(hexin);
+ std::vector<unsigned char> correctout = ParseHex(hexout);
+ std::vector<unsigned char> buf, buf2;
+
+ assert(key.size() == 16);
+ assert(in.size() == 16);
+ assert(correctout.size() == 16);
+ AES128Encrypt enc(key.data());
+ buf.resize(correctout.size());
+ buf2.resize(correctout.size());
+ enc.Encrypt(buf.data(), in.data());
+ BOOST_CHECK_EQUAL(HexStr(buf), HexStr(correctout));
+ AES128Decrypt dec(key.data());
+ dec.Decrypt(buf2.data(), buf.data());
+ BOOST_CHECK_EQUAL(HexStr(buf2), HexStr(in));
+}
+
+static void TestAES256(const std::string &hexkey, const std::string &hexin, const std::string &hexout)
+{
+ std::vector<unsigned char> key = ParseHex(hexkey);
+ std::vector<unsigned char> in = ParseHex(hexin);
+ std::vector<unsigned char> correctout = ParseHex(hexout);
+ std::vector<unsigned char> buf;
+
+ assert(key.size() == 32);
+ assert(in.size() == 16);
+ assert(correctout.size() == 16);
+ AES256Encrypt enc(key.data());
+ buf.resize(correctout.size());
+ enc.Encrypt(buf.data(), in.data());
+ BOOST_CHECK(buf == correctout);
+ AES256Decrypt dec(key.data());
+ dec.Decrypt(buf.data(), buf.data());
+ BOOST_CHECK(buf == in);
+}
+
+static void TestAES128CBC(const std::string &hexkey, const std::string &hexiv, bool pad, const std::string &hexin, const std::string &hexout)
+{
+ std::vector<unsigned char> key = ParseHex(hexkey);
+ std::vector<unsigned char> iv = ParseHex(hexiv);
+ std::vector<unsigned char> in = ParseHex(hexin);
+ std::vector<unsigned char> correctout = ParseHex(hexout);
+ std::vector<unsigned char> realout(in.size() + AES_BLOCKSIZE);
+
+ // Encrypt the plaintext and verify that it equals the cipher
+ AES128CBCEncrypt enc(key.data(), iv.data(), pad);
+ int size = enc.Encrypt(in.data(), in.size(), realout.data());
+ realout.resize(size);
+ BOOST_CHECK(realout.size() == correctout.size());
+ BOOST_CHECK_MESSAGE(realout == correctout, HexStr(realout) + std::string(" != ") + hexout);
+
+ // Decrypt the cipher and verify that it equals the plaintext
+ std::vector<unsigned char> decrypted(correctout.size());
+ AES128CBCDecrypt dec(key.data(), iv.data(), pad);
+ size = dec.Decrypt(correctout.data(), correctout.size(), decrypted.data());
+ decrypted.resize(size);
+ BOOST_CHECK(decrypted.size() == in.size());
+ BOOST_CHECK_MESSAGE(decrypted == in, HexStr(decrypted) + std::string(" != ") + hexin);
+
+ // Encrypt and re-decrypt substrings of the plaintext and verify that they equal each-other
+ for(std::vector<unsigned char>::iterator i(in.begin()); i != in.end(); ++i)
+ {
+ std::vector<unsigned char> sub(i, in.end());
+ std::vector<unsigned char> subout(sub.size() + AES_BLOCKSIZE);
+ int _size = enc.Encrypt(sub.data(), sub.size(), subout.data());
+ if (_size != 0)
+ {
+ subout.resize(_size);
+ std::vector<unsigned char> subdecrypted(subout.size());
+ _size = dec.Decrypt(subout.data(), subout.size(), subdecrypted.data());
+ subdecrypted.resize(_size);
+ BOOST_CHECK(decrypted.size() == in.size());
+ BOOST_CHECK_MESSAGE(subdecrypted == sub, HexStr(subdecrypted) + std::string(" != ") + HexStr(sub));
+ }
+ }
+}
+
+static void TestAES256CBC(const std::string &hexkey, const std::string &hexiv, bool pad, const std::string &hexin, const std::string &hexout)
+{
+ std::vector<unsigned char> key = ParseHex(hexkey);
+ std::vector<unsigned char> iv = ParseHex(hexiv);
+ std::vector<unsigned char> in = ParseHex(hexin);
+ std::vector<unsigned char> correctout = ParseHex(hexout);
+ std::vector<unsigned char> realout(in.size() + AES_BLOCKSIZE);
+
+ // Encrypt the plaintext and verify that it equals the cipher
+ AES256CBCEncrypt enc(key.data(), iv.data(), pad);
+ int size = enc.Encrypt(in.data(), in.size(), realout.data());
+ realout.resize(size);
+ BOOST_CHECK(realout.size() == correctout.size());
+ BOOST_CHECK_MESSAGE(realout == correctout, HexStr(realout) + std::string(" != ") + hexout);
+
+ // Decrypt the cipher and verify that it equals the plaintext
+ std::vector<unsigned char> decrypted(correctout.size());
+ AES256CBCDecrypt dec(key.data(), iv.data(), pad);
+ size = dec.Decrypt(correctout.data(), correctout.size(), decrypted.data());
+ decrypted.resize(size);
+ BOOST_CHECK(decrypted.size() == in.size());
+ BOOST_CHECK_MESSAGE(decrypted == in, HexStr(decrypted) + std::string(" != ") + hexin);
+
+ // Encrypt and re-decrypt substrings of the plaintext and verify that they equal each-other
+ for(std::vector<unsigned char>::iterator i(in.begin()); i != in.end(); ++i)
+ {
+ std::vector<unsigned char> sub(i, in.end());
+ std::vector<unsigned char> subout(sub.size() + AES_BLOCKSIZE);
+ int _size = enc.Encrypt(sub.data(), sub.size(), subout.data());
+ if (_size != 0)
+ {
+ subout.resize(_size);
+ std::vector<unsigned char> subdecrypted(subout.size());
+ _size = dec.Decrypt(subout.data(), subout.size(), subdecrypted.data());
+ subdecrypted.resize(_size);
+ BOOST_CHECK(decrypted.size() == in.size());
+ BOOST_CHECK_MESSAGE(subdecrypted == sub, HexStr(subdecrypted) + std::string(" != ") + HexStr(sub));
+ }
+ }
+}
+
+static void TestChaCha20(const std::string &hexkey, uint64_t nonce, uint64_t seek, const std::string& hexout)
+{
+ std::vector<unsigned char> key = ParseHex(hexkey);
+ ChaCha20 rng(key.data(), key.size());
+ rng.SetIV(nonce);
+ rng.Seek(seek);
+ std::vector<unsigned char> out = ParseHex(hexout);
+ std::vector<unsigned char> outres;
+ outres.resize(out.size());
+ rng.Output(outres.data(), outres.size());
+ BOOST_CHECK(out == outres);
+}
+
+static std::string LongTestString(void) {
+ std::string ret;
+ for (int i=0; i<200000; i++) {
+ ret += (unsigned char)(i);
+ ret += (unsigned char)(i >> 4);
+ ret += (unsigned char)(i >> 8);
+ ret += (unsigned char)(i >> 12);
+ ret += (unsigned char)(i >> 16);
+ }
+ return ret;
+}
+
+const std::string test1 = LongTestString();
+
+BOOST_AUTO_TEST_CASE(ripemd160_testvectors) {
+ TestRIPEMD160("", "9c1185a5c5e9fc54612808977ee8f548b2258d31");
+ TestRIPEMD160("abc", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc");
+ TestRIPEMD160("message digest", "5d0689ef49d2fae572b881b123a85ffa21595f36");
+ TestRIPEMD160("secure hash algorithm", "20397528223b6a5f4cbc2808aba0464e645544f9");
+ TestRIPEMD160("RIPEMD160 is considered to be safe", "a7d78608c7af8a8e728778e81576870734122b66");
+ TestRIPEMD160("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "12a053384a9c0c88e405a06c27dcf49ada62eb2b");
+ TestRIPEMD160("For this sample, this 63-byte string will be used as input data",
+ "de90dbfee14b63fb5abf27c2ad4a82aaa5f27a11");
+ TestRIPEMD160("This is exactly 64 bytes long, not counting the terminating byte",
+ "eda31d51d3a623b81e19eb02e24ff65d27d67b37");
+ TestRIPEMD160(std::string(1000000, 'a'), "52783243c1697bdbe16d37f97f68f08325dc1528");
+ TestRIPEMD160(test1, "464243587bd146ea835cdf57bdae582f25ec45f1");
+}
+
+BOOST_AUTO_TEST_CASE(sha1_testvectors) {
+ TestSHA1("", "da39a3ee5e6b4b0d3255bfef95601890afd80709");
+ TestSHA1("abc", "a9993e364706816aba3e25717850c26c9cd0d89d");
+ TestSHA1("message digest", "c12252ceda8be8994d5fa0290a47231c1d16aae3");
+ TestSHA1("secure hash algorithm", "d4d6d2f0ebe317513bbd8d967d89bac5819c2f60");
+ TestSHA1("SHA1 is considered to be safe", "f2b6650569ad3a8720348dd6ea6c497dee3a842a");
+ TestSHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "84983e441c3bd26ebaae4aa1f95129e5e54670f1");
+ TestSHA1("For this sample, this 63-byte string will be used as input data",
+ "4f0ea5cd0585a23d028abdc1a6684e5a8094dc49");
+ TestSHA1("This is exactly 64 bytes long, not counting the terminating byte",
+ "fb679f23e7d1ce053313e66e127ab1b444397057");
+ TestSHA1(std::string(1000000, 'a'), "34aa973cd4c4daa4f61eeb2bdbad27316534016f");
+ TestSHA1(test1, "b7755760681cbfd971451668f32af5774f4656b5");
+}
+
+BOOST_AUTO_TEST_CASE(sha256_testvectors) {
+ TestSHA256("", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
+ TestSHA256("abc", "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
+ TestSHA256("message digest",
+ "f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650");
+ TestSHA256("secure hash algorithm",
+ "f30ceb2bb2829e79e4ca9753d35a8ecc00262d164cc077080295381cbd643f0d");
+ TestSHA256("SHA256 is considered to be safe",
+ "6819d915c73f4d1e77e4e1b52d1fa0f9cf9beaead3939f15874bd988e2a23630");
+ TestSHA256("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1");
+ TestSHA256("For this sample, this 63-byte string will be used as input data",
+ "f08a78cbbaee082b052ae0708f32fa1e50c5c421aa772ba5dbb406a2ea6be342");
+ TestSHA256("This is exactly 64 bytes long, not counting the terminating byte",
+ "ab64eff7e88e2e46165e29f2bce41826bd4c7b3552f6b382a9e7d3af47c245f8");
+ TestSHA256("As Bitcoin relies on 80 byte header hashes, we want to have an example for that.",
+ "7406e8de7d6e4fffc573daef05aefb8806e7790f55eab5576f31349743cca743");
+ TestSHA256(std::string(1000000, 'a'),
+ "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0");
+ TestSHA256(test1, "a316d55510b49662420f49d145d42fb83f31ef8dc016aa4e32df049991a91e26");
+}
+
+BOOST_AUTO_TEST_CASE(sha512_testvectors) {
+ TestSHA512("",
+ "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce"
+ "47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e");
+ TestSHA512("abc",
+ "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"
+ "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f");
+ TestSHA512("message digest",
+ "107dbf389d9e9f71a3a95f6c055b9251bc5268c2be16d6c13492ea45b0199f33"
+ "09e16455ab1e96118e8a905d5597b72038ddb372a89826046de66687bb420e7c");
+ TestSHA512("secure hash algorithm",
+ "7746d91f3de30c68cec0dd693120a7e8b04d8073cb699bdce1a3f64127bca7a3"
+ "d5db502e814bb63c063a7a5043b2df87c61133395f4ad1edca7fcf4b30c3236e");
+ TestSHA512("SHA512 is considered to be safe",
+ "099e6468d889e1c79092a89ae925a9499b5408e01b66cb5b0a3bd0dfa51a9964"
+ "6b4a3901caab1318189f74cd8cf2e941829012f2449df52067d3dd5b978456c2");
+ TestSHA512("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+ "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c335"
+ "96fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445");
+ TestSHA512("For this sample, this 63-byte string will be used as input data",
+ "b3de4afbc516d2478fe9b518d063bda6c8dd65fc38402dd81d1eb7364e72fb6e"
+ "6663cf6d2771c8f5a6da09601712fb3d2a36c6ffea3e28b0818b05b0a8660766");
+ TestSHA512("This is exactly 64 bytes long, not counting the terminating byte",
+ "70aefeaa0e7ac4f8fe17532d7185a289bee3b428d950c14fa8b713ca09814a38"
+ "7d245870e007a80ad97c369d193e41701aa07f3221d15f0e65a1ff970cedf030");
+ TestSHA512("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno"
+ "ijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+ "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"
+ "501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909");
+ TestSHA512(std::string(1000000, 'a'),
+ "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb"
+ "de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b");
+ TestSHA512(test1,
+ "40cac46c147e6131c5193dd5f34e9d8bb4951395f27b08c558c65ff4ba2de594"
+ "37de8c3ef5459d76a52cedc02dc499a3c9ed9dedbfb3281afd9653b8a112fafc");
+}
+
+BOOST_AUTO_TEST_CASE(hmac_sha256_testvectors) {
+ // test cases 1, 2, 3, 4, 6 and 7 of RFC 4231
+ TestHMACSHA256("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "4869205468657265",
+ "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7");
+ TestHMACSHA256("4a656665",
+ "7768617420646f2079612077616e7420666f72206e6f7468696e673f",
+ "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843");
+ TestHMACSHA256("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
+ "dddddddddddddddddddddddddddddddddddd",
+ "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe");
+ TestHMACSHA256("0102030405060708090a0b0c0d0e0f10111213141516171819",
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+ "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b");
+ TestHMACSHA256("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaa",
+ "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a"
+ "65204b6579202d2048617368204b6579204669727374",
+ "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54");
+ TestHMACSHA256("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaa",
+ "5468697320697320612074657374207573696e672061206c6172676572207468"
+ "616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074"
+ "68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565"
+ "647320746f20626520686173686564206265666f7265206265696e6720757365"
+ "642062792074686520484d414320616c676f726974686d2e",
+ "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2");
+ // Test case with key length 63 bytes.
+ TestHMACSHA256("4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665"
+ "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a6566",
+ "7768617420646f2079612077616e7420666f72206e6f7468696e673f",
+ "9de4b546756c83516720a4ad7fe7bdbeac4298c6fdd82b15f895a6d10b0769a6");
+ // Test case with key length 64 bytes.
+ TestHMACSHA256("4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665"
+ "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665",
+ "7768617420646f2079612077616e7420666f72206e6f7468696e673f",
+ "528c609a4c9254c274585334946b7c2661bad8f1fc406b20f6892478d19163dd");
+ // Test case with key length 65 bytes.
+ TestHMACSHA256("4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665"
+ "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665"
+ "4a",
+ "7768617420646f2079612077616e7420666f72206e6f7468696e673f",
+ "d06af337f359a2330deffb8e3cbe4b5b7aa8ca1f208528cdbd245d5dc63c4483");
+}
+
+BOOST_AUTO_TEST_CASE(hmac_sha512_testvectors) {
+ // test cases 1, 2, 3, 4, 6 and 7 of RFC 4231
+ TestHMACSHA512("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+ "4869205468657265",
+ "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cde"
+ "daa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854");
+ TestHMACSHA512("4a656665",
+ "7768617420646f2079612077616e7420666f72206e6f7468696e673f",
+ "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea250554"
+ "9758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737");
+ TestHMACSHA512("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
+ "dddddddddddddddddddddddddddddddddddd",
+ "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39"
+ "bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb");
+ TestHMACSHA512("0102030405060708090a0b0c0d0e0f10111213141516171819",
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
+ "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+ "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3db"
+ "a91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd");
+ TestHMACSHA512("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaa",
+ "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a"
+ "65204b6579202d2048617368204b6579204669727374",
+ "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f352"
+ "6b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598");
+ TestHMACSHA512("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaa",
+ "5468697320697320612074657374207573696e672061206c6172676572207468"
+ "616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074"
+ "68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565"
+ "647320746f20626520686173686564206265666f7265206265696e6720757365"
+ "642062792074686520484d414320616c676f726974686d2e",
+ "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944"
+ "b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58");
+ // Test case with key length 127 bytes.
+ TestHMACSHA512("4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665"
+ "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665"
+ "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665"
+ "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a6566",
+ "7768617420646f2079612077616e7420666f72206e6f7468696e673f",
+ "267424dfb8eeb999f3e5ec39a4fe9fd14c923e6187e0897063e5c9e02b2e624a"
+ "c04413e762977df71a9fb5d562b37f89dfdfb930fce2ed1fa783bbc2a203d80e");
+ // Test case with key length 128 bytes.
+ TestHMACSHA512("4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665"
+ "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665"
+ "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665"
+ "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665",
+ "7768617420646f2079612077616e7420666f72206e6f7468696e673f",
+ "43aaac07bb1dd97c82c04df921f83b16a68d76815cd1a30d3455ad43a3d80484"
+ "2bb35462be42cc2e4b5902de4d204c1c66d93b47d1383e3e13a3788687d61258");
+ // Test case with key length 129 bytes.
+ TestHMACSHA512("4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665"
+ "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665"
+ "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665"
+ "4a6566654a6566654a6566654a6566654a6566654a6566654a6566654a656665"
+ "4a",
+ "7768617420646f2079612077616e7420666f72206e6f7468696e673f",
+ "0b273325191cfc1b4b71d5075c8fcad67696309d292b1dad2cd23983a35feb8e"
+ "fb29795e79f2ef27f68cb1e16d76178c307a67beaad9456fac5fdffeadb16e2c");
+}
+
+BOOST_AUTO_TEST_CASE(aes_testvectors) {
+ // AES test vectors from FIPS 197.
+ TestAES128("000102030405060708090a0b0c0d0e0f", "00112233445566778899aabbccddeeff", "69c4e0d86a7b0430d8cdb78070b4c55a");
+ TestAES256("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "00112233445566778899aabbccddeeff", "8ea2b7ca516745bfeafc49904b496089");
+
+ // AES-ECB test vectors from NIST sp800-38a.
+ TestAES128("2b7e151628aed2a6abf7158809cf4f3c", "6bc1bee22e409f96e93d7e117393172a", "3ad77bb40d7a3660a89ecaf32466ef97");
+ TestAES128("2b7e151628aed2a6abf7158809cf4f3c", "ae2d8a571e03ac9c9eb76fac45af8e51", "f5d3d58503b9699de785895a96fdbaaf");
+ TestAES128("2b7e151628aed2a6abf7158809cf4f3c", "30c81c46a35ce411e5fbc1191a0a52ef", "43b1cd7f598ece23881b00e3ed030688");
+ TestAES128("2b7e151628aed2a6abf7158809cf4f3c", "f69f2445df4f9b17ad2b417be66c3710", "7b0c785e27e8ad3f8223207104725dd4");
+ TestAES256("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "6bc1bee22e409f96e93d7e117393172a", "f3eed1bdb5d2a03c064b5a7e3db181f8");
+ TestAES256("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "ae2d8a571e03ac9c9eb76fac45af8e51", "591ccb10d410ed26dc5ba74a31362870");
+ TestAES256("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "30c81c46a35ce411e5fbc1191a0a52ef", "b6ed21b99ca6f4f9f153e7b1beafed1d");
+ TestAES256("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "f69f2445df4f9b17ad2b417be66c3710", "23304b7a39f9f3ff067d8d8f9e24ecc7");
+}
+
+BOOST_AUTO_TEST_CASE(aes_cbc_testvectors) {
+
+ // NIST AES CBC 128-bit encryption test-vectors
+ TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", false, \
+ "6bc1bee22e409f96e93d7e117393172a", "7649abac8119b246cee98e9b12e9197d");
+ TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "7649ABAC8119B246CEE98E9B12E9197D", false, \
+ "ae2d8a571e03ac9c9eb76fac45af8e51", "5086cb9b507219ee95db113a917678b2");
+ TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "5086cb9b507219ee95db113a917678b2", false, \
+ "30c81c46a35ce411e5fbc1191a0a52ef", "73bed6b8e3c1743b7116e69e22229516");
+ TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "73bed6b8e3c1743b7116e69e22229516", false, \
+ "f69f2445df4f9b17ad2b417be66c3710", "3ff1caa1681fac09120eca307586e1a7");
+
+ // The same vectors with padding enabled
+ TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", true, \
+ "6bc1bee22e409f96e93d7e117393172a", "7649abac8119b246cee98e9b12e9197d8964e0b149c10b7b682e6e39aaeb731c");
+ TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "7649ABAC8119B246CEE98E9B12E9197D", true, \
+ "ae2d8a571e03ac9c9eb76fac45af8e51", "5086cb9b507219ee95db113a917678b255e21d7100b988ffec32feeafaf23538");
+ TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "5086cb9b507219ee95db113a917678b2", true, \
+ "30c81c46a35ce411e5fbc1191a0a52ef", "73bed6b8e3c1743b7116e69e22229516f6eccda327bf8e5ec43718b0039adceb");
+ TestAES128CBC("2b7e151628aed2a6abf7158809cf4f3c", "73bed6b8e3c1743b7116e69e22229516", true, \
+ "f69f2445df4f9b17ad2b417be66c3710", "3ff1caa1681fac09120eca307586e1a78cb82807230e1321d3fae00d18cc2012");
+
+ // NIST AES CBC 256-bit encryption test-vectors
+ TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \
+ "000102030405060708090A0B0C0D0E0F", false, "6bc1bee22e409f96e93d7e117393172a", \
+ "f58c4c04d6e5f1ba779eabfb5f7bfbd6");
+ TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \
+ "F58C4C04D6E5F1BA779EABFB5F7BFBD6", false, "ae2d8a571e03ac9c9eb76fac45af8e51", \
+ "9cfc4e967edb808d679f777bc6702c7d");
+ TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \
+ "9CFC4E967EDB808D679F777BC6702C7D", false, "30c81c46a35ce411e5fbc1191a0a52ef",
+ "39f23369a9d9bacfa530e26304231461");
+ TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \
+ "39F23369A9D9BACFA530E26304231461", false, "f69f2445df4f9b17ad2b417be66c3710", \
+ "b2eb05e2c39be9fcda6c19078c6a9d1b");
+
+ // The same vectors with padding enabled
+ TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \
+ "000102030405060708090A0B0C0D0E0F", true, "6bc1bee22e409f96e93d7e117393172a", \
+ "f58c4c04d6e5f1ba779eabfb5f7bfbd6485a5c81519cf378fa36d42b8547edc0");
+ TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \
+ "F58C4C04D6E5F1BA779EABFB5F7BFBD6", true, "ae2d8a571e03ac9c9eb76fac45af8e51", \
+ "9cfc4e967edb808d679f777bc6702c7d3a3aa5e0213db1a9901f9036cf5102d2");
+ TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \
+ "9CFC4E967EDB808D679F777BC6702C7D", true, "30c81c46a35ce411e5fbc1191a0a52ef",
+ "39f23369a9d9bacfa530e263042314612f8da707643c90a6f732b3de1d3f5cee");
+ TestAES256CBC("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", \
+ "39F23369A9D9BACFA530E26304231461", true, "f69f2445df4f9b17ad2b417be66c3710", \
+ "b2eb05e2c39be9fcda6c19078c6a9d1b3f461796d6b0d6b2e0c2a72b4d80e644");
+}
+
+
+BOOST_AUTO_TEST_CASE(chacha20_testvector)
+{
+ // Test vector from RFC 7539
+ TestChaCha20("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", 0x4a000000UL, 1,
+ "224f51f3401bd9e12fde276fb8631ded8c131f823d2c06e27e4fcaec9ef3cf788a3b0aa372600a92b57974cded2b9334794cb"
+ "a40c63e34cdea212c4cf07d41b769a6749f3f630f4122cafe28ec4dc47e26d4346d70b98c73f3e9c53ac40c5945398b6eda1a"
+ "832c89c167eacd901d7e2bf363");
+
+ // Test vectors from https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7
+ TestChaCha20("0000000000000000000000000000000000000000000000000000000000000000", 0, 0,
+ "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b"
+ "8f41518a11cc387b669b2ee6586");
+ TestChaCha20("0000000000000000000000000000000000000000000000000000000000000001", 0, 0,
+ "4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d79"
+ "2b1c43fea817e9ad275ae546963");
+ TestChaCha20("0000000000000000000000000000000000000000000000000000000000000000", 0x0100000000000000ULL, 0,
+ "de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df137821031e85a050278a7084527214f73efc7fa5b52770"
+ "62eb7a0433e445f41e3");
+ TestChaCha20("0000000000000000000000000000000000000000000000000000000000000000", 1, 0,
+ "ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd138e50d32111e4caf237ee53ca8ad6426194a88545ddc4"
+ "97a0b466e7d6bbdb0041b2f586b");
+ TestChaCha20("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", 0x0706050403020100ULL, 0,
+ "f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3b"
+ "e59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc1"
+ "18be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5"
+ "a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5"
+ "360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78"
+ "fab78c9");
+}
+
+BOOST_AUTO_TEST_CASE(countbits_tests)
+{
+ FastRandomContext ctx;
+ for (unsigned int i = 0; i <= 64; ++i) {
+ if (i == 0) {
+ // Check handling of zero.
+ BOOST_CHECK_EQUAL(CountBits(0), 0U);
+ } else if (i < 10) {
+ for (uint64_t j = 1 << (i - 1); (j >> i) == 0; ++j) {
+ // Exhaustively test up to 10 bits
+ BOOST_CHECK_EQUAL(CountBits(j), i);
+ }
+ } else {
+ for (int k = 0; k < 1000; k++) {
+ // Randomly test 1000 samples of each length above 10 bits.
+ uint64_t j = ((uint64_t)1) << (i - 1) | ctx.randbits(i - 1);
+ BOOST_CHECK_EQUAL(CountBits(j), i);
+ }
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(sha256d64)
+{
+ for (int i = 0; i <= 32; ++i) {
+ unsigned char in[64 * 32];
+ unsigned char out1[32 * 32], out2[32 * 32];
+ for (int j = 0; j < 64 * i; ++j) {
+ in[j] = InsecureRandBits(8);
+ }
+ for (int j = 0; j < i; ++j) {
+ CHash256().Write(in + 64 * j, 64).Finalize(out1 + 32 * j);
+ }
+ SHA256D64(out2, in, i);
+ BOOST_CHECK(memcmp(out1, out2, 32 * i) == 0);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/cuckoocache_tests.cpp b/src/test/cuckoocache_tests.cpp
new file mode 100644
index 0000000000..ec7aba34ca
--- /dev/null
+++ b/src/test/cuckoocache_tests.cpp
@@ -0,0 +1,380 @@
+// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <boost/test/unit_test.hpp>
+#include <cuckoocache.h>
+#include <script/sigcache.h>
+#include <test/test_bitcoin.h>
+#include <random.h>
+#include <thread>
+
+/** Test Suite for CuckooCache
+ *
+ * 1) All tests should have a deterministic result (using insecure rand
+ * with deterministic seeds)
+ * 2) Some test methods are templated to allow for easier testing
+ * against new versions / comparing
+ * 3) Results should be treated as a regression test, i.e., did the behavior
+ * change significantly from what was expected. This can be OK, depending on
+ * the nature of the change, but requires updating the tests to reflect the new
+ * expected behavior. For example improving the hit rate may cause some tests
+ * using BOOST_CHECK_CLOSE to fail.
+ *
+ */
+FastRandomContext local_rand_ctx(true);
+
+BOOST_AUTO_TEST_SUITE(cuckoocache_tests);
+
+
+/** insecure_GetRandHash fills in a uint256 from local_rand_ctx
+ */
+static void insecure_GetRandHash(uint256& t)
+{
+ uint32_t* ptr = (uint32_t*)t.begin();
+ for (uint8_t j = 0; j < 8; ++j)
+ *(ptr++) = local_rand_ctx.rand32();
+}
+
+
+
+/* Test that no values not inserted into the cache are read out of it.
+ *
+ * There are no repeats in the first 200000 insecure_GetRandHash calls
+ */
+BOOST_AUTO_TEST_CASE(test_cuckoocache_no_fakes)
+{
+ local_rand_ctx = FastRandomContext(true);
+ CuckooCache::cache<uint256, SignatureCacheHasher> cc{};
+ size_t megabytes = 4;
+ cc.setup_bytes(megabytes << 20);
+ uint256 v;
+ for (int x = 0; x < 100000; ++x) {
+ insecure_GetRandHash(v);
+ cc.insert(v);
+ }
+ for (int x = 0; x < 100000; ++x) {
+ insecure_GetRandHash(v);
+ BOOST_CHECK(!cc.contains(v, false));
+ }
+};
+
+/** This helper returns the hit rate when megabytes*load worth of entries are
+ * inserted into a megabytes sized cache
+ */
+template <typename Cache>
+static double test_cache(size_t megabytes, double load)
+{
+ local_rand_ctx = FastRandomContext(true);
+ std::vector<uint256> hashes;
+ Cache set{};
+ size_t bytes = megabytes * (1 << 20);
+ set.setup_bytes(bytes);
+ uint32_t n_insert = static_cast<uint32_t>(load * (bytes / sizeof(uint256)));
+ hashes.resize(n_insert);
+ for (uint32_t i = 0; i < n_insert; ++i) {
+ uint32_t* ptr = (uint32_t*)hashes[i].begin();
+ for (uint8_t j = 0; j < 8; ++j)
+ *(ptr++) = local_rand_ctx.rand32();
+ }
+ /** We make a copy of the hashes because future optimizations of the
+ * cuckoocache may overwrite the inserted element, so the test is
+ * "future proofed".
+ */
+ std::vector<uint256> hashes_insert_copy = hashes;
+ /** Do the insert */
+ for (uint256& h : hashes_insert_copy)
+ set.insert(h);
+ /** Count the hits */
+ uint32_t count = 0;
+ for (uint256& h : hashes)
+ count += set.contains(h, false);
+ double hit_rate = ((double)count) / ((double)n_insert);
+ return hit_rate;
+}
+
+/** The normalized hit rate for a given load.
+ *
+ * The semantics are a little confusing, so please see the below
+ * explanation.
+ *
+ * Examples:
+ *
+ * 1) at load 0.5, we expect a perfect hit rate, so we multiply by
+ * 1.0
+ * 2) at load 2.0, we expect to see half the entries, so a perfect hit rate
+ * would be 0.5. Therefore, if we see a hit rate of 0.4, 0.4*2.0 = 0.8 is the
+ * normalized hit rate.
+ *
+ * This is basically the right semantics, but has a bit of a glitch depending on
+ * how you measure around load 1.0 as after load 1.0 your normalized hit rate
+ * becomes effectively perfect, ignoring freshness.
+ */
+static double normalize_hit_rate(double hits, double load)
+{
+ return hits * std::max(load, 1.0);
+}
+
+/** Check the hit rate on loads ranging from 0.1 to 1.6 */
+BOOST_AUTO_TEST_CASE(cuckoocache_hit_rate_ok)
+{
+ /** Arbitrarily selected Hit Rate threshold that happens to work for this test
+ * as a lower bound on performance.
+ */
+ double HitRateThresh = 0.98;
+ size_t megabytes = 4;
+ for (double load = 0.1; load < 2; load *= 2) {
+ double hits = test_cache<CuckooCache::cache<uint256, SignatureCacheHasher>>(megabytes, load);
+ BOOST_CHECK(normalize_hit_rate(hits, load) > HitRateThresh);
+ }
+}
+
+
+/** This helper checks that erased elements are preferentially inserted onto and
+ * that the hit rate of "fresher" keys is reasonable*/
+template <typename Cache>
+static void test_cache_erase(size_t megabytes)
+{
+ double load = 1;
+ local_rand_ctx = FastRandomContext(true);
+ std::vector<uint256> hashes;
+ Cache set{};
+ size_t bytes = megabytes * (1 << 20);
+ set.setup_bytes(bytes);
+ uint32_t n_insert = static_cast<uint32_t>(load * (bytes / sizeof(uint256)));
+ hashes.resize(n_insert);
+ for (uint32_t i = 0; i < n_insert; ++i) {
+ uint32_t* ptr = (uint32_t*)hashes[i].begin();
+ for (uint8_t j = 0; j < 8; ++j)
+ *(ptr++) = local_rand_ctx.rand32();
+ }
+ /** We make a copy of the hashes because future optimizations of the
+ * cuckoocache may overwrite the inserted element, so the test is
+ * "future proofed".
+ */
+ std::vector<uint256> hashes_insert_copy = hashes;
+
+ /** Insert the first half */
+ for (uint32_t i = 0; i < (n_insert / 2); ++i)
+ set.insert(hashes_insert_copy[i]);
+ /** Erase the first quarter */
+ for (uint32_t i = 0; i < (n_insert / 4); ++i)
+ set.contains(hashes[i], true);
+ /** Insert the second half */
+ for (uint32_t i = (n_insert / 2); i < n_insert; ++i)
+ set.insert(hashes_insert_copy[i]);
+
+ /** elements that we marked as erased but are still there */
+ size_t count_erased_but_contained = 0;
+ /** elements that we did not erase but are older */
+ size_t count_stale = 0;
+ /** elements that were most recently inserted */
+ size_t count_fresh = 0;
+
+ for (uint32_t i = 0; i < (n_insert / 4); ++i)
+ count_erased_but_contained += set.contains(hashes[i], false);
+ for (uint32_t i = (n_insert / 4); i < (n_insert / 2); ++i)
+ count_stale += set.contains(hashes[i], false);
+ for (uint32_t i = (n_insert / 2); i < n_insert; ++i)
+ count_fresh += set.contains(hashes[i], false);
+
+ double hit_rate_erased_but_contained = double(count_erased_but_contained) / (double(n_insert) / 4.0);
+ double hit_rate_stale = double(count_stale) / (double(n_insert) / 4.0);
+ double hit_rate_fresh = double(count_fresh) / (double(n_insert) / 2.0);
+
+ // Check that our hit_rate_fresh is perfect
+ BOOST_CHECK_EQUAL(hit_rate_fresh, 1.0);
+ // Check that we have a more than 2x better hit rate on stale elements than
+ // erased elements.
+ BOOST_CHECK(hit_rate_stale > 2 * hit_rate_erased_but_contained);
+}
+
+BOOST_AUTO_TEST_CASE(cuckoocache_erase_ok)
+{
+ size_t megabytes = 4;
+ test_cache_erase<CuckooCache::cache<uint256, SignatureCacheHasher>>(megabytes);
+}
+
+template <typename Cache>
+static void test_cache_erase_parallel(size_t megabytes)
+{
+ double load = 1;
+ local_rand_ctx = FastRandomContext(true);
+ std::vector<uint256> hashes;
+ Cache set{};
+ size_t bytes = megabytes * (1 << 20);
+ set.setup_bytes(bytes);
+ uint32_t n_insert = static_cast<uint32_t>(load * (bytes / sizeof(uint256)));
+ hashes.resize(n_insert);
+ for (uint32_t i = 0; i < n_insert; ++i) {
+ uint32_t* ptr = (uint32_t*)hashes[i].begin();
+ for (uint8_t j = 0; j < 8; ++j)
+ *(ptr++) = local_rand_ctx.rand32();
+ }
+ /** We make a copy of the hashes because future optimizations of the
+ * cuckoocache may overwrite the inserted element, so the test is
+ * "future proofed".
+ */
+ std::vector<uint256> hashes_insert_copy = hashes;
+ boost::shared_mutex mtx;
+
+ {
+ /** Grab lock to make sure we release inserts */
+ boost::unique_lock<boost::shared_mutex> l(mtx);
+ /** Insert the first half */
+ for (uint32_t i = 0; i < (n_insert / 2); ++i)
+ set.insert(hashes_insert_copy[i]);
+ }
+
+ /** Spin up 3 threads to run contains with erase.
+ */
+ std::vector<std::thread> threads;
+ /** Erase the first quarter */
+ for (uint32_t x = 0; x < 3; ++x)
+ /** Each thread is emplaced with x copy-by-value
+ */
+ threads.emplace_back([&, x] {
+ boost::shared_lock<boost::shared_mutex> l(mtx);
+ size_t ntodo = (n_insert/4)/3;
+ size_t start = ntodo*x;
+ size_t end = ntodo*(x+1);
+ for (uint32_t i = start; i < end; ++i)
+ set.contains(hashes[i], true);
+ });
+
+ /** Wait for all threads to finish
+ */
+ for (std::thread& t : threads)
+ t.join();
+ /** Grab lock to make sure we observe erases */
+ boost::unique_lock<boost::shared_mutex> l(mtx);
+ /** Insert the second half */
+ for (uint32_t i = (n_insert / 2); i < n_insert; ++i)
+ set.insert(hashes_insert_copy[i]);
+
+ /** elements that we marked erased but that are still there */
+ size_t count_erased_but_contained = 0;
+ /** elements that we did not erase but are older */
+ size_t count_stale = 0;
+ /** elements that were most recently inserted */
+ size_t count_fresh = 0;
+
+ for (uint32_t i = 0; i < (n_insert / 4); ++i)
+ count_erased_but_contained += set.contains(hashes[i], false);
+ for (uint32_t i = (n_insert / 4); i < (n_insert / 2); ++i)
+ count_stale += set.contains(hashes[i], false);
+ for (uint32_t i = (n_insert / 2); i < n_insert; ++i)
+ count_fresh += set.contains(hashes[i], false);
+
+ double hit_rate_erased_but_contained = double(count_erased_but_contained) / (double(n_insert) / 4.0);
+ double hit_rate_stale = double(count_stale) / (double(n_insert) / 4.0);
+ double hit_rate_fresh = double(count_fresh) / (double(n_insert) / 2.0);
+
+ // Check that our hit_rate_fresh is perfect
+ BOOST_CHECK_EQUAL(hit_rate_fresh, 1.0);
+ // Check that we have a more than 2x better hit rate on stale elements than
+ // erased elements.
+ BOOST_CHECK(hit_rate_stale > 2 * hit_rate_erased_but_contained);
+}
+BOOST_AUTO_TEST_CASE(cuckoocache_erase_parallel_ok)
+{
+ size_t megabytes = 4;
+ test_cache_erase_parallel<CuckooCache::cache<uint256, SignatureCacheHasher>>(megabytes);
+}
+
+
+template <typename Cache>
+static void test_cache_generations()
+{
+ // This test checks that for a simulation of network activity, the fresh hit
+ // rate is never below 99%, and the number of times that it is worse than
+ // 99.9% are less than 1% of the time.
+ double min_hit_rate = 0.99;
+ double tight_hit_rate = 0.999;
+ double max_rate_less_than_tight_hit_rate = 0.01;
+ // A cache that meets this specification is therefore shown to have a hit
+ // rate of at least tight_hit_rate * (1 - max_rate_less_than_tight_hit_rate) +
+ // min_hit_rate*max_rate_less_than_tight_hit_rate = 0.999*99%+0.99*1% == 99.89%
+ // hit rate with low variance.
+
+ // We use deterministic values, but this test has also passed on many
+ // iterations with non-deterministic values, so it isn't "overfit" to the
+ // specific entropy in FastRandomContext(true) and implementation of the
+ // cache.
+ local_rand_ctx = FastRandomContext(true);
+
+ // block_activity models a chunk of network activity. n_insert elements are
+ // added to the cache. The first and last n/4 are stored for removal later
+ // and the middle n/2 are not stored. This models a network which uses half
+ // the signatures of recently (since the last block) added transactions
+ // immediately and never uses the other half.
+ struct block_activity {
+ std::vector<uint256> reads;
+ block_activity(uint32_t n_insert, Cache& c) : reads()
+ {
+ std::vector<uint256> inserts;
+ inserts.resize(n_insert);
+ reads.reserve(n_insert / 2);
+ for (uint32_t i = 0; i < n_insert; ++i) {
+ uint32_t* ptr = (uint32_t*)inserts[i].begin();
+ for (uint8_t j = 0; j < 8; ++j)
+ *(ptr++) = local_rand_ctx.rand32();
+ }
+ for (uint32_t i = 0; i < n_insert / 4; ++i)
+ reads.push_back(inserts[i]);
+ for (uint32_t i = n_insert - (n_insert / 4); i < n_insert; ++i)
+ reads.push_back(inserts[i]);
+ for (auto h : inserts)
+ c.insert(h);
+ }
+ };
+
+ const uint32_t BLOCK_SIZE = 1000;
+ // We expect window size 60 to perform reasonably given that each epoch
+ // stores 45% of the cache size (~472k).
+ const uint32_t WINDOW_SIZE = 60;
+ const uint32_t POP_AMOUNT = (BLOCK_SIZE / WINDOW_SIZE) / 2;
+ const double load = 10;
+ const size_t megabytes = 4;
+ const size_t bytes = megabytes * (1 << 20);
+ const uint32_t n_insert = static_cast<uint32_t>(load * (bytes / sizeof(uint256)));
+
+ std::vector<block_activity> hashes;
+ Cache set{};
+ set.setup_bytes(bytes);
+ hashes.reserve(n_insert / BLOCK_SIZE);
+ std::deque<block_activity> last_few;
+ uint32_t out_of_tight_tolerance = 0;
+ uint32_t total = n_insert / BLOCK_SIZE;
+ // we use the deque last_few to model a sliding window of blocks. at each
+ // step, each of the last WINDOW_SIZE block_activities checks the cache for
+ // POP_AMOUNT of the hashes that they inserted, and marks these erased.
+ for (uint32_t i = 0; i < total; ++i) {
+ if (last_few.size() == WINDOW_SIZE)
+ last_few.pop_front();
+ last_few.emplace_back(BLOCK_SIZE, set);
+ uint32_t count = 0;
+ for (auto& act : last_few)
+ for (uint32_t k = 0; k < POP_AMOUNT; ++k) {
+ count += set.contains(act.reads.back(), true);
+ act.reads.pop_back();
+ }
+ // We use last_few.size() rather than WINDOW_SIZE for the correct
+ // behavior on the first WINDOW_SIZE iterations where the deque is not
+ // full yet.
+ double hit = (double(count)) / (last_few.size() * POP_AMOUNT);
+ // Loose Check that hit rate is above min_hit_rate
+ BOOST_CHECK(hit > min_hit_rate);
+ // Tighter check, count number of times we are less than tight_hit_rate
+ // (and implicitly, greater than min_hit_rate)
+ out_of_tight_tolerance += hit < tight_hit_rate;
+ }
+ // Check that being out of tolerance happens less than
+ // max_rate_less_than_tight_hit_rate of the time
+ BOOST_CHECK(double(out_of_tight_tolerance) / double(total) < max_rate_less_than_tight_hit_rate);
+}
+BOOST_AUTO_TEST_CASE(cuckoocache_generations)
+{
+ test_cache_generations<CuckooCache::cache<uint256, SignatureCacheHasher>>();
+}
+
+BOOST_AUTO_TEST_SUITE_END();
diff --git a/src/test/data/README.md b/src/test/data/README.md
new file mode 100644
index 0000000000..2463daa42a
--- /dev/null
+++ b/src/test/data/README.md
@@ -0,0 +1,12 @@
+Description
+------------
+
+This directory contains data-driven tests for various aspects of Bitcoin.
+
+License
+--------
+
+The data files in this directory are distributed under the MIT software
+license, see the accompanying file COPYING or
+http://www.opensource.org/licenses/mit-license.php.
+
diff --git a/src/test/data/base58_encode_decode.json b/src/test/data/base58_encode_decode.json
new file mode 100644
index 0000000000..1a4bd7f458
--- /dev/null
+++ b/src/test/data/base58_encode_decode.json
@@ -0,0 +1,16 @@
+[
+["", ""],
+["61", "2g"],
+["626262", "a3gV"],
+["636363", "aPEr"],
+["73696d706c792061206c6f6e6720737472696e67", "2cFupjhnEsSn59qHXstmK2ffpLv2"],
+["00eb15231dfceb60925886b67d065299925915aeb172c06647", "1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L"],
+["516b6fcd0f", "ABnLTmg"],
+["bf4f89001e670274dd", "3SEo3LWLoPntC"],
+["572e4794", "3EFU7m"],
+["ecac89cad93923c02321", "EJDM8drfXA6uyA"],
+["10c8511e", "Rt5zm"],
+["00000000000000000000", "1111111111"],
+["000111d38e5fc9071ffcd20b4a763cc9ae4f252bb4e48fd66a835e252ada93ff480d6dd43dc62a641155a5", "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"],
+["000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", "1cWB5HCBdLjAuqGGReWE3R3CguuwSjw6RHn39s2yuDRTS5NsBgNiFpWgAnEx6VQi8csexkgYw3mdYrMHr8x9i7aEwP8kZ7vccXWqKDvGv3u1GxFKPuAkn8JCPPGDMf3vMMnbzm6Nh9zh1gcNsMvH3ZNLmP5fSG6DGbbi2tuwMWPthr4boWwCxf7ewSgNQeacyozhKDDQQ1qL5fQFUW52QKUZDZ5fw3KXNQJMcNTcaB723LchjeKun7MuGW5qyCBZYzA1KjofN1gYBV3NqyhQJ3Ns746GNuf9N2pQPmHz4xpnSrrfCvy6TVVz5d4PdrjeshsWQwpZsZGzvbdAdN8MKV5QsBDY"]
+]
diff --git a/src/test/data/key_io_invalid.json b/src/test/data/key_io_invalid.json
new file mode 100644
index 0000000000..9b52943ac6
--- /dev/null
+++ b/src/test/data/key_io_invalid.json
@@ -0,0 +1,182 @@
+[
+ [
+ ""
+ ],
+ [
+ "x"
+ ],
+ [
+ "37qgekLpCCHrQuSjvX3fs496FWTGsHFHizjJAs6NPcR47aefnnCWECAhHV6E3g4YN7u7Yuwod5Y"
+ ],
+ [
+ "dzb7VV1Ui55BARxv7ATxAtCUeJsANKovDGWFVgpTbhq9gvPqP3yv"
+ ],
+ [
+ "MuNu7ZAEDFiHthiunm7dPjwKqrVNCM3mAz6rP9zFveQu14YA8CxExSJTHcVP9DErn6u84E6Ej7S"
+ ],
+ [
+ "rPpQpYknyNQ5AEHuY6H8ijJJrYc2nDKKk9jjmKEXsWzyAQcFGpDLU2Zvsmoi8JLR7hAwoy3RQWf"
+ ],
+ [
+ "4Uc3FmN6NQ6zLBK5QQBXRBUREaaHwCZYsGCueHauuDmJpZKn6jkEskMB2Zi2CNgtb5r6epWEFfUJq"
+ ],
+ [
+ "7aQgR5DFQ25vyXmqZAWmnVCjL3PkBcdVkBUpjrjMTcghHx3E8wb"
+ ],
+ [
+ "17QpPprjeg69fW1DV8DcYYCKvWjYhXvWkov6MJ1iTTvMFj6weAqW7wybZeH57WTNxXVCRH4veVs"
+ ],
+ [
+ "KxuACDviz8Xvpn1xAh9MfopySZNuyajYMZWz16Dv2mHHryznWUp3"
+ ],
+ [
+ "7nK3GSmqdXJQtdohvGfJ7KsSmn3TmGqExug49583bDAL91pVSGq5xS9SHoAYL3Wv3ijKTit65th"
+ ],
+ [
+ "cTivdBmq7bay3RFGEBBuNfMh2P1pDCgRYN2Wbxmgwr4ki3jNUL2va"
+ ],
+ [
+ "gjMV4vjNjyMrna4fsAr8bWxAbwtmMUBXJS3zL4NJt5qjozpbQLmAfK1uA3CquSqsZQMpoD1g2nk"
+ ],
+ [
+ "emXm1naBMoVzPjbk7xpeTVMFy4oDEe25UmoyGgKEB1gGWsK8kRGs"
+ ],
+ [
+ "7VThQnNRj1o3Zyvc7XHPRrjDf8j2oivPTeDXnRPYWeYGE4pXeRJDZgf28ppti5hsHWXS2GSobdqyo"
+ ],
+ [
+ "1G9u6oCVCPh2o8m3t55ACiYvG1y5BHewUkDSdiQarDcYXXhFHYdzMdYfUAhfxn5vNZBwpgUNpso"
+ ],
+ [
+ "31QQ7ZMLkScDiB4VyZjuptr7AEc9j1SjstF7pRoLhHTGkW4Q2y9XELobQmhhWxeRvqcukGd1XCq"
+ ],
+ [
+ "DHqKSnpxa8ZdQyH8keAhvLTrfkyBMQxqngcQA5N8LQ9KVt25kmGN"
+ ],
+ [
+ "2LUHcJPbwLCy9GLH1qXmfmAwvadWw4bp4PCpDfduLqV17s6iDcy1imUwhQJhAoNoN1XNmweiJP4i"
+ ],
+ [
+ "7USRzBXAnmck8fX9HmW7RAb4qt92VFX6soCnts9s74wxm4gguVhtG5of8fZGbNPJA83irHVY6bCos"
+ ],
+ [
+ "1DGezo7BfVebZxAbNT3XGujdeHyNNBF3vnficYoTSp4PfK2QaML9bHzAMxke3wdKdHYWmsMTJVu"
+ ],
+ [
+ "2D12DqDZKwCxxkzs1ZATJWvgJGhQ4cFi3WrizQ5zLAyhN5HxuAJ1yMYaJp8GuYsTLLxTAz6otCfb"
+ ],
+ [
+ "8AFJzuTujXjw1Z6M3fWhQ1ujDW7zsV4ePeVjVo7D1egERqSW9nZ"
+ ],
+ [
+ "163Q17qLbTCue8YY3AvjpUhotuaodLm2uqMhpYirsKjVqnxJRWTEoywMVY3NbBAHuhAJ2cF9GAZ"
+ ],
+ [
+ "2MnmgiRH4eGLyLc9eAqStzk7dFgBjFtUCtu"
+ ],
+ [
+ "461QQ2sYWxU7H2PV4oBwJGNch8XVTYYbZxU"
+ ],
+ [
+ "2UCtv53VttmQYkVU4VMtXB31REvQg4ABzs41AEKZ8UcB7DAfVzdkV9JDErwGwyj5AUHLkmgZeobs"
+ ],
+ [
+ "cSNjAsnhgtiFMi6MtfvgscMB2Cbhn2v1FUYfviJ1CdjfidvmeW6mn"
+ ],
+ [
+ "gmsow2Y6EWAFDFE1CE4Hd3Tpu2BvfmBfG1SXsuRARbnt1WjkZnFh1qGTiptWWbjsq2Q6qvpgJVj"
+ ],
+ [
+ "nksUKSkzS76v8EsSgozXGMoQFiCoCHzCVajFKAXqzK5on9ZJYVHMD5CKwgmX3S3c7M1U3xabUny"
+ ],
+ [
+ "L3favK1UzFGgdzYBF2oBT5tbayCo4vtVBLJhg2iYuMeePxWG8SQc"
+ ],
+ [
+ "7VxLxGGtYT6N99GdEfi6xz56xdQ8nP2dG1CavuXx7Rf2PrvNMTBNevjkfgs9JmkcGm6EXpj8ipyPZ"
+ ],
+ [
+ "2mbZwFXF6cxShaCo2czTRB62WTx9LxhTtpP"
+ ],
+ [
+ "dB7cwYdcPSgiyAwKWL3JwCVwSk6epU2txw"
+ ],
+ [
+ "HPhFUhUAh8ZQQisH8QQWafAxtQYju3SFTX"
+ ],
+ [
+ "4ctAH6AkHzq5ioiM1m9T3E2hiYEev5mTsB"
+ ],
+ [
+ "Hn1uFi4dNexWrqARpjMqgT6cX1UsNPuV3cHdGg9ExyXw8HTKadbktRDtdeVmY3M1BxJStiL4vjJ"
+ ],
+ [
+ "Sq3fDbvutABmnAHHExJDgPLQn44KnNC7UsXuT7KZecpaYDMU9Txs"
+ ],
+ [
+ "6TqWyrqdgUEYDQU1aChMuFMMEimHX44qHFzCUgGfqxGgZNMUVWJ"
+ ],
+ [
+ "giqJo7oWqFxNKWyrgcBxAVHXnjJ1t6cGoEffce5Y1y7u649Noj5wJ4mmiUAKEVVrYAGg2KPB3Y4"
+ ],
+ [
+ "cNzHY5e8vcmM3QVJUcjCyiKMYfeYvyueq5qCMV3kqcySoLyGLYUK"
+ ],
+ [
+ "37uTe568EYc9WLoHEd9jXEvUiWbq5LFLscNyqvAzLU5vBArUJA6eydkLmnMwJDjkL5kXc2VK7ig"
+ ],
+ [
+ "EsYbG4tWWWY45G31nox838qNdzksbPySWc"
+ ],
+ [
+ "nbuzhfwMoNzA3PaFnyLcRxE9bTJPDkjZ6Rf6Y6o2ckXZfzZzXBT"
+ ],
+ [
+ "cQN9PoxZeCWK1x56xnz6QYAsvR11XAce3Ehp3gMUdfSQ53Y2mPzx"
+ ],
+ [
+ "1Gm3N3rkef6iMbx4voBzaxtXcmmiMTqZPhcuAepRzYUJQW4qRpEnHvMojzof42hjFRf8PE2jPde"
+ ],
+ [
+ "2TAq2tuN6x6m233bpT7yqdYQPELdTDJn1eU"
+ ],
+ [
+ "ntEtnnGhqPii4joABvBtSEJG6BxjT2tUZqE8PcVYgk3RHpgxgHDCQxNbLJf7ardf1dDk2oCQ7Cf"
+ ],
+ [
+ "Ky1YjoZNgQ196HJV3HpdkecfhRBmRZdMJk89Hi5KGfpfPwS2bUbfd"
+ ],
+ [
+ "2A1q1YsMZowabbvta7kTy2Fd6qN4r5ZCeG3qLpvZBMzCixMUdkN2Y4dHB1wPsZAeVXUGD83MfRED"
+ ],
+ [
+ "tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty"
+ ],
+ [
+ "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5"
+ ],
+ [
+ "BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2"
+ ],
+ [
+ "bc1rw5uspcuh"
+ ],
+ [
+ "bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90"
+ ],
+ [
+ "BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P"
+ ],
+ [
+ "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sL5k7"
+ ],
+ [
+ "bc1zw508d6qejxtdg4y5r3zarvaryvqyzf3du"
+ ],
+ [
+ "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv"
+ ],
+ [
+ "bc1gmk9yu"
+ ]
+]
diff --git a/src/test/data/key_io_valid.json b/src/test/data/key_io_valid.json
new file mode 100644
index 0000000000..8418a6002d
--- /dev/null
+++ b/src/test/data/key_io_valid.json
@@ -0,0 +1,533 @@
+[
+ [
+ "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",
+ "76a91465a16059864a2fdbc7c99a4723a8395bc6f188eb88ac",
+ {
+ "isPrivkey": false,
+ "chain": "main"
+ }
+ ],
+ [
+ "3CMNFxN1oHBc4R1EpboAL5yzHGgE611Xou",
+ "a91474f209f6ea907e2ea48f74fae05782ae8a66525787",
+ {
+ "isPrivkey": false,
+ "chain": "main"
+ }
+ ],
+ [
+ "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs",
+ "76a91453c0307d6851aa0ce7825ba883c6bd9ad242b48688ac",
+ {
+ "isPrivkey": false,
+ "chain": "test"
+ }
+ ],
+ [
+ "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs",
+ "76a91453c0307d6851aa0ce7825ba883c6bd9ad242b48688ac",
+ {
+ "isPrivkey": false,
+ "chain": "regtest"
+ }
+ ],
+ [
+ "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br",
+ "a9146349a418fc4578d10a372b54b45c280cc8c4382f87",
+ {
+ "isPrivkey": false,
+ "chain": "test"
+ }
+ ],
+ [
+ "5Kd3NBUAdUnhyzenEwVLy9pBKxSwXvE9FMPyR4UKZvpe6E3AgLr",
+ "eddbdc1168f1daeadbd3e44c1e3f8f5a284c2029f78ad26af98583a499de5b19",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "chain": "main"
+ }
+ ],
+ [
+ "Kz6UJmQACJmLtaQj5A3JAge4kVTNQ8gbvXuwbmCj7bsaabudb3RD",
+ "55c9bccb9ed68446d1b75273bbce89d7fe013a8acd1625514420fb2aca1a21c4",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "chain": "main"
+ }
+ ],
+ [
+ "9213qJab2HNEpMpYNBa7wHGFKKbkDn24jpANDs2huN3yi4J11ko",
+ "36cb93b9ab1bdabf7fb9f2c04f1b9cc879933530ae7842398eef5a63a56800c2",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "chain": "test"
+ }
+ ],
+ [
+ "9213qJab2HNEpMpYNBa7wHGFKKbkDn24jpANDs2huN3yi4J11ko",
+ "36cb93b9ab1bdabf7fb9f2c04f1b9cc879933530ae7842398eef5a63a56800c2",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "chain": "regtest"
+ }
+ ],
+ [
+ "cTpB4YiyKiBcPxnefsDpbnDxFDffjqJob8wGCEDXxgQ7zQoMXJdH",
+ "b9f4892c9e8282028fea1d2667c4dc5213564d41fc5783896a0d843fc15089f3",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "chain": "test"
+ }
+ ],
+ [
+ "cTpB4YiyKiBcPxnefsDpbnDxFDffjqJob8wGCEDXxgQ7zQoMXJdH",
+ "b9f4892c9e8282028fea1d2667c4dc5213564d41fc5783896a0d843fc15089f3",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "chain": "regtest"
+ }
+ ],
+ [
+ "1Ax4gZtb7gAit2TivwejZHYtNNLT18PUXJ",
+ "76a9146d23156cbbdcc82a5a47eee4c2c7c583c18b6bf488ac",
+ {
+ "isPrivkey": false,
+ "chain": "main"
+ }
+ ],
+ [
+ "3QjYXhTkvuj8qPaXHTTWb5wjXhdsLAAWVy",
+ "a914fcc5460dd6e2487c7d75b1963625da0e8f4c597587",
+ {
+ "isPrivkey": false,
+ "chain": "main"
+ }
+ ],
+ [
+ "n3ZddxzLvAY9o7184TB4c6FJasAybsw4HZ",
+ "76a914f1d470f9b02370fdec2e6b708b08ac431bf7a5f788ac",
+ {
+ "isPrivkey": false,
+ "chain": "test"
+ }
+ ],
+ [
+ "2NBFNJTktNa7GZusGbDbGKRZTxdK9VVez3n",
+ "a914c579342c2c4c9220205e2cdc285617040c924a0a87",
+ {
+ "isPrivkey": false,
+ "chain": "test"
+ }
+ ],
+ [
+ "5K494XZwps2bGyeL71pWid4noiSNA2cfCibrvRWqcHSptoFn7rc",
+ "a326b95ebae30164217d7a7f57d72ab2b54e3be64928a19da0210b9568d4015e",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "chain": "main"
+ }
+ ],
+ [
+ "L1RrrnXkcKut5DEMwtDthjwRcTTwED36thyL1DebVrKuwvohjMNi",
+ "7d998b45c219a1e38e99e7cbd312ef67f77a455a9b50c730c27f02c6f730dfb4",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "chain": "main"
+ }
+ ],
+ [
+ "93DVKyFYwSN6wEo3E2fCrFPUp17FtrtNi2Lf7n4G3garFb16CRj",
+ "d6bca256b5abc5602ec2e1c121a08b0da2556587430bcf7e1898af2224885203",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "chain": "test"
+ }
+ ],
+ [
+ "cTDVKtMGVYWTHCb1AFjmVbEbWjvKpKqKgMaR3QJxToMSQAhmCeTN",
+ "a81ca4e8f90181ec4b61b6a7eb998af17b2cb04de8a03b504b9e34c4c61db7d9",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "chain": "test"
+ }
+ ],
+ [
+ "1C5bSj1iEGUgSTbziymG7Cn18ENQuT36vv",
+ "76a9147987ccaa53d02c8873487ef919677cd3db7a691288ac",
+ {
+ "isPrivkey": false,
+ "chain": "main"
+ }
+ ],
+ [
+ "3AnNxabYGoTxYiTEZwFEnerUoeFXK2Zoks",
+ "a91463bcc565f9e68ee0189dd5cc67f1b0e5f02f45cb87",
+ {
+ "isPrivkey": false,
+ "chain": "main"
+ }
+ ],
+ [
+ "n3LnJXCqbPjghuVs8ph9CYsAe4Sh4j97wk",
+ "76a914ef66444b5b17f14e8fae6e7e19b045a78c54fd7988ac",
+ {
+ "isPrivkey": false,
+ "chain": "test"
+ }
+ ],
+ [
+ "2NB72XtkjpnATMggui83aEtPawyyKvnbX2o",
+ "a914c3e55fceceaa4391ed2a9677f4a4d34eacd021a087",
+ {
+ "isPrivkey": false,
+ "chain": "test"
+ }
+ ],
+ [
+ "5KaBW9vNtWNhc3ZEDyNCiXLPdVPHCikRxSBWwV9NrpLLa4LsXi9",
+ "e75d936d56377f432f404aabb406601f892fd49da90eb6ac558a733c93b47252",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "chain": "main"
+ }
+ ],
+ [
+ "L1axzbSyynNYA8mCAhzxkipKkfHtAXYF4YQnhSKcLV8YXA874fgT",
+ "8248bd0375f2f75d7e274ae544fb920f51784480866b102384190b1addfbaa5c",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "chain": "main"
+ }
+ ],
+ [
+ "927CnUkUbasYtDwYwVn2j8GdTuACNnKkjZ1rpZd2yBB1CLcnXpo",
+ "44c4f6a096eac5238291a94cc24c01e3b19b8d8cef72874a079e00a242237a52",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "chain": "test"
+ }
+ ],
+ [
+ "cUcfCMRjiQf85YMzzQEk9d1s5A4K7xL5SmBCLrezqXFuTVefyhY7",
+ "d1de707020a9059d6d3abaf85e17967c6555151143db13dbb06db78df0f15c69",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "chain": "test"
+ }
+ ],
+ [
+ "1Gqk4Tv79P91Cc1STQtU3s1W6277M2CVWu",
+ "76a914adc1cc2081a27206fae25792f28bbc55b831549d88ac",
+ {
+ "isPrivkey": false,
+ "chain": "main"
+ }
+ ],
+ [
+ "33vt8ViH5jsr115AGkW6cEmEz9MpvJSwDk",
+ "a914188f91a931947eddd7432d6e614387e32b24470987",
+ {
+ "isPrivkey": false,
+ "chain": "main"
+ }
+ ],
+ [
+ "mhaMcBxNh5cqXm4aTQ6EcVbKtfL6LGyK2H",
+ "76a9141694f5bc1a7295b600f40018a618a6ea48eeb49888ac",
+ {
+ "isPrivkey": false,
+ "chain": "test"
+ }
+ ],
+ [
+ "2MxgPqX1iThW3oZVk9KoFcE5M4JpiETssVN",
+ "a9143b9b3fd7a50d4f08d1a5b0f62f644fa7115ae2f387",
+ {
+ "isPrivkey": false,
+ "chain": "test"
+ }
+ ],
+ [
+ "5HtH6GdcwCJA4ggWEL1B3jzBBUB8HPiBi9SBc5h9i4Wk4PSeApR",
+ "091035445ef105fa1bb125eccfb1882f3fe69592265956ade751fd095033d8d0",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "chain": "main"
+ }
+ ],
+ [
+ "L2xSYmMeVo3Zek3ZTsv9xUrXVAmrWxJ8Ua4cw8pkfbQhcEFhkXT8",
+ "ab2b4bcdfc91d34dee0ae2a8c6b6668dadaeb3a88b9859743156f462325187af",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "chain": "main"
+ }
+ ],
+ [
+ "92xFEve1Z9N8Z641KQQS7ByCSb8kGjsDzw6fAmjHN1LZGKQXyMq",
+ "b4204389cef18bbe2b353623cbf93e8678fbc92a475b664ae98ed594e6cf0856",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "chain": "test"
+ }
+ ],
+ [
+ "92xFEve1Z9N8Z641KQQS7ByCSb8kGjsDzw6fAmjHN1LZGKQXyMq",
+ "b4204389cef18bbe2b353623cbf93e8678fbc92a475b664ae98ed594e6cf0856",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "chain": "regtest"
+ }
+ ],
+ [
+ "cVM65tdYu1YK37tNoAyGoJTR13VBYFva1vg9FLuPAsJijGvG6NEA",
+ "e7b230133f1b5489843260236b06edca25f66adb1be455fbd38d4010d48faeef",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "chain": "test"
+ }
+ ],
+ [
+ "1JwMWBVLtiqtscbaRHai4pqHokhFCbtoB4",
+ "76a914c4c1b72491ede1eedaca00618407ee0b772cad0d88ac",
+ {
+ "isPrivkey": false,
+ "chain": "main"
+ }
+ ],
+ [
+ "3QCzvfL4ZRvmJFiWWBVwxfdaNBT8EtxB5y",
+ "a914f6fe69bcb548a829cce4c57bf6fff8af3a5981f987",
+ {
+ "isPrivkey": false,
+ "chain": "main"
+ }
+ ],
+ [
+ "mizXiucXRCsEriQCHUkCqef9ph9qtPbZZ6",
+ "76a914261f83568a098a8638844bd7aeca039d5f2352c088ac",
+ {
+ "isPrivkey": false,
+ "chain": "test"
+ }
+ ],
+ [
+ "2NEWDzHWwY5ZZp8CQWbB7ouNMLqCia6YRda",
+ "a914e930e1834a4d234702773951d627cce82fbb5d2e87",
+ {
+ "isPrivkey": false,
+ "chain": "test"
+ }
+ ],
+ [
+ "5KQmDryMNDcisTzRp3zEq9e4awRmJrEVU1j5vFRTKpRNYPqYrMg",
+ "d1fab7ab7385ad26872237f1eb9789aa25cc986bacc695e07ac571d6cdac8bc0",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "chain": "main"
+ }
+ ],
+ [
+ "L39Fy7AC2Hhj95gh3Yb2AU5YHh1mQSAHgpNixvm27poizcJyLtUi",
+ "b0bbede33ef254e8376aceb1510253fc3550efd0fcf84dcd0c9998b288f166b3",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "chain": "main"
+ }
+ ],
+ [
+ "91cTVUcgydqyZLgaANpf1fvL55FH53QMm4BsnCADVNYuWuqdVys",
+ "037f4192c630f399d9271e26c575269b1d15be553ea1a7217f0cb8513cef41cb",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "chain": "test"
+ }
+ ],
+ [
+ "cQspfSzsgLeiJGB2u8vrAiWpCU4MxUT6JseWo2SjXy4Qbzn2fwDw",
+ "6251e205e8ad508bab5596bee086ef16cd4b239e0cc0c5d7c4e6035441e7d5de",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "chain": "test"
+ }
+ ],
+ [
+ "19dcawoKcZdQz365WpXWMhX6QCUpR9SY4r",
+ "76a9145eadaf9bb7121f0f192561a5a62f5e5f5421029288ac",
+ {
+ "isPrivkey": false,
+ "chain": "main"
+ }
+ ],
+ [
+ "37Sp6Rv3y4kVd1nQ1JV5pfqXccHNyZm1x3",
+ "a9143f210e7277c899c3a155cc1c90f4106cbddeec6e87",
+ {
+ "isPrivkey": false,
+ "chain": "main"
+ }
+ ],
+ [
+ "myoqcgYiehufrsnnkqdqbp69dddVDMopJu",
+ "76a914c8a3c2a09a298592c3e180f02487cd91ba3400b588ac",
+ {
+ "isPrivkey": false,
+ "chain": "test"
+ }
+ ],
+ [
+ "2N7FuwuUuoTBrDFdrAZ9KxBmtqMLxce9i1C",
+ "a91499b31df7c9068d1481b596578ddbb4d3bd90baeb87",
+ {
+ "isPrivkey": false,
+ "chain": "test"
+ }
+ ],
+ [
+ "5KL6zEaMtPRXZKo1bbMq7JDjjo1bJuQcsgL33je3oY8uSJCR5b4",
+ "c7666842503db6dc6ea061f092cfb9c388448629a6fe868d068c42a488b478ae",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "chain": "main"
+ }
+ ],
+ [
+ "KwV9KAfwbwt51veZWNscRTeZs9CKpojyu1MsPnaKTF5kz69H1UN2",
+ "07f0803fc5399e773555ab1e8939907e9badacc17ca129e67a2f5f2ff84351dd",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "chain": "main"
+ }
+ ],
+ [
+ "93N87D6uxSBzwXvpokpzg8FFmfQPmvX4xHoWQe3pLdYpbiwT5YV",
+ "ea577acfb5d1d14d3b7b195c321566f12f87d2b77ea3a53f68df7ebf8604a801",
+ {
+ "isCompressed": false,
+ "isPrivkey": true,
+ "chain": "test"
+ }
+ ],
+ [
+ "cMxXusSihaX58wpJ3tNuuUcZEQGt6DKJ1wEpxys88FFaQCYjku9h",
+ "0b3b34f0958d8a268193a9814da92c3e8b58b4a4378a542863e34ac289cd830c",
+ {
+ "isCompressed": true,
+ "isPrivkey": true,
+ "chain": "test"
+ }
+ ],
+ [
+ "13p1ijLwsnrcuyqcTvJXkq2ASdXqcnEBLE",
+ "76a9141ed467017f043e91ed4c44b4e8dd674db211c4e688ac",
+ {
+ "isPrivkey": false,
+ "chain": "main"
+ }
+ ],
+ [
+ "3ALJH9Y951VCGcVZYAdpA3KchoP9McEj1G",
+ "a9145ece0cadddc415b1980f001785947120acdb36fc87",
+ {
+ "isPrivkey": false,
+ "chain": "main"
+ }
+ ],
+ [
+ "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4",
+ "0014751e76e8199196d454941c45d1b3a323f1433bd6",
+ {
+ "isPrivkey": false,
+ "chain": "main",
+ "tryCaseFlip": true
+ }
+ ],
+ [
+ "bcrt1qw508d6qejxtdg4y5r3zarvary0c5xw7kygt080",
+ "0014751e76e8199196d454941c45d1b3a323f1433bd6",
+ {
+ "isPrivkey": false,
+ "chain": "regtest",
+ "tryCaseFlip": true
+ }
+ ],
+ [
+ "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
+ "00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262",
+ {
+ "isPrivkey": false,
+ "chain": "test",
+ "tryCaseFlip": true
+ }
+ ],
+ [
+ "bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx",
+ "5128751e76e8199196d454941c45d1b3a323f1433bd6751e76e8199196d454941c45d1b3a323f1433bd6",
+ {
+ "isPrivkey": false,
+ "chain": "main",
+ "tryCaseFlip": true
+ }
+ ],
+ [
+ "bc1sw50qa3jx3s",
+ "6002751e",
+ {
+ "isPrivkey": false,
+ "chain": "main",
+ "tryCaseFlip": true
+ }
+ ],
+ [
+ "bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj",
+ "5210751e76e8199196d454941c45d1b3a323",
+ {
+ "isPrivkey": false,
+ "chain": "main",
+ "tryCaseFlip": true
+ }
+ ],
+ [
+ "tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy",
+ "0020000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433",
+ {
+ "isPrivkey": false,
+ "chain": "test",
+ "tryCaseFlip": true
+ }
+ ],
+ [
+ "bcrt1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvseswlauz7",
+ "0020000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433",
+ {
+ "isPrivkey": false,
+ "chain": "regtest",
+ "tryCaseFlip": true
+ }
+ ]
+]
diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json
new file mode 100644
index 0000000000..9b320b6943
--- /dev/null
+++ b/src/test/data/script_tests.json
@@ -0,0 +1,2619 @@
+[
+["Format is: [[wit..., amount]?, scriptSig, scriptPubKey, flags, expected_scripterror, ... comments]"],
+["It is evaluated as if there was a crediting coinbase transaction with two 0"],
+["pushes as scriptSig, and one output of 0 satoshi and given scriptPubKey,"],
+["followed by a spending transaction which spends this output as only input (and"],
+["correct prevout hash), using the given scriptSig. All nLockTimes are 0, all"],
+["nSequences are max."],
+
+["", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "Test the test: we should have an empty stack after scriptSig evaluation"],
+[" ", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "and multiple spaces should not change that."],
+[" ", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+[" ", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["1 2", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK", "Similarly whitespace around and between symbols"],
+["1 2", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK"],
+[" 1 2", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK"],
+["1 2 ", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK"],
+[" 1 2 ", "2 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK"],
+
+["1", "", "P2SH,STRICTENC", "OK"],
+["0x02 0x01 0x00", "", "P2SH,STRICTENC", "OK", "all bytes are significant, not only the last one"],
+["0x09 0x00000000 0x00000000 0x10", "", "P2SH,STRICTENC", "OK", "equals zero when cast to Int64"],
+
+["0x01 0x0b", "11 EQUAL", "P2SH,STRICTENC", "OK", "push 1 byte"],
+["0x02 0x417a", "'Az' EQUAL", "P2SH,STRICTENC", "OK"],
+["0x4b 0x417a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a",
+ "'Azzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' EQUAL", "P2SH,STRICTENC", "OK", "push 75 bytes"],
+
+["0x4c 0x01 0x07","7 EQUAL", "P2SH,STRICTENC", "OK", "0x4c is OP_PUSHDATA1"],
+["0x4d 0x0100 0x08","8 EQUAL", "P2SH,STRICTENC", "OK", "0x4d is OP_PUSHDATA2"],
+["0x4e 0x01000000 0x09","9 EQUAL", "P2SH,STRICTENC", "OK", "0x4e is OP_PUSHDATA4"],
+
+["0x4c 0x00","0 EQUAL", "P2SH,STRICTENC", "OK"],
+["0x4d 0x0000","0 EQUAL", "P2SH,STRICTENC", "OK"],
+["0x4e 0x00000000","0 EQUAL", "P2SH,STRICTENC", "OK"],
+["0x4f 1000 ADD","999 EQUAL", "P2SH,STRICTENC", "OK"],
+["0", "IF 0x50 ENDIF 1", "P2SH,STRICTENC", "OK", "0x50 is reserved (ok if not executed)"],
+["0x51", "0x5f ADD 0x60 EQUAL", "P2SH,STRICTENC", "OK", "0x51 through 0x60 push 1 through 16 onto stack"],
+["1","NOP", "P2SH,STRICTENC", "OK"],
+["0", "IF VER ELSE 1 ENDIF", "P2SH,STRICTENC", "OK", "VER non-functional (ok if not executed)"],
+["0", "IF RESERVED RESERVED1 RESERVED2 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK", "RESERVED ok in un-executed IF"],
+
+["1", "DUP IF ENDIF", "P2SH,STRICTENC", "OK"],
+["1", "IF 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["1", "DUP IF ELSE ENDIF", "P2SH,STRICTENC", "OK"],
+["1", "IF 1 ELSE ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+
+["1 1", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "OK"],
+["1 0", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "OK"],
+["1 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "OK"],
+["0 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "OK"],
+
+["1 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "OK"],
+["1 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "OK"],
+["1 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "OK"],
+["0 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "OK"],
+
+["0", "IF 0 ELSE 1 ELSE 0 ENDIF", "P2SH,STRICTENC", "OK", "Multiple ELSE's are valid and executed inverts on each ELSE encountered"],
+["1", "IF 1 ELSE 0 ELSE ENDIF", "P2SH,STRICTENC", "OK"],
+["1", "IF ELSE 0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["1", "IF 1 ELSE 0 ELSE 1 ENDIF ADD 2 EQUAL", "P2SH,STRICTENC", "OK"],
+["'' 1", "IF SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ENDIF 0x14 0x68ca4fec736264c13b859bac43d5173df6871682 EQUAL", "P2SH,STRICTENC", "OK"],
+
+["1", "NOTIF 0 ELSE 1 ELSE 0 ENDIF", "P2SH,STRICTENC", "OK", "Multiple ELSE's are valid and execution inverts on each ELSE encountered"],
+["0", "NOTIF 1 ELSE 0 ELSE ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "NOTIF ELSE 0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "NOTIF 1 ELSE 0 ELSE 1 ENDIF ADD 2 EQUAL", "P2SH,STRICTENC", "OK"],
+["'' 0", "NOTIF SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ENDIF 0x14 0x68ca4fec736264c13b859bac43d5173df6871682 EQUAL", "P2SH,STRICTENC", "OK"],
+
+["0", "IF 1 IF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 1 IF 1 ELSE RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL", "P2SH,STRICTENC", "OK", "Nested ELSE ELSE"],
+["1", "NOTIF 0 NOTIF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 0 NOTIF 1 ELSE RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL", "P2SH,STRICTENC", "OK"],
+
+["0", "IF RETURN ENDIF 1", "P2SH,STRICTENC", "OK", "RETURN only works if executed"],
+
+["1 1", "VERIFY", "P2SH,STRICTENC", "OK"],
+["1 0x05 0x01 0x00 0x00 0x00 0x00", "VERIFY", "P2SH,STRICTENC", "OK", "values >4 bytes can be cast to boolean"],
+["1 0x01 0x80", "IF 0 ENDIF", "P2SH,STRICTENC", "OK", "negative 0 is false"],
+
+["10 0 11 TOALTSTACK DROP FROMALTSTACK", "ADD 21 EQUAL", "P2SH,STRICTENC", "OK"],
+["'gavin_was_here' TOALTSTACK 11 FROMALTSTACK", "'gavin_was_here' EQUALVERIFY 11 EQUAL", "P2SH,STRICTENC", "OK"],
+
+["0 IFDUP", "DEPTH 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["1 IFDUP", "DEPTH 2 EQUALVERIFY 1 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC", "OK"],
+["0x05 0x0100000000 IFDUP", "DEPTH 2 EQUALVERIFY 0x05 0x0100000000 EQUAL", "P2SH,STRICTENC", "OK", "IFDUP dups non ints"],
+["0 DROP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["0", "DUP 1 ADD 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["0 1", "NIP", "P2SH,STRICTENC", "OK"],
+["1 0", "OVER DEPTH 3 EQUALVERIFY", "P2SH,STRICTENC", "OK"],
+["22 21 20", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "OK"],
+["22 21 20", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "OK"],
+["22 21 20", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "OK"],
+["22 21 20", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "OK"],
+["22 21 20", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "OK"],
+["22 21 20", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "OK"],
+["22 21 20", "ROT 22 EQUAL", "P2SH,STRICTENC", "OK"],
+["22 21 20", "ROT DROP 20 EQUAL", "P2SH,STRICTENC", "OK"],
+["22 21 20", "ROT DROP DROP 21 EQUAL", "P2SH,STRICTENC", "OK"],
+["22 21 20", "ROT ROT 21 EQUAL", "P2SH,STRICTENC", "OK"],
+["22 21 20", "ROT ROT ROT 20 EQUAL", "P2SH,STRICTENC", "OK"],
+["25 24 23 22 21 20", "2ROT 24 EQUAL", "P2SH,STRICTENC", "OK"],
+["25 24 23 22 21 20", "2ROT DROP 25 EQUAL", "P2SH,STRICTENC", "OK"],
+["25 24 23 22 21 20", "2ROT 2DROP 20 EQUAL", "P2SH,STRICTENC", "OK"],
+["25 24 23 22 21 20", "2ROT 2DROP DROP 21 EQUAL", "P2SH,STRICTENC", "OK"],
+["25 24 23 22 21 20", "2ROT 2DROP 2DROP 22 EQUAL", "P2SH,STRICTENC", "OK"],
+["25 24 23 22 21 20", "2ROT 2DROP 2DROP DROP 23 EQUAL", "P2SH,STRICTENC", "OK"],
+["25 24 23 22 21 20", "2ROT 2ROT 22 EQUAL", "P2SH,STRICTENC", "OK"],
+["25 24 23 22 21 20", "2ROT 2ROT 2ROT 20 EQUAL", "P2SH,STRICTENC", "OK"],
+["1 0", "SWAP 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["0 1", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP", "P2SH,STRICTENC", "OK"],
+["13 14", "2DUP ROT EQUALVERIFY EQUAL", "P2SH,STRICTENC", "OK"],
+["-1 0 1 2", "3DUP DEPTH 7 EQUALVERIFY ADD ADD 3 EQUALVERIFY 2DROP 0 EQUALVERIFY", "P2SH,STRICTENC", "OK"],
+["1 2 3 5", "2OVER ADD ADD 8 EQUALVERIFY ADD ADD 6 EQUAL", "P2SH,STRICTENC", "OK"],
+["1 3 5 7", "2SWAP ADD 4 EQUALVERIFY ADD 12 EQUAL", "P2SH,STRICTENC", "OK"],
+["0", "SIZE 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["1", "SIZE 1 EQUAL", "P2SH,STRICTENC", "OK"],
+["127", "SIZE 1 EQUAL", "P2SH,STRICTENC", "OK"],
+["128", "SIZE 2 EQUAL", "P2SH,STRICTENC", "OK"],
+["32767", "SIZE 2 EQUAL", "P2SH,STRICTENC", "OK"],
+["32768", "SIZE 3 EQUAL", "P2SH,STRICTENC", "OK"],
+["8388607", "SIZE 3 EQUAL", "P2SH,STRICTENC", "OK"],
+["8388608", "SIZE 4 EQUAL", "P2SH,STRICTENC", "OK"],
+["2147483647", "SIZE 4 EQUAL", "P2SH,STRICTENC", "OK"],
+["2147483648", "SIZE 5 EQUAL", "P2SH,STRICTENC", "OK"],
+["549755813887", "SIZE 5 EQUAL", "P2SH,STRICTENC", "OK"],
+["549755813888", "SIZE 6 EQUAL", "P2SH,STRICTENC", "OK"],
+["9223372036854775807", "SIZE 8 EQUAL", "P2SH,STRICTENC", "OK"],
+["-1", "SIZE 1 EQUAL", "P2SH,STRICTENC", "OK"],
+["-127", "SIZE 1 EQUAL", "P2SH,STRICTENC", "OK"],
+["-128", "SIZE 2 EQUAL", "P2SH,STRICTENC", "OK"],
+["-32767", "SIZE 2 EQUAL", "P2SH,STRICTENC", "OK"],
+["-32768", "SIZE 3 EQUAL", "P2SH,STRICTENC", "OK"],
+["-8388607", "SIZE 3 EQUAL", "P2SH,STRICTENC", "OK"],
+["-8388608", "SIZE 4 EQUAL", "P2SH,STRICTENC", "OK"],
+["-2147483647", "SIZE 4 EQUAL", "P2SH,STRICTENC", "OK"],
+["-2147483648", "SIZE 5 EQUAL", "P2SH,STRICTENC", "OK"],
+["-549755813887", "SIZE 5 EQUAL", "P2SH,STRICTENC", "OK"],
+["-549755813888", "SIZE 6 EQUAL", "P2SH,STRICTENC", "OK"],
+["-9223372036854775807", "SIZE 8 EQUAL", "P2SH,STRICTENC", "OK"],
+["'abcdefghijklmnopqrstuvwxyz'", "SIZE 26 EQUAL", "P2SH,STRICTENC", "OK"],
+
+["42", "SIZE 1 EQUALVERIFY 42 EQUAL", "P2SH,STRICTENC", "OK", "SIZE does not consume argument"],
+
+["2 -2 ADD", "0 EQUAL", "P2SH,STRICTENC", "OK"],
+["2147483647 -2147483647 ADD", "0 EQUAL", "P2SH,STRICTENC", "OK"],
+["-1 -1 ADD", "-2 EQUAL", "P2SH,STRICTENC", "OK"],
+
+["0 0","EQUAL", "P2SH,STRICTENC", "OK"],
+["1 1 ADD", "2 EQUAL", "P2SH,STRICTENC", "OK"],
+["1 1ADD", "2 EQUAL", "P2SH,STRICTENC", "OK"],
+["111 1SUB", "110 EQUAL", "P2SH,STRICTENC", "OK"],
+["111 1 ADD 12 SUB", "100 EQUAL", "P2SH,STRICTENC", "OK"],
+["0 ABS", "0 EQUAL", "P2SH,STRICTENC", "OK"],
+["16 ABS", "16 EQUAL", "P2SH,STRICTENC", "OK"],
+["-16 ABS", "-16 NEGATE EQUAL", "P2SH,STRICTENC", "OK"],
+["0 NOT", "NOP", "P2SH,STRICTENC", "OK"],
+["1 NOT", "0 EQUAL", "P2SH,STRICTENC", "OK"],
+["11 NOT", "0 EQUAL", "P2SH,STRICTENC", "OK"],
+["0 0NOTEQUAL", "0 EQUAL", "P2SH,STRICTENC", "OK"],
+["1 0NOTEQUAL", "1 EQUAL", "P2SH,STRICTENC", "OK"],
+["111 0NOTEQUAL", "1 EQUAL", "P2SH,STRICTENC", "OK"],
+["-111 0NOTEQUAL", "1 EQUAL", "P2SH,STRICTENC", "OK"],
+["1 1 BOOLAND", "NOP", "P2SH,STRICTENC", "OK"],
+["1 0 BOOLAND", "NOT", "P2SH,STRICTENC", "OK"],
+["0 1 BOOLAND", "NOT", "P2SH,STRICTENC", "OK"],
+["0 0 BOOLAND", "NOT", "P2SH,STRICTENC", "OK"],
+["16 17 BOOLAND", "NOP", "P2SH,STRICTENC", "OK"],
+["1 1 BOOLOR", "NOP", "P2SH,STRICTENC", "OK"],
+["1 0 BOOLOR", "NOP", "P2SH,STRICTENC", "OK"],
+["0 1 BOOLOR", "NOP", "P2SH,STRICTENC", "OK"],
+["0 0 BOOLOR", "NOT", "P2SH,STRICTENC", "OK"],
+["0x01 0x80", "DUP BOOLOR", "P2SH,STRICTENC", "EVAL_FALSE", "negative-0 negative-0 BOOLOR"],
+["0x01 0x00", "DUP BOOLOR", "P2SH,STRICTENC", "EVAL_FALSE", " non-minimal-0 non-minimal-0 BOOLOR"],
+["0x01 0x81", "DUP BOOLOR", "P2SH,STRICTENC", "OK", "-1 -1 BOOLOR"],
+["0x01 0x80", "DUP BOOLAND", "P2SH,STRICTENC", "EVAL_FALSE", "negative-0 negative-0 BOOLAND"],
+["0x01 0x00", "DUP BOOLAND", "P2SH,STRICTENC", "EVAL_FALSE", " non-minimal-0 non-minimal-0 BOOLAND"],
+["0x01 0x81", "DUP BOOLAND", "P2SH,STRICTENC", "OK", "-1 -1 BOOLAND"],
+["0x01 0x00", "NOT", "P2SH,STRICTENC", "OK", "non-minimal-0 NOT"],
+["0x01 0x80", "NOT", "P2SH,STRICTENC", "OK", "negative-0 NOT"],
+["0x01 0x81", "NOT", "P2SH,STRICTENC", "EVAL_FALSE", "negative 1 NOT"],
+["0x01 0x80 0", "NUMEQUAL", "P2SH", "OK", "-0 0 NUMEQUAL"],
+["0x01 0x00 0", "NUMEQUAL", "P2SH", "OK", "non-minimal-0 0 NUMEQUAL"],
+["0x02 0x00 0x00 0", "NUMEQUAL", "P2SH", "OK", "non-minimal-0 0 NUMEQUAL"],
+["16 17 BOOLOR", "NOP", "P2SH,STRICTENC", "OK"],
+["11 10 1 ADD", "NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["11 10 1 ADD", "NUMEQUALVERIFY 1", "P2SH,STRICTENC", "OK"],
+["11 10 1 ADD", "NUMNOTEQUAL NOT", "P2SH,STRICTENC", "OK"],
+["111 10 1 ADD", "NUMNOTEQUAL", "P2SH,STRICTENC", "OK"],
+["11 10", "LESSTHAN NOT", "P2SH,STRICTENC", "OK"],
+["4 4", "LESSTHAN NOT", "P2SH,STRICTENC", "OK"],
+["10 11", "LESSTHAN", "P2SH,STRICTENC", "OK"],
+["-11 11", "LESSTHAN", "P2SH,STRICTENC", "OK"],
+["-11 -10", "LESSTHAN", "P2SH,STRICTENC", "OK"],
+["11 10", "GREATERTHAN", "P2SH,STRICTENC", "OK"],
+["4 4", "GREATERTHAN NOT", "P2SH,STRICTENC", "OK"],
+["10 11", "GREATERTHAN NOT", "P2SH,STRICTENC", "OK"],
+["-11 11", "GREATERTHAN NOT", "P2SH,STRICTENC", "OK"],
+["-11 -10", "GREATERTHAN NOT", "P2SH,STRICTENC", "OK"],
+["11 10", "LESSTHANOREQUAL NOT", "P2SH,STRICTENC", "OK"],
+["4 4", "LESSTHANOREQUAL", "P2SH,STRICTENC", "OK"],
+["10 11", "LESSTHANOREQUAL", "P2SH,STRICTENC", "OK"],
+["-11 11", "LESSTHANOREQUAL", "P2SH,STRICTENC", "OK"],
+["-11 -10", "LESSTHANOREQUAL", "P2SH,STRICTENC", "OK"],
+["11 10", "GREATERTHANOREQUAL", "P2SH,STRICTENC", "OK"],
+["4 4", "GREATERTHANOREQUAL", "P2SH,STRICTENC", "OK"],
+["10 11", "GREATERTHANOREQUAL NOT", "P2SH,STRICTENC", "OK"],
+["-11 11", "GREATERTHANOREQUAL NOT", "P2SH,STRICTENC", "OK"],
+["-11 -10", "GREATERTHANOREQUAL NOT", "P2SH,STRICTENC", "OK"],
+["1 0 MIN", "0 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["0 1 MIN", "0 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["-1 0 MIN", "-1 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["0 -2147483647 MIN", "-2147483647 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["2147483647 0 MAX", "2147483647 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["0 100 MAX", "100 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["-100 0 MAX", "0 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["0 -2147483647 MAX", "0 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["0 0 1", "WITHIN", "P2SH,STRICTENC", "OK"],
+["1 0 1", "WITHIN NOT", "P2SH,STRICTENC", "OK"],
+["0 -2147483647 2147483647", "WITHIN", "P2SH,STRICTENC", "OK"],
+["-1 -100 100", "WITHIN", "P2SH,STRICTENC", "OK"],
+["11 -100 100", "WITHIN", "P2SH,STRICTENC", "OK"],
+["-2147483647 -100 100", "WITHIN NOT", "P2SH,STRICTENC", "OK"],
+["2147483647 -100 100", "WITHIN NOT", "P2SH,STRICTENC", "OK"],
+
+["2147483647 2147483647 SUB", "0 EQUAL", "P2SH,STRICTENC", "OK"],
+["2147483647 DUP ADD", "4294967294 EQUAL", "P2SH,STRICTENC", "OK", ">32 bit EQUAL is valid"],
+["2147483647 NEGATE DUP ADD", "-4294967294 EQUAL", "P2SH,STRICTENC", "OK"],
+
+["''", "RIPEMD160 0x14 0x9c1185a5c5e9fc54612808977ee8f548b2258d31 EQUAL", "P2SH,STRICTENC", "OK"],
+["'a'", "RIPEMD160 0x14 0x0bdc9d2d256b3ee9daae347be6f4dc835a467ffe EQUAL", "P2SH,STRICTENC", "OK"],
+["'abcdefghijklmnopqrstuvwxyz'", "RIPEMD160 0x14 0xf71c27109c692c1b56bbdceb5b9d2865b3708dbc EQUAL", "P2SH,STRICTENC", "OK"],
+["''", "SHA1 0x14 0xda39a3ee5e6b4b0d3255bfef95601890afd80709 EQUAL", "P2SH,STRICTENC", "OK"],
+["'a'", "SHA1 0x14 0x86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 EQUAL", "P2SH,STRICTENC", "OK"],
+["'abcdefghijklmnopqrstuvwxyz'", "SHA1 0x14 0x32d10c7b8cf96570ca04ce37f2a19d84240d3a89 EQUAL", "P2SH,STRICTENC", "OK"],
+["''", "SHA256 0x20 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 EQUAL", "P2SH,STRICTENC", "OK"],
+["'a'", "SHA256 0x20 0xca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb EQUAL", "P2SH,STRICTENC", "OK"],
+["'abcdefghijklmnopqrstuvwxyz'", "SHA256 0x20 0x71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73 EQUAL", "P2SH,STRICTENC", "OK"],
+["''", "DUP HASH160 SWAP SHA256 RIPEMD160 EQUAL", "P2SH,STRICTENC", "OK"],
+["''", "DUP HASH256 SWAP SHA256 SHA256 EQUAL", "P2SH,STRICTENC", "OK"],
+["''", "NOP HASH160 0x14 0xb472a266d0bd89c13706a4132ccfb16f7c3b9fcb EQUAL", "P2SH,STRICTENC", "OK"],
+["'a'", "HASH160 NOP 0x14 0x994355199e516ff76c4fa4aab39337b9d84cf12b EQUAL", "P2SH,STRICTENC", "OK"],
+["'abcdefghijklmnopqrstuvwxyz'", "HASH160 0x4c 0x14 0xc286a1af0947f58d1ad787385b1c2c4a976f9e71 EQUAL", "P2SH,STRICTENC", "OK"],
+["''", "HASH256 0x20 0x5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456 EQUAL", "P2SH,STRICTENC", "OK"],
+["'a'", "HASH256 0x20 0xbf5d3affb73efd2ec6c36ad3112dd933efed63c4e1cbffcfa88e2759c144f2d8 EQUAL", "P2SH,STRICTENC", "OK"],
+["'abcdefghijklmnopqrstuvwxyz'", "HASH256 0x4c 0x20 0xca139bc10c2f660da42666f72e89a225936fc60f193c161124a672050c434671 EQUAL", "P2SH,STRICTENC", "OK"],
+
+
+["1","NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 1 EQUAL", "P2SH,STRICTENC", "OK"],
+["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' EQUAL", "P2SH,STRICTENC", "OK"],
+
+["1", "NOP", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", "OK", "Discourage NOPx flag allows OP_NOP"],
+
+["0", "IF NOP10 ENDIF 1", "P2SH,STRICTENC,DISCOURAGE_UPGRADABLE_NOPS", "OK",
+ "Discouraged NOPs are allowed if not executed"],
+
+["0", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "OK", "opcodes above MAX_OPCODE invalid if executed"],
+["0", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xc0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xc4 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xc5 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xc6 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xc7 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xc8 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xc9 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xca ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xcb ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xcc ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xcd ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xce ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xcf ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xd0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xd1 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xd2 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xd3 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xd4 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xd5 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xd6 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xd7 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xd8 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xd9 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xda ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xdb ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xdc ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xdd ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xde ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xdf ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xe0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xe1 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xe2 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xe3 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xe4 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xe5 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xe6 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xe7 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xe8 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xe9 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xea ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xeb ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xec ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xed ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xee ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xef ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xf0 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xf1 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xf2 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xf3 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xf4 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xf5 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xf6 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xf7 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xf8 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xf9 ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xfa ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xfb ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xfc ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xfd ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xfe ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+["0", "IF 0xff ELSE 1 ENDIF", "P2SH,STRICTENC", "OK"],
+
+["NOP",
+"'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'",
+"P2SH,STRICTENC", "OK",
+"520 byte push"],
+["1",
+"0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161",
+"P2SH,STRICTENC", "OK",
+"201 opcodes executed. 0x61 is NOP"],
+["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"P2SH,STRICTENC", "OK",
+"1,000 stack size (0x6f is 3DUP)"],
+["1 TOALTSTACK 2 TOALTSTACK 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"1 2 3 4 5 6 7 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"P2SH,STRICTENC", "OK",
+"1,000 stack size (altstack cleared between scriptSig/scriptPubKey)"],
+["'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f 2DUP 0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161",
+"P2SH,STRICTENC", "OK",
+"Max-size (10,000-byte), max-push(520 bytes), max-opcodes(201), max stack size(1,000 items). 0x6f is 3DUP, 0x61 is NOP"],
+
+["0",
+"IF 0x5050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050 ENDIF 1",
+"P2SH,STRICTENC", "OK",
+">201 opcodes, but RESERVED (0x50) doesn't count towards opcode limit."],
+
+["NOP","1", "P2SH,STRICTENC", "OK"],
+
+["1", "0x01 0x01 EQUAL", "P2SH,STRICTENC", "OK", "The following is useful for checking implementations of BN_bn2mpi"],
+["127", "0x01 0x7F EQUAL", "P2SH,STRICTENC", "OK"],
+["128", "0x02 0x8000 EQUAL", "P2SH,STRICTENC", "OK", "Leave room for the sign bit"],
+["32767", "0x02 0xFF7F EQUAL", "P2SH,STRICTENC", "OK"],
+["32768", "0x03 0x008000 EQUAL", "P2SH,STRICTENC", "OK"],
+["8388607", "0x03 0xFFFF7F EQUAL", "P2SH,STRICTENC", "OK"],
+["8388608", "0x04 0x00008000 EQUAL", "P2SH,STRICTENC", "OK"],
+["2147483647", "0x04 0xFFFFFF7F EQUAL", "P2SH,STRICTENC", "OK"],
+["2147483648", "0x05 0x0000008000 EQUAL", "P2SH,STRICTENC", "OK"],
+["549755813887", "0x05 0xFFFFFFFF7F EQUAL", "P2SH,STRICTENC", "OK"],
+["549755813888", "0x06 0x000000008000 EQUAL", "P2SH,STRICTENC", "OK"],
+["9223372036854775807", "0x08 0xFFFFFFFFFFFFFF7F EQUAL", "P2SH,STRICTENC", "OK"],
+["-1", "0x01 0x81 EQUAL", "P2SH,STRICTENC", "OK", "Numbers are little-endian with the MSB being a sign bit"],
+["-127", "0x01 0xFF EQUAL", "P2SH,STRICTENC", "OK"],
+["-128", "0x02 0x8080 EQUAL", "P2SH,STRICTENC", "OK"],
+["-32767", "0x02 0xFFFF EQUAL", "P2SH,STRICTENC", "OK"],
+["-32768", "0x03 0x008080 EQUAL", "P2SH,STRICTENC", "OK"],
+["-8388607", "0x03 0xFFFFFF EQUAL", "P2SH,STRICTENC", "OK"],
+["-8388608", "0x04 0x00008080 EQUAL", "P2SH,STRICTENC", "OK"],
+["-2147483647", "0x04 0xFFFFFFFF EQUAL", "P2SH,STRICTENC", "OK"],
+["-2147483648", "0x05 0x0000008080 EQUAL", "P2SH,STRICTENC", "OK"],
+["-4294967295", "0x05 0xFFFFFFFF80 EQUAL", "P2SH,STRICTENC", "OK"],
+["-549755813887", "0x05 0xFFFFFFFFFF EQUAL", "P2SH,STRICTENC", "OK"],
+["-549755813888", "0x06 0x000000008080 EQUAL", "P2SH,STRICTENC", "OK"],
+["-9223372036854775807", "0x08 0xFFFFFFFFFFFFFFFF EQUAL", "P2SH,STRICTENC", "OK"],
+
+["2147483647", "1ADD 2147483648 EQUAL", "P2SH,STRICTENC", "OK", "We can do math on 4-byte integers, and compare 5-byte ones"],
+["2147483647", "1ADD 1", "P2SH,STRICTENC", "OK"],
+["-2147483647", "1ADD 1", "P2SH,STRICTENC", "OK"],
+
+["1", "0x02 0x0100 EQUAL NOT", "P2SH,STRICTENC", "OK", "Not the same byte array..."],
+["1", "0x02 0x0100 NUMEQUAL", "P2SH,STRICTENC", "OK", "... but they are numerically equal"],
+["11", "0x4c 0x03 0x0b0000 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["0", "0x01 0x80 EQUAL NOT", "P2SH,STRICTENC", "OK"],
+["0", "0x01 0x80 NUMEQUAL", "P2SH,STRICTENC", "OK", "Zero numerically equals negative zero"],
+["0", "0x02 0x0080 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["0x03 0x000080", "0x04 0x00000080 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["0x03 0x100080", "0x04 0x10000080 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["0x03 0x100000", "0x04 0x10000000 NUMEQUAL", "P2SH,STRICTENC", "OK"],
+
+["NOP", "NOP 1", "P2SH,STRICTENC", "OK", "The following tests check the if(stack.size() < N) tests in each opcode"],
+["1", "IF 1 ENDIF", "P2SH,STRICTENC", "OK", "They are here to catch copy-and-paste errors"],
+["0", "NOTIF 1 ENDIF", "P2SH,STRICTENC", "OK", "Most of them are duplicated elsewhere,"],
+["1", "VERIFY 1", "P2SH,STRICTENC", "OK", "but, hey, more is always better, right?"],
+
+["0", "TOALTSTACK 1", "P2SH,STRICTENC", "OK"],
+["1", "TOALTSTACK FROMALTSTACK", "P2SH,STRICTENC", "OK"],
+["0 0", "2DROP 1", "P2SH,STRICTENC", "OK"],
+["0 1", "2DUP", "P2SH,STRICTENC", "OK"],
+["0 0 1", "3DUP", "P2SH,STRICTENC", "OK"],
+["0 1 0 0", "2OVER", "P2SH,STRICTENC", "OK"],
+["0 1 0 0 0 0", "2ROT", "P2SH,STRICTENC", "OK"],
+["0 1 0 0", "2SWAP", "P2SH,STRICTENC", "OK"],
+["1", "IFDUP", "P2SH,STRICTENC", "OK"],
+["NOP", "DEPTH 1", "P2SH,STRICTENC", "OK"],
+["0", "DROP 1", "P2SH,STRICTENC", "OK"],
+["1", "DUP", "P2SH,STRICTENC", "OK"],
+["0 1", "NIP", "P2SH,STRICTENC", "OK"],
+["1 0", "OVER", "P2SH,STRICTENC", "OK"],
+["1 0 0 0 3", "PICK", "P2SH,STRICTENC", "OK"],
+["1 0", "PICK", "P2SH,STRICTENC", "OK"],
+["1 0 0 0 3", "ROLL", "P2SH,STRICTENC", "OK"],
+["1 0", "ROLL", "P2SH,STRICTENC", "OK"],
+["1 0 0", "ROT", "P2SH,STRICTENC", "OK"],
+["1 0", "SWAP", "P2SH,STRICTENC", "OK"],
+["0 1", "TUCK", "P2SH,STRICTENC", "OK"],
+
+["1", "SIZE", "P2SH,STRICTENC", "OK"],
+
+["0 0", "EQUAL", "P2SH,STRICTENC", "OK"],
+["0 0", "EQUALVERIFY 1", "P2SH,STRICTENC", "OK"],
+["0 0 1", "EQUAL EQUAL", "P2SH,STRICTENC", "OK", "OP_0 and bools must have identical byte representations"],
+
+["0", "1ADD", "P2SH,STRICTENC", "OK"],
+["2", "1SUB", "P2SH,STRICTENC", "OK"],
+["-1", "NEGATE", "P2SH,STRICTENC", "OK"],
+["-1", "ABS", "P2SH,STRICTENC", "OK"],
+["0", "NOT", "P2SH,STRICTENC", "OK"],
+["-1", "0NOTEQUAL", "P2SH,STRICTENC", "OK"],
+
+["1 0", "ADD", "P2SH,STRICTENC", "OK"],
+["1 0", "SUB", "P2SH,STRICTENC", "OK"],
+["-1 -1", "BOOLAND", "P2SH,STRICTENC", "OK"],
+["-1 0", "BOOLOR", "P2SH,STRICTENC", "OK"],
+["0 0", "NUMEQUAL", "P2SH,STRICTENC", "OK"],
+["0 0", "NUMEQUALVERIFY 1", "P2SH,STRICTENC", "OK"],
+["-1 0", "NUMNOTEQUAL", "P2SH,STRICTENC", "OK"],
+["-1 0", "LESSTHAN", "P2SH,STRICTENC", "OK"],
+["1 0", "GREATERTHAN", "P2SH,STRICTENC", "OK"],
+["0 0", "LESSTHANOREQUAL", "P2SH,STRICTENC", "OK"],
+["0 0", "GREATERTHANOREQUAL", "P2SH,STRICTENC", "OK"],
+["-1 0", "MIN", "P2SH,STRICTENC", "OK"],
+["1 0", "MAX", "P2SH,STRICTENC", "OK"],
+["-1 -1 0", "WITHIN", "P2SH,STRICTENC", "OK"],
+
+["0", "RIPEMD160", "P2SH,STRICTENC", "OK"],
+["0", "SHA1", "P2SH,STRICTENC", "OK"],
+["0", "SHA256", "P2SH,STRICTENC", "OK"],
+["0", "HASH160", "P2SH,STRICTENC", "OK"],
+["0", "HASH256", "P2SH,STRICTENC", "OK"],
+["NOP", "CODESEPARATOR 1", "P2SH,STRICTENC", "OK"],
+
+["NOP", "NOP1 1", "P2SH,STRICTENC", "OK"],
+["NOP", "CHECKLOCKTIMEVERIFY 1", "P2SH,STRICTENC", "OK"],
+["NOP", "CHECKSEQUENCEVERIFY 1", "P2SH,STRICTENC", "OK"],
+["NOP", "NOP4 1", "P2SH,STRICTENC", "OK"],
+["NOP", "NOP5 1", "P2SH,STRICTENC", "OK"],
+["NOP", "NOP6 1", "P2SH,STRICTENC", "OK"],
+["NOP", "NOP7 1", "P2SH,STRICTENC", "OK"],
+["NOP", "NOP8 1", "P2SH,STRICTENC", "OK"],
+["NOP", "NOP9 1", "P2SH,STRICTENC", "OK"],
+["NOP", "NOP10 1", "P2SH,STRICTENC", "OK"],
+
+["", "0 0 0 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "CHECKMULTISIG is allowed to have zero keys and/or sigs"],
+["", "0 0 0 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 0 1 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "Zero sigs means no sigs are checked"],
+["", "0 0 0 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+
+["", "0 0 0 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "CHECKMULTISIG is allowed to have zero keys and/or sigs"],
+["", "0 0 0 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 0 1 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "Zero sigs means no sigs are checked"],
+["", "0 0 0 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+
+["", "0 0 'a' 'b' 2 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK", "Test from up to 20 pubkeys, all not checked"],
+["", "0 0 'a' 'b' 'c' 3 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 4 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 5 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 6 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 7 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 8 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 9 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 10 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 11 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 12 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 13 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 14 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 15 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 16 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 17 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 18 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 19 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG VERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 1 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 2 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 3 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 4 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 5 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 6 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 7 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 8 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 9 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 10 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 11 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 12 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 13 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 14 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 15 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 16 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 17 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 18 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 19 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+["", "0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY DEPTH 0 EQUAL", "P2SH,STRICTENC", "OK"],
+
+["",
+"0 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG",
+"P2SH,STRICTENC", "OK",
+"nOpCount is incremented by the number of keys evaluated in addition to the usual one op per op. In this case we have zero keys, so we can execute 201 CHECKMULTISIGS"],
+
+["1",
+"0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY 0 0 0 CHECKMULTISIGVERIFY",
+"P2SH,STRICTENC", "OK"],
+
+["",
+"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG",
+"P2SH,STRICTENC", "OK",
+"Even though there are no signatures being checked nOpCount is incremented by the number of keys."],
+
+["1",
+"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY",
+"P2SH,STRICTENC", "OK"],
+
+["0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "OK", "Very basic P2SH"],
+["0x4c 0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "OK"],
+
+["0x40 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242",
+"0x4d 0x4000 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 EQUAL",
+"P2SH,STRICTENC", "OK",
+"Basic PUSH signedness check"],
+
+["0x4c 0x40 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242",
+"0x4d 0x4000 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 EQUAL",
+"P2SH,STRICTENC", "OK",
+"Basic PUSHDATA1 signedness check"],
+
+["all PUSHDATA forms are equivalent"],
+
+["0x4c 0x4b 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "0x4b 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 EQUAL", "", "OK", "PUSHDATA1 of 75 bytes equals direct push of it"],
+["0x4d 0xFF00 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "0x4c 0xFF 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 EQUAL", "", "OK", "PUSHDATA2 of 255 bytes equals PUSHDATA1 of it"],
+
+["0x00", "SIZE 0 EQUAL", "P2SH,STRICTENC", "OK", "Basic OP_0 execution"],
+
+["Numeric pushes"],
+
+["0x01 0x81", "0x4f EQUAL", "", "OK", "OP1_NEGATE pushes 0x81"],
+["0x01 0x01", "0x51 EQUAL", "", "OK", "OP_1 pushes 0x01"],
+["0x01 0x02", "0x52 EQUAL", "", "OK", "OP_2 pushes 0x02"],
+["0x01 0x03", "0x53 EQUAL", "", "OK", "OP_3 pushes 0x03"],
+["0x01 0x04", "0x54 EQUAL", "", "OK", "OP_4 pushes 0x04"],
+["0x01 0x05", "0x55 EQUAL", "", "OK", "OP_5 pushes 0x05"],
+["0x01 0x06", "0x56 EQUAL", "", "OK", "OP_6 pushes 0x06"],
+["0x01 0x07", "0x57 EQUAL", "", "OK", "OP_7 pushes 0x07"],
+["0x01 0x08", "0x58 EQUAL", "", "OK", "OP_8 pushes 0x08"],
+["0x01 0x09", "0x59 EQUAL", "", "OK", "OP_9 pushes 0x09"],
+["0x01 0x0a", "0x5a EQUAL", "", "OK", "OP_10 pushes 0x0a"],
+["0x01 0x0b", "0x5b EQUAL", "", "OK", "OP_11 pushes 0x0b"],
+["0x01 0x0c", "0x5c EQUAL", "", "OK", "OP_12 pushes 0x0c"],
+["0x01 0x0d", "0x5d EQUAL", "", "OK", "OP_13 pushes 0x0d"],
+["0x01 0x0e", "0x5e EQUAL", "", "OK", "OP_14 pushes 0x0e"],
+["0x01 0x0f", "0x5f EQUAL", "", "OK", "OP_15 pushes 0x0f"],
+["0x01 0x10", "0x60 EQUAL", "", "OK", "OP_16 pushes 0x10"],
+
+["Equivalency of different numeric encodings"],
+
+["0x02 0x8000", "128 NUMEQUAL", "", "OK", "0x8000 equals 128"],
+["0x01 0x00", "0 NUMEQUAL", "", "OK", "0x00 numequals 0"],
+["0x01 0x80", "0 NUMEQUAL", "", "OK", "0x80 (negative zero) numequals 0"],
+["0x02 0x0080", "0 NUMEQUAL", "", "OK", "0x0080 numequals 0"],
+["0x02 0x0500", "5 NUMEQUAL", "", "OK", "0x0500 numequals 5"],
+["0x03 0xff7f80", "0x02 0xffff NUMEQUAL", "", "OK", ""],
+["0x03 0xff7f00", "0x02 0xff7f NUMEQUAL", "", "OK", ""],
+["0x04 0xffff7f80", "0x03 0xffffff NUMEQUAL", "", "OK", ""],
+["0x04 0xffff7f00", "0x03 0xffff7f NUMEQUAL", "", "OK", ""],
+
+["Unevaluated non-minimal pushes are ignored"],
+
+["0 IF 0x4c 0x00 ENDIF 1", "", "MINIMALDATA", "OK", "non-minimal PUSHDATA1 ignored"],
+["0 IF 0x4d 0x0000 ENDIF 1", "", "MINIMALDATA", "OK", "non-minimal PUSHDATA2 ignored"],
+["0 IF 0x4c 0x00000000 ENDIF 1", "", "MINIMALDATA", "OK", "non-minimal PUSHDATA4 ignored"],
+["0 IF 0x01 0x81 ENDIF 1", "", "MINIMALDATA", "OK", "1NEGATE equiv"],
+["0 IF 0x01 0x01 ENDIF 1", "", "MINIMALDATA", "OK", "OP_1 equiv"],
+["0 IF 0x01 0x02 ENDIF 1", "", "MINIMALDATA", "OK", "OP_2 equiv"],
+["0 IF 0x01 0x03 ENDIF 1", "", "MINIMALDATA", "OK", "OP_3 equiv"],
+["0 IF 0x01 0x04 ENDIF 1", "", "MINIMALDATA", "OK", "OP_4 equiv"],
+["0 IF 0x01 0x05 ENDIF 1", "", "MINIMALDATA", "OK", "OP_5 equiv"],
+["0 IF 0x01 0x06 ENDIF 1", "", "MINIMALDATA", "OK", "OP_6 equiv"],
+["0 IF 0x01 0x07 ENDIF 1", "", "MINIMALDATA", "OK", "OP_7 equiv"],
+["0 IF 0x01 0x08 ENDIF 1", "", "MINIMALDATA", "OK", "OP_8 equiv"],
+["0 IF 0x01 0x09 ENDIF 1", "", "MINIMALDATA", "OK", "OP_9 equiv"],
+["0 IF 0x01 0x0a ENDIF 1", "", "MINIMALDATA", "OK", "OP_10 equiv"],
+["0 IF 0x01 0x0b ENDIF 1", "", "MINIMALDATA", "OK", "OP_11 equiv"],
+["0 IF 0x01 0x0c ENDIF 1", "", "MINIMALDATA", "OK", "OP_12 equiv"],
+["0 IF 0x01 0x0d ENDIF 1", "", "MINIMALDATA", "OK", "OP_13 equiv"],
+["0 IF 0x01 0x0e ENDIF 1", "", "MINIMALDATA", "OK", "OP_14 equiv"],
+["0 IF 0x01 0x0f ENDIF 1", "", "MINIMALDATA", "OK", "OP_15 equiv"],
+["0 IF 0x01 0x10 ENDIF 1", "", "MINIMALDATA", "OK", "OP_16 equiv"],
+
+["Numeric minimaldata rules are only applied when a stack item is numerically evaluated; the push itself is allowed"],
+
+["0x01 0x00", "1", "MINIMALDATA", "OK"],
+["0x01 0x80", "1", "MINIMALDATA", "OK"],
+["0x02 0x0180", "1", "MINIMALDATA", "OK"],
+["0x02 0x0100", "1", "MINIMALDATA", "OK"],
+["0x02 0x0200", "1", "MINIMALDATA", "OK"],
+["0x02 0x0300", "1", "MINIMALDATA", "OK"],
+["0x02 0x0400", "1", "MINIMALDATA", "OK"],
+["0x02 0x0500", "1", "MINIMALDATA", "OK"],
+["0x02 0x0600", "1", "MINIMALDATA", "OK"],
+["0x02 0x0700", "1", "MINIMALDATA", "OK"],
+["0x02 0x0800", "1", "MINIMALDATA", "OK"],
+["0x02 0x0900", "1", "MINIMALDATA", "OK"],
+["0x02 0x0a00", "1", "MINIMALDATA", "OK"],
+["0x02 0x0b00", "1", "MINIMALDATA", "OK"],
+["0x02 0x0c00", "1", "MINIMALDATA", "OK"],
+["0x02 0x0d00", "1", "MINIMALDATA", "OK"],
+["0x02 0x0e00", "1", "MINIMALDATA", "OK"],
+["0x02 0x0f00", "1", "MINIMALDATA", "OK"],
+["0x02 0x1000", "1", "MINIMALDATA", "OK"],
+
+["Valid version of the 'Test every numeric-accepting opcode for correct handling of the numeric minimal encoding rule' script_invalid test"],
+
+["1 0x02 0x0000", "PICK DROP", "", "OK"],
+["1 0x02 0x0000", "ROLL DROP 1", "", "OK"],
+["0x02 0x0000", "1ADD DROP 1", "", "OK"],
+["0x02 0x0000", "1SUB DROP 1", "", "OK"],
+["0x02 0x0000", "NEGATE DROP 1", "", "OK"],
+["0x02 0x0000", "ABS DROP 1", "", "OK"],
+["0x02 0x0000", "NOT DROP 1", "", "OK"],
+["0x02 0x0000", "0NOTEQUAL DROP 1", "", "OK"],
+
+["0 0x02 0x0000", "ADD DROP 1", "", "OK"],
+["0x02 0x0000 0", "ADD DROP 1", "", "OK"],
+["0 0x02 0x0000", "SUB DROP 1", "", "OK"],
+["0x02 0x0000 0", "SUB DROP 1", "", "OK"],
+["0 0x02 0x0000", "BOOLAND DROP 1", "", "OK"],
+["0x02 0x0000 0", "BOOLAND DROP 1", "", "OK"],
+["0 0x02 0x0000", "BOOLOR DROP 1", "", "OK"],
+["0x02 0x0000 0", "BOOLOR DROP 1", "", "OK"],
+["0 0x02 0x0000", "NUMEQUAL DROP 1", "", "OK"],
+["0x02 0x0000 1", "NUMEQUAL DROP 1", "", "OK"],
+["0 0x02 0x0000", "NUMEQUALVERIFY 1", "", "OK"],
+["0x02 0x0000 0", "NUMEQUALVERIFY 1", "", "OK"],
+["0 0x02 0x0000", "NUMNOTEQUAL DROP 1", "", "OK"],
+["0x02 0x0000 0", "NUMNOTEQUAL DROP 1", "", "OK"],
+["0 0x02 0x0000", "LESSTHAN DROP 1", "", "OK"],
+["0x02 0x0000 0", "LESSTHAN DROP 1", "", "OK"],
+["0 0x02 0x0000", "GREATERTHAN DROP 1", "", "OK"],
+["0x02 0x0000 0", "GREATERTHAN DROP 1", "", "OK"],
+["0 0x02 0x0000", "LESSTHANOREQUAL DROP 1", "", "OK"],
+["0x02 0x0000 0", "LESSTHANOREQUAL DROP 1", "", "OK"],
+["0 0x02 0x0000", "GREATERTHANOREQUAL DROP 1", "", "OK"],
+["0x02 0x0000 0", "GREATERTHANOREQUAL DROP 1", "", "OK"],
+["0 0x02 0x0000", "MIN DROP 1", "", "OK"],
+["0x02 0x0000 0", "MIN DROP 1", "", "OK"],
+["0 0x02 0x0000", "MAX DROP 1", "", "OK"],
+["0x02 0x0000 0", "MAX DROP 1", "", "OK"],
+
+["0x02 0x0000 0 0", "WITHIN DROP 1", "", "OK"],
+["0 0x02 0x0000 0", "WITHIN DROP 1", "", "OK"],
+["0 0 0x02 0x0000", "WITHIN DROP 1", "", "OK"],
+
+["0 0 0x02 0x0000", "CHECKMULTISIG DROP 1", "", "OK"],
+["0 0x02 0x0000 0", "CHECKMULTISIG DROP 1", "", "OK"],
+["0 0x02 0x0000 0 1", "CHECKMULTISIG DROP 1", "", "OK"],
+["0 0 0x02 0x0000", "CHECKMULTISIGVERIFY 1", "", "OK"],
+["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", "", "OK"],
+
+["While not really correctly DER encoded, the empty signature is allowed by"],
+["STRICTENC to provide a compact way to provide a delibrately invalid signature."],
+["0", "0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 CHECKSIG NOT", "STRICTENC", "OK"],
+["0 0", "1 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 1 CHECKMULTISIG NOT", "STRICTENC", "OK"],
+
+["CHECKMULTISIG evaluation order tests. CHECKMULTISIG evaluates signatures and"],
+["pubkeys in a specific order, and will exit early if the number of signatures"],
+["left to check is greater than the number of keys left. As STRICTENC fails the"],
+["script when it reaches an invalidly encoded signature or pubkey, we can use it"],
+["to test the exact order in which signatures and pubkeys are evaluated by"],
+["distinguishing CHECKMULTISIG returning false on the stack and the script as a"],
+["whole failing."],
+["See also the corresponding inverted versions of these tests in script_invalid.json"],
+[
+ "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501",
+ "2 0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT",
+ "STRICTENC", "OK",
+ "2-of-2 CHECKMULTISIG NOT with the second pubkey invalid, and both signatures validly encoded. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid pubkey."
+],
+[
+ "0 0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501",
+ "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT",
+ "STRICTENC", "OK",
+ "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but second signature invalid. Valid pubkey fails, and CHECKMULTISIG exits early, prior to evaluation of second invalid signature."
+],
+
+["Increase test coverage for DERSIG"],
+["0x4a 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "", "OK", "Overly long signature is correctly encoded"],
+["0x25 0x30220220000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "", "OK", "Missing S is correctly encoded"],
+["0x27 0x3024021077777777777777777777777777777777020a7777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "S with invalid S length is correctly encoded"],
+["0x27 0x302403107777777777777777777777777777777702107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Non-integer R is correctly encoded"],
+["0x27 0x302402107777777777777777777777777777777703107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Non-integer S is correctly encoded"],
+["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Zero-length R is correctly encoded"],
+["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "", "OK", "Zero-length S is correctly encoded for DERSIG"],
+["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "", "OK", "Negative S is correctly encoded"],
+
+["2147483648", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "OK", "CSV passes if stack top bit 1 << 31 is set"],
+
+["", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "Test the test: we should have an empty stack after scriptSig evaluation"],
+[" ", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE", "and multiple spaces should not change that."],
+[" ", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"],
+[" ", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"],
+
+["", "", "P2SH,STRICTENC","EVAL_FALSE"],
+["", "NOP", "P2SH,STRICTENC","EVAL_FALSE"],
+["", "NOP DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"],
+["NOP", "", "P2SH,STRICTENC", "EVAL_FALSE"],
+["NOP", "DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"],
+["NOP","NOP", "P2SH,STRICTENC", "EVAL_FALSE"],
+["NOP","NOP DEPTH", "P2SH,STRICTENC", "EVAL_FALSE"],
+
+["DEPTH", "", "P2SH,STRICTENC", "EVAL_FALSE"],
+
+["0x4c01","0x01 NOP", "P2SH,STRICTENC","BAD_OPCODE", "PUSHDATA1 with not enough bytes"],
+["0x4d0200ff","0x01 NOP", "P2SH,STRICTENC","BAD_OPCODE", "PUSHDATA2 with not enough bytes"],
+["0x4e03000000ffff","0x01 NOP", "P2SH,STRICTENC","BAD_OPCODE", "PUSHDATA4 with not enough bytes"],
+
+["1", "IF 0x50 ENDIF 1", "P2SH,STRICTENC","BAD_OPCODE", "0x50 is reserved"],
+["0x52", "0x5f ADD 0x60 EQUAL", "P2SH,STRICTENC","EVAL_FALSE", "0x51 through 0x60 push 1 through 16 onto stack"],
+["0","NOP", "P2SH,STRICTENC","EVAL_FALSE",""],
+["1", "IF VER ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VER non-functional"],
+["0", "IF VERIF ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VERIF illegal everywhere"],
+["0", "IF ELSE 1 ELSE VERIF ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VERIF illegal everywhere"],
+["0", "IF VERNOTIF ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VERNOTIF illegal everywhere"],
+["0", "IF ELSE 1 ELSE VERNOTIF ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "VERNOTIF illegal everywhere"],
+
+["1 IF", "1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "IF/ENDIF can't span scriptSig/scriptPubKey"],
+["1 IF 0 ENDIF", "1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"],
+["1 ELSE 0 ENDIF", "1", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"],
+["0 NOTIF", "123", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"],
+
+["0", "DUP IF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"],
+["0", "IF 1 ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"],
+["0", "DUP IF ELSE ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"],
+["0", "IF 1 ELSE ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"],
+["0", "NOTIF ELSE 1 ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"],
+
+["0 1", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"],
+["0 0", "IF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"],
+["1 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"],
+["0 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"],
+
+["0 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"],
+["0 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"],
+["1 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"],
+["0 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF", "P2SH,STRICTENC", "EVAL_FALSE"],
+
+["1", "IF RETURN ELSE ELSE 1 ENDIF", "P2SH,STRICTENC", "OP_RETURN", "Multiple ELSEs"],
+["1", "IF 1 ELSE ELSE RETURN ENDIF", "P2SH,STRICTENC", "OP_RETURN"],
+
+["1", "ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "Malformed IF/ELSE/ENDIF sequence"],
+["1", "ELSE ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"],
+["1", "ENDIF ELSE", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"],
+["1", "ENDIF ELSE IF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"],
+["1", "IF ELSE ENDIF ELSE", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"],
+["1", "IF ELSE ENDIF ELSE ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"],
+["1", "IF ENDIF ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"],
+["1", "IF ELSE ELSE ENDIF ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL"],
+
+["1", "RETURN", "P2SH,STRICTENC", "OP_RETURN"],
+["1", "DUP IF RETURN ENDIF", "P2SH,STRICTENC", "OP_RETURN"],
+
+["1", "RETURN 'data'", "P2SH,STRICTENC", "OP_RETURN", "canonical prunable txout format"],
+["0 IF", "RETURN ENDIF 1", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "still prunable because IF/ENDIF can't span scriptSig/scriptPubKey"],
+
+["0", "VERIFY 1", "P2SH,STRICTENC", "VERIFY"],
+["1", "VERIFY", "P2SH,STRICTENC", "EVAL_FALSE"],
+["1", "VERIFY 0", "P2SH,STRICTENC", "EVAL_FALSE"],
+
+["1 TOALTSTACK", "FROMALTSTACK 1", "P2SH,STRICTENC", "INVALID_ALTSTACK_OPERATION", "alt stack not shared between sig/pubkey"],
+
+["IFDUP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["DROP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["DUP", "DEPTH 0 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "DUP 1 ADD 2 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"],
+["NOP", "NIP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "1 NIP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "1 0 NIP", "P2SH,STRICTENC", "EVAL_FALSE"],
+["NOP", "OVER 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "OVER", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["0 1", "OVER DEPTH 3 EQUALVERIFY", "P2SH,STRICTENC", "EVAL_FALSE"],
+["19 20 21", "PICK 19 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "0 PICK", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "-1 PICK", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["19 20 21", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"],
+["19 20 21", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"],
+["19 20 21", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"],
+["NOP", "0 ROLL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "-1 ROLL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["19 20 21", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"],
+["19 20 21", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"],
+["19 20 21", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL", "P2SH,STRICTENC", "EQUALVERIFY"],
+["NOP", "ROT 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "1 ROT 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "1 2 ROT 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "0 1 2 ROT", "P2SH,STRICTENC", "EVAL_FALSE"],
+["NOP", "SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["0 1", "SWAP 1 EQUALVERIFY", "P2SH,STRICTENC", "EQUALVERIFY"],
+["NOP", "TUCK 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "TUCK 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1 0", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP", "P2SH,STRICTENC", "EVAL_FALSE"],
+["NOP", "2DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "2DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "3DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "3DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1 2", "3DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "2OVER 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "2 3 2OVER 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "2SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "2 3 2SWAP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+
+["'a' 'b'", "CAT", "P2SH,STRICTENC", "DISABLED_OPCODE", "CAT disabled"],
+["'a' 'b' 0", "IF CAT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "CAT disabled"],
+["'abc' 1 1", "SUBSTR", "P2SH,STRICTENC", "DISABLED_OPCODE", "SUBSTR disabled"],
+["'abc' 1 1 0", "IF SUBSTR ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "SUBSTR disabled"],
+["'abc' 2 0", "IF LEFT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "LEFT disabled"],
+["'abc' 2 0", "IF RIGHT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "RIGHT disabled"],
+
+["NOP", "SIZE 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+
+["'abc'", "IF INVERT ELSE 1 ENDIF", "P2SH,STRICTENC", "DISABLED_OPCODE", "INVERT disabled"],
+["1 2 0 IF AND ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "AND disabled"],
+["1 2 0 IF OR ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "OR disabled"],
+["1 2 0 IF XOR ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "XOR disabled"],
+["2 0 IF 2MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "2MUL disabled"],
+["2 0 IF 2DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "2DIV disabled"],
+["2 2 0 IF MUL ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "MUL disabled"],
+["2 2 0 IF DIV ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "DIV disabled"],
+["2 2 0 IF MOD ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "MOD disabled"],
+["2 2 0 IF LSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "LSHIFT disabled"],
+["2 2 0 IF RSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "DISABLED_OPCODE", "RSHIFT disabled"],
+
+["", "EQUAL NOT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "EQUAL must error when there are no stack items"],
+["0", "EQUAL NOT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "EQUAL must error when there are not 2 stack items"],
+["0 1","EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"],
+["1 1 ADD", "0 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"],
+["11 1 ADD 12 SUB", "11 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"],
+
+["2147483648 0 ADD", "NOP", "P2SH,STRICTENC", "UNKNOWN_ERROR", "arithmetic operands must be in range [-2^31...2^31] "],
+["-2147483648 0 ADD", "NOP", "P2SH,STRICTENC", "UNKNOWN_ERROR", "arithmetic operands must be in range [-2^31...2^31] "],
+["2147483647 DUP ADD", "4294967294 NUMEQUAL", "P2SH,STRICTENC", "UNKNOWN_ERROR", "NUMEQUAL must be in numeric range"],
+["'abcdef' NOT", "0 EQUAL", "P2SH,STRICTENC", "UNKNOWN_ERROR", "NOT is an arithmetic operand"],
+
+["2 DUP MUL", "4 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"],
+["2 DUP DIV", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"],
+["2 2MUL", "4 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"],
+["2 2DIV", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"],
+["7 3 MOD", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"],
+["2 2 LSHIFT", "8 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"],
+["2 1 RSHIFT", "1 EQUAL", "P2SH,STRICTENC", "DISABLED_OPCODE", "disabled"],
+
+["1", "NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"],
+["'NOP_1_to_10' NOP1 CHECKLOCKTIMEVERIFY CHECKSEQUENCEVERIFY NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL", "P2SH,STRICTENC", "EVAL_FALSE"],
+
+["Ensure 100% coverage of discouraged NOPS"],
+["1", "NOP1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
+["1", "NOP4", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
+["1", "NOP5", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
+["1", "NOP6", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
+["1", "NOP7", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
+["1", "NOP8", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
+["1", "NOP9", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
+["1", "NOP10", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS"],
+
+["NOP10", "1", "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in scriptSig"],
+
+["1 0x01 0xb9", "HASH160 0x14 0x15727299b05b45fdaf9ac9ecf7565cfe27c3e567 EQUAL",
+ "P2SH,DISCOURAGE_UPGRADABLE_NOPS", "DISCOURAGE_UPGRADABLE_NOPS", "Discouraged NOP10 in redeemScript"],
+
+["0x50","1", "P2SH,STRICTENC", "BAD_OPCODE", "opcode 0x50 is reserved"],
+["1", "IF 0xba ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE", "opcodes above MAX_OPCODE invalid if executed"],
+["1", "IF 0xbb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xbc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xbd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xbe ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xbf ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xc0 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xc1 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xc2 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xc3 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xc4 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xc5 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xc6 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xc7 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xc8 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xc9 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xca ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xcb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xcc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xcd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xce ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xcf ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xd0 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xd1 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xd2 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xd3 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xd4 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xd5 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xd6 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xd7 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xd8 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xd9 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xda ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xdb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xdc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xdd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xde ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xdf ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xe0 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xe1 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xe2 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xe3 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xe4 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xe5 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xe6 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xe7 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xe8 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xe9 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xea ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xeb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xec ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xed ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xee ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xef ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xf0 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xf1 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xf2 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xf3 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xf4 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xf5 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xf6 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xf7 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xf8 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xf9 ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xfa ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xfb ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xfc ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xfd ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xfe ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+["1", "IF 0xff ELSE 1 ENDIF", "P2SH,STRICTENC", "BAD_OPCODE"],
+
+["1 IF 1 ELSE", "0xff ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "invalid because scriptSig and scriptPubKey are processed separately"],
+
+["NOP", "RIPEMD160", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "SHA1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "SHA256", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "HASH160", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "HASH256", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+
+["NOP",
+"'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'",
+"P2SH,STRICTENC",
+"PUSH_SIZE",
+">520 byte push"],
+["0",
+"IF 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' ENDIF 1",
+"P2SH,STRICTENC",
+"PUSH_SIZE",
+">520 byte push in non-executed IF branch"],
+["1",
+"0x61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161",
+"P2SH,STRICTENC",
+"OP_COUNT",
+">201 opcodes executed. 0x61 is NOP"],
+["0",
+"IF 0x6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161 ENDIF 1",
+"P2SH,STRICTENC",
+"OP_COUNT",
+">201 opcodes including non-executed IF branch. 0x61 is NOP"],
+["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"1 2 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"P2SH,STRICTENC",
+"STACK_SIZE",
+">1,000 stack size (0x6f is 3DUP)"],
+["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"1 TOALTSTACK 2 TOALTSTACK 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
+"P2SH,STRICTENC",
+"STACK_SIZE",
+">1,000 stack+altstack size"],
+["NOP",
+"0 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f 2DUP 0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161",
+"P2SH,STRICTENC",
+"SCRIPT_SIZE",
+"10,001-byte scriptPubKey"],
+
+["NOP1","NOP10", "P2SH,STRICTENC", "EVAL_FALSE"],
+
+["1","VER", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VER is reserved"],
+["1","VERIF", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VERIF is reserved"],
+["1","VERNOTIF", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VERNOTIF is reserved"],
+["1","RESERVED", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED is reserved"],
+["1","RESERVED1", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED1 is reserved"],
+["1","RESERVED2", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED2 is reserved"],
+["1","0xba", "P2SH,STRICTENC", "BAD_OPCODE", "0xba == MAX_OPCODE + 1"],
+
+["2147483648", "1ADD 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"],
+["2147483648", "NEGATE 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers"],
+["-2147483648", "1ADD 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "Because we use a sign bit, -2147483648 is also 5 bytes"],
+["2147483647", "1ADD 1SUB 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers, even if the result is 4-bytes"],
+["2147483648", "1SUB 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do math on 5-byte integers, even if the result is 4-bytes"],
+
+["2147483648 1", "BOOLOR 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do BOOLOR on 5-byte integers (but we can still do IF etc)"],
+["2147483648 1", "BOOLAND 1", "P2SH,STRICTENC", "UNKNOWN_ERROR", "We cannot do BOOLAND on 5-byte integers"],
+
+["1", "1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "ENDIF without IF"],
+["1", "IF 1", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "IF without ENDIF"],
+["1 IF 1", "ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "IFs don't carry over"],
+
+["NOP", "IF 1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "The following tests check the if(stack.size() < N) tests in each opcode"],
+["NOP", "NOTIF 1 ENDIF", "P2SH,STRICTENC", "UNBALANCED_CONDITIONAL", "They are here to catch copy-and-paste errors"],
+["NOP", "VERIFY 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "Most of them are duplicated elsewhere,"],
+
+["NOP", "TOALTSTACK 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "but, hey, more is always better, right?"],
+["1", "FROMALTSTACK", "P2SH,STRICTENC", "INVALID_ALTSTACK_OPERATION"],
+["1", "2DROP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "2DUP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1 1", "3DUP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1 1 1", "2OVER", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1 1 1 1 1", "2ROT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1 1 1", "2SWAP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "IFDUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "DROP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "DUP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "NIP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "OVER", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1 1 1 3", "PICK", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["0", "PICK 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1 1 1 3", "ROLL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["0", "ROLL 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1 1", "ROT", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "SWAP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "TUCK", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+
+["NOP", "SIZE 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+
+["1", "EQUAL 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "EQUALVERIFY 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+
+["NOP", "1ADD 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "1SUB 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "NEGATE 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "ABS 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "NOT 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "0NOTEQUAL 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+
+["1", "ADD", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "SUB", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "BOOLAND", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "BOOLOR", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "NUMEQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "NUMEQUALVERIFY 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "NUMNOTEQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "LESSTHAN", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "GREATERTHAN", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "LESSTHANOREQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "GREATERTHANOREQUAL", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "MIN", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1", "MAX", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["1 1", "WITHIN", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+
+["NOP", "RIPEMD160 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "SHA1 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "SHA256 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "HASH160 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+["NOP", "HASH256 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
+
+["Increase CHECKSIG and CHECKMULTISIG negative test coverage"],
+["", "CHECKSIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKSIG must error when there are no stack items"],
+["0", "CHECKSIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKSIG must error when there are not 2 stack items"],
+["", "CHECKMULTISIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKMULTISIG must error when there are no stack items"],
+["", "-1 CHECKMULTISIG NOT", "STRICTENC", "PUBKEY_COUNT", "CHECKMULTISIG must error when the specified number of pubkeys is negative"],
+["", "1 CHECKMULTISIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKMULTISIG must error when there are not enough pubkeys on the stack"],
+["", "-1 0 CHECKMULTISIG NOT", "STRICTENC", "SIG_COUNT", "CHECKMULTISIG must error when the specified number of signatures is negative"],
+["", "1 'pk1' 1 CHECKMULTISIG NOT", "STRICTENC", "INVALID_STACK_OPERATION", "CHECKMULTISIG must error when there are not enough signatures on the stack"],
+["", "'dummy' 'sig1' 1 'pk1' 1 CHECKMULTISIG IF 1 ENDIF", "", "EVAL_FALSE", "CHECKMULTISIG must push false to stack when signature is invalid when NOT in strict enc mode"],
+
+["",
+"0 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG 0 0 CHECKMULTISIG",
+"P2SH,STRICTENC",
+"OP_COUNT",
+"202 CHECKMULTISIGS, fails due to 201 op limit"],
+
+["1",
+"0 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY 0 0 CHECKMULTISIGVERIFY",
+"P2SH,STRICTENC",
+"INVALID_STACK_OPERATION",
+""],
+
+["",
+"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIG",
+"P2SH,STRICTENC",
+"OP_COUNT",
+"Fails due to 201 script operation limit"],
+
+["1",
+"NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY 0 0 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 20 CHECKMULTISIGVERIFY",
+"P2SH,STRICTENC",
+"OP_COUNT",
+""],
+
+
+["0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21", "21 CHECKMULTISIG 1", "P2SH,STRICTENC", "PUBKEY_COUNT", "nPubKeys > 20"],
+["0 'sig' 1 0", "CHECKMULTISIG 1", "P2SH,STRICTENC", "SIG_COUNT", "nSigs > nPubKeys"],
+
+
+["NOP 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "SIG_PUSHONLY", "Tests for Script.IsPushOnly()"],
+["NOP1 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "P2SH,STRICTENC", "SIG_PUSHONLY"],
+
+["0 0x01 0x50", "HASH160 0x14 0xece424a6bb6ddf4db592c0faed60685047a361b1 EQUAL", "P2SH,STRICTENC", "BAD_OPCODE", "OP_RESERVED in P2SH should fail"],
+["0 0x01 VER", "HASH160 0x14 0x0f4d7845db968f2a81b530b6f3c1d6246d4c7e01 EQUAL", "P2SH,STRICTENC", "BAD_OPCODE", "OP_VER in P2SH should fail"],
+
+["0x00", "'00' EQUAL", "P2SH,STRICTENC", "EVAL_FALSE", "Basic OP_0 execution"],
+
+["MINIMALDATA enforcement for PUSHDATAs"],
+
+["0x4c 0x00", "DROP 1", "MINIMALDATA", "MINIMALDATA", "Empty vector minimally represented by OP_0"],
+["0x01 0x81", "DROP 1", "MINIMALDATA", "MINIMALDATA", "-1 minimally represented by OP_1NEGATE"],
+["0x01 0x01", "DROP 1", "MINIMALDATA", "MINIMALDATA", "1 to 16 minimally represented by OP_1 to OP_16"],
+["0x01 0x02", "DROP 1", "MINIMALDATA", "MINIMALDATA"],
+["0x01 0x03", "DROP 1", "MINIMALDATA", "MINIMALDATA"],
+["0x01 0x04", "DROP 1", "MINIMALDATA", "MINIMALDATA"],
+["0x01 0x05", "DROP 1", "MINIMALDATA", "MINIMALDATA"],
+["0x01 0x06", "DROP 1", "MINIMALDATA", "MINIMALDATA"],
+["0x01 0x07", "DROP 1", "MINIMALDATA", "MINIMALDATA"],
+["0x01 0x08", "DROP 1", "MINIMALDATA", "MINIMALDATA"],
+["0x01 0x09", "DROP 1", "MINIMALDATA", "MINIMALDATA"],
+["0x01 0x0a", "DROP 1", "MINIMALDATA", "MINIMALDATA"],
+["0x01 0x0b", "DROP 1", "MINIMALDATA", "MINIMALDATA"],
+["0x01 0x0c", "DROP 1", "MINIMALDATA", "MINIMALDATA"],
+["0x01 0x0d", "DROP 1", "MINIMALDATA", "MINIMALDATA"],
+["0x01 0x0e", "DROP 1", "MINIMALDATA", "MINIMALDATA"],
+["0x01 0x0f", "DROP 1", "MINIMALDATA", "MINIMALDATA"],
+["0x01 0x10", "DROP 1", "MINIMALDATA", "MINIMALDATA"],
+
+["0x4c 0x48 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA",
+ "MINIMALDATA",
+ "PUSHDATA1 of 72 bytes minimally represented by direct push"],
+
+["0x4d 0xFF00 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA",
+ "MINIMALDATA",
+ "PUSHDATA2 of 255 bytes minimally represented by PUSHDATA1"],
+
+["0x4e 0x00010000 0x11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA",
+ "MINIMALDATA",
+ "PUSHDATA4 of 256 bytes minimally represented by PUSHDATA2"],
+
+["MINIMALDATA enforcement for numeric arguments"],
+
+["0x01 0x00", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 0"],
+["0x02 0x0000", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 0"],
+["0x01 0x80", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "0x80 (negative zero) numequals 0"],
+["0x02 0x0080", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 0"],
+["0x02 0x0500", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 5"],
+["0x03 0x050000", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals 5"],
+["0x02 0x0580", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals -5"],
+["0x03 0x050080", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "numequals -5"],
+["0x03 0xff7f80", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "Minimal encoding is 0xffff"],
+["0x03 0xff7f00", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "Minimal encoding is 0xff7f"],
+["0x04 0xffff7f80", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "Minimal encoding is 0xffffff"],
+["0x04 0xffff7f00", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR", "Minimal encoding is 0xffff7f"],
+
+["Test every numeric-accepting opcode for correct handling of the numeric minimal encoding rule"],
+
+["1 0x02 0x0000", "PICK DROP", "MINIMALDATA", "UNKNOWN_ERROR"],
+["1 0x02 0x0000", "ROLL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0x02 0x0000", "1ADD DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0x02 0x0000", "1SUB DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0x02 0x0000", "NEGATE DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0x02 0x0000", "ABS DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0x02 0x0000", "NOT DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0x02 0x0000", "0NOTEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+
+["0 0x02 0x0000", "ADD DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0x02 0x0000 0", "ADD DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0 0x02 0x0000", "SUB DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0x02 0x0000 0", "SUB DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0 0x02 0x0000", "BOOLAND DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0x02 0x0000 0", "BOOLAND DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0 0x02 0x0000", "BOOLOR DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0x02 0x0000 0", "BOOLOR DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0 0x02 0x0000", "NUMEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0x02 0x0000 1", "NUMEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0 0x02 0x0000", "NUMEQUALVERIFY 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0x02 0x0000 0", "NUMEQUALVERIFY 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0 0x02 0x0000", "NUMNOTEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0x02 0x0000 0", "NUMNOTEQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0 0x02 0x0000", "LESSTHAN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0x02 0x0000 0", "LESSTHAN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0 0x02 0x0000", "GREATERTHAN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0x02 0x0000 0", "GREATERTHAN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0 0x02 0x0000", "LESSTHANOREQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0x02 0x0000 0", "LESSTHANOREQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0 0x02 0x0000", "GREATERTHANOREQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0x02 0x0000 0", "GREATERTHANOREQUAL DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0 0x02 0x0000", "MIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0x02 0x0000 0", "MIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0 0x02 0x0000", "MAX DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0x02 0x0000 0", "MAX DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+
+["0x02 0x0000 0 0", "WITHIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0 0x02 0x0000 0", "WITHIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0 0 0x02 0x0000", "WITHIN DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+
+["0 0 0x02 0x0000", "CHECKMULTISIG DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0 0x02 0x0000 0", "CHECKMULTISIG DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0 0x02 0x0000 0 1", "CHECKMULTISIG DROP 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0 0 0x02 0x0000", "CHECKMULTISIGVERIFY 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", "MINIMALDATA", "UNKNOWN_ERROR"],
+
+
+["Order of CHECKMULTISIG evaluation tests, inverted by swapping the order of"],
+["pubkeys/signatures so they fail due to the STRICTENC rules on validly encoded"],
+["signatures and pubkeys."],
+[
+ "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501",
+ "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0 2 CHECKMULTISIG NOT",
+ "STRICTENC",
+ "PUBKEYTYPE",
+ "2-of-2 CHECKMULTISIG NOT with the first pubkey invalid, and both signatures validly encoded."
+],
+[
+ "0 0x47 0x3044022044dc17b0887c161bb67ba9635bf758735bdde503e4b0a0987f587f14a4e1143d022009a215772d49a85dae40d8ca03955af26ad3978a0ff965faa12915e9586249a501 1",
+ "2 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 2 CHECKMULTISIG NOT",
+ "STRICTENC",
+ "SIG_DER",
+ "2-of-2 CHECKMULTISIG NOT with both pubkeys valid, but first signature invalid."
+],
+[
+ "0 0x47 0x304402205451ce65ad844dbb978b8bdedf5082e33b43cae8279c30f2c74d9e9ee49a94f802203fe95a7ccf74da7a232ee523ef4a53cb4d14bdd16289680cdb97a63819b8f42f01 0x46 0x304402205451ce65ad844dbb978b8bdedf5082e33b43cae8279c30f2c74d9e9ee49a94f802203fe95a7ccf74da7a232ee523ef4a53cb4d14bdd16289680cdb97a63819b8f42f",
+ "2 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 3 CHECKMULTISIG",
+ "P2SH,STRICTENC",
+ "SIG_DER",
+ "2-of-3 with one valid and one invalid signature due to parse error, nSigs > validSigs"
+],
+
+["Increase DERSIG test coverage"],
+["0x4a 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Overly long signature is incorrectly encoded for DERSIG"],
+["0x25 0x30220220000000000000000000000000000000000000000000000000000000000000000000", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Missing S is incorrectly encoded for DERSIG"],
+["0x27 0x3024021077777777777777777777777777777777020a7777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "S with invalid S length is incorrectly encoded for DERSIG"],
+["0x27 0x302403107777777777777777777777777777777702107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Non-integer R is incorrectly encoded for DERSIG"],
+["0x27 0x302402107777777777777777777777777777777703107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Non-integer S is incorrectly encoded for DERSIG"],
+["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Zero-length R is incorrectly encoded for DERSIG"],
+["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Zero-length S is incorrectly encoded for DERSIG"],
+["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Negative S is incorrectly encoded for DERSIG"],
+
+["Some basic segwit checks"],
+[["00", 0.00000000 ], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "P2SH,WITNESS", "EVAL_FALSE", "Invalid witness script"],
+[["51", 0.00000000 ], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "P2SH,WITNESS", "WITNESS_PROGRAM_MISMATCH", "Witness script hash mismatch"],
+[["00", 0.00000000 ], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "", "OK", "Invalid witness script without WITNESS"],
+[["51", 0.00000000 ], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "", "OK", "Witness script hash mismatch without WITNESS"],
+
+["Automatically generated test cases"],
+[
+ "0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001",
+ "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
+ "",
+ "OK",
+ "P2PK"
+],
+[
+ "0x47 0x304402200a5c6163f07b8c3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001",
+ "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
+ "",
+ "EVAL_FALSE",
+ "P2PK, bad sig"
+],
+[
+ "0x47 0x304402206e05a6fe23c59196ffe176c9ddc31e73a9885638f9d1328d47c0c703863b8876022076feb53811aa5b04e0e79f938eb19906cc5e67548bc555a8e8b8b0fc603d840c01 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508",
+ "DUP HASH160 0x14 0x1018853670f9f3b0582c5b9ee8ce93764ac32b93 EQUALVERIFY CHECKSIG",
+ "",
+ "OK",
+ "P2PKH"
+],
+[
+ "0x47 0x3044022034bb0494b50b8ef130e2185bb220265b9284ef5b4b8a8da4d8415df489c83b5102206259a26d9cc0a125ac26af6153b17c02956855ebe1467412f066e402f5f05d1201 0x21 0x03363d90d446b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640",
+ "DUP HASH160 0x14 0xc0834c0c158f53be706d234c38fd52de7eece656 EQUALVERIFY CHECKSIG",
+ "",
+ "EQUALVERIFY",
+ "P2PKH, bad pubkey"
+],
+[
+ "0x47 0x304402204710a85181663b32d25c70ec2bbd14adff5ddfff6cb50d09e155ef5f541fc86c0220056b0cc949be9386ecc5f6c2ac0493269031dbb185781db90171b54ac127790281",
+ "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
+ "",
+ "OK",
+ "P2PK anyonecanpay"
+],
+[
+ "0x47 0x304402204710a85181663b32d25c70ec2bbd14adff5ddfff6cb50d09e155ef5f541fc86c0220056b0cc949be9386ecc5f6c2ac0493269031dbb185781db90171b54ac127790201",
+ "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
+ "",
+ "EVAL_FALSE",
+ "P2PK anyonecanpay marked with normal hashtype"
+],
+[
+ "0x47 0x3044022003fef42ed6c7be8917441218f525a60e2431be978e28b7aca4d7a532cc413ae8022067a1f82c74e8d69291b90d148778405c6257bbcfc2353cc38a3e1f22bf44254601 0x23 0x210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac",
+ "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL",
+ "P2SH",
+ "OK",
+ "P2SH(P2PK)"
+],
+[
+ "0x47 0x3044022003fef42ed6c7be8917441218f525a60e2431be978e28b7aca4d7a532cc413ae8022067a1f82c74e8d69291b90d148778405c6257bbcfc2353cc38a3e1f22bf44254601 0x23 0x210279be667ef9dcbbac54a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac",
+ "HASH160 0x14 0x23b0ad3477f2178bc0b3eed26e4e6316f4e83aa1 EQUAL",
+ "P2SH",
+ "EVAL_FALSE",
+ "P2SH(P2PK), bad redeemscript"
+],
+[
+ "0x47 0x30440220781ba4f59a7b207a10db87628bc2168df4d59b844b397d2dbc9a5835fb2f2b7602206ed8fbcc1072fe2dfc5bb25909269e5dc42ffcae7ec2bc81d59692210ff30c2b01 0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x19 0x76a91491b24bf9f5288532960ac687abb035127b1d28a588ac",
+ "HASH160 0x14 0x7f67f0521934a57d3039f77f9f32cf313f3ac74b EQUAL",
+ "P2SH",
+ "OK",
+ "P2SH(P2PKH)"
+],
+[
+ "0x47 0x304402204e2eb034be7b089534ac9e798cf6a2c79f38bcb34d1b179efd6f2de0841735db022071461beb056b5a7be1819da6a3e3ce3662831ecc298419ca101eb6887b5dd6a401 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac",
+ "HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL",
+ "",
+ "OK",
+ "P2SH(P2PKH), bad sig but no VERIFY_P2SH"
+],
+[
+ "0x47 0x304402204e2eb034be7b089534ac9e798cf6a2c79f38bcb34d1b179efd6f2de0841735db022071461beb056b5a7be1819da6a3e3ce3662831ecc298419ca101eb6887b5dd6a401 0x19 0x76a9147cf9c846cd4882efec4bf07e44ebdad495c94f4b88ac",
+ "HASH160 0x14 0x2df519943d5acc0ef5222091f9dfe3543f489a82 EQUAL",
+ "P2SH",
+ "EQUALVERIFY",
+ "P2SH(P2PKH), bad sig"
+],
+[
+ "0 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901",
+ "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
+ "",
+ "OK",
+ "3-of-3"
+],
+[
+ "0 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0",
+ "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
+ "",
+ "EVAL_FALSE",
+ "3-of-3, 2 sigs"
+],
+[
+ "0 0x47 0x304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001 0x47 0x30440220563e5b3b1fc11662a84bc5ea2a32cc3819703254060ba30d639a1aaf2d5068ad0220601c1f47ddc76d93284dd9ed68f7c9974c4a0ea7cbe8a247d6bc3878567a5fca01 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae",
+ "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL",
+ "P2SH",
+ "OK",
+ "P2SH(2-of-3)"
+],
+[
+ "0 0x47 0x304402205b7d2c2f177ae76cfbbf14d589c113b0b35db753d305d5562dd0b61cbf366cfb02202e56f93c4f08a27f986cd424ffc48a462c3202c4902104d4d0ff98ed28f4bf8001 0 0x4c69 0x52210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179821038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f515082103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff464053ae",
+ "HASH160 0x14 0xc9e4a896d149702d0d1695434feddd52e24ad78d EQUAL",
+ "P2SH",
+ "EVAL_FALSE",
+ "P2SH(2-of-3), 1 sig"
+],
+[
+ "0x47 0x304402200060558477337b9022e70534f1fea71a318caf836812465a2509931c5e7c4987022078ec32bd50ac9e03a349ba953dfd9fe1c8d2dd8bdb1d38ddca844d3d5c78c11801",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "",
+ "OK",
+ "P2PK with too much R padding but no DERSIG"
+],
+[
+ "0x47 0x304402200060558477337b9022e70534f1fea71a318caf836812465a2509931c5e7c4987022078ec32bd50ac9e03a349ba953dfd9fe1c8d2dd8bdb1d38ddca844d3d5c78c11801",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "DERSIG",
+ "SIG_DER",
+ "P2PK with too much R padding"
+],
+[
+ "0x48 0x304502202de8c03fc525285c9c535631019a5f2af7c6454fa9eb392a3756a4917c420edd02210046130bf2baf7cfc065067c8b9e33a066d9c15edcea9feb0ca2d233e3597925b401",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "",
+ "OK",
+ "P2PK with too much S padding but no DERSIG"
+],
+[
+ "0x48 0x304502202de8c03fc525285c9c535631019a5f2af7c6454fa9eb392a3756a4917c420edd02210046130bf2baf7cfc065067c8b9e33a066d9c15edcea9feb0ca2d233e3597925b401",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "DERSIG",
+ "SIG_DER",
+ "P2PK with too much S padding"
+],
+[
+ "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "",
+ "OK",
+ "P2PK with too little R padding but no DERSIG"
+],
+[
+ "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "DERSIG",
+ "SIG_DER",
+ "P2PK with too little R padding"
+],
+[
+ "0x47 0x30440220005ece1335e7f757a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601",
+ "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
+ "",
+ "OK",
+ "P2PK NOT with bad sig with too much R padding but no DERSIG"
+],
+[
+ "0x47 0x30440220005ece1335e7f757a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601",
+ "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
+ "DERSIG",
+ "SIG_DER",
+ "P2PK NOT with bad sig with too much R padding"
+],
+[
+ "0x47 0x30440220005ece1335e7f657a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601",
+ "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
+ "",
+ "EVAL_FALSE",
+ "P2PK NOT with too much R padding but no DERSIG"
+],
+[
+ "0x47 0x30440220005ece1335e7f657a1a1f476a7fb5bd90964e8a022489f890614a04acfb734c002206c12b8294a6513c7710e8c82d3c23d75cdbfe83200eb7efb495701958501a5d601",
+ "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG NOT",
+ "DERSIG",
+ "SIG_DER",
+ "P2PK NOT with too much R padding"
+],
+[
+ "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "",
+ "OK",
+ "BIP66 example 1, without DERSIG"
+],
+[
+ "0x47 0x30440220d7a0417c3f6d1a15094d1cf2a3378ca0503eb8a57630953a9e2987e21ddd0a6502207a6266d686c99090920249991d3d42065b6d43eb70187b219c0db82e4f94d1a201",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "DERSIG",
+ "SIG_DER",
+ "BIP66 example 1, with DERSIG"
+],
+[
+ "0x47 0x304402208e43c0b91f7c1e5bc58e41c8185f8a6086e111b0090187968a86f2822462d3c902200a58f4076b1133b18ff1dc83ee51676e44c60cc608d9534e0df5ace0424fc0be01",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+ "",
+ "EVAL_FALSE",
+ "BIP66 example 2, without DERSIG"
+],
+[
+ "0x47 0x304402208e43c0b91f7c1e5bc58e41c8185f8a6086e111b0090187968a86f2822462d3c902200a58f4076b1133b18ff1dc83ee51676e44c60cc608d9534e0df5ace0424fc0be01",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+ "DERSIG",
+ "SIG_DER",
+ "BIP66 example 2, with DERSIG"
+],
+[
+ "0",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "",
+ "EVAL_FALSE",
+ "BIP66 example 3, without DERSIG"
+],
+[
+ "0",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "DERSIG",
+ "EVAL_FALSE",
+ "BIP66 example 3, with DERSIG"
+],
+[
+ "0",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+ "",
+ "OK",
+ "BIP66 example 4, without DERSIG"
+],
+[
+ "0",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+ "DERSIG",
+ "OK",
+ "BIP66 example 4, with DERSIG"
+],
+[
+ "0x09 0x300602010102010101",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+ "DERSIG",
+ "OK",
+ "BIP66 example 4, with DERSIG, non-null DER-compliant signature"
+],
+[
+ "0",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+ "DERSIG,NULLFAIL",
+ "OK",
+ "BIP66 example 4, with DERSIG and NULLFAIL"
+],
+[
+ "0x09 0x300602010102010101",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+ "DERSIG,NULLFAIL",
+ "NULLFAIL",
+ "BIP66 example 4, with DERSIG and NULLFAIL, non-null DER-compliant signature"
+],
+[
+ "1",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "",
+ "EVAL_FALSE",
+ "BIP66 example 5, without DERSIG"
+],
+[
+ "1",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG",
+ "DERSIG",
+ "SIG_DER",
+ "BIP66 example 5, with DERSIG"
+],
+[
+ "1",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+ "",
+ "OK",
+ "BIP66 example 6, without DERSIG"
+],
+[
+ "1",
+ "0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 CHECKSIG NOT",
+ "DERSIG",
+ "SIG_DER",
+ "BIP66 example 6, with DERSIG"
+],
+[
+ "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0x47 0x3044022027c2714269ca5aeecc4d70edc88ba5ee0e3da4986e9216028f489ab4f1b8efce022022bd545b4951215267e4c5ceabd4c5350331b2e4a0b6494c56f361fa5a57a1a201",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
+ "",
+ "OK",
+ "BIP66 example 7, without DERSIG"
+],
+[
+ "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0x47 0x3044022027c2714269ca5aeecc4d70edc88ba5ee0e3da4986e9216028f489ab4f1b8efce022022bd545b4951215267e4c5ceabd4c5350331b2e4a0b6494c56f361fa5a57a1a201",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
+ "DERSIG",
+ "SIG_DER",
+ "BIP66 example 7, with DERSIG"
+],
+[
+ "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0x47 0x3044022079ea80afd538d9ada421b5101febeb6bc874e01dde5bca108c1d0479aec339a4022004576db8f66130d1df686ccf00935703689d69cf539438da1edab208b0d63c4801",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
+ "",
+ "EVAL_FALSE",
+ "BIP66 example 8, without DERSIG"
+],
+[
+ "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0x47 0x3044022079ea80afd538d9ada421b5101febeb6bc874e01dde5bca108c1d0479aec339a4022004576db8f66130d1df686ccf00935703689d69cf539438da1edab208b0d63c4801",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
+ "DERSIG",
+ "SIG_DER",
+ "BIP66 example 8, with DERSIG"
+],
+[
+ "0 0 0x47 0x3044022081aa9d436f2154e8b6d600516db03d78de71df685b585a9807ead4210bd883490220534bb6bdf318a419ac0749660b60e78d17d515558ef369bf872eff405b676b2e01",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
+ "",
+ "EVAL_FALSE",
+ "BIP66 example 9, without DERSIG"
+],
+[
+ "0 0 0x47 0x3044022081aa9d436f2154e8b6d600516db03d78de71df685b585a9807ead4210bd883490220534bb6bdf318a419ac0749660b60e78d17d515558ef369bf872eff405b676b2e01",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
+ "DERSIG",
+ "SIG_DER",
+ "BIP66 example 9, with DERSIG"
+],
+[
+ "0 0 0x47 0x30440220da6f441dc3b4b2c84cfa8db0cd5b34ed92c9e01686de5a800d40498b70c0dcac02207c2cf91b0c32b860c4cd4994be36cfb84caf8bb7c3a8e4d96a31b2022c5299c501",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
+ "",
+ "OK",
+ "BIP66 example 10, without DERSIG"
+],
+[
+ "0 0 0x47 0x30440220da6f441dc3b4b2c84cfa8db0cd5b34ed92c9e01686de5a800d40498b70c0dcac02207c2cf91b0c32b860c4cd4994be36cfb84caf8bb7c3a8e4d96a31b2022c5299c501",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
+ "DERSIG",
+ "SIG_DER",
+ "BIP66 example 10, with DERSIG"
+],
+[
+ "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
+ "",
+ "EVAL_FALSE",
+ "BIP66 example 11, without DERSIG"
+],
+[
+ "0 0x47 0x30440220cae00b1444babfbf6071b0ba8707f6bd373da3df494d6e74119b0430c5db810502205d5231b8c5939c8ff0c82242656d6e06edb073d42af336c99fe8837c36ea39d501 0",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG",
+ "DERSIG",
+ "EVAL_FALSE",
+ "BIP66 example 11, with DERSIG"
+],
+[
+ "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
+ "",
+ "OK",
+ "BIP66 example 12, without DERSIG"
+],
+[
+ "0 0x47 0x30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201 0",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 2 CHECKMULTISIG NOT",
+ "DERSIG",
+ "OK",
+ "BIP66 example 12, with DERSIG"
+],
+[
+ "0x48 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb12510101",
+ "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
+ "",
+ "OK",
+ "P2PK with multi-byte hashtype, without DERSIG"
+],
+[
+ "0x48 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb12510101",
+ "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
+ "DERSIG",
+ "SIG_DER",
+ "P2PK with multi-byte hashtype, with DERSIG"
+],
+[
+ "0x48 0x304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef001",
+ "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
+ "",
+ "OK",
+ "P2PK with high S but no LOW_S"
+],
+[
+ "0x48 0x304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef001",
+ "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
+ "LOW_S",
+ "SIG_HIGH_S",
+ "P2PK with high S"
+],
+[
+ "0x47 0x3044022057292e2d4dfe775becdd0a9e6547997c728cdf35390f6a017da56d654d374e4902206b643be2fc53763b4e284845bfea2c597d2dc7759941dce937636c9d341b71ed01",
+ "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
+ "",
+ "OK",
+ "P2PK with hybrid pubkey but no STRICTENC"
+],
+[
+ "0x47 0x3044022057292e2d4dfe775becdd0a9e6547997c728cdf35390f6a017da56d654d374e4902206b643be2fc53763b4e284845bfea2c597d2dc7759941dce937636c9d341b71ed01",
+ "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
+ "STRICTENC",
+ "PUBKEYTYPE",
+ "P2PK with hybrid pubkey"
+],
+[
+ "0x47 0x30440220035d554e3153c14950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101",
+ "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
+ "",
+ "EVAL_FALSE",
+ "P2PK NOT with hybrid pubkey but no STRICTENC"
+],
+[
+ "0x47 0x30440220035d554e3153c14950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101",
+ "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
+ "STRICTENC",
+ "PUBKEYTYPE",
+ "P2PK NOT with hybrid pubkey"
+],
+[
+ "0x47 0x30440220035d554e3153c04950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101",
+ "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
+ "",
+ "OK",
+ "P2PK NOT with invalid hybrid pubkey but no STRICTENC"
+],
+[
+ "0x47 0x30440220035d554e3153c04950c9993f41c496607a8e24093db0595be7bf875cf64fcf1f02204731c8c4e5daf15e706cec19cdd8f2c5b1d05490e11dab8465ed426569b6e92101",
+ "0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG NOT",
+ "STRICTENC",
+ "PUBKEYTYPE",
+ "P2PK NOT with invalid hybrid pubkey"
+],
+[
+ "0 0x47 0x304402202e79441ad1baf5a07fb86bae3753184f6717d9692680947ea8b6e8b777c69af1022079a262e13d868bb5a0964fefe3ba26942e1b0669af1afb55ef3344bc9d4fc4c401",
+ "1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
+ "",
+ "OK",
+ "1-of-2 with the second 1 hybrid pubkey and no STRICTENC"
+],
+[
+ "0 0x47 0x304402202e79441ad1baf5a07fb86bae3753184f6717d9692680947ea8b6e8b777c69af1022079a262e13d868bb5a0964fefe3ba26942e1b0669af1afb55ef3344bc9d4fc4c401",
+ "1 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
+ "STRICTENC",
+ "OK",
+ "1-of-2 with the second 1 hybrid pubkey"
+],
+[
+ "0 0x47 0x3044022079c7824d6c868e0e1a273484e28c2654a27d043c8a27f49f52cb72efed0759090220452bbbf7089574fa082095a4fc1b3a16bafcf97a3a34d745fafc922cce66b27201",
+ "1 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x41 0x0679be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 2 CHECKMULTISIG",
+ "STRICTENC",
+ "PUBKEYTYPE",
+ "1-of-2 with the first 1 hybrid pubkey"
+],
+[
+ "0x47 0x304402206177d513ec2cda444c021a1f4f656fc4c72ba108ae063e157eb86dc3575784940220666fc66702815d0e5413bb9b1df22aed44f5f1efb8b99d41dd5dc9a5be6d205205",
+ "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
+ "",
+ "OK",
+ "P2PK with undefined hashtype but no STRICTENC"
+],
+[
+ "0x47 0x304402206177d513ec2cda444c021a1f4f656fc4c72ba108ae063e157eb86dc3575784940220666fc66702815d0e5413bb9b1df22aed44f5f1efb8b99d41dd5dc9a5be6d205205",
+ "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG",
+ "STRICTENC",
+ "SIG_HASHTYPE",
+ "P2PK with undefined hashtype"
+],
+[
+ "0x47 0x304402207409b5b320296e5e2136a7b281a7f803028ca4ca44e2b83eebd46932677725de02202d4eea1c8d3c98e6f42614f54764e6e5e6542e213eb4d079737e9a8b6e9812ec05",
+ "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT",
+ "",
+ "OK",
+ "P2PK NOT with invalid sig and undefined hashtype but no STRICTENC"
+],
+[
+ "0x47 0x304402207409b5b320296e5e2136a7b281a7f803028ca4ca44e2b83eebd46932677725de02202d4eea1c8d3c98e6f42614f54764e6e5e6542e213eb4d079737e9a8b6e9812ec05",
+ "0x41 0x048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf CHECKSIG NOT",
+ "STRICTENC",
+ "SIG_HASHTYPE",
+ "P2PK NOT with invalid sig and undefined hashtype"
+],
+[
+ "1 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901",
+ "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
+ "",
+ "OK",
+ "3-of-3 with nonzero dummy but no NULLDUMMY"
+],
+[
+ "1 0x47 0x3044022051254b9fb476a52d85530792b578f86fea70ec1ffb4393e661bcccb23d8d63d3022076505f94a403c86097841944e044c70c2045ce90e36de51f7e9d3828db98a07501 0x47 0x304402200a358f750934b3feb822f1966bfcd8bbec9eeaa3a8ca941e11ee5960e181fa01022050bf6b5a8e7750f70354ae041cb68a7bade67ec6c3ab19eb359638974410626e01 0x47 0x304402200955d031fff71d8653221e85e36c3c85533d2312fc3045314b19650b7ae2f81002202a6bb8505e36201909d0921f01abff390ae6b7ff97bbf959f98aedeb0a56730901",
+ "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG",
+ "NULLDUMMY",
+ "SIG_NULLDUMMY",
+ "3-of-3 with nonzero dummy"
+],
+[
+ "1 0x47 0x304402201bb2edab700a5d020236df174fefed78087697143731f659bea59642c759c16d022061f42cdbae5bcd3e8790f20bf76687443436e94a634321c16a72aa54cbc7c2ea01 0x47 0x304402204bb4a64f2a6e5c7fb2f07fef85ee56fde5e6da234c6a984262307a20e99842d702206f8303aaba5e625d223897e2ffd3f88ef1bcffef55f38dc3768e5f2e94c923f901 0x47 0x3044022040c2809b71fffb155ec8b82fe7a27f666bd97f941207be4e14ade85a1249dd4d02204d56c85ec525dd18e29a0533d5ddf61b6b1bb32980c2f63edf951aebf7a27bfe01",
+ "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT",
+ "",
+ "OK",
+ "3-of-3 NOT with invalid sig and nonzero dummy but no NULLDUMMY"
+],
+[
+ "1 0x47 0x304402201bb2edab700a5d020236df174fefed78087697143731f659bea59642c759c16d022061f42cdbae5bcd3e8790f20bf76687443436e94a634321c16a72aa54cbc7c2ea01 0x47 0x304402204bb4a64f2a6e5c7fb2f07fef85ee56fde5e6da234c6a984262307a20e99842d702206f8303aaba5e625d223897e2ffd3f88ef1bcffef55f38dc3768e5f2e94c923f901 0x47 0x3044022040c2809b71fffb155ec8b82fe7a27f666bd97f941207be4e14ade85a1249dd4d02204d56c85ec525dd18e29a0533d5ddf61b6b1bb32980c2f63edf951aebf7a27bfe01",
+ "3 0x21 0x0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 3 CHECKMULTISIG NOT",
+ "NULLDUMMY",
+ "SIG_NULLDUMMY",
+ "3-of-3 NOT with invalid sig with nonzero dummy"
+],
+[
+ "0 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901 DUP",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
+ "",
+ "OK",
+ "2-of-2 with two identical keys and sigs pushed using OP_DUP but no SIGPUSHONLY"
+],
+[
+ "0 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901 DUP",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
+ "SIGPUSHONLY",
+ "SIG_PUSHONLY",
+ "2-of-2 with two identical keys and sigs pushed using OP_DUP"
+],
+[
+ "0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac",
+ "HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL",
+ "",
+ "OK",
+ "P2SH(P2PK) with non-push scriptSig but no P2SH or SIGPUSHONLY"
+],
+[
+ "0x47 0x304402203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022054e1c258c2981cdfba5df1f46661fb6541c44f77ca0092f3600331abfffb125101 NOP8",
+ "0x21 0x03363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640 CHECKSIG",
+ "",
+ "OK",
+ "P2PK with non-push scriptSig but with P2SH validation"
+],
+[
+ "0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac",
+ "HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL",
+ "P2SH",
+ "SIG_PUSHONLY",
+ "P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY"
+],
+[
+ "0x47 0x3044022018a2a81a93add5cb5f5da76305718e4ea66045ec4888b28d84cb22fae7f4645b02201e6daa5ed5d2e4b2b2027cf7ffd43d8d9844dd49f74ef86899ec8e669dfd39aa01 NOP8 0x23 0x2103363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640ac",
+ "HASH160 0x14 0x215640c2f72f0d16b4eced26762035a42ffed39a EQUAL",
+ "SIGPUSHONLY",
+ "SIG_PUSHONLY",
+ "P2SH(P2PK) with non-push scriptSig but not P2SH"
+],
+[
+ "0 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901 0x47 0x304402200abeb4bd07f84222f474aed558cfbdfc0b4e96cde3c2935ba7098b1ff0bd74c302204a04c1ca67b2a20abee210cf9a21023edccbbf8024b988812634233115c6b73901",
+ "2 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 0x21 0x038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508 2 CHECKMULTISIG",
+ "SIGPUSHONLY",
+ "OK",
+ "2-of-2 with two identical keys and sigs pushed"
+],
+[
+ "11 0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001",
+ "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
+ "P2SH",
+ "OK",
+ "P2PK with unnecessary input but no CLEANSTACK"
+],
+[
+ "11 0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001",
+ "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
+ "CLEANSTACK,P2SH",
+ "CLEANSTACK",
+ "P2PK with unnecessary input"
+],
+[
+ "11 0x47 0x304402202f7505132be14872581f35d74b759212d9da40482653f1ffa3116c3294a4a51702206adbf347a2240ca41c66522b1a22a41693610b76a8e7770645dc721d1635854f01 0x43 0x410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
+ "HASH160 0x14 0x31edc23bdafda4639e669f89ad6b2318dd79d032 EQUAL",
+ "P2SH",
+ "OK",
+ "P2SH with unnecessary input but no CLEANSTACK"
+],
+[
+ "11 0x47 0x304402202f7505132be14872581f35d74b759212d9da40482653f1ffa3116c3294a4a51702206adbf347a2240ca41c66522b1a22a41693610b76a8e7770645dc721d1635854f01 0x43 0x410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
+ "HASH160 0x14 0x31edc23bdafda4639e669f89ad6b2318dd79d032 EQUAL",
+ "CLEANSTACK,P2SH",
+ "CLEANSTACK",
+ "P2SH with unnecessary input"
+],
+[
+ "0x47 0x304402202f7505132be14872581f35d74b759212d9da40482653f1ffa3116c3294a4a51702206adbf347a2240ca41c66522b1a22a41693610b76a8e7770645dc721d1635854f01 0x43 0x410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
+ "HASH160 0x14 0x31edc23bdafda4639e669f89ad6b2318dd79d032 EQUAL",
+ "CLEANSTACK,P2SH",
+ "OK",
+ "P2SH with CLEANSTACK"
+],
+
+["Testing with uncompressed keys in witness v0 without WITNESS_PUBKEYTYPE"],
+[
+ [
+ "304402200d461c140cfdfcf36b94961db57ae8c18d1cb80e9d95a9e47ac22470c1bf125502201c8dc1cbfef6a3ef90acbbb992ca22fe9466ee6f9d4898eda277a7ac3ab4b25101",
+ "410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0xb95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64",
+ "P2SH,WITNESS",
+ "OK",
+ "Basic P2WSH"
+],
+[
+ [
+ "304402201e7216e5ccb3b61d46946ec6cc7e8c4e0117d13ac2fd4b152197e4805191c74202203e9903e33e84d9ee1dd13fb057afb7ccfb47006c23f6a067185efbc9dd780fc501",
+ "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
+ 0.00000001
+ ],
+ "",
+ "0 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5",
+ "P2SH,WITNESS",
+ "OK",
+ "Basic P2WPKH"
+],
+[
+ [
+ "3044022066e02c19a513049d49349cf5311a1b012b7c4fae023795a18ab1d91c23496c22022025e216342c8e07ce8ef51e8daee88f84306a9de66236cab230bb63067ded1ad301",
+ "410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
+ 0.00000001
+ ],
+ "0x22 0x0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64",
+ "HASH160 0x14 0xf386c2ba255cc56d20cfa6ea8b062f8b59945518 EQUAL",
+ "P2SH,WITNESS",
+ "OK",
+ "Basic P2SH(P2WSH)"
+],
+[
+ [
+ "304402200929d11561cd958460371200f82e9cae64c727a495715a31828e27a7ad57b36d0220361732ced04a6f97351ecca21a56d0b8cd4932c1da1f8f569a2b68e5e48aed7801",
+ "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
+ 0.00000001
+ ],
+ "0x16 0x001491b24bf9f5288532960ac687abb035127b1d28a5",
+ "HASH160 0x14 0x17743beb429c55c942d2ec703b98c4d57c2df5c6 EQUAL",
+ "P2SH,WITNESS",
+ "OK",
+ "Basic P2SH(P2WPKH)"
+],
+[
+ [
+ "304402202589f0512cb2408fb08ed9bd24f85eb3059744d9e4f2262d0b7f1338cff6e8b902206c0978f449693e0578c71bc543b11079fd0baae700ee5e9a6bee94db490af9fc01",
+ "41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac",
+ 0.00000000
+ ],
+ "",
+ "0 0x20 0xac8ebd9e52c17619a381fa4f71aebb696087c6ef17c960fd0587addad99c0610",
+ "P2SH,WITNESS",
+ "EVAL_FALSE",
+ "Basic P2WSH with the wrong key"
+],
+[
+ [
+ "304402206ef7fdb2986325d37c6eb1a8bb24aeb46dede112ed8fc76c7d7500b9b83c0d3d02201edc2322c794fe2d6b0bd73ed319e714aa9b86d8891961530d5c9b7156b60d4e01",
+ "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf",
+ 0.00000000
+ ],
+ "",
+ "0 0x14 0x7cf9c846cd4882efec4bf07e44ebdad495c94f4b",
+ "P2SH,WITNESS",
+ "EVAL_FALSE",
+ "Basic P2WPKH with the wrong key"
+],
+[
+ [
+ "30440220069ea3581afaf8187f63feee1fd2bd1f9c0dc71ea7d6e8a8b07ee2ebcf824bf402201a4fdef4c532eae59223be1eda6a397fc835142d4ddc6c74f4aa85b766a5c16f01",
+ "41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac",
+ 0.00000000
+ ],
+ "0x22 0x0020ac8ebd9e52c17619a381fa4f71aebb696087c6ef17c960fd0587addad99c0610",
+ "HASH160 0x14 0x61039a003883787c0d6ebc66d97fdabe8e31449d EQUAL",
+ "P2SH,WITNESS",
+ "EVAL_FALSE",
+ "Basic P2SH(P2WSH) with the wrong key"
+],
+[
+ [
+ "304402204209e49457c2358f80d0256bc24535b8754c14d08840fc4be762d6f5a0aed80b02202eaf7d8fc8d62f60c67adcd99295528d0e491ae93c195cec5a67e7a09532a88001",
+ "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf",
+ 0.00000000
+ ],
+ "0x16 0x00147cf9c846cd4882efec4bf07e44ebdad495c94f4b",
+ "HASH160 0x14 0x4e0c2aed91315303fc6a1dc4c7bc21c88f75402e EQUAL",
+ "P2SH,WITNESS",
+ "EVAL_FALSE",
+ "Basic P2SH(P2WPKH) with the wrong key"
+],
+[
+ [
+ "304402202589f0512cb2408fb08ed9bd24f85eb3059744d9e4f2262d0b7f1338cff6e8b902206c0978f449693e0578c71bc543b11079fd0baae700ee5e9a6bee94db490af9fc01",
+ "41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac",
+ 0.00000000
+ ],
+ "",
+ "0 0x20 0xac8ebd9e52c17619a381fa4f71aebb696087c6ef17c960fd0587addad99c0610",
+ "P2SH",
+ "OK",
+ "Basic P2WSH with the wrong key but no WITNESS"
+],
+[
+ [
+ "304402206ef7fdb2986325d37c6eb1a8bb24aeb46dede112ed8fc76c7d7500b9b83c0d3d02201edc2322c794fe2d6b0bd73ed319e714aa9b86d8891961530d5c9b7156b60d4e01",
+ "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf",
+ 0.00000000
+ ],
+ "",
+ "0 0x14 0x7cf9c846cd4882efec4bf07e44ebdad495c94f4b",
+ "P2SH",
+ "OK",
+ "Basic P2WPKH with the wrong key but no WITNESS"
+],
+[
+ [
+ "30440220069ea3581afaf8187f63feee1fd2bd1f9c0dc71ea7d6e8a8b07ee2ebcf824bf402201a4fdef4c532eae59223be1eda6a397fc835142d4ddc6c74f4aa85b766a5c16f01",
+ "41048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26cafac",
+ 0.00000000
+ ],
+ "0x22 0x0020ac8ebd9e52c17619a381fa4f71aebb696087c6ef17c960fd0587addad99c0610",
+ "HASH160 0x14 0x61039a003883787c0d6ebc66d97fdabe8e31449d EQUAL",
+ "P2SH",
+ "OK",
+ "Basic P2SH(P2WSH) with the wrong key but no WITNESS"
+],
+[
+ [
+ "304402204209e49457c2358f80d0256bc24535b8754c14d08840fc4be762d6f5a0aed80b02202eaf7d8fc8d62f60c67adcd99295528d0e491ae93c195cec5a67e7a09532a88001",
+ "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf",
+ 0.00000000
+ ],
+ "0x16 0x00147cf9c846cd4882efec4bf07e44ebdad495c94f4b",
+ "HASH160 0x14 0x4e0c2aed91315303fc6a1dc4c7bc21c88f75402e EQUAL",
+ "P2SH",
+ "OK",
+ "Basic P2SH(P2WPKH) with the wrong key but no WITNESS"
+],
+[
+ [
+ "3044022066faa86e74e8b30e82691b985b373de4f9e26dc144ec399c4f066aa59308e7c202204712b86f28c32503faa051dbeabff2c238ece861abc36c5e0b40b1139ca222f001",
+ "410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
+ 0.00000000
+ ],
+ "",
+ "0 0x20 0xb95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64",
+ "P2SH,WITNESS",
+ "EVAL_FALSE",
+ "Basic P2WSH with wrong value"
+],
+[
+ [
+ "304402203b3389b87448d7dfdb5e82fb854fcf92d7925f9938ea5444e36abef02c3d6a9602202410bc3265049abb07fd2e252c65ab7034d95c9d5acccabe9fadbdc63a52712601",
+ "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
+ 0.00000000
+ ],
+ "",
+ "0 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5",
+ "P2SH,WITNESS",
+ "EVAL_FALSE",
+ "Basic P2WPKH with wrong value"
+],
+[
+ [
+ "3044022000a30c4cfc10e4387be528613575434826ad3c15587475e0df8ce3b1746aa210022008149265e4f8e9dafe1f3ea50d90cb425e9e40ea7ebdd383069a7cfa2b77004701",
+ "410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
+ 0.00000000
+ ],
+ "0x22 0x0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64",
+ "HASH160 0x14 0xf386c2ba255cc56d20cfa6ea8b062f8b59945518 EQUAL",
+ "P2SH,WITNESS",
+ "EVAL_FALSE",
+ "Basic P2SH(P2WSH) with wrong value"
+],
+[
+ [
+ "304402204fc3a2cd61a47913f2a5f9107d0ad4a504c7b31ee2d6b3b2f38c2b10ee031e940220055d58b7c3c281aaa381d8f486ac0f3e361939acfd568046cb6a311cdfa974cf01",
+ "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
+ 0.00000000
+ ],
+ "0x16 0x001491b24bf9f5288532960ac687abb035127b1d28a5",
+ "HASH160 0x14 0x17743beb429c55c942d2ec703b98c4d57c2df5c6 EQUAL",
+ "P2SH,WITNESS",
+ "EVAL_FALSE",
+ "Basic P2SH(P2WPKH) with wrong value"
+],
+[
+ [
+ "304402205ae57ae0534c05ca9981c8a6cdf353b505eaacb7375f96681a2d1a4ba6f02f84022056248e68643b7d8ce7c7d128c9f1f348bcab8be15d094ad5cadd24251a28df8001",
+ "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
+ 0.00000000
+ ],
+ "",
+ "1 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5",
+ "DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM,P2SH,WITNESS",
+ "DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM",
+ "P2WPKH with future witness version"
+],
+[
+ [
+ "3044022064100ca0e2a33332136775a86cd83d0230e58b9aebb889c5ac952abff79a46ef02205f1bf900e022039ad3091bdaf27ac2aef3eae9ed9f190d821d3e508405b9513101",
+ "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
+ 0.00000000
+ ],
+ "",
+ "0 0x1f 0xb34b78da162751647974d5cb7410aa428ad339dbf7d1e16e833f68a0cbf1c3",
+ "P2SH,WITNESS",
+ "WITNESS_PROGRAM_WRONG_LENGTH",
+ "P2WPKH with wrong witness program length"
+],
+[
+ "",
+ "0 0x20 0xb95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64",
+ "P2SH,WITNESS",
+ "WITNESS_PROGRAM_WITNESS_EMPTY",
+ "P2WSH with empty witness"
+],
+[
+ [
+ "3044022039105b995a5f448639a997a5c90fda06f50b49df30c3bdb6663217bf79323db002206fecd54269dec569fcc517178880eb58bb40f381a282bb75766ff3637d5f4b4301",
+ "400479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
+ 0.00000000
+ ],
+ "",
+ "0 0x20 0xb95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64",
+ "P2SH,WITNESS",
+ "WITNESS_PROGRAM_MISMATCH",
+ "P2WSH with witness program mismatch"
+],
+[
+ [
+ "304402201a96950593cb0af32d080b0f193517f4559241a8ebd1e95e414533ad64a3f423022047f4f6d3095c23235bdff3aeff480d0529c027a3f093cb265b7cbf148553b85101",
+ "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
+ "",
+ 0.00000000
+ ],
+ "",
+ "0 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5",
+ "P2SH,WITNESS",
+ "WITNESS_PROGRAM_MISMATCH",
+ "P2WPKH with witness program mismatch"
+],
+[
+ [
+ "304402201a96950593cb0af32d080b0f193517f4559241a8ebd1e95e414533ad64a3f423022047f4f6d3095c23235bdff3aeff480d0529c027a3f093cb265b7cbf148553b85101",
+ "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
+ 0.00000000
+ ],
+ "11",
+ "0 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5",
+ "P2SH,WITNESS",
+ "WITNESS_MALLEATED",
+ "P2WPKH with non-empty scriptSig"
+],
+[
+ [
+ "304402204209e49457c2358f80d0256bc24535b8754c14d08840fc4be762d6f5a0aed80b02202eaf7d8fc8d62f60c67adcd99295528d0e491ae93c195cec5a67e7a09532a88001",
+ "048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf",
+ 0.00000000
+ ],
+ "11 0x16 0x00147cf9c846cd4882efec4bf07e44ebdad495c94f4b",
+ "HASH160 0x14 0x4e0c2aed91315303fc6a1dc4c7bc21c88f75402e EQUAL",
+ "P2SH,WITNESS",
+ "WITNESS_MALLEATED_P2SH",
+ "P2SH(P2WPKH) with superfluous push in scriptSig"
+],
+[
+ [
+ "",
+ 0.00000000
+ ],
+ "0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001",
+ "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG",
+ "P2SH,WITNESS",
+ "WITNESS_UNEXPECTED",
+ "P2PK with witness"
+],
+
+["Testing with compressed keys in witness v0 with WITNESS_PUBKEYTYPE"],
+[
+ [
+ "304402204256146fcf8e73b0fd817ffa2a4e408ff0418ff987dd08a4f485b62546f6c43c02203f3c8c3e2febc051e1222867f5f9d0eaf039d6792911c10940aa3cc74123378e01",
+ "210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0x1863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "OK",
+ "Basic P2WSH with compressed key"
+],
+[
+ [
+ "304402204edf27486f11432466b744df533e1acac727e0c83e5f912eb289a3df5bf8035f022075809fdd876ede40ad21667eba8b7e96394938f9c9c50f11b6a1280cce2cea8601",
+ "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
+ 0.00000001
+ ],
+ "",
+ "0 0x14 0x751e76e8199196d454941c45d1b3a323f1433bd6",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "OK",
+ "Basic P2WPKH with compressed key"
+],
+[
+ [
+ "304402203a549090cc46bce1e5e95c4922ea2c12747988e0207b04c42f81cdbe87bb1539022050f57a245b875fd5119c419aaf050bcdf41384f0765f04b809e5bced1fe7093d01",
+ "210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac",
+ 0.00000001
+ ],
+ "0x22 0x00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262",
+ "HASH160 0x14 0xe4300531190587e3880d4c3004f5355d88ff928d EQUAL",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "OK",
+ "Basic P2SH(P2WSH) with compressed key"
+],
+[
+ [
+ "304402201bc0d53046827f4a35a3166e33e3b3366c4085540dc383b95d21ed2ab11e368a0220333e78c6231214f5f8e59621e15d7eeab0d4e4d0796437e00bfbd2680c5f9c1701",
+ "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
+ 0.00000001
+ ],
+ "0x16 0x0014751e76e8199196d454941c45d1b3a323f1433bd6",
+ "HASH160 0x14 0xbcfeb728b584253d5f3f70bcb780e9ef218a68f4 EQUAL",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "OK",
+ "Basic P2SH(P2WPKH) with compressed key"
+],
+
+["Testing with uncompressed keys in witness v0 with WITNESS_PUBKEYTYPE"],
+[
+ [
+ "304402200d461c140cfdfcf36b94961db57ae8c18d1cb80e9d95a9e47ac22470c1bf125502201c8dc1cbfef6a3ef90acbbb992ca22fe9466ee6f9d4898eda277a7ac3ab4b25101",
+ "410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0xb95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "WITNESS_PUBKEYTYPE",
+ "Basic P2WSH"
+],
+[
+ [
+ "304402201e7216e5ccb3b61d46946ec6cc7e8c4e0117d13ac2fd4b152197e4805191c74202203e9903e33e84d9ee1dd13fb057afb7ccfb47006c23f6a067185efbc9dd780fc501",
+ "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
+ 0.00000001
+ ],
+ "",
+ "0 0x14 0x91b24bf9f5288532960ac687abb035127b1d28a5",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "WITNESS_PUBKEYTYPE",
+ "Basic P2WPKH"
+],
+[
+ [
+ "3044022066e02c19a513049d49349cf5311a1b012b7c4fae023795a18ab1d91c23496c22022025e216342c8e07ce8ef51e8daee88f84306a9de66236cab230bb63067ded1ad301",
+ "410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac",
+ 0.00000001
+ ],
+ "0x22 0x0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64",
+ "HASH160 0x14 0xf386c2ba255cc56d20cfa6ea8b062f8b59945518 EQUAL",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "WITNESS_PUBKEYTYPE",
+ "Basic P2SH(P2WSH)"
+],
+[
+ [
+ "304402200929d11561cd958460371200f82e9cae64c727a495715a31828e27a7ad57b36d0220361732ced04a6f97351ecca21a56d0b8cd4932c1da1f8f569a2b68e5e48aed7801",
+ "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
+ 0.00000001
+ ],
+ "0x16 0x001491b24bf9f5288532960ac687abb035127b1d28a5",
+ "HASH160 0x14 0x17743beb429c55c942d2ec703b98c4d57c2df5c6 EQUAL",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "WITNESS_PUBKEYTYPE",
+ "Basic P2SH(P2WPKH)"
+],
+
+["Testing P2WSH multisig with compressed keys"],
+[
+ [
+ "",
+ "304402207eb8a59b5c65fc3f6aeef77066556ed5c541948a53a3ba7f7c375b8eed76ee7502201e036a7a9a98ff919ff94dc905d67a1ec006f79ef7cff0708485c8bb79dce38e01",
+ "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0x06c24420938f0fa3c1cb2707d867154220dca365cdbfa0dd2a83854730221460",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "OK",
+ "P2WSH CHECKMULTISIG with compressed keys"
+],
+[
+ [
+ "",
+ "3044022033706aed33b8155d5486df3b9bca8cdd3bd4bdb5436dce46d72cdaba51d22b4002203626e94fe53a178af46624f17315c6931f20a30b103f5e044e1eda0c3fe185c601",
+ "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",
+ 0.00000001
+ ],
+ "0x22 0x002006c24420938f0fa3c1cb2707d867154220dca365cdbfa0dd2a83854730221460",
+ "HASH160 0x14 0x26282aad7c29369d15fed062a778b6100d31a340 EQUAL",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "OK",
+ "P2SH(P2WSH) CHECKMULTISIG with compressed keys"
+],
+[
+ [
+ "",
+ "304402204048b7371ab1c544362efb89af0c80154747d665aa4fcfb2edfd2d161e57b42e02207e043748e96637080ffc3acbd4dcc6fee1e58d30f6d1269535f32188e5ddae7301",
+ "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0x06c24420938f0fa3c1cb2707d867154220dca365cdbfa0dd2a83854730221460",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "OK",
+ "P2WSH CHECKMULTISIG with compressed keys"
+],
+[
+ [
+ "",
+ "3044022073902ef0b8a554c36c44cc03c1b64df96ce2914ebcf946f5bb36078fd5245cdf02205b148f1ba127065fb8c83a5a9576f2dcd111739788ed4bb3ee08b2bd3860c91c01",
+ "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",
+ 0.00000001
+ ],
+ "0x22 0x002006c24420938f0fa3c1cb2707d867154220dca365cdbfa0dd2a83854730221460",
+ "HASH160 0x14 0x26282aad7c29369d15fed062a778b6100d31a340 EQUAL",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "OK",
+ "P2SH(P2WSH) CHECKMULTISIG with compressed keys"
+],
+
+["Testing P2WSH multisig with compressed and uncompressed keys (first key being the key closer to the top of stack)"],
+[
+ [
+ "",
+ "304402202d092ededd1f060609dbf8cb76950634ff42b3e62cf4adb69ab92397b07d742302204ff886f8d0817491a96d1daccdcc820f6feb122ee6230143303100db37dfa79f01",
+ "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0x08a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa",
+ "P2SH,WITNESS",
+ "OK",
+ "P2WSH CHECKMULTISIG with first key uncompressed and signing with the first key"
+],
+[
+ [
+ "",
+ "304402202dd7e91243f2235481ffb626c3b7baf2c859ae3a5a77fb750ef97b99a8125dc002204960de3d3c3ab9496e218ec57e5240e0e10a6f9546316fe240c216d45116d29301",
+ "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae",
+ 0.00000001
+ ],
+ "0x22 0x002008a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa",
+ "HASH160 0x14 0x6f5ecd4b83b77f3c438f5214eff96454934fc5d1 EQUAL",
+ "P2SH,WITNESS",
+ "OK",
+ "P2SH(P2WSH) CHECKMULTISIG first key uncompressed and signing with the first key"
+],
+[
+ [
+ "",
+ "304402202d092ededd1f060609dbf8cb76950634ff42b3e62cf4adb69ab92397b07d742302204ff886f8d0817491a96d1daccdcc820f6feb122ee6230143303100db37dfa79f01",
+ "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0x08a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "WITNESS_PUBKEYTYPE",
+ "P2WSH CHECKMULTISIG with first key uncompressed and signing with the first key"
+],
+[
+ [
+ "",
+ "304402202dd7e91243f2235481ffb626c3b7baf2c859ae3a5a77fb750ef97b99a8125dc002204960de3d3c3ab9496e218ec57e5240e0e10a6f9546316fe240c216d45116d29301",
+ "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae",
+ 0.00000001
+ ],
+ "0x22 0x002008a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa",
+ "HASH160 0x14 0x6f5ecd4b83b77f3c438f5214eff96454934fc5d1 EQUAL",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "WITNESS_PUBKEYTYPE",
+ "P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the first key"
+],
+[
+ [
+ "",
+ "304402201e9e6f7deef5b2f21d8223c5189b7d5e82d237c10e97165dd08f547c4e5ce6ed02206796372eb1cc6acb52e13ee2d7f45807780bf96b132cb6697f69434be74b1af901",
+ "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0x08a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa",
+ "P2SH,WITNESS",
+ "OK",
+ "P2WSH CHECKMULTISIG with first key uncompressed and signing with the second key"
+],
+[
+ [
+ "",
+ "3044022045e667f3f0f3147b95597a24babe9afecea1f649fd23637dfa7ed7e9f3ac18440220295748e81005231135289fe3a88338dabba55afa1bdb4478691337009d82b68d01",
+ "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae",
+ 0.00000001
+ ],
+ "0x22 0x002008a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa",
+ "HASH160 0x14 0x6f5ecd4b83b77f3c438f5214eff96454934fc5d1 EQUAL",
+ "P2SH,WITNESS",
+ "OK",
+ "P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the second key"
+],
+[
+ [
+ "",
+ "304402201e9e6f7deef5b2f21d8223c5189b7d5e82d237c10e97165dd08f547c4e5ce6ed02206796372eb1cc6acb52e13ee2d7f45807780bf96b132cb6697f69434be74b1af901",
+ "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0x08a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "WITNESS_PUBKEYTYPE",
+ "P2WSH CHECKMULTISIG with first key uncompressed and signing with the second key"
+],
+[
+ [
+ "",
+ "3044022045e667f3f0f3147b95597a24babe9afecea1f649fd23637dfa7ed7e9f3ac18440220295748e81005231135289fe3a88338dabba55afa1bdb4478691337009d82b68d01",
+ "5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae",
+ 0.00000001
+ ],
+ "0x22 0x002008a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa",
+ "HASH160 0x14 0x6f5ecd4b83b77f3c438f5214eff96454934fc5d1 EQUAL",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "WITNESS_PUBKEYTYPE",
+ "P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the second key"
+],
+[
+ [
+ "",
+ "3044022046f5367a261fd8f8d7de6eb390491344f8ec2501638fb9a1095a0599a21d3f4c02205c1b3b51d20091c5f1020841bbca87b44ebe25405c64e4acf758f2eae8665f8401",
+ "5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0x230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb",
+ "P2SH,WITNESS",
+ "OK",
+ "P2WSH CHECKMULTISIG with second key uncompressed and signing with the first key"
+],
+[
+ [
+ "",
+ "3044022053e210e4fb1881e6092fd75c3efc5163105599e246ded661c0ee2b5682cc2d6c02203a26b7ada8682a095b84c6d1b881637000b47d761fc837c4cee33555296d63f101",
+ "5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",
+ 0.00000001
+ ],
+ "0x22 0x0020230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb",
+ "HASH160 0x14 0x3478e7019ce61a68148f87549579b704cbe4c393 EQUAL",
+ "P2SH,WITNESS",
+ "OK",
+ "P2SH(P2WSH) CHECKMULTISIG second key uncompressed and signing with the first key"
+],
+[
+ [
+ "",
+ "3044022046f5367a261fd8f8d7de6eb390491344f8ec2501638fb9a1095a0599a21d3f4c02205c1b3b51d20091c5f1020841bbca87b44ebe25405c64e4acf758f2eae8665f8401",
+ "5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0x230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "OK",
+ "P2WSH CHECKMULTISIG with second key uncompressed and signing with the first key should pass as the uncompressed key is not used"
+],
+[
+ [
+ "",
+ "3044022053e210e4fb1881e6092fd75c3efc5163105599e246ded661c0ee2b5682cc2d6c02203a26b7ada8682a095b84c6d1b881637000b47d761fc837c4cee33555296d63f101",
+ "5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",
+ 0.00000001
+ ],
+ "0x22 0x0020230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb",
+ "HASH160 0x14 0x3478e7019ce61a68148f87549579b704cbe4c393 EQUAL",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "OK",
+ "P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the first key should pass as the uncompressed key is not used"
+],
+[
+ [
+ "",
+ "304402206c6d9f5daf85b54af2a93ec38b15ab27f205dbf5c735365ff12451e43613d1f40220736a44be63423ed5ebf53491618b7cc3d8a5093861908da853739c73717938b701",
+ "5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0x230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb",
+ "P2SH,WITNESS",
+ "OK",
+ "P2WSH CHECKMULTISIG with second key uncompressed and signing with the second key"
+],
+[
+ [
+ "",
+ "30440220687871bc6144012d75baf585bb26ce13997f7d8c626f4d8825b069c3b2d064470220108936fe1c57327764782253e99090b09c203ec400ed35ce9e026ce2ecf842a001",
+ "5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",
+ 0.00000001
+ ],
+ "0x22 0x0020230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb",
+ "HASH160 0x14 0x3478e7019ce61a68148f87549579b704cbe4c393 EQUAL",
+ "P2SH,WITNESS",
+ "OK",
+ "P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the second key"
+],
+[
+ [
+ "",
+ "304402206c6d9f5daf85b54af2a93ec38b15ab27f205dbf5c735365ff12451e43613d1f40220736a44be63423ed5ebf53491618b7cc3d8a5093861908da853739c73717938b701",
+ "5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",
+ 0.00000001
+ ],
+ "",
+ "0 0x20 0x230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "WITNESS_PUBKEYTYPE",
+ "P2WSH CHECKMULTISIG with second key uncompressed and signing with the second key"
+],
+[
+ [
+ "",
+ "30440220687871bc6144012d75baf585bb26ce13997f7d8c626f4d8825b069c3b2d064470220108936fe1c57327764782253e99090b09c203ec400ed35ce9e026ce2ecf842a001",
+ "5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",
+ 0.00000001
+ ],
+ "0x22 0x0020230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb",
+ "HASH160 0x14 0x3478e7019ce61a68148f87549579b704cbe4c393 EQUAL",
+ "P2SH,WITNESS,WITNESS_PUBKEYTYPE",
+ "WITNESS_PUBKEYTYPE",
+ "P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the second key"
+],
+
+["CHECKSEQUENCEVERIFY tests"],
+["", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "INVALID_STACK_OPERATION", "CSV automatically fails on an empty stack"],
+["-1", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "NEGATIVE_LOCKTIME", "CSV automatically fails if stack top is negative"],
+["0x0100", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY,MINIMALDATA", "UNKNOWN_ERROR", "CSV fails if stack top is not minimally encoded"],
+["0", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", "CSV fails if stack top bit 1 << 31 is set and the tx version < 2"],
+["4294967296", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME",
+ "CSV fails if stack top bit 1 << 31 is not set, and tx version < 2"],
+
+["MINIMALIF tests"],
+["MINIMALIF is not applied to non-segwit scripts"],
+["1", "IF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "OK"],
+["2", "IF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "OK"],
+["0x02 0x0100", "IF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "OK"],
+["0", "IF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"],
+["0x01 0x00", "IF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"],
+["1", "NOTIF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"],
+["2", "NOTIF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"],
+["0x02 0x0100", "NOTIF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"],
+["0", "NOTIF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "OK"],
+["0x01 0x00", "NOTIF 1 ENDIF", "P2SH,WITNESS,MINIMALIF", "OK"],
+["Normal P2SH IF 1 ENDIF"],
+["1 0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH,WITNESS,MINIMALIF", "OK"],
+["2 0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH,WITNESS,MINIMALIF", "OK"],
+["0x02 0x0100 0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH,WITNESS,MINIMALIF", "OK"],
+["0 0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"],
+["0x01 0x00 0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"],
+["0x03 0x635168", "HASH160 0x14 0xe7309652a8e3f600f06f5d8d52d6df03d2176cc3 EQUAL", "P2SH,WITNESS,MINIMALIF", "UNBALANCED_CONDITIONAL"],
+["Normal P2SH NOTIF 1 ENDIF"],
+["1 0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"],
+["2 0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"],
+["0x02 0x0100 0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH,WITNESS,MINIMALIF", "EVAL_FALSE"],
+["0 0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH,WITNESS,MINIMALIF", "OK"],
+["0x01 0x00 0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH,WITNESS,MINIMALIF", "OK"],
+["0x03 0x645168", "HASH160 0x14 0x0c3f8fe3d6ca266e76311ecda544c67d15fdd5b0 EQUAL", "P2SH,WITNESS,MINIMALIF", "UNBALANCED_CONDITIONAL"],
+["P2WSH IF 1 ENDIF"],
+[["01", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS", "OK"],
+[["02", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS", "OK"],
+[["0100", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS", "OK"],
+[["", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS", "CLEANSTACK"],
+[["00", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS", "CLEANSTACK"],
+[["01", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS,MINIMALIF", "OK"],
+[["02", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"],
+[["0100", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"],
+[["", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS,MINIMALIF", "CLEANSTACK"],
+[["00", "635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"],
+[["635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS", "UNBALANCED_CONDITIONAL"],
+[["635168", 0.00000001], "", "0 0x20 0xc7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "P2SH,WITNESS,MINIMALIF", "UNBALANCED_CONDITIONAL"],
+["P2WSH NOTIF 1 ENDIF"],
+[["01", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS", "CLEANSTACK"],
+[["02", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS", "CLEANSTACK"],
+[["0100", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS", "CLEANSTACK"],
+[["", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS", "OK"],
+[["00", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS", "OK"],
+[["01", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS,MINIMALIF", "CLEANSTACK"],
+[["02", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"],
+[["0100", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"],
+[["", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS,MINIMALIF", "OK"],
+[["00", "645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"],
+[["645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS", "UNBALANCED_CONDITIONAL"],
+[["645168", 0.00000001], "", "0 0x20 0xf913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "P2SH,WITNESS,MINIMALIF", "UNBALANCED_CONDITIONAL"],
+
+
+
+["P2SH-P2WSH IF 1 ENDIF"],
+[["01", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS", "OK"],
+[["02", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS", "OK"],
+[["0100", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS", "OK"],
+[["", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS", "CLEANSTACK"],
+[["00", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS", "CLEANSTACK"],
+[["01", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS,MINIMALIF", "OK"],
+[["02", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"],
+[["0100", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"],
+[["", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS,MINIMALIF", "CLEANSTACK"],
+[["00", "635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"],
+[["635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS", "UNBALANCED_CONDITIONAL"],
+[["635168", 0.00000001], "0x22 0x0020c7eaf06d5ae01a58e376e126eb1e6fab2036076922b96b2711ffbec1e590665d", "HASH160 0x14 0x9b27ee6d9010c21bf837b334d043be5d150e7ba7 EQUAL", "P2SH,WITNESS,MINIMALIF", "UNBALANCED_CONDITIONAL"],
+["P2SH-P2WSH NOTIF 1 ENDIF"],
+[["01", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS", "CLEANSTACK"],
+[["02", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS", "CLEANSTACK"],
+[["0100", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS", "CLEANSTACK"],
+[["", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS", "OK"],
+[["00", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS", "OK"],
+[["01", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS,MINIMALIF", "CLEANSTACK"],
+[["02", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"],
+[["0100", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"],
+[["", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS,MINIMALIF", "OK"],
+[["00", "645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS,MINIMALIF", "MINIMALIF"],
+[["645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS", "UNBALANCED_CONDITIONAL"],
+[["645168", 0.00000001], "0x22 0x0020f913eacf2e38a5d6fc3a8311d72ae704cb83866350a984dd3e5eb76d2a8c28e8", "HASH160 0x14 0xdbb7d1c0a56b7a9c423300c8cca6e6e065baf1dc EQUAL", "P2SH,WITNESS,MINIMALIF", "UNBALANCED_CONDITIONAL"],
+
+["NULLFAIL should cover all signatures and signatures only"],
+["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66 and NULLFAIL-compliant"],
+["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "OK", "BIP66 and NULLFAIL-compliant"],
+["1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "OK", "BIP66 and NULLFAIL-compliant, not NULLDUMMY-compliant"],
+["1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL,NULLDUMMY", "SIG_NULLDUMMY", "BIP66 and NULLFAIL-compliant, not NULLDUMMY-compliant"],
+["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x09 0x300602010102010101", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66-compliant but not NULLFAIL-compliant"],
+["0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x09 0x300602010102010101", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "NULLFAIL", "BIP66-compliant but not NULLFAIL-compliant"],
+["0 0x09 0x300602010102010101 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG", "OK", "BIP66-compliant but not NULLFAIL-compliant"],
+["0 0x09 0x300602010102010101 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "0x01 0x14 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0x01 0x14 CHECKMULTISIG NOT", "DERSIG,NULLFAIL", "NULLFAIL", "BIP66-compliant but not NULLFAIL-compliant"],
+
+["The End"]
+]
diff --git a/src/test/data/sighash.json b/src/test/data/sighash.json
new file mode 100644
index 0000000000..d66a56ac35
--- /dev/null
+++ b/src/test/data/sighash.json
@@ -0,0 +1,503 @@
+[
+ ["raw_transaction, script, input_index, hashType, signature_hash (result)"],
+ ["907c2bc503ade11cc3b04eb2918b6f547b0630ab569273824748c87ea14b0696526c66ba740200000004ab65ababfd1f9bdd4ef073c7afc4ae00da8a66f429c917a0081ad1e1dabce28d373eab81d8628de802000000096aab5253ab52000052ad042b5f25efb33beec9f3364e8a9139e8439d9d7e26529c3c30b6c3fd89f8684cfd68ea0200000009ab53526500636a52ab599ac2fe02a526ed040000000008535300516352515164370e010000000003006300ab2ec229", "", 2, 1864164639, "31af167a6cf3f9d5f6875caa4d31704ceb0eba078d132b78dab52c3b8997317e"],
+ ["a0aa3126041621a6dea5b800141aa696daf28408959dfb2df96095db9fa425ad3f427f2f6103000000015360290e9c6063fa26912c2e7fb6a0ad80f1c5fea1771d42f12976092e7a85a4229fdb6e890000000001abc109f6e47688ac0e4682988785744602b8c87228fcef0695085edf19088af1a9db126e93000000000665516aac536affffffff8fe53e0806e12dfd05d67ac68f4768fdbe23fc48ace22a5aa8ba04c96d58e2750300000009ac51abac63ab5153650524aa680455ce7b000000000000499e50030000000008636a00ac526563ac5051ee030000000003abacabd2b6fe000000000003516563910fb6b5", "65", 0, -1391424484, "48d6a1bd2cd9eec54eb866fc71209418a950402b5d7e52363bfb75c98e141175"],
+ ["6e7e9d4b04ce17afa1e8546b627bb8d89a6a7fefd9d892ec8a192d79c2ceafc01694a6a7e7030000000953ac6a51006353636a33bced1544f797f08ceed02f108da22cd24c9e7809a446c61eb3895914508ac91f07053a01000000055163ab516affffffff11dc54eee8f9e4ff0bcf6b1a1a35b1cd10d63389571375501af7444073bcec3c02000000046aab53514a821f0ce3956e235f71e4c69d91abe1e93fb703bd33039ac567249ed339bf0ba0883ef300000000090063ab65000065ac654bec3cc504bcf499020000000005ab6a52abac64eb060100000000076a6a5351650053bbbc130100000000056a6aab53abd6e1380100000000026a51c4e509b8", "acab655151", 0, 479279909, "2a3d95b09237b72034b23f2d2bb29fa32a58ab5c6aa72f6aafdfa178ab1dd01c"],
+ ["73107cbd025c22ebc8c3e0a47b2a760739216a528de8d4dab5d45cbeb3051cebae73b01ca10200000007ab6353656a636affffffffe26816dffc670841e6a6c8c61c586da401df1261a330a6c6b3dd9f9a0789bc9e000000000800ac6552ac6aac51ffffffff0174a8f0010000000004ac52515100000000", "5163ac63635151ac", 1, 1190874345, "06e328de263a87b09beabe222a21627a6ea5c7f560030da31610c4611f4a46bc"],
+ ["e93bbf6902be872933cb987fc26ba0f914fcfc2f6ce555258554dd9939d12032a8536c8802030000000453ac5353eabb6451e074e6fef9de211347d6a45900ea5aaf2636ef7967f565dce66fa451805c5cd10000000003525253ffffffff047dc3e6020000000007516565ac656aabec9eea010000000001633e46e600000000000015080a030000000001ab00000000", "5300ac6a53ab6a", 1, -886562767, "f03aa4fc5f97e826323d0daa03343ebf8a34ed67a1ce18631f8b88e5c992e798"],
+ ["50818f4c01b464538b1e7e7f5ae4ed96ad23c68c830e78da9a845bc19b5c3b0b20bb82e5e9030000000763526a63655352ffffffff023b3f9c040000000008630051516a6a5163a83caf01000000000553ab65510000000000", "6aac", 0, 946795545, "746306f322de2b4b58ffe7faae83f6a72433c22f88062cdde881d4dd8a5a4e2d"],
+ ["a93e93440250f97012d466a6cc24839f572def241c814fe6ae94442cf58ea33eb0fdd9bcc1030000000600636a0065acffffffff5dee3a6e7e5ad6310dea3e5b3ddda1a56bf8de7d3b75889fc024b5e233ec10f80300000007ac53635253ab53ffffffff0160468b04000000000800526a5300ac526a00000000", "ac00636a53", 1, 1773442520, "5c9d3a2ce9365bb72cfabbaa4579c843bb8abf200944612cf8ae4b56a908bcbd"],
+ ["ce7d371f0476dda8b811d4bf3b64d5f86204725deeaa3937861869d5b2766ea7d17c57e40b0100000003535265ffffffff7e7e9188f76c34a46d0bbe856bde5cb32f089a07a70ea96e15e92abb37e479a10100000006ab6552ab655225bcab06d1c2896709f364b1e372814d842c9c671356a1aa5ca4e060462c65ae55acc02d0000000006abac0063ac5281b33e332f96beebdbc6a379ebe6aea36af115c067461eb99d22ba1afbf59462b59ae0bd0200000004ab635365be15c23801724a1704000000000965006a65ac00000052ca555572", "53ab530051ab", 1, 2030598449, "c336b2f7d3702fbbdeffc014d106c69e3413c7c71e436ba7562d8a7a2871f181"],
+ ["d3b7421e011f4de0f1cea9ba7458bf3486bee722519efab711a963fa8c100970cf7488b7bb0200000003525352dcd61b300148be5d05000000000000000000", "535251536aac536a", 0, -1960128125, "29aa6d2d752d3310eba20442770ad345b7f6a35f96161ede5f07b33e92053e2a"],
+ ["04bac8c5033460235919a9c63c42b2db884c7c8f2ed8fcd69ff683a0a2cccd9796346a04050200000003655351fcad3a2c5a7cbadeb4ec7acc9836c3f5c3e776e5c566220f7f965cf194f8ef98efb5e3530200000007526a006552526526a2f55ba5f69699ece76692552b399ba908301907c5763d28a15b08581b23179cb01eac03000000075363ab6a516351073942c2025aa98a05000000000765006aabac65abd7ffa6030000000004516a655200000000", "53ac6365ac526a", 1, 764174870, "bf5fdc314ded2372a0ad078568d76c5064bf2affbde0764c335009e56634481b"],
+ ["c363a70c01ab174230bbe4afe0c3efa2d7f2feaf179431359adedccf30d1f69efe0c86ed390200000002ab51558648fe0231318b04000000000151662170000000000008ac5300006a63acac00000000", "", 0, 2146479410, "191ab180b0d753763671717d051f138d4866b7cb0d1d4811472e64de595d2c70"],
+ ["8d437a7304d8772210a923fd81187c425fc28c17a5052571501db05c7e89b11448b36618cd02000000026a6340fec14ad2c9298fde1477f1e8325e5747b61b7e2ff2a549f3d132689560ab6c45dd43c3010000000963ac00ac000051516a447ed907a7efffebeb103988bf5f947fc688aab2c6a7914f48238cf92c337fad4a79348102000000085352ac526a5152517436edf2d80e3ef06725227c970a816b25d0b58d2cd3c187a7af2cea66d6b27ba69bf33a0300000007000063ab526553f3f0d6140386815d030000000003ab6300de138f00000000000900525153515265abac1f87040300000000036aac6500000000", "51", 3, -315779667, "b6632ac53578a741ae8c36d8b69e79f39b89913a2c781cdf1bf47a8c29d997a5"],
+ ["fd878840031e82fdbe1ad1d745d1185622b0060ac56638290ec4f66b1beef4450817114a2c0000000009516a63ab53650051abffffffff37b7a10322b5418bfd64fb09cd8a27ddf57731aeb1f1f920ffde7cb2dfb6cdb70300000008536a5365ac53515369ecc034f1594690dbe189094dc816d6d57ea75917de764cbf8eccce4632cbabe7e116cd0100000003515352ffffffff035777fc000000000003515200abe9140300000000050063005165bed6d10200000000076300536363ab65195e9110", "635265", 0, 1729787658, "6e3735d37a4b28c45919543aabcb732e7a3e1874db5315abb7cc6b143d62ff10"],
+ ["f40a750702af06efff3ea68e5d56e42bc41cdb8b6065c98f1221fe04a325a898cb61f3d7ee030000000363acacffffffffb5788174aef79788716f96af779d7959147a0c2e0e5bfb6c2dba2df5b4b97894030000000965510065535163ac6affffffff0445e6fd0200000000096aac536365526a526aa6546b000000000008acab656a6552535141a0fd010000000000c897ea030000000008526500ab526a6a631b39dba3", "00abab5163ac", 1, -1778064747, "d76d0fc0abfa72d646df888bce08db957e627f72962647016eeae5a8412354cf"],
+ ["a63bc673049c75211aa2c09ecc38e360eaa571435fedd2af1116b5c1fa3d0629c269ecccbf0000000008ac65ab516352ac52ffffffffbf1a76fdda7f451a5f0baff0f9ccd0fe9136444c094bb8c544b1af0fa2774b06010000000463535253ffffffff13d6b7c3ddceef255d680d87181e100864eeb11a5bb6a3528cb0d70d7ee2bbbc02000000056a0052abab951241809623313b198bb520645c15ec96bfcc74a2b0f3db7ad61d455cc32db04afc5cc702000000016309c9ae25014d9473020000000004abab6aac3bb1e803", "", 3, -232881718, "6e48f3da3a4ac07eb4043a232df9f84e110485d7c7669dd114f679c27d15b97e"],
+ ["4c565efe04e7d32bac03ae358d63140c1cfe95de15e30c5b84f31bb0b65bb542d637f49e0f010000000551abab536348ae32b31c7d3132030a510a1b1aacf7b7c3f19ce8dc49944ef93e5fa5fe2d356b4a73a00100000009abac635163ac00ab514c8bc57b6b844e04555c0a4f4fb426df139475cd2396ae418bc7015820e852f711519bc202000000086a00510000abac52488ff4aec72cbcfcc98759c58e20a8d2d9725aa4a80f83964e69bc4e793a4ff25cd75dc701000000086a52ac6aac5351532ec6b10802463e0200000000000553005265523e08680100000000002f39a6b0", "", 3, 70712784, "c6076b6a45e6fcfba14d3df47a34f6aadbacfba107e95621d8d7c9c0e40518ed"],
+ ["1233d5e703403b3b8b4dae84510ddfc126b4838dcb47d3b23df815c0b3a07b55bf3098110e010000000163c5c55528041f480f40cf68a8762d6ed3efe2bd402795d5233e5d94bf5ddee71665144898030000000965525165655151656affffffff6381667e78bb74d0880625993bec0ea3bd41396f2bcccc3cc097b240e5e92d6a01000000096363acac6a63536365ffffffff04610ad60200000000065251ab65ab52e90d680200000000046351516ae30e98010000000008abab52520063656a671856010000000004ac6aac514c84e383", "6aabab636300", 1, -114996813, "aeb8c5a62e8a0b572c28f2029db32854c0b614dbecef0eaa726abebb42eebb8d"],
+ ["0c69702103b25ceaed43122cc2672de84a3b9aa49872f2a5bb458e19a52f8cc75973abb9f102000000055365656aacffffffff3ffb1cf0f76d9e3397de0942038c856b0ebbea355dc9d8f2b06036e19044b0450100000000ffffffff4b7793f4169617c54b734f2cd905ed65f1ce3d396ecd15b6c426a677186ca0620200000008655263526551006a181a25b703240cce0100000000046352ab53dee22903000000000865526a6a516a51005e121602000000000852ab52ababac655200000000", "6a516aab63", 1, -2040012771, "a6e6cb69f409ec14e10dd476f39167c29e586e99bfac93a37ed2c230fcc1dbbe"],
+ ["fd22692802db8ae6ab095aeae3867305a954278f7c076c542f0344b2591789e7e33e4d29f4020000000151ffffffffb9409129cfed9d3226f3b6bab7a2c83f99f48d039100eeb5796f00903b0e5e5e0100000006656552ac63abd226abac0403e649000000000007abab51ac5100ac8035f10000000000095165006a63526a52510d42db030000000007635365ac6a63ab24ef5901000000000453ab6a0000000000", "536a52516aac6a", 1, 309309168, "7ca0f75e6530ec9f80d031fc3513ca4ecd67f20cb38b4dacc6a1d825c3cdbfdb"],
+ ["a43f85f701ffa54a3cc57177510f3ea28ecb6db0d4431fc79171cad708a6054f6e5b4f89170000000008ac6a006a536551652bebeaa2013e779c05000000000665ac5363635100000000", "ac", 0, 2028978692, "58294f0d7f2e68fe1fd30c01764fe1619bcc7961d68968944a0e263af6550437"],
+ ["c2b0b99001acfecf7da736de0ffaef8134a9676811602a6299ba5a2563a23bb09e8cbedf9300000000026300ffffffff042997c50300000000045252536a272437030000000007655353ab6363ac663752030000000002ab6a6d5c900000000000066a6a5265abab00000000", "52ac525163515251", 0, -894181723, "8b300032a1915a4ac05cea2f7d44c26f2a08d109a71602636f15866563eaafdc"],
+ ["82f9f10304c17a9d954cf3380db817814a8c738d2c811f0412284b2c791ec75515f38c4f8c020000000265ab5729ca7db1b79abee66c8a757221f29280d0681355cb522149525f36da760548dbd7080a0100000001510b477bd9ce9ad5bb81c0306273a3a7d051e053f04ecf3a1dbeda543e20601a5755c0cfae030000000451ac656affffffff71141a04134f6c292c2e0d415e6705dfd8dcee892b0d0807828d5aeb7d11f5ef0300000001520b6c6dc802a6f3dd0000000000056aab515163bfb6800300000000015300000000", "", 3, -635779440, "d55ed1e6c53510f2608716c12132a11fb5e662ec67421a513c074537eeccc34b"],
+ ["8edcf5a1014b604e53f0d12fe143cf4284f86dc79a634a9f17d7e9f8725f7beb95e8ffcd2403000000046aabac52ffffffff01c402b5040000000005ab6a63525100000000", "6351525251acabab6a", 0, 1520147826, "2765bbdcd3ebb8b1a316c04656b28d637f80bffbe9b040661481d3dc83eea6d6"],
+ ["2074bad5011847f14df5ea7b4afd80cd56b02b99634893c6e3d5aaad41ca7c8ee8e5098df003000000026a6affffffff018ad59700000000000900ac656a526551635300000000", "65635265", 0, -1804671183, "663c999a52288c9999bff36c9da2f8b78d5c61b8347538f76c164ccba9868d0a"],
+ ["7100b11302e554d4ef249ee416e7510a485e43b2ba4b8812d8fe5529fe33ea75f36d392c4403000000020000ffffffff3d01a37e075e9a7715a657ae1bdf1e44b46e236ad16fd2f4c74eb9bf370368810000000007636553ac536365ffffffff01db696a0400000000065200ac656aac00000000", "63005151", 0, -1210499507, "b9c3aee8515a4a3b439de1ffc9c156824bda12cb75bfe5bc863164e8fd31bd7a"],
+ ["02c1017802091d1cb08fec512db7b012fe4220d57a5f15f9e7676358b012786e1209bcff950100000004acab6352ffffffff799bc282724a970a6fea1828984d0aeb0f16b67776fa213cbdc4838a2f1961a3010000000951516a536552ab6aabffffffff016c7b4b03000000000865abac5253ac5352b70195ad", "65655200516a", 0, -241626954, "be567cb47170b34ff81c66c1142cb9d27f9b6898a384d6dfc4fce16b75b6cb14"],
+ ["cb3178520136cd294568b83bb2520f78fecc507898f4a2db2674560d72fd69b9858f75b3b502000000066aac00515100ffffffff03ab005a01000000000563526363006e3836030000000001abfbda3200000000000665ab0065006500000000", "ab516a0063006a5300", 0, 1182109299, "2149e79c3f4513da4e4378608e497dcfdfc7f27c21a826868f728abd2b8a637a"],
+ ["18a4b0c004702cf0e39686ac98aab78ad788308f1d484b1ddfe70dc1997148ba0e28515c310300000000ffffffff05275a52a23c59da91129093364e275da5616c4070d8a05b96df5a2080ef259500000000096aac51656a6aac53ab66e64966b3b36a07dd2bb40242dd4a3743d3026e7e1e0d9e9e18f11d068464b989661321030000000265ac383339c4fae63379cafb63b0bab2eca70e1f5fc7d857eb5c88ccd6c0465093924bba8b2a000000000300636ab5e0545402bc2c4c010000000000cd41c002000000000000000000", "abac635253656a00", 3, 2052372230, "32db877b6b1ca556c9e859442329406f0f8246706522369839979a9f7a235a32"],
+ ["1d9c5df20139904c582285e1ea63dec934251c0f9cf5c47e86abfb2b394ebc57417a81f67c010000000353515222ba722504800d3402000000000353656a3c0b4a0200000000000fb8d20500000000076300ab005200516462f30400000000015200000000", "ab65", 0, -210854112, "edf73e2396694e58f6b619f68595b0c1cdcb56a9b3147845b6d6afdb5a80b736"],
+ ["4504cb1904c7a4acf375ddae431a74de72d5436efc73312cf8e9921f431267ea6852f9714a01000000066a656a656553a2fbd587c098b3a1c5bd1d6480f730a0d6d9b537966e20efc0e352d971576d0f87df0d6d01000000016321aeec3c4dcc819f1290edb463a737118f39ab5765800547522708c425306ebfca3f396603000000055300ac656a1d09281d05bfac57b5eb17eb3fa81ffcedfbcd3a917f1be0985c944d473d2c34d245eb350300000007656a51525152ac263078d9032f470f0500000000066aac00000052e12da60200000000003488410200000000076365006300ab539981e432", "52536a52526a", 1, -31909119, "f0a2deee7fd8a3a9fad6927e763ded11c940ee47e9e6d410f94fda5001f82e0c"],
+ ["14bc7c3e03322ec0f1311f4327e93059c996275302554473104f3f7b46ca179bfac9ef753503000000016affffffff9d405eaeffa1ca54d9a05441a296e5cc3a3e32bb8307afaf167f7b57190b07e00300000008abab51ab5263abab45533aa242c61bca90dd15d46079a0ab0841d85df67b29ba87f2393cd764a6997c372b55030000000452005263ffffffff0250f40e02000000000651516a0063630e95ab0000000000046a5151ac00000000", "6a65005151", 0, -1460947095, "aa418d096929394c9147be8818d8c9dafe6d105945ab9cd7ec682df537b5dd79"],
+ ["2b3bd0dd04a1832f893bf49a776cd567ec4b43945934f4786b615d6cb850dfc0349b33301a000000000565ac000051cf80c670f6ddafab63411adb4d91a69c11d9ac588898cbfb4cb16061821cc104325c895103000000025163ffffffffa9e2d7506d2d7d53b882bd377bbcc941f7a0f23fd15d2edbef3cd9df8a4c39d10200000009ac63006a52526a5265ffffffff44c099cdf10b10ce87d4b38658d002fd6ea17ae4a970053c05401d86d6e75f99000000000963ab53526a5252ab63ffffffff035af69c01000000000100ba9b8b0400000000004cead10500000000026a520b77d667", "ab52abac526553", 3, -1955078165, "eb9ceecc3b401224cb79a44d23aa8f428e29f1405daf69b4e01910b848ef1523"],
+ ["35df11f004a48ba439aba878fe9df20cc935b4a761c262b1b707e6f2b33e2bb7565cd68b130000000000ffffffffb2a2f99abf64163bb57ca900500b863f40c02632dfd9ea2590854c5fb4811da90200000006ac006363636affffffffaf9d89b2a8d2670ca37c8f7c140600b81259f2e037cb4590578ec6e37af8bf200000000005abac6a655270a4751eb551f058a93301ffeda2e252b6614a1fdd0e283e1d9fe53c96c5bbaafaac57b8030000000153ffffffff020d9f3b02000000000100ed7008030000000004abac000000000000", "abac", 3, 593793071, "88fdee1c2d4aeead71d62396e28dc4d00e5a23498eea66844b9f5d26d1f21042"],
+ ["a08ff466049fb7619e25502ec22fedfb229eaa1fe275aa0b5a23154b318441bf547989d0510000000005ab5363636affffffff2b0e335cb5383886751cdbd993dc0720817745a6b1c9b8ab3d15547fc9aafd03000000000965656a536a52656a532b53d10584c290d3ac1ab74ab0a19201a4a039cb59dc58719821c024f6bf2eb26322b33f010000000965ac6aac0053ab6353ffffffff048decba6ebbd2db81e416e39dde1f821ba69329725e702bcdea20c5cc0ecc6402000000086363ab5351ac6551466e377b0468c0fa00000000000651ab53ac6a513461c6010000000008636a636365535100eeb3dc010000000006526a52ac516a43f362010000000005000063536500000000", "0063516a", 1, -1158911348, "f6a1ecb50bd7c2594ebecea5a1aa23c905087553e40486dade793c2f127fdfae"],
+ ["5ac2f17d03bc902e2bac2469907ec7d01a62b5729340bc58c343b7145b66e6b97d434b30fa000000000163ffffffff44028aa674192caa0d0b4ebfeb969c284cb16b80c312d096efd80c6c6b094cca000000000763acabac516a52ffffffff10c809106e04b10f9b43085855521270fb48ab579266e7474657c6c625062d2d030000000351636595a0a97004a1b69603000000000465ab005352ad68010000000008636a5263acac5100da7105010000000002acab90325200000000000000000000", "6a6aab516a63526353", 2, 1518400956, "f7efb74b1dcc49d316b49c632301bc46f98d333c427e55338be60c7ef0d953be"],
+ ["aeb2e11902dc3770c218b97f0b1960d6ee70459ecb6a95eff3f05295dc1ef4a0884f10ba460300000005516352526393e9b1b3e6ae834102d699ddd3845a1e159aa7cf7635edb5c02003f7830fee3788b795f20100000009ab006a526553ac006ad8809c570469290e0400000000050000abab00b10fd5040000000008ab655263abac53ab630b180300000000009d9993040000000002516300000000", "5351ababac6a65", 0, 1084852870, "f2286001af0b0170cbdad92693d0a5ebaa8262a4a9d66e002f6d79a8c94026d1"],
+ ["9860ca9a0294ff4812534def8c3a3e3db35b817e1a2ddb7f0bf673f70eab71bb79e90a2f3100000000086a636551acac5165ffffffffed4d6d3cd9ff9b2d490e0c089739121161a1445844c3e204296816ab06e0a83702000000035100ac88d0db5201c3b59a050000000005ac6a0051ab00000000", "535263ab006a526aab", 1, -962088116, "30df2473e1403e2b8e637e576825f785528d998af127d501556e5f7f5ed89a2a"],
+ ["4ddaa680026ec4d8060640304b86823f1ac760c260cef81d85bd847952863d629a3002b54b0200000008526365636a656aab65457861fc6c24bdc760c8b2e906b6656edaf9ed22b5f50e1fb29ec076ceadd9e8ebcb6b000000000152ffffffff033ff04f00000000000551526a00657a1d900300000000002153af040000000003006a6300000000", "ab526a53acabab", 0, 1055317633, "7f21b62267ed52462e371a917eb3542569a4049b9dfca2de3c75872b39510b26"],
+ ["01e76dcd02ad54cbc8c71d68eaf3fa7c883b65d74217b30ba81f1f5144ef80b706c0dc82ca000000000352ab6a078ec18bcd0514825feced2e8b8ea1ccb34429fae41c70cc0b73a2799e85603613c6870002000000086363ab6365536a53ffffffff043acea90000000000016ad20e1803000000000100fa00830200000000056352515351e864ee00000000000865535253ab6a6551d0c46672", "6a6365abacab", 0, -1420559003, "8af0b4cbdbc011be848edf4dbd2cde96f0578d662cfebc42252495387114224a"],
+ ["fa00b26402670b97906203434aa967ce1559d9bd097d56dbe760469e6032e7ab61accb54160100000006635163630052fffffffffe0d3f4f0f808fd9cfb162e9f0c004601acf725cd7ea5683bbdc9a9a433ef15a0200000005ab52536563d09c7bef049040f305000000000153a7c7b9020000000004ac63ab52847a2503000000000553ab00655390ed80010000000005006553ab52860671d4", "536565ab52", 0, 799022412, "40ed8e7bbbd893e15f3cce210ae02c97669818de5946ca37eefc7541116e2c78"],
+ ["cb5c06dc01b022ee6105ba410f0eb12b9ce5b5aa185b28532492d839a10cef33d06134b91b010000000153ffffffff02cec0530400000000005e1e4504000000000865656551acacac6a00000000", "ab53", 0, -1514251329, "136beb95459fe6b126cd6cefd54eb5d971524b0e883e41a292a78f78015cb8d5"],
+ ["f10a0356031cd569d652dbca8e7a4d36c8da33cdff428d003338602b7764fe2c96c505175b010000000465ac516affffffffbb54563c71136fa944ee20452d78dc87073ac2365ba07e638dce29a5d179da600000000003635152ffffffff9a411d8e2d421b1e6085540ee2809901e590940bbb41532fa38bd7a16b68cc350100000007535251635365636195df1603b61c45010000000002ab65bf6a310400000000026352fcbba10200000000016aa30b7ff0", "5351", 0, 1552495929, "9eb8adf2caecb4bf9ac59d7f46bd20e83258472db2f569ee91aba4cf5ee78e29"],
+ ["c3325c9b012f659466626ca8f3c61dfd36f34670abc054476b7516a1839ec43cd0870aa0c0000000000753525265005351e7e3f04b0112650500000000000363ac6300000000", "acac", 0, -68961433, "5ca70e727d91b1a42b78488af2ed551642c32d3de4712a51679f60f1456a8647"],
+ ["2333e54c044370a8af16b9750ac949b151522ea6029bacc9a34261599549581c7b4e5ece470000000007510052006563abffffffff80630fc0155c750ce20d0ca4a3d0c8e8d83b014a5b40f0b0be0dd4c63ac28126020000000465000000ffffffff1b5f1433d38cdc494093bb1d62d84b10abbdae57e3d04e82e600857ab3b1dc990300000003515100b76564be13e4890a908ea7508afdad92ec1b200a9a67939fadce6eb7a29eb4550a0a28cb0300000001acffffffff02926c930300000000016373800201000000000153d27ee740", "ab6365ab516a53", 3, 598653797, "2be27a686eb7940dd32c44ff3a97c1b28feb7ab9c5c0b1593b2d762361cfc2db"],
+ ["b500ca48011ec57c2e5252e5da6432089130603245ffbafb0e4c5ffe6090feb629207eeb0e010000000652ab6a636aab8302c9d2042b44f40500000000015278c05a050000000004ac5251524be080020000000007636aac63ac5252c93a9a04000000000965ab6553636aab5352d91f9ddb", "52005100", 0, -2024394677, "49c8a6940a461cc7225637f1e512cdd174c99f96ec05935a59637ededc77124c"],
+ ["f52ff64b02ee91adb01f3936cc42e41e1672778962b68cf013293d649536b519bc3271dd2c00000000020065afee11313784849a7c15f44a61cd5fd51ccfcdae707e5896d131b082dc9322a19e12858501000000036aac654e8ca882022deb7c020000000006006a515352abd3defc0000000000016300000000", "63520063", 0, 1130989496, "7f208df9a5507e98c62cebc5c1e2445eb632e95527594929b9577b53363e96f6"],
+ ["ab7d6f36027a7adc36a5cf7528fe4fb5d94b2c96803a4b38a83a675d7806dda62b380df86a0000000003000000ffffffff5bc00131e29e22057c04be854794b4877dda42e416a7a24706b802ff9da521b20000000007ac6a0065ac52ac957cf45501b9f06501000000000500ac6363ab25f1110b", "00526500536a635253", 0, 911316637, "5fa09d43c8aef6f6fa01c383a69a5a61a609cd06e37dce35a39dc9eae3ddfe6c"],
+ ["f940888f023dce6360263c850372eb145b864228fdbbb4c1186174fa83aab890ff38f8c9a90300000000ffffffff01e80ccdb081e7bbae1c776531adcbfb77f2e5a7d0e5d0d0e2e6c8758470e85f00000000020053ffffffff03b49088050000000004656a52ab428bd604000000000951630065ab63ac636a0cbacf0400000000070063ac5265ac53d6e16604", "ac63", 0, 39900215, "713ddeeefcfe04929e7b6593c792a4efbae88d2b5280d1f0835d2214eddcbad6"],
+ ["530ecd0b01ec302d97ef6f1b5a6420b9a239714013e20d39aa3789d191ef623fc215aa8b940200000005ac5351ab6a3823ab8202572eaa04000000000752ab6a51526563fd8a270100000000036a006581a798f0", "525153656a0063", 0, 1784562684, "fe42f73a8742676e640698222b1bd6b9c338ff1ccd766d3d88d7d3c6c6ac987e"],
+ ["5d781d9303acfcce964f50865ddfddab527ea971aee91234c88e184979985c00b4de15204b0100000003ab6352a009c8ab01f93c8ef2447386c434b4498538f061845862c3f9d5751ad0fce52af442b3a902000000045165ababb909c66b5a3e7c81b3c45396b944be13b8aacfc0204f3f3c105a66fa8fa6402f1b5efddb01000000096a65ac636aacab656ac3c677c402b79fa4050000000004006aab5133e35802000000000751ab635163ab0078c2e025", "6aac51636a6a005265", 0, -882306874, "551ce975d58647f10adefb3e529d9bf9cda34751627ec45e690f135ef0034b95"],
+ ["25ee54ef0187387564bb86e0af96baec54289ca8d15e81a507a2ed6668dc92683111dfb7a50100000004005263634cecf17d0429aa4d000000000007636a6aabab5263daa75601000000000251ab4df70a01000000000151980a890400000000065253ac6a006377fd24e3", "65ab", 0, 797877378, "069f38fd5d47abff46f04ee3ae27db03275e9aa4737fa0d2f5394779f9654845"],
+ ["a9c57b1a018551bcbc781b256642532bbc09967f1cbe30a227d352a19365d219d3f11649a3030000000451655352b140942203182894030000000006ab00ac6aab654add350400000000003d379505000000000553abacac00e1739d36", "5363", 0, -1069721025, "6da32416deb45a0d720a1dbe6d357886eabc44029dd5db74d50feaffbe763245"],
+ ["05c4fb94040f5119dc0b10aa9df054871ed23c98c890f1e931a98ffb0683dac45e98619fdc0200000007acab6a525263513e7495651c9794c4d60da835d303eb4ee6e871f8292f6ad0b32e85ef08c9dc7aa4e03c9c010000000500ab52acacfffffffffee953259cf14ced323fe8d567e4c57ba331021a1ef5ac2fa90f7789340d7c550100000007ac6aacac6a6a53ffffffff08d9dc820d00f18998af247319f9de5c0bbd52a475ea587f16101af3afab7c210100000003535363569bca7c0468e34f00000000000863536353ac51ac6584e319010000000006650052ab6a533debea030000000003ac0053ee7070020000000006ac52005253ac00000000", "6351005253", 2, 1386916157, "76c4013c40bfa1481badd9d342b6d4b8118de5ab497995fafbf73144469e5ff0"],
+ ["c95ab19104b63986d7303f4363ca8f5d2fa87c21e3c5d462b99f1ebcb7c402fc012f5034780000000009006aac63ac65655265ffffffffbe91afa68af40a8700fd579c86d4b706c24e47f7379dad6133de389f815ef7f501000000046aac00abffffffff1520db0d81be4c631878494668d258369f30b8f2b7a71e257764e9a27f24b48701000000076a515100535300b0a989e1164db9499845bac01d07a3a7d6d2c2a76e4c04abe68f808b6e2ef5068ce6540e0100000009ac53636a63ab65656affffffff0309aac6050000000005ab6563656a6067e8020000000003ac536aec91c8030000000009655251ab65ac6a53acc7a45bc5", "63526a65abac", 1, 512079270, "fb7eca81d816354b6aedec8cafc721d5b107336657acafd0d246049556f9e04b"],
+ ["ca66ae10049533c2b39f1449791bd6d3f039efe0a121ab7339d39ef05d6dcb200ec3fb2b3b020000000465006a53ffffffff534b8f97f15cc7fb4f4cea9bf798472dc93135cd5b809e4ca7fe4617a61895980100000000ddd83c1dc96f640929dd5e6f1151dab1aa669128591f153310d3993e562cc7725b6ae3d903000000046a52536582f8ccddb8086d8550f09128029e1782c3f2624419abdeaf74ecb24889cc45ac1a64492a0100000002516a4867b41502ee6ccf03000000000752acacab52ab6a4b7ba80000000000075151ab0052536300000000", "6553", 2, -62969257, "8085e904164ab9a8c20f58f0d387f6adb3df85532e11662c03b53c3df8c943cb"],
+ ["ba646d0b0453999f0c70cb0430d4cab0e2120457bb9128ed002b6e9500e9c7f8d7baa20abe0200000001652a4e42935b21db02b56bf6f08ef4be5adb13c38bc6a0c3187ed7f6197607ba6a2c47bc8a03000000040052516affffffffa55c3cbfc19b1667594ac8681ba5d159514b623d08ed4697f56ce8fcd9ca5b0b00000000096a6a5263ac655263ab66728c2720fdeabdfdf8d9fb2bfe88b295d3b87590e26a1e456bad5991964165f888c03a0200000006630051ac00acffffffff0176fafe0100000000070063acac65515200000000", "63", 1, 2002322280, "9db4e320208185ee70edb4764ee195deca00ba46412d5527d9700c1cf1c3d057"],
+ ["2ddb8f84039f983b45f64a7a79b74ff939e3b598b38f436def7edd57282d0803c7ef34968d02000000026a537eb00c4187de96e6e397c05f11915270bcc383959877868ba93bac417d9f6ed9f627a7930300000004516551abffffffffacc12f1bb67be3ae9f1d43e55fda8b885340a0df1175392a8bbd9f959ad3605003000000025163ffffffff02ff0f4700000000000070bd99040000000003ac53abf8440b42", "", 2, -393923011, "0133f1a161363b71dfb3a90065c7128c56bd0028b558b610142df79e055ab5c7"],
+ ["b21fc15403b4bdaa994204444b59323a7b8714dd471bd7f975a4e4b7b48787e720cbd1f5f00000000000ffffffff311533001cb85c98c1d58de0a5fbf27684a69af850d52e22197b0dc941bc6ca9030000000765ab6363ab5351a8ae2c2c7141ece9a4ff75c43b7ea9d94ec79b7e28f63e015ac584d984a526a73fe1e04e0100000007526352536a5365ffffffff02a0a9ea030000000002ab52cfc4f300000000000465525253e8e0f342", "000000", 1, 1305253970, "d1df1f4bba2484cff8a816012bb6ec91c693e8ca69fe85255e0031711081c46a"],
+ ["d1704d6601acf710b19fa753e307cfcee2735eada0d982b5df768573df690f460281aad12d0000000007656300005100acffffffff0232205505000000000351ab632ca1bc0300000000016300000000", "ac65ab65ab51", 0, 165179664, "40b4f03c68288bdc996011b0f0ddb4b48dc3be6762db7388bdc826113266cd6c"],
+ ["d2f6c096025cc909952c2400bd83ac3d532bfa8a1f8f3e73c69b1fd7b8913379793f3ce92202000000076a00ab6a53516ade5332d81d58b22ed47b2a249ab3a2cb3a6ce9a6b5a6810e18e3e1283c1a1b3bd73e3ab00300000002acabffffffff01a9b2d40500000000056352abab00dc4b7f69", "ab0065", 0, -78019184, "2ef025e907f0fa454a2b48a4f3b81346ba2b252769b5c35d742d0c8985e0bf5e"],
+ ["3e6db1a1019444dba461247224ad5933c997256d15c5d37ade3d700506a0ba0a57824930d7010000000852ab6500ab00ac00ffffffff03389242020000000001aba8465a0200000000086a6a636a5100ab52394e6003000000000953ac51526351000053d21d9800", "abababacab53ab65", 0, 1643661850, "1f8a3aca573a609f4aea0c69522a82fcb4e15835449da24a05886ddc601f4f6a"],
+ ["f821a042036ad43634d29913b77c0fc87b4af593ac86e9a816a9d83fd18dfcfc84e1e1d57102000000076a63ac52006351ffffffffbcdaf490fc75086109e2f832c8985716b3a624a422cf9412fe6227c10585d21203000000095252abab5352ac526affffffff2efed01a4b73ad46c7f7bc7fa3bc480f8e32d741252f389eaca889a2e9d2007e000000000353ac53ffffffff032ac8b3020000000009636300000063516300d3d9f2040000000006510065ac656aafa5de0000000000066352ab5300ac9042b57d", "525365", 1, 667065611, "0d17a92c8d5041ba09b506ddf9fd48993be389d000aad54f9cc2a44fcc70426b"],
+ ["58e3f0f704a186ef55d3919061459910df5406a9121f375e7502f3be872a449c3f2bb058380100000000f0e858da3ac57b6c973f889ad879ffb2bd645e91b774006dfa366c74e2794aafc8bbc871010000000751ac65516a515131a68f120fd88ca08687ceb4800e1e3fbfea7533d34c84fef70cc5a96b648d580369526d000000000600ac00515363f6191d5b3e460fa541a30a6e83345dedfa3ed31ad8574d46d7bbecd3c9074e6ba5287c24020000000151e3e19d6604162602010000000004005100ac71e17101000000000065b5e90300000000040053ab53f6b7d101000000000200ac00000000", "6563ab", 1, -669018604, "8221d5dfb75fc301a80e919e158e0b1d1e86ffb08870a326c89408d9bc17346b"],
+ ["efec1cce044a676c1a3d973f810edb5a9706eb4cf888a240f2b5fb08636bd2db482327cf500000000005ab51656a52ffffffff46ef019d7c03d9456e5134eb0a7b5408d274bd8e33e83df44fab94101f7c5b650200000009ac5100006353630051407aadf6f5aaffbd318fdbbc9cae4bd883e67d524df06bb006ce2f7c7e2725744afb76960100000005536aab53acec0d64eae09e2fa1a7c4960354230d51146cf6dc45ee8a51f489e20508a785cbe6ca86fc000000000651536a516300ffffffff014ef598020000000006636aac655265a6ae1b75", "53516a5363526563ab", 2, -1823982010, "13e8b5ab4e5b2ceeff0045c625e19898bda2d39fd7af682e2d1521303cfe1154"],
+ ["3c436c2501442a5b700cbc0622ee5143b34b1b8021ea7bbc29e4154ab1f5bdfb3dff9d640501000000086aab5251ac5252acffffffff0170b9a20300000000066aab6351525114b13791", "63acabab52ab51ac65", 0, -2140612788, "87ddf1f9acb6640448e955bd1968f738b4b3e073983af7b83394ab7557f5cd61"],
+ ["d62f183e037e0d52dcf73f9b31f70554bce4f693d36d17552d0e217041e01f15ad3840c838000000000963acac6a6a6a63ab63ffffffffabdfb395b6b4e63e02a763830f536fc09a35ff8a0cf604021c3c751fe4c88f4d0300000006ab63ab65ac53aa4d30de95a2327bccf9039fb1ad976f84e0b4a0936d82e67eafebc108993f1e57d8ae39000000000165ffffffff04364ad30500000000036a005179fd84010000000007ab636aac6363519b9023030000000008510065006563ac6acd2a4a02000000000000000000", "52", 1, 595020383, "da8405db28726dc4e0f82b61b2bfd82b1baa436b4e59300305cc3b090b157504"],
+ ["44c200a5021238de8de7d80e7cce905606001524e21c8d8627e279335554ca886454d692e6000000000500acac52abbb8d1dc876abb1f514e96b21c6e83f429c66accd961860dc3aed5071e153e556e6cf076d02000000056553526a51870a928d0360a580040000000004516a535290e1e302000000000851ab6a00510065acdd7fc5040000000007515363ab65636abb1ec182", "6363", 0, -785766894, "ed53cc766cf7cb8071cec9752460763b504b2183442328c5a9761eb005c69501"],
+ ["d682d52d034e9b062544e5f8c60f860c18f029df8b47716cabb6c1b4a4b310a0705e754556020000000400656a0016eeb88eef6924fed207fba7ddd321ff3d84f09902ff958c815a2bf2bb692eb52032c4d803000000076365ac516a520099788831f8c8eb2552389839cfb81a9dc55ecd25367acad4e03cfbb06530f8cccf82802701000000085253655300656a53ffffffff02d543200500000000056a510052ac03978b05000000000700ac51525363acfdc4f784", "", 2, -696035135, "e1a256854099907050cfee7778f2018082e735a1f1a3d91437584850a74c87bb"],
+ ["e8c0dec5026575ddf31343c20aeeca8770afb33d4e562aa8ee52eeda6b88806fdfd4fe0a97030000000953acabab65ab516552ffffffffdde122c2c3e9708874286465f8105f43019e837746686f442666629088a970e0010000000153ffffffff01f98eee0100000000025251fe87379a", "63", 1, 633826334, "abe441209165d25bc6d8368f2e7e7dc21019056719fef1ace45542aa2ef282e2"],
+ ["b288c331011c17569293c1e6448e33a64205fc9dc6e35bc756a1ac8b97d18e912ea88dc0770200000007635300ac6aacabfc3c890903a3ccf8040000000004656500ac9c65c9040000000009ab6a6aabab65abac63ac5f7702000000000365005200000000", "526a63", 0, 1574937329, "0dd1bd5c25533bf5f268aa316ce40f97452cca2061f0b126a59094ca5b65f7a0"],
+ ["fc0a092003cb275fa9a25a72cf85d69c19e4590bfde36c2b91cd2c9c56385f51cc545530210000000004ab530063ffffffff729b006eb6d14d6e5e32b1c376acf1c62830a5d9246da38dbdb4db9f51fd1c74020000000463636500ffffffff0ae695c6d12ab7dcb8d3d4b547b03f178c7268765d1de9af8523d244e3836b12030000000151ffffffff0115c1e20100000000066a6aabac6a6a1ff59aec", "ab0053ac", 0, 931831026, "73fe22099c826c34a74edf45591f5d7b3a888c8178cd08facdfd96a9a681261c"],
+ ["0fcae7e004a71a4a7c8f66e9450c0c1785268679f5f1a2ee0fb3e72413d70a9049ecff75de020000000452005251ffffffff99c8363c4b95e7ec13b8c017d7bb6e80f7c04b1187d6072961e1c2479b1dc0320200000000ffffffff7cf03b3d66ab53ed740a70c5c392b84f780fff5472aee82971ac3bfeeb09b2df0200000006ab5265636a0058e4fe9257d7c7c7e82ff187757c6eadc14cceb6664dba2de03a018095fd3006682a5b9600000000056353536a636de26b2303ff76de010000000001acdc0a2e020000000001ab0a53ed020000000007530063ab51510088417307", "ac6aacab5165535253", 2, -902160694, "eea96a48ee572aea33d75d0587ce954fcfb425531a7da39df26ef9a6635201be"],
+ ["612701500414271138e30a46b7a5d95c70c78cc45bf8e40491dac23a6a1b65a51af04e6b94020000000451655153ffffffffeb72dc0e49b2fad3075c19e1e6e4b387f1365dca43d510f6a02136318ddecb7f0200000003536352e115ffc4f9bae25ef5baf534a890d18106fb07055c4d7ec9553ba89ed1ac2101724e507303000000080063006563acabac2ff07f69a080cf61a9d19f868239e6a4817c0eeb6a4f33fe254045d8af2bca289a8695de0300000000430736c404d317840500000000086a00abac5351ab65306e0503000000000963ab0051536aabab6a6c8aca01000000000565516351ab5dcf960100000000016a00000000", "ab", 2, -604581431, "5ec805e74ee934aa815ca5f763425785ae390282d46b5f6ea076b6ad6255a842"],
+ ["6b68ba00023bb4f446365ea04d68d48539aae66f5b04e31e6b38b594d2723ab82d44512460000000000200acffffffff5dfc6febb484fff69c9eeb7c7eb972e91b6d949295571b8235b1da8955f3137b020000000851ac6352516a535325828c8a03365da801000000000800636aabac6551ab0f594d03000000000963ac536365ac63636a45329e010000000005abac53526a00000000", "005151", 0, 1317038910, "42f5ba6f5fe1e00e652a08c46715871dc4b40d89d9799fd7c0ea758f86eab6a7"],
+ ["aff5850c0168a67296cc790c1b04a9ed9ad1ba0469263a9432fcb53676d1bb4e0eea8ea1410100000005ac65526a537d5fcb1d01d9c26d0200000000065265ab5153acc0617ca1", "51ab650063", 0, 1712981774, "8449d5247071325e5f8edcc93cb9666c0fecabb130ce0e5bef050575488477eb"],
+ ["e6d6b9d8042c27aec99af8c12b6c1f7a80453e2252c02515e1f391da185df0874e133696b50300000006ac5165650065ffffffff6a4b60a5bfe7af72b198eaa3cde2e02aa5fa36bdf5f24ebce79f6ecb51f3b554000000000652656aababac2ec4c5a6cebf86866b1fcc4c5bd5f4b19785a8eea2cdfe58851febf87feacf6f355324a80100000001537100145149ac1e287cef62f6f5343579189fad849dd33f25c25bfca841cb696f10c5a34503000000046a636a63df9d7c4c018d96e20100000000015100000000", "53ab", 1, -1924777542, "f98f95d0c5ec3ac3e699d81f6c440d2e7843eab15393eb023bc5a62835d6dcea"],
+ ["046ac25e030a344116489cc48025659a363da60bc36b3a8784df137a93b9afeab91a04c1ed020000000951ab0000526a65ac51ffffffff6c094a03869fde55b9a8c4942a9906683f0a96e2d3e5a03c73614ea3223b2c29020000000500ab636a6affffffff3da7aa5ecef9071600866267674b54af1740c5aeb88a290c459caa257a2683cb0000000004ab6565ab7e2a1b900301b916030000000005abac63656308f4ed03000000000852ab53ac63ac51ac73d620020000000003ab00008deb1285", "6a", 2, 1299505108, "f79e6b776e2592bad45ca328c54abf14050c241d8f822d982c36ea890fd45757"],
+ ["bd515acd0130b0ac47c2d87f8d65953ec7d657af8d96af584fc13323d0c182a2e5f9a96573000000000652ac51acac65ffffffff0467aade000000000003655363dc577d050000000006515252ab5300137f60030000000007535163530065004cdc860500000000036a5265241bf53e", "acab", 0, 621090621, "771d4d87f1591a13d77e51858c16d78f1956712fe09a46ff1abcabbc1e7af711"],
+ ["ff1ae37103397245ac0fa1c115b079fa20930757f5b6623db3579cb7663313c2dc4a3ffdb300000000076353656a000053ffffffff83c59e38e5ad91216ee1a312d15b4267bae2dd2e57d1a3fd5c2f0f809eeb5d46010000000800abab6a6a53ab51ffffffff9d5e706c032c1e0ca75915f8c6686f64ec995ebcd2539508b7dd8abc3e4d7d2a01000000006b2bdcda02a8fe070500000000045253000019e31d04000000000700ab63acab526a00000000", "53656aab6a525251", 0, 881938872, "726bb88cdf3af2f7603a31f33d2612562306d08972a4412a55dbbc0e3363721c"],
+ ["ff5400dd02fec5beb9a396e1cbedc82bedae09ed44bae60ba9bef2ff375a6858212478844b03000000025253ffffffff01e46c203577a79d1172db715e9cc6316b9cfc59b5e5e4d9199fef201c6f9f0f000000000900ab6552656a5165acffffffff02e8ce62040000000002515312ce3e00000000000251513f119316", "", 0, 1541581667, "1e0da47eedbbb381b0e0debbb76e128d042e02e65b11125e17fd127305fc65cd"],
+ ["28e3daa603c03626ad91ffd0ff927a126e28d29db5012588b829a06a652ea4a8a5732407030200000004ab6552acffffffff8e643146d3d0568fc2ad854fd7864d43f6f16b84e395db82b739f6f5c84d97b40000000004515165526b01c2dc1469db0198bd884e95d8f29056c48d7e74ff9fd37a9dec53e44b8769a6c99c030200000009ab006a516a53630065eea8738901002398000000000007ac5363516a51abeaef12f5", "52ab52515253ab", 2, 1687390463, "55591346aec652980885a558cc5fc2e3f8d21cbd09f314a798e5a7ead5113ea6"],
+ ["b54bf5ac043b62e97817abb892892269231b9b220ba08bc8dbc570937cd1ea7cdc13d9676c010000000451ab5365a10adb7b35189e1e8c00b86250f769319668189b7993d6bdac012800f1749150415b2deb0200000003655300ffffffff60b9f4fb9a7e17069fd00416d421f804e2ef2f2c67de4ca04e0241b9f9c1cc5d0200000003ab6aacfffffffff048168461cce1d40601b42fbc5c4f904ace0d35654b7cc1937ccf53fe78505a0100000008526563525265abacffffffff01dbf4e6040000000007acac656553636500000000", "63", 2, 882302077, "f5b38b0f06e246e47ce622e5ee27d5512c509f8ac0e39651b3389815eff2ab93"],
+ ["ebf628b30360bab3fa4f47ce9e0dcbe9ceaf6675350e638baff0c2c197b2419f8e4fb17e16000000000452516365ac4d909a79be207c6e5fb44fbe348acc42fc7fe7ef1d0baa0e4771a3c4a6efdd7e2c118b0100000003acacacffffffffa6166e9101f03975721a3067f1636cc390d72617be72e5c3c4f73057004ee0ee010000000863636a6a516a5252c1b1e82102d8d54500000000000153324c900400000000015308384913", "0063516a51", 1, -1658428367, "eb2d8dea38e9175d4d33df41f4087c6fea038a71572e3bad1ea166353bf22184"],
+ ["d6a8500303f1507b1221a91adb6462fb62d741b3052e5e7684ea7cd061a5fc0b0e93549fa50100000004acab65acfffffffffdec79bf7e139c428c7cfd4b35435ae94336367c7b5e1f8e9826fcb0ebaaaea30300000000ffffffffd115fdc00713d52c35ea92805414bd57d1e59d0e6d3b79a77ee18a3228278ada020000000453005151ffffffff040231510300000000085100ac6a6a000063c6041c0400000000080000536a6563acac138a0b04000000000263abd25fbe03000000000900656a00656aac510000000000", "ac526aac6a00", 1, -2007972591, "13d12a51598b34851e7066cd93ab8c5212d60c6ed2dae09d91672c10ccd7f87c"],
+ ["658cb1c1049564e728291a56fa79987a4ed3146775fce078bd2e875d1a5ca83baf6166a82302000000056a656351ab2170e7d0826cbdb45fda0457ca7689745fd70541e2137bb4f52e7b432dcfe2112807bd720300000007006a0052536351ffffffff8715ca2977696abf86d433d5c920ef26974f50e9f4a20c584fecbb68e530af5101000000009e49d864155bf1d3c757186d29f3388fd89c7f55cc4d9158b4cf74ca27a35a1dd93f945502000000096a535353ac656351510d29fa870230b809040000000006ab6a6a526a633b41da050000000004ab6a6a65ed63bf62", "52acabac", 2, -1774073281, "53ab197fa7e27b8a3f99ff48305e67081eb90e95d89d7e92d80cee25a03a6689"],
+ ["e92492cc01aec4e62df67ea3bc645e2e3f603645b3c5b353e4ae967b562d23d6e043badecd0100000003acab65ffffffff02c7e5ea040000000002ab52e1e584010000000005536365515195d16047", "6551", 0, -424930556, "93c34627f526d73f4bea044392d1a99776b4409f7d3d835f23b03c358f5a61c2"],
+ ["02e242db04be2d8ced9179957e98cee395d4767966f71448dd084426844cbc6d15f2182e85030000000200650c8ffce3db9de9c3f9cdb9104c7cb26647a7531ad1ebf7591c259a9c9985503be50f8de30000000007ac6a51636a6353ffffffffa2e33e7ff06fd6469987ddf8a626853dbf30c01719efb259ae768f051f803cd30300000000fffffffffd69d8aead941683ca0b1ee235d09eade960e0b1df3cd99f850afc0af1b73e070300000001ab60bb602a011659670100000000076363526300acac00000000", "6353ab515251", 3, 1451100552, "bbc9069b8615f3a52ac8a77359098dcc6c1ba88c8372d5d5fe080b99eb781e55"],
+ ["b28d5f5e015a7f24d5f9e7b04a83cd07277d452e898f78b50aae45393dfb87f94a26ef57720200000008ababac630053ac52ffffffff046475ed040000000008ab5100526363ac65c9834a04000000000251abae26b30100000000040000ac65ceefb900000000000000000000", "ac6551ac6a536553", 0, -1756558188, "5848d93491044d7f21884eef7a244fe7d38886f8ae60df49ce0dfb2a342cd51a"],
+ ["efb8b09801f647553b91922a5874f8e4bb2ed8ddb3536ed2d2ed0698fac5e0e3a298012391030000000952ac005263ac52006affffffff04cdfa0f050000000007ac53ab51abac65b68d1b02000000000553ab65ac00d057d50000000000016a9e1fda010000000007ac63ac536552ac00000000", "6aac", 0, 1947322973, "603a9b61cd30fcea43ef0a5c18b88ca372690b971b379ee9e01909c336280511"],
+ ["68a59fb901c21946797e7d07a4a3ea86978ce43df0479860d7116ac514ba955460bae78fff0000000001abffffffff03979be80100000000036553639300bc040000000008006552006a656565cfa78d0000000000076552acab63ab5100000000", "ab65ab", 0, 995583673, "3b320dd47f2702452a49a1288bdc74a19a4b849b132b6cad9a1d945d87dfbb23"],
+ ["67761f2a014a16f3940dcb14a22ba5dc057fcffdcd2cf6150b01d516be00ef55ef7eb07a830100000004636a6a51ffffffff01af67bd050000000008526553526300510000000000", "6a00", 0, 1570943676, "079fa62e9d9d7654da8b74b065da3154f3e63c315f25751b4d896733a1d67807"],
+ ["e20fe96302496eb436eee98cd5a32e1c49f2a379ceb71ada8a48c5382df7c8cd88bdc47ced03000000016556aa0e180660925a841b457aed0aae47fca2a92fa1d7afeda647abf67198a3902a7c80dd00000000085152ac636a535265bd18335e01803c810100000000046500ac52f371025e", "6363ab", 1, -651254218, "2921a0e5e3ba83c57ba57c25569380c17986bf34c366ec216d4188d5ba8b0b47"],
+ ["4e1bd9fa011fe7aa14eee8e78f27c9fde5127f99f53d86bc67bdab23ca8901054ee8a8b6eb0300000009ac535153006a6a0063ffffffff044233670500000000000a667205000000000652ab636a51abe5bf35030000000003535351d579e505000000000700630065ab51ac3419ac30", "52abac52", 0, -1807563680, "4aae6648f856994bed252d319932d78db55da50d32b9008216d5366b44bfdf8a"],
+ ["ec02fbee03120d02fde12574649660c441b40d330439183430c6feb404064d4f507e704f3c0100000000ffffffffe108d99c7a4e5f75cc35c05debb615d52fac6e3240a6964a29c1704d98017fb60200000002ab63fffffffff726ec890038977adfc9dadbeaf5e486d5fcb65dc23acff0dd90b61b8e2773410000000002ac65e9dace55010f881b010000000005ac00ab650000000000", "51ac525152ac6552", 2, -1564046020, "3f988922d8cd11c7adff1a83ce9499019e5ab5f424752d8d361cf1762e04269b"],
+ ["23dbdcc1039c99bf11938d8e3ccec53b60c6c1d10c8eb6c31197d62c6c4e2af17f52115c3a0300000008636352000063ababffffffff17823880e1df93e63ad98c29bfac12e36efd60254346cac9d3f8ada020afc0620300000003ab63631c26f002ac66e86cd22a25e3ed3cb39d982f47c5118f03253054842daadc88a6c41a2e1500000000096a00ab636a53635163195314de015570fd0100000000096a5263acab5200005300000000", "ababac6a6553", 1, 11586329, "bd36a50e0e0a4ecbf2709e68daef41eddc1c0c9769efaee57910e99c0a1d1343"],
+ ["33b03bf00222c7ca35c2f8870bbdef2a543b70677e413ce50494ac9b22ea673287b6aa55c50000000005ab00006a52ee4d97b527eb0b427e4514ea4a76c81e68c34900a23838d3e57d0edb5410e62eeb8c92b6000000000553ac6aacac42e59e170326245c000000000009656553536aab516aabb1a10603000000000852ab52ab6a516500cc89c802000000000763ac6a63ac516300000000", "", 0, 557416556, "41bead1b073e1e9fee065dd612a617ca0689e8f9d3fed9d0acfa97398ebb404c"],
+ ["813eda1103ac8159850b4524ef65e4644e0fc30efe57a5db0c0365a30446d518d9b9aa8fdd0000000003656565c2f1e89448b374b8f12055557927d5b33339c52228f7108228149920e0b77ef0bcd69da60000000006abac00ab63ab82cdb7978d28630c5e1dc630f332c4245581f787936f0b1e84d38d33892141974c75b4750300000004ac53ab65ffffffff0137edfb02000000000000000000", "0063", 1, -1948560575, "71dfcd2eb7f2e6473aed47b16a6d5fcbd0af22813d892e9765023151e07771ec"],
+ ["9e45d9aa0248c16dbd7f435e8c54ae1ad086de50c7b25795a704f3d8e45e1886386c653fbf01000000025352fb4a1acefdd27747b60d1fb79b96d14fb88770c75e0da941b7803a513e6d4c908c6445c7010000000163ffffffff014069a8010000000001520a794fb3", "51ac005363", 1, -719113284, "0d31a221c69bd322ef7193dd7359ddfefec9e0a1521d4a8740326d46e44a5d6a"],
+ ["36e42018044652286b19a90e5dd4f8d9f361d0760d080c5c5add1970296ff0f1de630233c8010000000200ac39260c7606017d2246ee14ddb7611586178067e6a4be38e788e33f39a3a95a55a13a6775010000000352ac638bea784f7c2354ed02ea0b93f0240cdfb91796fa77649beee6f7027caa70778b091deee700000000066a65ac656363ffffffff4d9d77ab676d711267ef65363f2d192e1bd55d3cd37f2280a34c72e8b4c559d700000000056a006aab00001764e1020d30220100000000085252516aacab0053472097040000000009635353ab6a636a5100a56407a1", "006a536551ab53ab", 0, 827296034, "daec2af5622bbe220c762da77bab14dc75e7d28aa1ade9b7f100798f7f0fd97a"],
+ ["5e06159a02762b5f3a5edcdfc91fd88c3bff08b202e69eb5ba74743e9f4291c4059ab008200000000001ac348f5446bb069ef977f89dbe925795d59fb5d98562679bafd61f5f5f3150c3559582992d0000000008ab5165515353abac762fc67703847ec6010000000000e200cf040000000002abaca64b86010000000008520000515363acabb82b491b", "ab53525352ab6a", 0, -61819505, "75a7db0df41485a28bf6a77a37ca15fa8eccc95b5d6014a731fd8adb9ada0f12"],
+ ["a1948872013b543d6d902ccdeead231c585195214ccf5d39f136023855958436a43266911501000000086aac006a6a6a51514951c9b2038a538a04000000000452526563c0f345050000000007526a5252ac526af9be8e03000000000752acac51ab006306198db2", "ab6353", 0, -326384076, "ced7ef84aad4097e1eb96310e0d1c8e512cfcb392a01d9010713459b23bc0cf4"],
+ ["c3efabba03cb656f154d1e159aa4a1a4bf9423a50454ebcef07bc3c42a35fb8ad84014864d0000000000d1cc73d260980775650caa272e9103dc6408bdacaddada6b9c67c88ceba6abaa9caa2f7d020000000553536a5265ffffffff9f946e8176d9b11ff854b76efcca0a4c236d29b69fb645ba29d406480427438e01000000066a0065005300ffffffff040419c0010000000003ab6a63cdb5b6010000000009006300ab5352656a63f9fe5e050000000004acac5352611b980100000000086a00acac00006a512d7f0c40", "0053", 0, -59089911, "c503001c16fbff82a99a18d88fe18720af63656fccd8511bca1c3d0d69bd7fc0"],
+ ["efb55c2e04b21a0c25e0e29f6586be9ef09f2008389e5257ebf2f5251051cdc6a79fce2dac020000000351006affffffffaba73e5b6e6c62048ba5676d18c33ccbcb59866470bb7911ccafb2238cfd493802000000026563ffffffffe62d7cb8658a6eca8a8babeb0f1f4fa535b62f5fc0ec70eb0111174e72bbec5e0300000009abababac516365526affffffffbf568789e681032d3e3be761642f25e46c20322fa80346c1146cb47ac999cf1b0300000000b3dbd55902528828010000000001ab0aac7b0100000000015300000000", "acac52", 3, 1638140535, "e84444d91580da41c8a7dcf6d32229bb106f1be0c811b2292967ead5a96ce9d4"],
+ ["91d3b21903629209b877b3e1aef09cd59aca6a5a0db9b83e6b3472aceec3bc2109e64ab85a0200000003530065ffffffffca5f92de2f1b7d8478b8261eaf32e5656b9eabbc58dcb2345912e9079a33c4cd010000000700ab65ab00536ad530611da41bbd51a389788c46678a265fe85737b8d317a83a8ff7a839debd18892ae5c80300000007ab6aac65ab51008b86c501038b8a9a05000000000263525b3f7a040000000007ab535353ab00abd4e3ff04000000000665ac51ab65630b7b656f", "6551525151516a00", 2, 499657927, "ef4bd7622eb7b2bbbbdc48663c1bc90e01d5bde90ff4cb946596f781eb420a0c"],
+ ["5d5c41ad0317aa7e40a513f5141ad5fc6e17d3916eebee4ddb400ddab596175b41a111ead20100000005536a5265acffffffff900ecb5e355c5c9f278c2c6ea15ac1558b041738e4bffe5ae06a9346d66d5b2b00000000080000ab636a65ab6affffffff99f4e08305fa5bd8e38fb9ca18b73f7a33c61ff7b3c68e696b30a04fea87f3ca000000000163d3d1760d019fc13a00000000000000000000", "ab53acabab6aac6a52", 2, 1007461922, "4012f5ff2f1238a0eb84854074670b4703238ebc15bfcdcd47ffa8498105fcd9"],
+ ["ceecfa6c02b7e3345445b82226b15b7a097563fa7d15f3b0c979232b138124b62c0be007890200000009abac51536a63525253ffffffffbae481ccb4f15d94db5ec0d8854c24c1cc8642bd0c6300ede98a91ca13a4539a0200000001ac50b0813d023110f5020000000006acabac526563e2b0d0040000000009656aac0063516a536300000000", "0063526500", 0, -1862053821, "e1600e6df8a6160a79ac32aa40bb4644daa88b5f76c0d7d13bf003327223f70c"],
+ ["ae62d5fd0380c4083a26642159f51af24bf55dc69008e6b7769442b6a69a603edd980a33000000000005ab5100ab53ffffffff49d048324d899d4b8ed5e739d604f5806a1104fede4cb9f92cc825a7fa7b4bfe0200000005536a000053ffffffff42e5cea5673c650881d0b4005fa4550fd86de5f21509c4564a379a0b7252ac0e0000000007530000526a53525f26a68a03bfacc3010000000000e2496f000000000009ab5253acac52636563b11cc600000000000700510065526a6a00000000", "abab", 1, -1600104856, "05cf0ec9c61f1a15f651a0b3c5c221aa543553ce6c804593f43bb5c50bb91ffb"],
+ ["f06f64af04fdcb830464b5efdb3d5ee25869b0744005375481d7b9d7136a0eb8828ad1f0240200000003516563fffffffffd3ba192dabe9c4eb634a1e3079fca4f072ee5ceb4b57deb6ade5527053a92c5000000000165ffffffff39f43401a36ba13a5c6dd7f1190e793933ae32ee3bf3e7bfb967be51e681af760300000009650000536552636a528e34f50b21183952cad945a83d4d56294b55258183e1627d6e8fb3beb8457ec36cadb0630000000005abab530052334a7128014bbfd10100000000085352ab006a63656afc424a7c", "53650051635253ac00", 2, 313255000, "d309da5afd91b7afa257cfd62df3ca9df036b6a9f4b38f5697d1daa1f587312b"],
+ ["6dfd2f98046b08e7e2ef5fff153e00545faf7076699012993c7a30cb1a50ec528281a9022f030000000152ffffffff1f535e4851920b968e6c437d84d6ecf586984ebddb7d5db6ae035bd02ba222a8010000000651006a53ab51605072acb3e17939fa0737bc3ee43bc393b4acd58451fc4ffeeedc06df9fc649828822d5010000000253525a4955221715f27788d302382112cf60719be9ae159c51f394519bd5f7e70a4f9816c7020200000009526a6a51636aab656a36d3a5ff0445548e0100000000086a6a00516a52655167030b050000000004ac6a63525cfda8030000000000e158200000000000010000000000", "535263ac6a65515153", 3, 585774166, "72b7da10704c3ca7d1deb60c31b718ee12c70dc9dfb9ae3461edce50789fe2ba"],
+ ["187eafed01389a45e75e9dda526d3acbbd41e6414936b3356473d1f9793d161603efdb45670100000002ab00ffffffff04371c8202000000000563630063523b3bde02000000000753516563006300e9e765010000000005516aac656a373f9805000000000665525352acab08d46763", "ab", 0, 122457992, "393aa6c758e0eed15fa4af6d9e2d7c63f49057246dbb92b4268ec24fc87301ca"],
+ ["7d50b977035d50411d814d296da9f7965ddc56f3250961ca5ba805cadd0454e7c521e31b0300000000003d0416c2cf115a397bacf615339f0e54f6c35ffec95aa009284d38390bdde1595cc7aa7c0100000005ab52ac5365ffffffff4232c6e796544d5ac848c9dc8d25cfa74e32e847a5fc74c74d8f38ca51188562030000000653ac51006a51ffffffff016bd8bb00000000000465ab5253163526f3", "51ab526a00005353", 1, -1311316785, "60b7544319b42e4159976c35c32c2644f0adf42eff13be1dc2f726fc0b6bb492"],
+ ["2a45cd1001bf642a2315d4a427eddcc1e2b0209b1c6abd2db81a800c5f1af32812de42032702000000050051525200ffffffff032177db050000000005530051abac49186f000000000004ab6aab00645c0000000000000765655263acabac00000000", "6a65", 0, -1774715722, "6a9ac3f7da4c7735fbc91f728b52ecbd602233208f96ac5592656074a5db118a"],
+ ["479358c202427f3c8d19e2ea3def6d6d3ef2281b4a93cd76214f0c7d8f040aa042fe19f71f0300000001abffffffffa2709be556cf6ecaa5ef530df9e4d056d0ed57ce96de55a5b1f369fa40d4e74a020000000700006a51635365c426be3f02af578505000000000363ab63fd8f590500000000065153abac53632dfb14b3", "520063ab51", 1, -763226778, "cfe147982afacde044ce66008cbc5b1e9f0fd9b8ed52b59fc7c0fecf95a39b0e"],
+ ["76179a8e03bec40747ad65ab0f8a21bc0d125b5c3c17ad5565556d5cb03ade7c83b4f32d98030000000151ffffffff99b900504e0c02b97a65e24f3ad8435dfa54e3c368f4e654803b756d011d24150200000003ac5353617a04ac61bb6cf697cfa4726657ba35ed0031432da8c0ffb252a190278830f9bd54f0320100000006656551005153c8e8fc8803677c77020000000007ac6553535253ac70f442030000000001535be0f20200000000026300bf46cb3a", "6aab52", 1, -58495673, "35e94b3776a6729d20aa2f3ddeeb06d3aad1c14cc4cde52fd21a4efc212ea16c"],
+ ["75ae53c2042f7546223ce5d5f9e00a968ddc68d52e8932ef2013fa40ce4e8c6ed0b6195cde01000000056563ac630079da0452c20697382e3dba6f4fc300da5f52e95a9dca379bb792907db872ba751b8024ee0300000009655151536500005163ffffffffe091b6d43f51ff00eff0ccfbc99b72d3aff208e0f44b44dfa5e1c7322cfc0c5f01000000075200005363ab63ffffffff7e96c3b83443260ac5cfd18258574fbc4225c630d3950df812bf51dceaeb0f9103000000065365655165639a6bf70b01b3e14305000000000563530063ac00000000", "6300ab00ac", 2, 982422189, "ee4ea49d2aae0dbba05f0b9785172da54408eb1ec67d36759ff7ed25bfc28766"],
+ ["1cdfa01e01e1b8078e9c2b0ca5082249bd18fdb8b629ead659adedf9a0dd5a04031871ba120200000008525351536565ab6affffffff011e28430200000000076a5363636aac52b2febd4a", "abacac63656300", 0, 387396350, "299dcaac2bdaa627eba0dfd74767ee6c6f27c9200b49da8ff6270b1041669e7e"],
+ ["cc28c1810113dfa6f0fcd9c7d9c9a30fb6f1d774356abeb527a8651f24f4e6b25cf763c4e00300000003ab636affffffff02dfc6050000000000080053636351ab0052afd56903000000000453ab5265f6c90d99", "006551abacacac", 0, 1299280838, "a4c0773204ab418a939e23f493bd4b3e817375d133d307609e9782f2cc38dbcf"],
+ ["ca816e7802cd43d66b9374cd9bf99a8da09402d69c688d8dcc5283ace8f147e1672b757e020200000005516aabab5240fb06c95c922342279fcd88ba6cd915933e320d7becac03192e0941e0345b79223e89570300000004005151ac353ecb5d0264dfbd010000000005ac6aacababd5d70001000000000752ac53ac6a5151ec257f71", "63ac", 1, 774695685, "cc180c4f797c16a639962e7aec58ec4b209853d842010e4d090895b22e7a7863"],
+ ["b42b955303942fedd7dc77bbd9040aa0de858afa100f399d63c7f167b7986d6c2377f66a7403000000066aac00525100ffffffff0577d04b64880425a3174055f94191031ad6b4ca6f34f6da9be7c3411d8b51fc000000000300526a6391e1cf0f22e45ef1c44298523b516b3e1249df153590f592fcb5c5fc432dc66f3b57cb03000000046a6aac65ffffffff0393a6c9000000000004516a65aca674ac0400000000046a525352c82c370000000000030053538e577f89", "", 1, -1237094944, "566953eb806d40a9fb684d46c1bf8c69dea86273424d562bd407b9461c8509af"],
+ ["92c9fe210201e781b72554a0ed5e22507fb02434ddbaa69aff6e74ea8bad656071f1923f3f02000000056a63ac6a514470cef985ba83dcb8eee2044807bedbf0d983ae21286421506ae276142359c8c6a34d68020000000863ac63525265006aa796dd0102ca3f9d05000000000800abab52ab535353cd5c83010000000007ac00525252005322ac75ee", "5165", 0, 97879971, "6e6307cef4f3a9b386f751a6f40acebab12a0e7e17171d2989293cbec7fd45c2"],
+ ["ccca1d5b01e40fe2c6b3ee24c660252134601dab785b8f55bd6201ffaf2fddc7b3e2192325030000000365535100496d4703b4b66603000000000665535253ac633013240000000000015212d2a502000000000951abac636353636a5337b82426", "0052", 0, -1691630172, "577bf2b3520b40aef44899a20d37833f1cded6b167e4d648fc5abe203e43b649"],
+ ["bc1a7a3c01691e2d0c4266136f12e391422f93655c71831d90935fbda7e840e50770c61da20000000008635253abac516353ffffffff031f32aa020000000003636563786dbc0200000000003e950f00000000000563516a655184b8a1de", "51536a", 0, -1627072905, "730bc25699b46703d7718fd5f5c34c4b5f00f594a9968ddc247fa7d5175124ed"],
+ ["076d209e02d904a6c40713c7225d23e7c25d4133c3c3477828f98c7d6dbd68744023dbb66b030000000753ab00536565acffffffff10975f1b8db8861ca94c8cc7c7cff086ddcd83e10b5fffd4fc8f2bdb03f9463c0100000000ffffffff029dff76010000000006526365530051a3be6004000000000000000000", "515253ac65acacac", 1, -1207502445, "66c488603b2bc53f0d22994a1f0f66fb2958203102eba30fe1d37b27a55de7a5"],
+ ["690fd1f80476db1f9eebe91317f2f130a60cbc1f4feadd9d6474d438e9cb7f91e4994600af0300000004ab536a63a15ce9fa6622d0c4171d895b42bff884dc6e8a7452f827fdc68a29c3c88e6fdee364eaf50000000002ab52ffffffff022dc39d3c0956b24d7f410b1e387859e7a72955f45d6ffb1e884d77888d18fe0300000005ac6a63656afffffffff10b06bce1800f5c49153d24748fdefb0bf514c12863247d1042d56018c3e25c03000000086a63ac6365536a52ffffffff031f162f0500000000060000655265abffbcd40500000000045151ac001a9c8c05000000000652ac53656a6300000000", "ac51ab63acac", 0, -67986012, "051c0df7ac688c2c930808dabde1f50300aea115f2bb3334f4753d5169b51e46"],
+ ["49ac2af00216c0307a29e83aa5de19770e6b20845de329290bd69cf0e0db7aed61ae41b39002000000035163ac8b2558ef84635bfc59635150e90b61fc753d34acfd10d97531043053e229cd720133cd95000000000463516a51ffffffff02458471040000000008abab636a51ac0065545aa80000000000096a6553516a5263ac6a00000000", "51526300ab5363", 1, 1449668540, "ddfd902bba312a06197810da96a0ddccb595f96670b28ded7dba88d8cd0469b8"],
+ ["fa4d868b024b010bd5dce46576c2fb489aa60bb797dac3c72a4836f49812c5c564c258414f03000000007a9b3a585e05027bdd89edbadf3c85ac61f8c3a04c773fa746517ae600ff1a9d6b6c02fb0200000004515163abffffffff01b17d020500000000046a65520000000000", "536565ab65635363", 0, -1718953372, "96c2b32f0a00a5925db7ba72d0b5d39922f30ea0f7443b22bc1b734808513c47"],
+ ["cac6382d0462375e83b67c7a86c922b569a7473bfced67f17afd96c3cd2d896cf113febf9e0300000003006a53ffffffffaa4913b7eae6821487dd3ca43a514e94dcbbf350f8cc4cafff9c1a88720711b800000000096a6a525300acac6353ffffffff184fc4109c34ea27014cc2c1536ef7ed1821951797a7141ddacdd6e429fae6ff01000000055251655200ffffffff9e7b79b4e6836e290d7b489ead931cba65d1030ccc06f20bd4ca46a40195b33c030000000008f6bc8304a09a2704000000000563655353511dbc73050000000000cf34c500000000000091f76e0000000000085200ab00005100abd07208cb", "0063656a", 2, -1488731031, "bf078519fa87b79f40abc38f1831731422722c59f88d86775535f209cb41b9b1"],
+ ["1711146502c1a0b82eaa7893976fefe0fb758c3f0e560447cef6e1bde11e42de91a125f71c030000000015bd8c04703b4030496c7461482481f290c623be3e76ad23d57a955807c9e851aaaa20270300000000d04abaf20326dcb7030000000001632225350400000000075263ac00520063dddad9020000000000af23d148", "52520053510063", 0, 1852122830, "e33d5ee08c0f3c130a44d7ce29606450271b676f4a80c52ab9ffab00cecf67f8"],
+ ["8d5b124d0231fbfc640c706ddb1d57bb49a18ba8ca0e1101e32c7e6e65a0d4c7971d93ea360100000008acabac0000abac65ffffffff8fe0fd7696597b845c079c3e7b87d4a44110c445a330d70342a5501955e17dd70100000004ab525363ef22e8a90346629f030000000009516a00ac63acac51657bd57b05000000000200acfd4288050000000009acab5352ab00ab636300000000", "53ac526553ab65", 0, 1253152975, "8b57a7c3170c6c02dd14ae1d392ce3d828197b20e9145c89c1cfd5de050e1562"],
+ ["38146dc502c7430e92b6708e9e107b61cd38e5e773d9395e5c8ad8986e7e4c03ee1c1e1e760100000000c8962ce2ac1bb3b1285c0b9ba07f4d2e5ce87c738c42ac0548cd8cec1100e6928cd6b0b6010000000763ab636aab52527cccefbd04e5f6f8020000000006006aabacac65ab2c4a00000000000351635209a6f40100000000026aacce57dc040000000008ab5353ab516a516a00000000", "ab", 0, -1205978252, "3cb5b030e7da0b60ccce5b4a7f3793e6ca56f03e3799fe2d6c3cc22d6d841dcb"],
+ ["22d81c740469695a6a83a9a4824f77ecff8804d020df23713990afce2b72591ed7de98500502000000065352526a6a6affffffff90dc85e118379b1005d7bbc7d2b8b0bab104dad7eaa49ff5bead892f17d8c3ba010000000665656300ab51ffffffff965193879e1d5628b52005d8560a35a2ba57a7f19201a4045b7cbab85133311d0200000003ac005348af21a13f9b4e0ad90ed20bf84e4740c8a9d7129632590349afc03799414b76fd6e826200000000025353ffffffff04a0d40d04000000000060702700000000000652655151516ad31f1502000000000365ac0069a1ac0500000000095100655300ab53525100000000", "51636a52ac", 0, -1644680765, "add7f5da27262f13da6a1e2cc2feafdc809bd66a67fb8ae2a6f5e6be95373b6f"],
+ ["a27dcbc801e3475174a183586082e0914c314bc9d79d1570f29b54591e5e0dff07fbb45a7f0000000004ac53ab51ffffffff027347f5020000000005535351ab63d0e5c9030000000009ac65ab6a63515200ab7cd632ed", "ac63636553", 0, -686435306, "883a6ea3b2cc53fe8a803c229106366ca14d25ffbab9fef8367340f65b201da6"],
+ ["b123ed2204410d4e8aaaa8cdb95234ca86dad9ff77fb4ae0fd4c06ebed36794f0215ede0040100000002ac63ffffffff3b58b81b19b90d8f402701389b238c3a84ff9ba9aeea298bbf15b41a6766d27a01000000056a6553ab00151824d401786153b819831fb15926ff1944ea7b03d884935a8bde01ed069d5fd80220310200000000ffffffffa9c9d246f1eb8b7b382a9032b55567e9a93f86c77f4e32c092aa1738f7f756c30100000002ab65ffffffff011a2b48000000000000ed44d1fb", "630051ab63", 2, -1118263883, "b5dab912bcabedff5f63f6dd395fc2cf030d83eb4dd28214baba68a45b4bfff0"],
+ ["1339051503e196f730955c5a39acd6ed28dec89b4dadc3f7c79b203b344511270e5747fa9900000000045151636affffffff378c6090e08a3895cedf1d25453bbe955a274657172491fd2887ed5c9aceca7b0100000000ffffffffcf7cc3c36ddf9d4749edfa9cefed496d2f86e870deb814bfcd3b5637a5496461030000000451006300ffffffff04dcf3fa010000000008526a63005263acabb41d84040000000004abac5153800eff020000000005656a535365106c5e00000000000000000000", "abac5300", 2, 2013719928, "7fc74de39ce6ca46ca25d760d3cec7bb21fd14f7efe1c443b5aa294f2cb5f546"],
+ ["0728c606014c1fd6005ccf878196ba71a54e86cc8c53d6db500c3cc0ac369a26fac6fcbc210000000005ab53ac5365ba9668290182d7870100000000066a000053655100000000", "65", 0, 1789961588, "ab6baa6da3b2bc853868d166f8996ad31d63ef981179f9104f49968fd61c8427"],
+ ["a1134397034bf4067b6c81c581e2b73fb63835a08819ba24e4e92df73074bf773c94577df7000000000465525251ffffffff8b6608feaa3c1f35f49c6330a769716fa01c5c6f6e0cdc2eb10dfc99bbc21e77010000000952656aac005352655180a0bda4bc72002c2ea8262e26e03391536ec36867258cab968a6fd6ec7523b64fa1d8c001000000056a53ac6353ffffffff04dbeeed05000000000553650052abcd5d0e01000000000463abab51104b2e0500000000066aac53ac5165283ca7010000000004535252ab00000000", "ab515151516552ab", 1, -324598676, "91178482112f94d1c8e929de443e4b9c893e18682998d393ca9ca77950412586"],
+ ["bcdafbae04aa18eb75855aeb1f5124f30044741351b33794254a80070940cb10552fa4fa8e0300000001acd0423fe6e3f3f88ae606f2e8cfab7a5ef87caa2a8f0401765ff9a47d718afcfb40c0099b0000000008ac6565ab53ac6aac645308009d680202d600e492b31ee0ab77c7c5883ebad5065f1ce87e4dfe6453e54023a0010000000151ffffffffb9d818b14245899e1d440152827c95268a676f14c3389fc47f5a11a7b38b1bde03000000026300ffffffff03cda22102000000000751ac535263005100a4d20400000000045200536ac8bef405000000000700ab51ab6563ac00000000", "6553516a526aab", 1, -2111409753, "5e1849e7368cf4f042718586d9bd831d61479b775bab97aba9f450042bd9876a"],
+ ["ed3bb93802ddbd08cb030ef60a2247f715a0226de390c9c1a81d52e83f8674879065b5f87d0300000003ab6552ffffffff04d2c5e60a21fb6da8de20bf206db43b720e2a24ce26779bca25584c3f765d1e0200000008ab656a6aacab00ab6e946ded025a811d04000000000951abac6352ac00ab5143cfa3030000000005635200636a00000000", "5352ac650065535300", 1, -668727133, "e9995065e1fddef72a796eef5274de62012249660dc9d233a4f24e02a2979c87"],
+ ["59f4629d030fa5d115c33e8d55a79ea3cba8c209821f979ed0e285299a9c72a73c5bba00150200000002636affffffffd8aca2176df3f7a96d0dc4ee3d24e6cecde1582323eec2ebef9a11f8162f17ac0000000007ab6565acab6553ffffffffeebc10af4f99c7a21cbc1d1074bd9f0ee032482a71800f44f26ee67491208e0403000000065352ac656351ffffffff0434e955040000000004ab515152caf2b305000000000365ac007b1473030000000003ab530033da970500000000060051536a5253bb08ab51", "", 2, 396340944, "0e9c47973ef2c292b2252c623f465bbb92046fe0b893eebf4e1c9e02cb01c397"],
+ ["286e3eb7043902bae5173ac3b39b44c5950bc363f474386a50b98c7bdab26f98dc83449c4a020000000752ac6a00510051ffffffff4339cd6a07f5a5a2cb5815e5845da70300f5c7833788363bf7fe67595d3225520100000000fffffffff9c2dd8b06ad910365ffdee1a966f124378a2b8021065c8764f6138bb1e951380200000005ab5153ac6affffffff0370202aba7a68df85436ea7c945139513384ef391fa33d16020420b8ad40e9a000000000900ab5165526353abacffffffff020c1907000000000004abac526a1b490b040000000000df1528f7", "5353ab", 3, -1407529517, "32154c09174a9906183abf26538c39e78468344ca0848bbd0785e24a3565d932"],
+ ["2e245cf80179e2e95cd1b34995c2aff49fe4519cd7cee93ad7587f7f7e8105fc2dff206cd30200000009006a63516a6553ab52350435a201d5ed2d02000000000352ab6558552c89", "00ab53", 0, -233917810, "4605ae5fd3d50f9c45d37db7118a81a9ef6eb475d2333f59df5d3e216f150d49"],
+ ["33a98004029d262f951881b20a8d746c8c707ea802cd2c8b02a33b7e907c58699f97e42be80100000007ac53536552abacdee04cc01d205fd8a3687fdf265b064d42ab38046d76c736aad8865ca210824b7c622ecf02000000070065006a536a6affffffff01431c5d010000000000270d48ee", "", 1, 921554116, "ff9d7394002f3f196ea25472ea6c46f753bd879a7244795157bb7235c9322902"],
+ ["aac18f2b02b144ed481557c53f2146ae523f24fcde40f3445ab0193b6b276c315dc2894d2300000000075165650000636a233526947dbffc76aec7db1e1baa6868ad4799c76e14794dcbaaec9e713a83967f6a65170200000005abac6551ab27d518be01b652a30000000000015300000000", "52ac5353", 1, 1559377136, "59fc2959bb7bb24576cc8a237961ed95bbb900679d94da6567734c4390cb6ef5"],
+ ["5ab79881033555b65fe58c928883f70ce7057426fbdd5c67d7260da0fe8b1b9e6a2674cb850300000009ac516aac6aac006a6affffffffa5be9223b43c2b1a4d120b5c5b6ec0484f637952a3252181d0f8e813e76e11580200000000e4b5ceb8118cb77215bbeedc9a076a4d087bb9cd1473ea32368b71daeeeacc451ec209010000000005acac5153aced7dc34e02bc5d11030000000005ac5363006a54185803000000000552ab00636a00000000", "5100", 1, 1927062711, "e9f53d531c12cce1c50abed4ac521a372b4449b6a12f9327c80020df6bff66c0"],
+ ["6c2c8fac0124b0b7d4b610c3c5b91dee32b7c927ac71abdf2d008990ca1ac40de0dfd530660300000006ababac5253656bd7eada01d847ec000000000004ac52006af4232ec8", "6a6a6a0051", 0, -340809707, "fb51eb9d7e47d32ff2086205214f90c7c139e08c257a64829ae4d2b301071c6a"],
+ ["6e3880af031735a0059c0bb5180574a7dcc88e522c8b56746d130f8d45a52184045f96793e0100000008acabac6a526a6553fffffffffe05f14cdef7d12a9169ec0fd37524b5fcd3295f73f48ca35a36e671da4a2f560000000008006a526a6351ab63ffffffffdfbd869ac9e472640a84caf28bdd82e8c6797f42d03b99817a705a24fde2736600000000010090a090a503db956b04000000000952ac53ab6a536a63ab358390010000000009656a5200525153ac65353ee204000000000763530052526aaba6ad83fb", "535151ab6300", 2, 222014018, "57a34ddeb1bf36d28c7294dda0432e9228a9c9e5cc5c692db98b6ed2e218d825"],
+ ["8df1cd19027db4240718dcaf70cdee33b26ea3dece49ae6917331a028c85c5a1fb7ee3e475020000000865ab6a00510063636157988bc84d8d55a8ba93cdea001b9bf9d0fa65b5db42be6084b5b1e1556f3602f65d4d0100000005ac00ab0052206c852902b2fb54030000000008ac5252536aacac5378c4a5050000000007acabac535163532784439e", "acab6a", 0, 1105620132, "edb7c74223d1f10f9b3b9c1db8064bc487321ff7bb346f287c6bc2fad83682de"],
+ ["0e803682024f79337b25c98f276d412bc27e56a300aa422c42994004790cee213008ff1b8303000000080051ac65ac655165f421a331892b19a44c9f88413d057fea03c3c4a6c7de4911fe6fe79cf2e9b3b10184b1910200000005525163630096cb1c670398277204000000000253acf7d5d502000000000963536a6a636a5363ab381092020000000002ac6a911ccf32", "6565", 1, -1492094009, "f0672638a0e568a919e9d8a9cbd7c0189a3e132940beeb52f111a89dcc2daa2c"],
+ ["7d71669d03022f9dd90edac323cde9e56354c6804c6b8e687e9ae699f46805aafb8bcaa636000000000253abffffffff698a5fdd3d7f2b8b000c68333e4dd58fa8045b3e2f689b889beeb3156cecdb490300000009525353abab0051acabc53f0aa821cdd69b473ec6e6cf45cf9b38996e1c8f52c27878a01ec8bb02e8cb31ad24e500000000055353ab0052ffffffff0447a23401000000000565ab53ab5133aaa0030000000006515163656563057d110300000000056a6aacac52cf13b5000000000003526a5100000000", "6a6a51", 1, -1349253507, "722efdd69a7d51d3d77bed0ac5544502da67e475ea5857cd5af6bdf640a69945"],
+ ["9ff618e60136f8e6bb7eabaaac7d6e2535f5fba95854be6d2726f986eaa9537cb283c701ff02000000026a65ffffffff012d1c0905000000000865ab00ac6a516a652f9ad240", "51515253635351ac", 0, 1571304387, "659cd3203095d4a8672646add7d77831a1926fc5b66128801979939383695a79"],
+ ["9fbd43ac025e1462ecd10b1a9182a8e0c542f6d1089322a41822ab94361e214ed7e1dfdd8a020000000263519d0437581538e8e0b6aea765beff5b4f3a4a202fca6e5d19b34c141078c6688f71ba5b8e0100000003ac6552ffffffff02077774050000000009655153655263acab6a0ae4e10100000000035152524c97136b", "635152ab", 0, 1969622955, "d82d4ccd9b67810f26a378ad9592eb7a30935cbbd27e859b00981aefd0a72e08"],
+ ["0117c92004314b84ed228fc11e2999e657f953b6de3b233331b5f0d0cf40d5cc149b93c7b30300000005515263516a083e8af1bd540e54bf5b309d36ba80ed361d77bbf4a1805c7aa73667ad9df4f97e2da410020000000600ab6351ab524d04f2179455e794b2fcb3d214670001c885f0802e4b5e015ed13a917514a7618f5f332203000000086a536aab51000063ecf029e65a4a009a5d67796c9f1eb358b0d4bd2620c8ad7330fb98f5a802ab92d0038b1002000000036a6551a184a88804b04490000000000009ab6a5152535165526a33d1ab020000000001518e92320000000000002913df04000000000952abac6353525353ac8b19bfdf", "000051ab0000", 0, 489433059, "8eebac87e60da524bbccaf285a44043e2c9232868dda6c6271a53c153e7f3a55"],
+ ["e7f5482903f98f0299e0984b361efb2fddcd9979869102281e705d3001a9d283fe9f3f3a1e02000000025365ffffffffcc5c7fe82feebad32a22715fc30bc584efc9cd9cadd57e5bc4b6a265547e676e0000000001ab579d21235bc2281e08bf5e7f8f64d3afb552839b9aa5c77cf762ba2366fffd7ebb74e49400000000055263ab63633df82cf40100982e05000000000453ac535300000000", "acacab", 2, -1362931214, "046de666545330e50d53083eb78c9336416902f9b96c77cc8d8e543da6dfc7e4"],
+ ["09adb2e90175ca0e816326ae2dce7750c1b27941b16f6278023dbc294632ab97977852a09d030000000465ab006affffffff027739cf0100000000075151ab63ac65ab8a5bb601000000000653ac5151520011313cdc", "ac", 0, -76831756, "478ee06501b4965b40bdba6cbaad9b779b38555a970912bb791b86b7191c54bc"],
+ ["f973867602e30f857855cd0364b5bbb894c049f44abbfd661d7ae5dbfeaafca89fac8959c20100000005ab52536a51ffffffffbeceb68a4715f99ba50e131884d8d20f4a179313691150adf0ebf29d05f8770303000000066352ab00ac63ffffffff021fddb90000000000036a656322a177000000000008526500ac5100acac84839083", "52acab53ac", 0, 1407879325, "db0329439490efc64b7104d6d009b03fbc6fac597cf54fd786fbbb5fd73b92b4"],
+ ["fd22ebaa03bd588ad16795bea7d4aa7f7d48df163d75ea3afebe7017ce2f350f6a0c1cb0bb00000000086aabac5153526363ffffffff488e0bb22e26a565d77ba07178d17d8f85702630ee665ec35d152fa05af3bda10200000004515163abffffffffeb21035849e85ad84b2805e1069a91bb36c425dc9c212d9bae50a95b6bfde1200300000001ab5df262fd02b69848040000000008ab6363636a6363ace23bf2010000000007655263635253534348c1da", "006353526563516a00", 0, -1491036196, "92364ba3c7a85d4e88885b8cb9b520dd81fc29e9d2b750d0790690e9c1246673"],
+ ["130b462d01dd49fac019dc4442d0fb54eaa6b1c2d1ad0197590b7df26969a67abd7f3fbb4f0100000008ac65abac53ab6563ffffffff0345f825000000000004ac53acac9d5816020000000002ababeff8e90500000000086aab006552ac6a53a892dc55", "ab0065ac530052", 0, 944483412, "1f4209fd4ce7f13d175fdd522474ae9b34776fe11a5f17a27d0796c77a2a7a9d"],
+ ["f8e50c2604609be2a95f6d0f31553081f4e1a49a0a30777fe51eb1c596c1a9a92c053cf28c0300000009656a51ac5252630052fffffffff792ed0132ae2bd2f11d4a2aab9d0c4fbdf9a66d9ae2dc4108afccdc14d2b1700100000007ab6a6563ac636a7bfb2fa116122b539dd6a2ab089f88f3bc5923e5050c8262c112ff9ce0a3cd51c6e3e84f02000000066551ac5352650d5e687ddf4cc9a497087cabecf74d236aa4fc3081c3f67b6d323cba795e10e7a171b725000000000852635351ab635100ffffffff02df5409020000000008ac6a53acab5151004156990200000000045163655200000000", "ac53abac65005300", 0, -173065000, "b596f206d7eba22b7e2d1b7a4f4cf69c7c541b6c84dcc943f84e19a99a923310"],
+ ["18020dd1017f149eec65b2ec23300d8df0a7dd64fc8558b36907723c03cd1ba672bbb0f51d0300000005ab65ab6a63ffffffff037cd7ae000000000009ab516a65005352ac65f1e4360400000000056353530053f118f0040000000009536363ab006500abac00000000", "63ab51acab52ac", 0, -550412404, "e19b796c14a0373674968e342f2741d8b51092a5f8409e9bff7dcd52e56fcbcb"],
+ ["b04154610363fdade55ceb6942d5e5a723323863b48a0cb04fdcf56210717955763f56b08d0300000009ac526a525151635151ffffffff93a176e76151a9eabdd7af00ef2af72f9e7af5ecb0aa4d45d00618f394cdd03c030000000074d818b332ebe05dc24c44d776cf9d275c61f471cc01efce12fd5a16464157f1842c65cb00000000066a0000ac6352d3c4134f01d8a1c0030000000005520000005200000000", "5200656a656351", 2, -9757957, "6e3e5ba77f760b6b5b5557b13043f1262418f3dd2ce7f0298b012811fc8ad5bc"],
+ ["9794b3ce033df7b1e32db62d2f0906b589eacdacf5743963dc2255b6b9a6cba211fadd0d41020000000600ab00650065ffffffffaae00687a6a4131152bbcaafedfaed461c86754b0bde39e2bef720e6d1860a0302000000070065516aac6552ffffffff50e4ef784d6230df7486e972e8918d919f005025bc2d9aacba130f58bed7056703000000075265ab52656a52ffffffff02c6f1a9000000000006005251006363cf450c040000000008abab63510053abac00000000", "ac0063ababab515353", 1, 2063905082, "fad092fc98f17c2c20e10ba9a8eb44cc2bcc964b006f4da45cb9ceb249c69698"],
+ ["94533db7015e70e8df715066efa69dbb9c3a42ff733367c18c22ff070392f988f3b93920820000000006535363636300ce4dac3e03169af80300000000080065ac6a53ac65ac39c050020000000006abacab6aacac708a02050000000005ac5251520000000000", "6553", 0, -360458507, "5418cf059b5f15774836edd93571e0eed3855ba67b2b08c99dccab69dc87d3e9"],
+ ["c8597ada04f59836f06c224a2640b79f3a8a7b41ef3efa2602592ddda38e7597da6c639fee0300000009005251635351acabacffffffff4c518f347ee694884b9d4072c9e916b1a1f0a7fc74a1c90c63fdf8e5a185b6ae02000000007113af55afb41af7518ea6146786c7c726641c68c8829a52925e8d4afd07d8945f68e7230300000008ab00ab65ab650063ffffffffc28e46d7598312c420e11dfaae12add68b4d85adb182ae5b28f8340185394b63000000000165ffffffff04dbabb7010000000000ee2f6000000000000852ab6500ab6a51acb62a27000000000009ac53515300ac006a6345fb7505000000000752516a0051636a00000000", "", 3, 15199787, "0d66003aff5bf78cf492ecbc8fd40c92891acd58d0a271be9062e035897f317e"],
+ ["1a28c4f702c8efaad96d879b38ec65c5283b5c084b819ad7db1c086e85e32446c7818dc7a90300000008656351536a525165fa78cef86c982f1aac9c5eb8b707aee8366f74574c8f42ef240599c955ef4401cf578be30200000002ab518893292204c430eb0100000000016503138a0300000000040053abac60e0eb010000000005525200ab63567c2d030000000004abab52006cf81e85", "ab51525152", 1, 2118315905, "4e4c9a781f626b59b1d3ad8f2c488eb6dee8bb19b9bc138bf0dc33e7799210d4"],
+ ["c6c7a87003f772bcae9f3a0ac5e499000b68703e1804b9ddc3e73099663564d53ddc4e1c6e01000000076a536a6aac63636e3102122f4c30056ef8711a6bf11f641ddfa6984c25ac38c3b3e286e74e839198a80a34010000000165867195cd425821dfa2f279cb1390029834c06f018b1e6af73823c867bf3a0524d1d6923b0300000005acab53ab65ffffffff02fa4c49010000000008ab656a0052650053e001100400000000008836d972", "ac526351acab", 1, 978122815, "a869c18a0edf563d6e5eddd5d5ae8686f41d07f394f95c9feb8b7e52761531ca"],
+ ["0ea580ac04c9495ab6af3b8d59108bb4194fcb9af90b3511c83f7bb046d87aedbf8423218e02000000085152acac006363ab9063d7dc25704e0caa5edde1c6f2dd137ded379ff597e055b2977b9c559b07a7134fcef2000000000200aca89e50181f86e9854ae3b453f239e2847cf67300fff802707c8e3867ae421df69274449402000000056365abababffffffff47a4760c881a4d7e51c69b69977707bd2fb3bcdc300f0efc61f5840e1ac72cee0000000000ffffffff0460179a020000000004ab53ab52a5250c0500000000096565acac6365ab52ab6c281e02000000000952635100ac006563654e55070400000000046552526500000000", "ab526563acac53ab", 2, 1426964167, "b1c50d58b753e8f6c7513752158e9802cf0a729ebe432b99acc0fe5d9b4e9980"],
+ ["c33028b301d5093e1e8397270d75a0b009b2a6509a01861061ab022ca122a6ba935b8513320200000000ffffffff013bcf5a0500000000015200000000", "", 0, -513413204, "6b1459536f51482f5dbf42d7e561896557461e1e3b6bf67871e2b51faae2832c"],
+ ["43b2727901a7dd06dd2abf690a1ccedc0b0739cb551200796669d9a25f24f71d8d101379f50300000000ffffffff0418e031040000000000863d770000000000085352ac526563ac5174929e040000000004ac65ac00ec31ac0100000000066a51ababab5300000000", "65", 0, -492874289, "154ff7a9f0875edcfb9f8657a0b98dd9600fabee3c43eb88af37cf99286d516c"],
+ ["4763ed4401c3e6ab204bed280528e84d5288f9cac5fb8a2e7bd699c7b98d4df4ac0c40e55303000000066a6aacab5165ffffffff015b57f80400000000046a63535100000000", "ac51abab53", 0, -592611747, "849033a2321b5755e56ef4527ae6f51e30e3bca50149d5707368479723d744f8"],
+ ["d24f647b02f71708a880e6819a1dc929c1a50b16447e158f8ff62f9ccd644e0ca3c592593702000000050053536a00ffffffff67868cd5414b6ca792030b18d649de5450a456407242b296d936bcf3db79e07b02000000005af6319c016022f50100000000036a516300000000", "6aab526353516a6a", 0, 1350782301, "8556fe52d1d0782361dc28baaf8774b13f3ce5ed486ae0f124b665111e08e3e3"],
+ ["fe6ddf3a02657e42a7496ef170b4a8caf245b925b91c7840fd28e4a22c03cb459cb498b8d603000000065263656a650071ce6bf8d905106f9f1faf6488164f3decac65bf3c5afe1dcee20e6bc3cb6d052561985a030000000163295b117601343dbb0000000000026563dba521df", "", 1, -1696179931, "d9684685c99ce48f398fb467a91a1a59629a850c429046fb3071f1fa9a5fe816"],
+ ["c61523ef0129bb3952533cbf22ed797fa2088f307837dd0be1849f20decf709cf98c6f032f03000000026563c0f1d378044338310400000000066363516a5165a14fcb0400000000095163536a6a00ab53657271d60200000000001d953f0500000000010000000000", "53516353005153", 0, 1141615707, "7e975a72db5adaa3c48d525d9c28ac11cf116d0f8b16ce08f735ad75a80aec66"],
+ ["ba3dac6c0182562b0a26d475fe1e36315f0913b6869bdad0ecf21f1339a5fcbccd32056c840200000000ffffffff04300351050000000000220ed405000000000851abac636565ac53dbbd19020000000007636363ac6a52acbb005a0500000000016abd0c78a8", "63006a635151005352", 0, 1359658828, "47bc8ab070273e1f4a0789c37b45569a6e16f3f3092d1ce94dddc3c34a28f9f4"],
+ ["ac27e7f5025fc877d1d99f7fc18dd4cadbafa50e34e1676748cc89c202f93abf36ed46362101000000036300abffffffff958cd5381962b765e14d87fc9524d751e4752dd66471f973ed38b9d562e525620100000003006500ffffffff02b67120050000000004ac51516adc330c0300000000015200000000", "656352", 1, 15049991, "f3374253d64ac264055bdbcc32e27426416bd595b7c7915936c70f839e504010"],
+ ["edb30140029182b80c8c3255b888f7c7f061c4174d1db45879dca98c9aab8c8fed647a6ffc03000000086a53510052ab6300ffffffff82f65f261db62d517362c886c429c8fbbea250bcaad93356be6f86ba573e9d930100000000ffffffff04daaf150400000000016a86d1300100000000096a6353535252ac5165d4ddaf000000000002abab5f1c6201000000000000000000", "ab6a6a00ac", 0, -2058017816, "8d7794703dad18e2e40d83f3e65269834bb293e2d2b8525932d6921884b8f368"],
+ ["7e50207303146d1f7ad62843ae8017737a698498d4b9118c7a89bb02e8370307fa4fada41d000000000753006300005152b7afefc85674b1104ba33ef2bf37c6ed26316badbc0b4aa6cb8b00722da4f82ff3555a6c020000000900ac656363ac51ac52ffffffff93fab89973bd322c5d7ad7e2b929315453e5f7ada3072a36d8e33ca8bebee6e0020000000300acab930da52b04384b04000000000004650052ac435e380200000000076a6a515263ab6aa9494705000000000600ab6a525252af8ba90100000000096565acab526353536a279b17ad", "acac005263536aac63", 1, -34754133, "4e6357da0057fb7ff79da2cc0f20c5df27ff8b2f8af4c1709e6530459f7972b0"],
+ ["c05764f40244fb4ebe4c54f2c5298c7c798aa90e62c29709acca0b4c2c6ec08430b26167440100000008acab6a6565005253ffffffffc02c2418f398318e7f34a3cf669d034eef2111ea95b9f0978b01493293293a870100000000e563e2e00238ee8d040000000002acab03fb060200000000076500ac656a516aa37f5534", "52ab6a0065", 1, -2033176648, "83deef4a698b62a79d4877dd9afebc3011a5275dbe06e89567e9ef84e8a4ee19"],
+ ["5a59e0b9040654a3596d6dab8146462363cd6549898c26e2476b1f6ae42915f73fd9aedfda00000000036363abffffffff9ac9e9ca90be0187be2214251ff08ba118e6bf5e2fd1ba55229d24e50a510d53010000000165ffffffff41d42d799ac4104644969937522873c0834cc2fcdab7cdbecd84d213c0e96fd60000000000ffffffffd838db2c1a4f30e2eaa7876ef778470f8729fcf258ad228b388df2488709f8410300000000fdf2ace002ceb6d903000000000265654c1310040000000003ac00657e91c0ec", "536a63ac", 0, 82144555, "98ccde2dc14d14f5d8b1eeea5364bd18fc84560fec2fcea8de4d88b49c00695e"],
+ ["156ebc8202065d0b114984ee98c097600c75c859bfee13af75dc93f57c313a877efb09f230010000000463536a51ffffffff81114e8a697be3ead948b43b5005770dd87ffb1d5ccd4089fa6c8b33d3029e9c03000000066a5251656351ffffffff01a87f140000000000050000ac51ac00000000", "00", 0, -362221092, "a903c84d8c5e71134d1ab6dc1e21ac307c4c1a32c90c90f556f257b8a0ec1bf5"],
+ ["15e37793023c7cbf46e073428908fce0331e49550f2a42b92468827852693f0532a01c29f70200000007005353636351acffffffff38426d9cec036f00eb56ec1dcd193647e56a7577278417b8a86a78ac53199bc403000000056353006a53ffffffff04a25ce103000000000900ab5365656a526a63c8eff7030000000004526353537ab6db0200000000016a11a3fa02000000000651acacab526500000000", "53ac6aab6a6551", 0, 1117532791, "83c68b3c5a89260ce16ce8b4dbf02e1f573c532d9a72f5ea57ab419fa2630214"],
+ ["f7a09f10027250fc1b70398fb5c6bffd2be9718d3da727e841a73596fdd63810c9e4520a6a010000000963ac516a636a65acac1d2e2c57ab28d311edc4f858c1663972eebc3bbc93ed774801227fda65020a7ec1965f780200000005ac5252516a8299fddc01dcbf7200000000000463ac6551960fda03", "65acab51", 1, 2017321737, "9c5fa02abfd34d0f9dec32bf3edb1089fca70016debdb41f4f54affcb13a2a2a"],
+ ["6d97a9a5029220e04f4ccc342d8394c751282c328bf1c132167fc05551d4ca4da4795f6d4e02000000076a0052ab525165ffffffff9516a205e555fa2a16b73e6db6c223a9e759a7e09c9a149a8f376c0a7233fa1b0100000007acab51ab63ac6affffffff04868aed04000000000652ac65ac536a396edf01000000000044386c0000000000076aab5363655200894d48010000000001ab8ebefc23", "6351526aac51", 1, 1943666485, "f0bd4ca8e97203b9b4e86bc24bdc8a1a726db5e99b91000a14519dc83fc55c29"],
+ ["8e3fddfb028d9e566dfdda251cd874cd3ce72e9dde837f95343e90bd2a93fe21c5daeb5eed01000000045151525140517dc818181f1e7564b8b1013fd68a2f9a56bd89469686367a0e72c06be435cf99db750000000003635251ffffffff01c051780300000000096552ababac6a65acab099766eb", "5163ab6a52ababab51", 1, 1296295812, "5509eba029cc11d7dd2808b8c9eb47a19022b8d8b7778893459bbc19ab7ea820"],
+ ["a603f37b02a35e5f25aae73d0adc0b4b479e68a734cf722723fd4e0267a26644c36faefdab0200000000ffffffff43374ad26838bf733f8302585b0f9c22e5b8179888030de9bdda180160d770650200000001004c7309ce01379099040000000005526552536500000000", "abababab005153", 0, 1409936559, "4ca73da4fcd5f1b10da07998706ffe16408aa5dff7cec40b52081a6514e3827e"],
+ ["9eeedaa8034471a3a0e3165620d1743237986f060c4434f095c226114dcb4b4ec78274729f03000000086a5365510052ac6afb505af3736e347e3f299a58b1b968fce0d78f7457f4eab69240cbc40872fd61b5bf8b120200000002ac52df8247cf979b95a4c97ecb8edf26b3833f967020cd2fb25146a70e60f82c9ee4b14e88b103000000008459e2fa0125cbcd05000000000000000000", "52ab5352006353516a", 0, -1832576682, "fb018ae54206fdd20c83ae5873ec82b8e320a27ed0d0662db09cda8a071f9852"],
+ ["05921d7c048cf26f76c1219d0237c226454c2a713c18bf152acc83c8b0647a94b13477c07f0300000003ac526afffffffff2f494453afa0cabffd1ba0a626c56f90681087a5c1bd81d6adeb89184b27b7402000000036a6352ffffffff0ad10e2d3ce355481d1b215030820da411d3f571c3f15e8daf22fe15342fed04000000000095f29f7b93ff814a9836f54dc6852ec414e9c4e16a506636715f569151559100ccfec1d100000000055263656a53ffffffff04f4ffef010000000008ac6a6aabacabab6a0e6689040000000006ab536a5352abe364d005000000000965536363655251ab53807e00010000000004526aab63f18003e3", "6363ac51", 3, -375891099, "001b0b176f0451dfe2d9787b42097ceb62c70d324e925ead4c58b09eebdf7f67"],
+ ["b9b44d9f04b9f15e787d7704e6797d51bc46382190c36d8845ec68dfd63ee64cf7a467b21e00000000096aac00530052ab636aba1bcb110a80c5cbe073f12c739e3b20836aa217a4507648d133a8eedd3f02cb55c132b203000000076a000063526352b1c288e3a9ff1f2da603f230b32ef7c0d402bdcf652545e2322ac01d725d75f5024048ad0100000000ffffffffffd882d963be559569c94febc0ef241801d09dc69527c9490210f098ed8203c700000000056a006300ab9109298d01719d9a0300000000066a52ab006365d7894c5b", "ac6351650063636a", 3, -622355349, "ac87b1b93a6baab6b2c6624f10e8ebf6849b0378ef9660a3329073e8f5553c8d"],
+ ["ff60473b02574f46d3e49814c484081d1adb9b15367ba8487291fc6714fd6e3383d5b335f001000000026a6ae0b82da3dc77e5030db23d77b58c3c20fa0b70aa7d341a0f95f3f72912165d751afd57230300000008ac536563516a6363ffffffff04f86c0200000000000553acab636ab13111000000000003510065f0d3f305000000000951ab516a65516aabab730a3a010000000002515200000000", "ac6a", 1, 1895032314, "0767e09bba8cd66d55915677a1c781acd5054f530d5cf6de2d34320d6c467d80"],
+ ["f218026204f4f4fc3d3bd0eada07c57b88570d544a0436ae9f8b753792c0c239810bb30fbc0200000002536affffffff8a468928d6ec4cc10aa0f73047697970e99fa64ae8a3b4dca7551deb0b639149010000000851ab520052650051ffffffffa98dc5df357289c9f6873d0f5afcb5b030d629e8f23aa082cf06ec9a95f3b0cf0000000000ffffffffea2c2850c5107705fd380d6f29b03f533482fd036db88739122aac9eff04e0aa010000000365536a03bd37db034ac4c4020000000007515152655200ac33b27705000000000151efb71e0000000000007b65425b", "515151", 3, -1772252043, "de35c84a58f2458c33f564b9e58bc57c3e028d629f961ad1b3c10ee020166e5a"],
+ ["48e7d42103b260b27577b70530d1ac2fed2551e9dd607cbcf66dca34bb8c03862cf8f5fd5401000000075151526aacab00ffffffff1e3d3b841552f7c6a83ee379d9d66636836673ce0b0eda95af8f2d2523c91813030000000665acac006365ffffffff388b3c386cd8c9ef67c83f3eaddc79f1ff910342602c9152ffe8003bce51b28b0100000008636363006a636a52ffffffff04b8f67703000000000852005353ac6552520cef720200000000085151ab6352ab00ab5096d6030000000005516a005100662582020000000001ac6c137280", "6a65", 1, 1513618429, "e2fa3e1976aed82c0987ab30d4542da2cb1cffc2f73be13480132da8c8558d5c"],
+ ["91ebc4cf01bc1e068d958d72ee6e954b196f1d85b3faf75a521b88a78021c543a06e056279000000000265ab7c12df0503832121030000000000cc41a6010000000005ab5263516540a951050000000006ab63ab65acac00000000", "526a0065636a6a6aac", 0, -614046478, "7de4ba875b2e584a7b658818c112e51ee5e86226f5a80e5f6b15528c86400573"],
+ ["3cd4474201be7a6c25403bf00ca62e2aa8f8f4f700154e1bb4d18c66f7bb7f9b975649f0dc0100000006535151535153ffffffff01febbeb000000000006005151006aac00000000", "", 0, -1674687131, "6b77ca70cc452cc89acb83b69857cda98efbfc221688fe816ef4cb4faf152f86"],
+ ["92fc95f00307a6b3e2572e228011b9c9ed41e58ddbaefe3b139343dbfb3b34182e9fcdc3f50200000002acab847bf1935fde8bcfe41c7dd99683289292770e7f163ad09deff0e0665ed473cd2b56b0f40300000006516551ab6351294dab312dd87b9327ce2e95eb44b712cfae0e50fda15b07816c8282e8365b643390eaab01000000026aacffffffff016e0b6b040000000001ac00000000", "650065acac005300", 2, -1885164012, "bd7d26bb3a98fc8c90c972500618bf894cb1b4fe37bf5481ff60eef439d3b970"],
+ ["4db591ab018adcef5f4f3f2060e41f7829ce3a07ea41d681e8cb70a0e37685561e4767ac3b0000000005000052acabd280e63601ae6ef20000000000036a636326c908f7", "ac6a51526300630052", 0, 862877446, "355ccaf30697c9c5b966e619a554d3323d7494c3ea280a9b0dfb73f953f5c1cb"],
+ ["503fd5ef029e1beb7b242d10032ac2768f9a1aca0b0faffe51cec24770664ec707ef7ede4f01000000045253ac53375e350cc77741b8e96eb1ce2d3ca91858c052e5f5830a0193200ae2a45b413dda31541f0000000003516553ffffffff0175a5ba0500000000015200000000", "6aab65510053ab65", 1, 1603081205, "353ca9619ccb0210ae18b24d0e57efa7abf8e58fa6f7102738e51e8e72c9f0c4"],
+ ["c80abebd042cfec3f5c1958ee6970d2b4586e0abec8305e1d99eb9ee69ecc6c2cbd76374380000000007ac53006300ac510acee933b44817db79320df8094af039fd82111c7726da3b33269d3820123694d849ee5001000000056a65ab526562699bea8530dc916f5d61f0babea709dac578774e8a4dcd9c640ec3aceb6cb2443f24f302000000020063ea780e9e57d1e4245c1e5df19b4582f1bf704049c5654f426d783069bcc039f2d8fa659f030000000851ab53635200006a8d00de0b03654e8500000000000463ab635178ebbb0400000000055100636aab239f1d030000000006ab006300536500000000", "6565ac515100", 3, 1460851377, "b35bb1b72d02fab866ed6bbbea9726ab32d968d33a776686df3ac16aa445871e"],
+ ["0337b2d5043eb6949a76d6632b8bb393efc7fe26130d7409ef248576708e2d7f9d0ced9d3102000000075352636a5163007034384dfa200f52160690fea6ce6c82a475c0ef1caf5c9e5a39f8f9ddc1c8297a5aa0eb02000000026a51ffffffff38e536298799631550f793357795d432fb2d4231f4effa183c4e2f61a816bcf0030000000463ac5300706f1cd3454344e521fde05b59b96e875c8295294da5d81d6cc7efcfe8128f150aa54d6503000000008f4a98c704c1561600000000000072cfa6000000000000e43def01000000000100cf31cc0500000000066365526a6500cbaa8e2e", "", 3, 2029506437, "7615b4a7b3be865633a31e346bc3db0bcc410502c8358a65b8127089d81b01f8"],
+ ["59f6cffd034733f4616a20fe19ea6aaf6abddb30b408a3a6bd86cd343ab6fe90dc58300cc90200000000ffffffffc835430a04c3882066abe7deeb0fa1fdaef035d3233460c67d9eabdb05e95e5a02000000080065ac535353ab00ffffffff4b9a043e89ad1b4a129c8777b0e8d87a014a0ab6a3d03e131c27337bbdcb43b402000000066a5100abac6ad9e9bf62014bb118010000000001526cbe484f", "ab526352ab65", 0, 2103515652, "4f2ccf981598639bec57f885b4c3d8ea8db445ea6e61cfd45789c69374862e5e"],
+ ["cbc79b10020b15d605680a24ee11d8098ad94ae5203cb6b0589e432832e20c27b72a926af20300000006ab65516a53acbb854f3146e55c508ece25fa3d99dbfde641a58ed88c051a8a51f3dacdffb1afb827814b02000000026352c43e6ef30302410a020000000000ff4bd90100000000065100ab63000008aa8e0400000000095265526565ac5365abc52c8a77", "53526aac0051", 0, 202662340, "984efe0d8d12e43827b9e4b27e97b3777ece930fd1f589d616c6f9b71dab710e"],
+ ["7c07419202fa756d29288c57b5c2b83f3c847a807f4a9a651a3f6cd6c46034ae0aa3a7446b0200000004ab6a6365ffffffff9da83cf4219bb96c76f2d77d5df31c1411a421171d9b59ec02e5c1218f29935403000000008c13879002f8b1ac0400000000086a63536a636553653c584f02000000000000000000", "abac53ab656363", 1, -1038419525, "4a74f365a161bc6c9bddd249cbd70f5dadbe3de70ef4bd745dcb6ee1cd299fbd"],
+ ["351cbb57021346e076d2a2889d491e9bfa28c54388c91b46ee8695874ad9aa576f1241874d0200000008ab6563525300516affffffffe13e61b8880b8cd52be4a59e00f9723a4722ea58013ec579f5b3693b9e115b1100000000096363abac5252635351ffffffff027fee02040000000008ab6a5200ab006a65b85f130200000000086a52630053ab52ab00000000", "ab6aab65", 1, 586415826, "08bbb746a596991ab7f53a76e19acad087f19cf3e1db54054aab403c43682d09"],
+ ["a8252ea903f1e8ff953adb16c1d1455a5036222c6ea98207fc21818f0ece2e1fac310f9a0100000000095163ac635363ac0000be6619e9fffcde50a0413078821283ce3340b3993ad00b59950bae7a9f931a9b0a3a035f010000000463005300b8b0583fbd6049a1715e7adacf770162811989f2be20af33f5f60f26eba653dc26b024a00000000006525351636552ffffffff046d2acc030000000002636a9a2d430500000000080065005165ab53abecf63204000000000052b9ed050000000008acacac53ab65656500000000", "65ab53635253636a51", 2, 1442639059, "8ca11838775822f9a5beee57bdb352f4ee548f122de4a5ca61c21b01a1d50325"],
+ ["2f1a425c0471a5239068c4f38f9df135b1d24bf52d730d4461144b97ea637504495aec360801000000055300515365c71801dd1f49f376dd134a9f523e0b4ae611a4bb122d8b26de66d95203f181d09037974300000000025152ffffffff9bdcea7bc72b6e5262e242c94851e3a5bf8f314b3e5de0e389fc9e5b3eadac030000000009525265655151005153ffffffffdbb53ce99b5a2320a4e6e2d13b01e88ed885a0957d222e508e9ec8e4f83496cb0200000007635200abac63ac04c96237020cc5490100000000080000516a51ac6553074a360200000000025152225520ca", "6551ab65ac65516a", 1, -489869549, "9bc5bb772c553831fb40abe466074e59a469154679c7dee042b8ea3001c20393"],
+ ["ef3acfd4024defb48def411b8f8ba2dc408dc9ee97a4e8bde4d6cb8e10280f29c98a6e8e9103000000035100513d5389e3d67e075469dfd9f204a7d16175653a149bd7851619610d7ca6eece85a516b2df0300000005516aac6552ca678bdf02f477f003000000000057e45b0300000000055252525252af35c20a", "5165ac53ab", 1, -1900839569, "78eb6b24365ac1edc386aa4ffd15772f601059581c8776c34f92f8a7763c9ccf"],
+ ["ff4468dc0108475fc8d4959a9562879ce4ab4867a419664bf6e065f17ae25043e6016c70480100000000ffffffff02133c6f0400000000000bd0a8020000000004006a520035afa4f6", "51ac65ab", 0, -537664660, "f6da59b9deac63e83728850ac791de61f5dfcaeed384ebcbb20e44afcd8c8910"],
+ ["4e8594d803b1d0a26911a2bcdd46d7cbc987b7095a763885b1a97ca9cbb747d32c5ab9aa91030000000353ac53a0cc4b215e07f1d648b6eeb5cdbe9fa32b07400aa773b9696f582cebfd9930ade067b2b200000000060065abab6500fc99833216b8e27a02defd9be47fafae4e4a97f52a9d2a210d08148d2a4e5d02730bcd460100000004516351ac37ce3ae1033baa55040000000006006a636a63acc63c990400000000025265eb1919030000000005656a6a516a00000000", "", 1, -75217178, "04c5ee48514cd033b82a28e336c4d051074f477ef2675ce0ce4bafe565ee9049"],
+ ["a88830a7023f13ed19ab14fd757358eb6af10d6520f9a54923a6d613ac4f2c11e249cda8aa030000000851630065abababacffffffff8f5fe0bc04a33504c4b47e3991d25118947a0261a9fa520356731eeabd561dd3020000000363ababffffffff038404bd010000000008ab5153516aab6a63d33a5601000000000263004642dc020000000009655152acac636352004be6f3af", "5253536565006aab6a", 0, 1174417836, "2e42ead953c9f4f81b72c27557e6dc7d48c37ff2f5c46c1dbe9778fb0d79f5b2"],
+ ["44e1a2b4010762af23d2027864c784e34ef322b6e24c70308a28c8f2157d90d17b99cd94a401000000085163656565006300ffffffff0198233d020000000002000000000000", "52525153656365", 0, 1119696980, "d9096de94d70c6337da6202e6e588166f31bff5d51bb5adc9468594559d65695"],
+ ["44ca65b901259245abd50a745037b17eb51d9ce1f41aa7056b4888285f48c6f26cb97b7a25020000000552636363abffffffff047820350400000000040053acab14f3e603000000000652635100ab630ce66c03000000000001bdc704000000000765650065ac51ac3e886381", "51", 0, -263340864, "ed5622ac642d11f90e68c0feea6a2fe36d880ecae6b8c0d89c4ea4b3d162bd90"],
+ ["cfa147d2017fe84122122b4dda2f0d6318e59e60a7207a2d00737b5d89694d480a2c26324b0000000006006351526552ffffffff0456b5b804000000000800516aab525363ab166633000000000004655363ab254c0e02000000000952ab6a6a00ab525151097c1b020000000009656a52ac6300530065ad0d6e50", "6a535165ac6a536500", 0, -574683184, "f926d4036eac7f019a2b0b65356c4ee2fe50e089dd7a70f1843a9f7bc6997b35"],
+ ["91c5d5f6022fea6f230cc4ae446ce040d8313071c5ac1749c82982cc1988c94cb1738aa48503000000016a19e204f30cb45dd29e68ff4ae160da037e5fc93538e21a11b92d9dd51cf0b5efacba4dd70000000005656a6aac51ffffffff03db126905000000000953006a53ab6563636a36a273030000000006656a52656552b03ede00000000000352516500000000", "530052526a00", 1, 1437328441, "255c125b60ee85f4718b2972174c83588ee214958c3627f51f13b5fb56c8c317"],
+ ["03f20dc202c886907b607e278731ebc5d7373c348c8c66cac167560f19b341b782dfb634cb03000000076a51ac6aab63abea3e8de7adb9f599c9caba95aa3fa852e947fc88ed97ee50e0a0ec0d14d164f44c0115c10100000004ab5153516fdd679e0414edbd000000000005ac636a53512021f2040000000007006a0051536a52c73db2050000000005525265ac5369046e000000000003ab006a1ef7bd1e", "52656a", 0, 1360223035, "5a0a05e32ce4cd0558aabd5d79cd5fcbffa95c07137506e875a9afcba4bef5a2"],
+ ["d9611140036881b61e01627078512bc3378386e1d4761f959d480fdb9d9710bebddba2079d020000000763536aab5153ab819271b41e228f5b04daa1d4e72c8e1955230accd790640b81783cfc165116a9f535a74c000000000163ffffffffa2e7bb9a28e810624c251ff5ba6b0f07a356ac082048cf9f39ec036bba3d431a02000000076a000000ac65acffffffff01678a820000000000085363515153ac635100000000", "535353", 2, -82213851, "52b9e0778206af68998cbc4ebdaad5a9469e04d0a0a6cef251abfdbb74e2f031"],
+ ["98b3a0bf034233afdcf0df9d46ac65be84ef839e58ee9fa59f32daaa7d684b6bdac30081c60200000007636351acabababffffffffc71cf82ded4d1593e5825618dc1d5752ae30560ecfaa07f192731d68ea768d0f0100000006650052636563f3a2888deb5ddd161430177ce298242c1a86844619bc60ca2590d98243b5385bc52a5b8f00000000095365acacab520052ac50d4722801c3b8a60300000000035165517e563b65", "51", 1, -168940690, "b6b684e2d2ecec8a8dce4ed3fc1147f8b2e45732444222aa8f52d860c2a27a9d"],
+ ["97be4f7702dc20b087a1fdd533c7de762a3f2867a8f439bddf0dcec9a374dfd0276f9c55cc0300000000cdfb1dbe6582499569127bda6ca4aaff02c132dc73e15dcd91d73da77e92a32a13d1a0ba0200000002ab51ffffffff048cfbe202000000000900516351515363ac535128ce0100000000076aac5365ab6aabc84e8302000000000863536a53ab6a6552f051230500000000066aac535153510848d813", "ac51", 0, 229541474, "e5da9a416ea883be1f8b8b2d178463633f19de3fa82ae25d44ffb531e35bdbc8"],
+ ["085b6e04040b5bff81e29b646f0ed4a45e05890a8d32780c49d09643e69cdccb5bd81357670100000001abffffffffa5c981fe758307648e783217e3b4349e31a557602225e237f62b636ec26df1a80300000004650052ab4792e1da2930cc90822a8d2a0a91ea343317bce5356b6aa8aae6c3956076aa33a5351a9c0300000004abac5265e27ddbcd472a2f13325cc6be40049d53f3e266ac082172f17f6df817db1936d9ff48c02b000000000152ffffffff021aa7670500000000085353635163ab51ac14d584000000000001aca4d136cc", "6a525300536352536a", 0, -1398925877, "41ecca1e8152ec55074f4c39f8f2a7204dda48e9ec1e7f99d5e7e4044d159d43"],
+ ["eec32fff03c6a18b12cd7b60b7bdc2dd74a08977e53fdd756000af221228fe736bd9c42d870100000007005353ac515265ffffffff037929791a188e9980e8b9cc154ad1b0d05fb322932501698195ab5b219488fc02000000070063510065ab6a0bfc176aa7e84f771ea3d45a6b9c24887ceea715a0ff10ede63db8f089e97d927075b4f1000000000551abab63abffffffff02eb933c000000000000262c420000000000036563632549c2b6", "6352", 2, 1480445874, "ff8a4016dfdd918f53a45d3a1f62b12c407cd147d68ca5c92b7520e12c353ff5"],
+ ["98ea7eac0313d9fb03573fb2b8e718180c70ce647bebcf49b97a8403837a2556cb8c9377f30000000004ac53ac65ffffffff8caac77a5e52f0d8213ef6ce998bedbb50cfdf108954771031c0e0cd2a78423900000000010066e99a44937ebb37015be3693761078ad5c73aa73ec623ac7300b45375cc8eef36087eb80000000007515352acac5100ffffffff0114a51b02000000000000000000", "6aacab", 0, 243527074, "bad77967f98941af4dd52a8517d5ad1e32307c0d511e15461e86465e1b8b5273"],
+ ["3ab70f4604e8fc7f9de395ec3e4c3de0d560212e84a63f8d75333b604237aa52a10da17196000000000763526a6553ac63a25de6fd66563d71471716fe59087be0dde98e969e2b359282cf11f82f14b00f1c0ac70f02000000050052516aacdffed6bb6889a13e46956f4b8af20752f10185838fd4654e3191bf49579c961f5597c36c0100000005ac636363abc3a1785bae5b8a1b4be5d0cbfadc240b4f7acaa7dfed6a66e852835df5eb9ac3c553766801000000036a65630733b7530218569602000000000952006a6a6a51acab52777f06030000000007ac0063530052abc08267c9", "000000536aac0000", 1, 1919096509, "df1c87cf3ba70e754d19618a39fdbd2970def0c1bfc4576260cba5f025b87532"],
+ ["bdb6b4d704af0b7234ced671c04ba57421aba7ead0a117d925d7ebd6ca078ec6e7b93eea6600000000026565ffffffff3270f5ad8f46495d69b9d71d4ab0238cbf86cc4908927fbb70a71fa3043108e6010000000700516a65655152ffffffff6085a0fdc03ae8567d0562c584e8bfe13a1bd1094c518690ebcb2b7c6ce5f04502000000095251530052536a53aba576a37f2c516aad9911f687fe83d0ae7983686b6269b4dd54701cb5ce9ec91f0e6828390300000000ffffffff04cc76cc020000000002656a01ffb702000000000253ab534610040000000009acab006565516a00521f55f5040000000000389dfee9", "6a525165", 0, 1336204763, "71c294523c48fd7747eebefbf3ca06e25db7b36bff6d95b41c522fecb264a919"],
+ ["54258edd017d22b274fbf0317555aaf11318affef5a5f0ae45a43d9ca4aa652c6e85f8a040010000000953ac65ab5251656500ffffffff03321d450000000000085265526a51526a529ede8b030000000003635151ce6065020000000001534c56ec1b", "acac", 0, 2094130012, "110d90fea9470dfe6c5048f45c3af5e8cc0cb77dd58fd13d338268e1c24b1ccc"],
+ ["ce0d322e04f0ffc7774218b251530a7b64ebefca55c90db3d0624c0ff4b3f03f918e8cf6f60300000003656500ffffffff9cce943872da8d8af29022d0b6321af5fefc004a281d07b598b95f6dcc07b1830200000007abab515351acab8d926410e69d76b7e584aad1470a97b14b9c879c8b43f9a9238e52a2c2fefc2001c56af8010000000400ab5253cd2cd1fe192ce3a93b5478af82fa250c27064df82ba416dfb0debf4f0eb307a746b6928901000000096500abacac6a0063514214524502947efc0200000000035251652c40340100000000096a6aab52000052656a5231c54c", "51", 2, -2090320538, "0322ca570446869ec7ec6ad66d9838cff95405002d474c0d3c17708c7ee039c6"],
+ ["47ac54940313430712ebb32004679d3a512242c2b33d549bf5bbc8420ec1fd0850ed50eb6d0300000009536aac6a65acacab51ffffffffb843e44266ce2462f92e6bff54316661048c8c17ecb092cb493b39bfca9117850000000001519ab348c05e74ebc3f67423724a3371dd99e3bceb4f098f8860148f48ad70000313c4c223000000000653006565656512c2d8dc033f3c97010000000002636aa993aa010000000006526365ab526ab7cf560300000000076a0065ac6a526500000000", "005352535300ab6a", 2, 59531991, "8b5b3d00d9c658f062fe6c5298e54b1fe4ed3a3eab2a87af4f3119edc47b1691"],
+ ["233cd90b043916fc41eb870c64543f0111fb31f3c486dc72457689dea58f75c16ae59e9eb2000000000500536a6a6affffffff9ae30de76be7cd57fb81220fce78d74a13b2dbcad4d023f3cadb3c9a0e45a3ce000000000965ac6353ac5165515130834512dfb293f87cb1879d8d1b20ebad9d7d3d5c3e399a291ce86a3b4d30e4e32368a9020000000453005165ffffffff26d84ae93eb58c81158c9b3c3cbc24a84614d731094f38d0eea8686dec02824d0300000005636a65abacf02c784001a0bd5d03000000000900655351ab65ac516a416ef503", "", 1, -295106477, "b79f31c289e95d9dadec48ebf88e27c1d920661e50d090e422957f90ff94cb6e"],
+ ["9200e26b03ff36bc4bf908143de5f97d4d02358db642bd5a8541e6ff709c420d1482d471b70000000008abab65536a636553ffffffff61ba6d15f5453b5079fb494af4c48de713a0c3e7f6454d7450074a2a80cb6d880300000007ac6a00ab5165515dfb7574fbce822892c2acb5d978188b1d65f969e4fe874b08db4c791d176113272a5cc10100000000ffffffff0420958d000000000009ac63516a0063516353dd885505000000000465ac00007b79e901000000000066d8bf010000000005525252006a00000000", "ac5152", 0, 2089531339, "89ec7fab7cfe7d8d7d96956613c49dc48bf295269cfb4ea44f7333d88c170e62"],
+ ["45f335ba01ce2073a8b0273884eb5b48f56df474fc3dff310d9706a8ac7202cf5ac188272103000000025363ffffffff049d859502000000000365ab6a8e98b1030000000002ac51f3a80603000000000752535151ac00000306e30300000000020051b58b2b3a", "", 0, 1899564574, "78e01310a228f645c23a2ad0acbb8d91cedff4ecdf7ca997662c6031eb702b11"],
+ ["d8f652a6043b4faeada05e14b81756cd6920cfcf332e97f4086961d49232ad6ffb6bc6c097000000000453526563ffffffff1ea4d60e5e91193fbbc1a476c8785a79a4c11ec5e5d6c9950c668ceacfe07a15020000000352ab51fffffffffe029a374595c4edd382875a8dd3f20b9820abb3e93f877b622598d11d0b09e503000000095351000052ac515152ffffffff9d65fea491b979699ceb13caf2479cd42a354bd674ded3925e760758e85a756803000000046365acabffffffff0169001d00000000000651636a65656300000000", "ab0063630000ac", 3, 1050965951, "4cc85cbc2863ee7dbce15490d8ca2c5ded61998257b9eeaff968fe38e9f009ae"],
+ ["718662be026e1dcf672869ac658fd0c87d6835cfbb34bd854c44e577d5708a7faecda96e260300000004526a636a489493073353b678549adc7640281b9cbcb225037f84007c57e55b874366bb7b0fa03bdc00000000095165ababac65ac00008ab7f2a802eaa53d000000000007acac516aac526ae92f380100000000056aac00536500000000", "ab00", 1, 43296088, "2d642ceee910abff0af2116af75b2e117ffb7469b2f19ad8fef08f558416d8f7"],
+ ["94083c840288d40a6983faca876d452f7c52a07de9268ad892e70a81e150d602a773c175ad03000000007ec3637d7e1103e2e7e0c61896cbbf8d7e205b2ecc93dd0d6d7527d39cdbf6d335789f660300000000ffffffff019e1f7b03000000000800ac0051acac0053539cb363", "", 1, -183614058, "a17b66d6bb427f42653d08207a22b02353dd19ccf2c7de6a9a3a2bdb7c49c9e7"],
+ ["30e0d4d20493d0cd0e640b757c9c47a823120e012b3b64c9c1890f9a087ae4f2001ca22a61010000000152f8f05468303b8fcfaad1fb60534a08fe90daa79bff51675472528ebe1438b6f60e7f60c10100000009526aab6551ac510053ffffffffaaab73957ea2133e32329795221ed44548a0d3a54d1cf9c96827e7cffd1706df0200000009ab00526a005265526affffffffd19a6fe54352015bf170119742821696f64083b5f14fb5c7d1b5a721a3d7786801000000085265abababac53abffffffff020f39bd030000000004ab6aac52049f6c050000000004ab52516aba5b4c60", "6a6365516a6a655253", 0, -624256405, "8e221a6c4bf81ca0d8a0464562674dcd14a76a32a4b7baf99450dd9195d411e6"],
+ ["f9c69d940276ec00f65f9fe08120fc89385d7350388508fd80f4a6ba2b5d4597a9e21c884f010000000663ab63ababab15473ae6d82c744c07fc876ecd53bd0f3018b2dbedad77d757d5bdf3811b23d294e8c0170000000001abafababe00157ede2050000000006ac6a5263635300000000", "ab53", 1, 606547088, "714d8b14699835b26b2f94c58b6ea4c53da3f7adf0c62ea9966b1e1758272c47"],
+ ["5c0ac112032d6885b7a9071d3c5f493aa16c610a4a57228b2491258c38de8302014276e8be030000000300ab6a17468315215262ad5c7393bb5e0c5a6429fd1911f78f6f72dafbbbb78f3149a5073e24740300000003ac5100ffffffff33c7a14a062bdea1be3c9c8e973f54ade53fe4a69dcb5ab019df5f3345050be00100000008ac63655163526aab428defc0033ec36203000000000765516365536a00ae55b2000000000002ab53f4c0080400000000095265516a536563536a00000000", "6a005151006a", 2, 272749594, "91082410630337a5d89ff19145097090f25d4a20bdd657b4b953927b2f62c73b"],
+ ["e3683329026720010b08d4bec0faa244f159ae10aa582252dd0f3f80046a4e145207d54d31000000000852acac52656aacac3aaf2a5017438ad6adfa3f9d05f53ebed9ceb1b10d809d507bcf75e0604254a8259fc29c020000000653526552ab51f926e52c04b44918030000000000f7679c0100000000090000525152005365539e3f48050000000009516500ab635363ab008396c905000000000253650591024f", "6a6365", 0, 908746924, "458aec3b5089a585b6bad9f99fd37a2b443dc5a2eefac2b7e8c5b06705efc9db"],
+ ["48c4afb204204209e1df6805f0697edaa42c0450bbbd767941fe125b9bc40614d63d757e2203000000066a5363005152dc8b6a605a6d1088e631af3c94b8164e36e61445e2c60130292d81dabd30d15f54b355a802000000036a6353ffffffff1d05dcec4f3dedcfd02c042ce5d230587ee92cb22b52b1e59863f3717df2362f0300000005536552ac52ffffffffd4d71c4f0a7d53ba47bb0289ca79b1e33d4c569c1e951dd611fc9c9c1ca8bc6c030000000865536a65ab51abacffffffff042f9aa905000000000753655153656351ab93d8010000000002655337440e0300000000005d4c690000000000015278587acb", "ab006565526a51", 0, 1502064227, "bbed77ff0f808aa8abd946ba9e7ec1ddb003a969fa223dee0af779643cb841a9"],
+ ["00b20fd104dd59705b84d67441019fa26c4c3dec5fd3b50eca1aa549e750ef9ddb774dcabe000000000651ac656aac65ffffffff52d4246f2db568fc9eea143e4d260c698a319f0d0670f84c9c83341204fde48b0200000000ffffffffb8aeabb85d3bcbc67b132f1fd815b451ea12dcf7fc169c1bc2e2cf433eb6777a03000000086a51ac6aab6563acd510d209f413da2cf036a31b0def1e4dcd8115abf2e511afbcccb5ddf41d9702f28c52900100000006ac52ab6a0065ffffffff039c8276000000000008ab53655200656a52401561010000000003acab0082b7160100000000035100ab00000000", "535265", 1, -947367579, "3212c6d6dd8d9d3b2ac959dec11f4638ccde9be6ed5d36955769294e23343da0"],
+ ["455131860220abbaa72015519090a666faf137a0febce7edd49da1eada41feab1505a0028b02000000036365ab453ead4225724eb69beb590f2ec56a7693a608871e0ab0c34f5e96157f90e0a96148f3c502000000085251ab51535163acffffffff022d1249040000000009abac00acac6565630088b310040000000000e3920e59", "5152ab6a52ac5152", 0, 294375737, "c40fd7dfa72321ac79516502500478d09a35cc22cc264d652c7d18b14400b739"],
+ ["624d28cb02c8747915e9af2b13c79b417eb34d2fa2a73547897770ace08c6dd9de528848d3030000000651ab63abab533c69d3f9b75b6ef8ed2df50c2210fd0bf4e889c42477d58682f711cbaece1a626194bb85030000000765acab53ac5353ffffffff018cc280040000000009abacabac52636352ac6859409e", "ac51ac", 1, 1005144875, "919144aada50db8675b7f9a6849c9d263b86450570293a03c245bd1e3095e292"],
+ ["8f28471d02f7d41b2e70e9b4c804f2d90d23fb24d53426fa746bcdcfffea864925bdeabe3e0200000001acffffffff76d1d35d04db0e64d65810c808fe40168f8d1f2143902a1cc551034fd193be0e0000000001acffffffff048a5565000000000005005151516afafb610400000000045263ac53648bb30500000000086363516a6a5165513245de01000000000000000000", "6a0053510053", 1, -1525137460, "305fc8ff5dc04ebd9b6448b03c9a3d945a11567206c8d5214666b30ec6d0d6cc"],
+ ["10ec50d7046b8b40e4222a3c6449490ebe41513aad2eca7848284a08f3069f3352c2a9954f0000000009526aac656352acac53ffffffff0d979f236155aa972472d43ee6f8ce22a2d052c740f10b59211454ff22cb7fd00200000007acacacab63ab53ffffffffbbf97ebde8969b35725b2e240092a986a2cbfd58de48c4475fe077bdd493a20c010000000663ab5365ababffffffff4600722d33b8dba300d3ad037bcfc6038b1db8abfe8008a15a1de2da2264007302000000035351ac6dbdafaf020d0ccf04000000000663ab6a51ab6ae06e5e0200000000036aabab00000000", "", 0, -1658960232, "2420dd722e229eccafae8508e7b8d75c6920bfdb3b5bac7cb8e23419480637c2"],
+ ["fef98b7101bf99277b08a6eff17d08f3fcb862e20e13138a77d66fba55d54f26304143e5360100000006515365abab00ffffffff04265965030000000004655252ace2c775010000000001002b23b4040000000007516a5153ab53ac456a7a00000000000753ab525251acacba521291", "526aacacab00abab53", 0, -1614097109, "4370d05c07e231d6515c7e454a4e401000b99329d22ed7def323976fa1d2eeb5"],
+ ["34a2b8830253661b373b519546552a2c3bff7414ea0060df183b1052683d78d8f54e842442000000000152ffffffffd961a8e34cf374151058dfcddc86509b33832bc57267c63489f69ff01199697c0300000002abacba856cfb01b17c2f050000000008515365ac53ab000000000000", "5263ab656a", 1, -2104480987, "2f9993e0a84a6ca560d6d1cc2b63ffe7fd71236d9cfe7d809491cef62bbfad84"],
+ ["43559290038f32fda86580dd8a4bc4422db88dd22a626b8bd4f10f1c9dd325c8dc49bf479f01000000026351ffffffff401339530e1ed3ffe996578a17c3ec9d6fccb0723dd63e7b3f39e2c44b976b7b0300000006ab6a65656a51ffffffff6fb9ba041c96b886482009f56c09c22e7b0d33091f2ac5418d05708951816ce7000000000551ac525100ffffffff020921e40500000000035365533986f40500000000016a00000000", "52ac51", 0, 1769771809, "02040283ef2291d8e1f79bb71bdabe7c1546c40d7ed615c375643000a8b9600d"],
+ ["6878a6bd02e7e1c8082d5e3ee1b746cfebfac9e8b97e61caa9e0759d8a8ecb3743e36a30de0100000002ab532a911b0f12b73e0071f5d50b6bdaf783f4b9a6ce90ec0cad9eecca27d5abae188241ddec0200000001651c7758d803f7457b0500000000036551515f4e90000000000001007022080200000000035365acc86b6946", "6351ab", 0, -1929374995, "f24be499c58295f3a07f5f1c6e5084496ae160450bd61fdb2934e615289448f1"],
+ ["35b6fc06047ebad04783a5167ab5fc9878a00c4eb5e7d70ef297c33d5abd5137a2dea9912402000000036aacacffffffff21dc291763419a584bdb3ed4f6f8c60b218aaa5b99784e4ba8acfec04993e50c03000000046a00ac6affffffff69e04d77e4b662a82db71a68dd72ef0af48ca5bebdcb40f5edf0caf591bb41020200000000b5db78a16d93f5f24d7d932f93a29bb4b784febd0cbb1943f90216dc80bba15a0567684b000000000853ab52ab5100006a1be2208a02f6bdc103000000000265ab8550ea04000000000365636a00000000", "", 0, -1114114836, "1c8655969b241e717b841526f87e6bd68b2329905ba3fc9e9f72526c0b3ea20c"],
+ ["bebb90c302bf91fd4501d33555a5fc5f2e1be281d9b7743680979b65c3c919108cc2f517510100000003abab00ffffffff969c30053f1276550532d0aa33cfe80ca63758cd215b740448a9c08a84826f3303000000056565ab5153ffffffff04bf6f2a04000000000565ab5265ab903e760100000000026a6a7103fa020000000006526553525365b05b2c000000000006ab000000535300000000", "51510053ab63635153", 1, 1081291172, "94338cd47a4639be30a71e21a7103cee4c99ef7297e0edd56aaf57a068b004de"],
+ ["af48319f031b4eeb4319714a285f44244f283cbff30dcb9275b06f2348ccd0d7f015b54f8500000000066363ac65ac6affffffff2560a9817ebbc738ad01d0c9b9cf657b8f9179b1a7f073eb0b67517409d108180200000005ac6365ab52ffffffff0bdd67cd4ecae96249a2e2a96db1490ee645f042fd9d5579de945e22b799f4d003000000086552ab515153ab00cf187c8202e51abf0300000000066552006a00abadf37d000000000004ac6a535100000000", "63ab65", 1, -1855554446, "60caf46a7625f303c04706cec515a44b68ec319ee92273acb566cca4f66861c1"],
+ ["f35befbc03faf8c25cc4bc0b92f6239f477e663b44b83065c9cb7cf231243032cf367ce3130000000005ab65526a517c4c334149a9c9edc39e29276a4b3ffbbab337de7908ea6f88af331228bd90086a6900ba020000000151279d19950d2fe81979b72ce3a33c6d82ebb92f9a2e164b6471ac857f3bbd3c0ea213b542010000000953ab51635363520065052657c20300a9ba04000000000452636a6a0516ea020000000008535253656365ababcfdd3f01000000000865ac516aac00530000000000", "", 2, -99793521, "c834a5485e68dc13edb6c79948784712122440d7fa5bbaa5cd2fc3d4dac8185d"],
+ ["d3da18520216601acf885414538ce2fb4d910997eeb91582cac42eb6982c9381589587794f0300000000fffffffff1b1c9880356852e10cf41c02e928748dd8fae2e988be4e1c4cb32d0bfaea6f7000000000465ab6aabffffffff02fb0d69050000000002ababeda8580500000000085163526565ac52522b913c95", "ac", 1, -1247973017, "99b32b5679d91e0f9cdd6737afeb07459806e5acd7630c6a3b9ab5d550d0c003"],
+ ["8218eb740229c695c252e3630fc6257c42624f974bc856b7af8208df643a6c520ef681bfd00000000002510066f30f270a09b2b420e274c14d07430008e7886ec621ba45665057120afce58befca96010300000004525153ab84c380a9015d96100000000000076a5300acac526500000000", "ac005263", 0, -1855679695, "5071f8acf96aea41c7518bd1b5b6bbe16258b529df0c03f9e374b83c66b742c6"],
+ ["1123e7010240310013c74e5def60d8e14dd67aedff5a57d07a24abc84d933483431b8cf8ea0300000003530051fc6775ff1a23c627a2e605dd2560e84e27f4208300071e90f4589e762ad9c9fe8d0da95e020000000465655200ffffffff04251598030000000004ab65ab639d28d90400000000096563636aacac525153474df801000000000851525165ac51006a75e23b040000000000e5bd3a4a", "6363636565", 0, -467124448, "9cb0dd04e9fe287b112e94a1647590d27e8b164ca13c4fe70c610fd13f82c2fd"],
+ ["fd92fe1003083c5179f97e77bf7d71975788138147adbdb283306802e261c0aee080fa22630200000000860c643ba9a1816b9badf36077b4554d11720e284e395a1121bc45279e148b2064c65e49020000000651ab6a53636a2c713088d20f4bc4001264d972cce05b9fe004dc33376ad24d0d013e417b91a5f1b6734e000000000100ffffffff02e3064c0500000000066552006a5165b86e8705000000000665ab65ab53522052eadb", "00ab53525265", 0, 776203277, "47207b48777727532f62e09afcd4104ea6687e723c7657c30504fa2081331cc8"],
+ ["d1b6a703038f14d41fcc5cc45455faa135a5322be4bf0f5cbcd526578fc270a236cacb853f0200000001abffffffff135aeff902fa38f202ccf5bd34437ff89c9dc57a028b62447a0a38579383e8ef0000000000ffffffffadf398d2c818d0b90bc474f540c3618a4a643482eeab73d36101987e2ec0335900000000004bd3323504e69fc10000000000055151535251790ada02000000000563ab6aab521337a704000000000963ac63abacac52656a1e9862010000000007656500ac51ab6a8f4ee672", "ab5251656565ac63", 2, 82008394, "b8f3d255549909c07588ecba10a02e55a2d6f2206d831af9da1a7dae64cfbc8b"],
+ ["81dadaa7011556683db3fe95262f4fdb20391b7e75b7ffcee51b176af64d83c06f85545d620200000005ab5151ab52ffffffff044805ef0300000000065353516352639702c802000000000900516351515252ab5270db08040000000009ac516aab526553abac4aabc90500000000096365ab0052636a525100000000", "6565ab6a5152", 0, -2126294159, "ad01ec9d6dbae325ec3a8e1fd98e2d03b1188378210efef093dd8b0b0ef3f19d"],
+ ["3b937e05032b8895d2f4945cb7e3679be2fbd15311e2414f4184706dbfc0558cf7de7b4d000000000001638b91a12668a3c3ce349788c961c26aa893c862f1e630f18d80e7843686b6e1e6fc396310000000000852635353ab65ac51eeb09dd1c9605391258ee6f74b9ae17b5e8c2ef010dc721c5433dcdc6e93a1593e3b6d1700000000085365ac6553526351ffffffff0308b18e04000000000253acb6dd00040000000008536aac5153ac516ab0a88201000000000500ac006500804e3ff2", "", 0, 416167343, "595a3c02254564634e8085283ec4ea7c23808da97ce9c5da7aecd7b553e7fd7f"],
+ ["a48f27ca047997470da74c8ee086ddad82f36d9c22e790bd6f8603ee6e27ad4d3174ea875403000000095153ac636aab6aacabffffffffefc936294e468d2c9a99e09909ba599978a8c0891ad47dc00ba424761627cef202000000056a51630053ffffffff304cae7ed2d3dbb4f2fbd679da442aed06221ffda9aee460a28ceec5a9399f4e0200000000f5bddf82c9c25fc29c5729274c1ff0b43934303e5f595ce86316fc66ad263b96ca46ab8d0100000003536500d7cf226b0146b00c04000000000200ac5c2014ce", "515100636563", 0, 1991799059, "9c051a7092fe17fa62b1720bc2c4cb2ffc1527d9fb0b006d2e142bb8fe07bf3c"],
+ ["180cd53101c5074cf0b7f089d139e837fe49932791f73fa2342bd823c6df6a2f72fe6dba1303000000076a6a63ac53acabffffffff03853bc1020000000007ac526a6a6a6a003c4a8903000000000453515163a0fbbd030000000005ab656a5253253d64cf", "ac65", 0, -1548453970, "4d8efb3b99b9064d2f6be33b194a903ffabb9d0e7baa97a48fcec038072aac06"],
+ ["c21ec8b60376c47e057f2c71caa90269888d0ffd5c46a471649144a920d0b409e56f190b700000000008acac6a526a536365ffffffff5d315d9da8bf643a9ba11299450b1f87272e6030fdb0c8adc04e6c1bfc87de9a0000000000ea43a9a142e5830c96b0ce827663af36b23b0277244658f8f606e95384574b91750b8e940000000007516a63ac0063acffffffff023c61be0400000000055165ab5263313cc8020000000006006a53526551ed8c3d56", "6a", 1, 1160627414, "a638cc17fd91f4b1e77877e8d82448c84b2a4e100df1373f779de7ad32695112"],
+ ["128cd90f04b66a4cbc78bf48748f6eec0f08d5193ee8d0a6f2e8d3e5f138ed12c2c87d01a301000000085200ab6aac00ab00ffffffff09fc88bb1851e3dfb3d30179c38e15aeb1b39929c7c74f6acd071994ed4806490300000000e7fc5ea12ec56f56c0d758ecf4bb88aa95f3b08176b336db3b9bec2f6e27336dce28adbe030000000400530051fffffffffd6ff1adcf1fbe0d883451ee46904f1b7e8820243d395559b2d4ee8190a6e891000000000080fb1ae702f85b400000000000035200ab8d9651010000000006ab6a52536aab00000000", "ab", 1, 1667598199, "c10ccc9db8a92d7d4b133a2980782dab9d9d1d633d0dde9f9612ada57771fd89"],
+ ["da9695a403493d3511c10e1fe1286f954db0366b7667c91ef18ae4578056c1bf752114ac5901000000035351519788d91dd1f9c62dc005d80ea54eb13f7131ca5aace3d5d29f9b58ccc5fbc9a27e779950010000000453ac6a00ffffffffe2556ff29ebe83eb42a32c7a8d93bc598043578f491b5935805a33608538845a030000000252ab65d21b3b018f26c4030000000006acab51535352e1cbcb10", "006565ab52", 2, -1550927794, "0ca673a1ee66f9625ceb9ab278ebef772c113c188112b02824570c17fdf48194"],
+ ["b240517501334021240427adb0b413433641555424f6d24647211e3e6bfbb22a8045cbda2f000000000071bac8630112717802000000000000000000", "6a5165abac52656551", 0, 1790414254, "2c8be597620d95abd88f9c1cf4967c1ae3ca2309f3afec8928058c9598660e9e"],
+ ["96bac43903044a199b4b3efeeec5d196ee23fb05495541fa2cd6fb6405a9432d1723363660010000000151ffffffffe6ce2b66ce1488918a3e880bebb0e750123f007c7bcbac8fcd67ce75cb6fbae80300000000ffffffff9c0955aa07f506455834895c0c56be5a095398f47c62a3d431fe125b161d666a0200000005520000abac7ffdbc540216f2f004000000000165a26dce010000000001ab00000000", "5151ab656a656a6a63", 0, -707123065, "26b22e18d5d9081fde9631594a4f7c49069ed2e429f3d08caf9d834f685ccab2"],
+ ["b8fd394001ed255f49ad491fecc990b7f38688e9c837ccbc7714ddbbf5404f42524e68c18f0000000007ab6353535363ab081e15ee02706f7d050000000008515200535351526364c7ec040000000005636a53acac9206cbe1", "655352ac", 0, -1251578838, "8e0697d8cd8a9ccea837fd798cc6c5ed29f6fbd1892ee9bcb6c944772778af19"],
+ ["e42a76740264677829e30ed610864160c7f97232c16528fe5610fc08814b21c34eefcea69d010000000653006a6a0052ffffffff647046cf44f217d040e6a8ff3f295312ab4dd5a0df231c66968ad1c6d8f4428000000000025352ffffffff0199a7f900000000000000000000", "655263006a005163", 1, 1122505713, "7cda43f1ff9191c646c56a4e29b1a8c6cb3f7b331da6883ef2f0480a515d0861"],
+ ["0f034f32027a8e094119443aa9cfe11737c6d7dda9a52b839bc073dcc0235b847b28e0fab60200000006ac53ac536a63eee63447dfdad80476994b68706e916df1bd9d7cb4f3a4f6b14369de84564bea2e8688bd030000000565636a65acf8434663020b35fe01000000000800abab655163acabb3d6a103000000000353acab345eeda0", "526a51ac63ab51", 1, 66020215, "4435e62ff6531ac73529aac9cf878a7219e0b6e6cac79af8487c5355d1ad6d43"],
+ ["a2dfa4690214c1ab25331815a5128f143219de51a47abdc7ce2d367e683eeb93960a31af9f010000000363636affffffff8be0628abb1861b078fcc19c236bc4cc726fa49068b88ad170adb2a97862e7460200000004ac655363ffffffff0441f11103000000000153dbab0c000000000009ab53ac5365526aab63abbb95050000000004ab52516a29a029040000000003ac526a00000000", "6a52ac63", 1, -1302210567, "913060c7454e6c80f5ba3835454b54db2188e37dc4ce72a16b37d11a430b3d23"],
+ ["9dbc591f04521670af83fb3bb591c5d4da99206f5d38e020289f7db95414390dddbbeb56680100000004ac5100acffffffffb6a40b5e29d5e459f8e72d39f800089529f0889006cad3d734011991da8ef09d0100000009526a5100acab536a515fc427436df97cc51dc8497642ffc868857ee245314d28b356bd70adba671bd6071301fc0000000000ffffffff487efde2f620566a9b017b2e6e6d42525e4070f73a602f85c6dfd58304518db30000000005516353006a8d8090180244904a0200000000046a65656ab1e9c203000000000451ab63aba06a5449", "", 0, -1414953913, "bae189eb3d64aedbc28a6c28f6c0ccbd58472caaf0cf45a5aabae3e031dd1fea"],
+ ["1345fb2c04bb21a35ae33a3f9f295bece34650308a9d8984a989dfe4c977790b0c21ff9a7f0000000006ac52ac6a0053ffffffff7baee9e8717d81d375a43b691e91579be53875350dfe23ba0058ea950029fcb7020000000753ab53ab63ab52ffffffff684b6b3828dfb4c8a92043b49b8cb15dd3a7c98b978da1d314dce5b9570dadd202000000086353ab6a5200ac63d1a8647bf667ceb2eae7ec75569ca249fbfd5d1b582acfbd7e1fcf5886121fca699c011d0100000003ac006affffffff049b1eb00300000000001e46dc0100000000080065ab6a6a630065ca95b40300000000030051520c8499010000000006ab6aac526a6500000000", "53526aac636300", 2, 1809978100, "cfeaa36790bc398783d4ca45e6354e1ea52ee74e005df7f9ebd10a680e9607bf"],
+ ["7d75dc8f011e5f9f7313ba6aedef8dbe10d0a471aca88bbfc0c4a448ce424a2c5580cda1560300000003ab5152ffffffff01997f8e0200000000096552ac6a65656563530d93bbcc", "00656a6563", 0, 1414485913, "ec91eda1149f75bffb97612569a78855498c5d5386d473752a2c81454f297fa7"],
+ ["1459179504b69f01c066e8ade5e124c748ae5652566b34ed673eea38568c483a5a4c4836ca0100000008ac5352006563656affffffff5d4e037880ab1975ce95ea378d2874dcd49d5e01e1cdbfae3343a01f383fa35800000000095251ac52ac6aac6500ffffffff7de3ae7d97373b7f2aeb4c55137b5e947b2d5fb325e892530cb589bc4f92abd503000000086563ac53ab520052ffffffffb4db36a32d6e543ef49f4bafde46053cb85b2a6c4f0e19fa0860d9083901a1190300000003ab51531bbcfe5504a6dbda040000000008536a5365abac6500d660c80300000000096565abab6a53536a6a54e84e010000000003acac52df2ccf0500000000025351220c857e", "", 2, 1879181631, "3aad18a209fab8db44954eb55fd3cc7689b5ec9c77373a4d5f4dae8f7ae58d14"],
+ ["d98b777f04b1b3f4de16b07a05c31d79965579d0edda05600c118908d7cf642c9cd670093f020000000953005351ac65ab5363a268caad6733b7d1718008997f249e1375eb3ab9fe68ab0fe170d8e745ea24f54ce67f9b00000000066500516a5151ffffffff7ef8040dfcc86a0651f5907e8bfd1017c940f51cf8d57e3d3fe78d57e40b1e610200000003535263ffffffff39846cfed4babc098ff465256ba3820c30d710581316afcb67cd31c623b703360300000001acffffffff03d405120100000000056300006a5201a73d050000000004ab636a6a294c8c000000000006ac65536553ac00000000", "63525351abac", 1, 2018694761, "86970af23c89b72a4f9d6281e46b9ef5220816bed71ebf1ae20df53f38fe16ff"],
+ ["cabb1b06045a895e6dcfc0c1e971e94130c46feace286759f69a16d298c8b0f6fd0afef8f20300000004ac006352ffffffffa299f5edac903072bfb7d29b663c1dd1345c2a33546a508ba5cf17aab911234602000000056a65515365ffffffff89a20dc2ee0524b361231092a070ace03343b162e7162479c96b757739c8394a0300000002abab92ec524daf73fabee63f95c1b79fa8b84e92d0e8bac57295e1d0adc55dc7af5534ebea410200000001534d70e79b04674f6f00000000000600abacab53517d60cc0200000000035265ab96c51d040000000004ac6300ac62a787050000000008006a516563ab63639e2e7ff7", "6551ac6351ac", 3, 1942663262, "d0c4a780e4e0bc22e2f231e23f01c9d536b09f6e5be51c123d218e906ec518be"],
+ ["8b96d7a30132f6005b5bd33ea82aa325e2bcb441f46f63b5fca159ac7094499f380f6b7e2e00000000076aacabac6300acffffffff0158056700000000000465005100c319e6d0", "52006a", 0, -1100733473, "fb4bd26a91b5cf225dd3f170eb09bad0eac314bc1e74503cc2a3f376833f183e"],
+ ["112191b7013cfbe18a175eaf09af7a43cbac2c396f3695bbe050e1e5f4250603056d60910e02000000001c8a5bba03738a22010000000005525352656a77a149010000000002510003b52302000000000351ac52722be8e6", "65ac6565", 0, -1847972737, "8e795aeef18f510d117dfa2b9f4a2bd2e2847a343205276cedd2ba14548fd63f"],
+ ["ce6e1a9e04b4c746318424705ea69517e5e0343357d131ad55d071562d0b6ebfedafd6cb840100000003656553ffffffff67bd2fa78e2f52d9f8900c58b84c27ef9d7679f67a0a6f78645ce61b883fb8de000000000100d699a56b9861d99be2838e8504884af4d30b909b1911639dd0c5ad47c557a0773155d4d303000000046a5151abffffffff9fdb84b77c326921a8266854f7bbd5a71305b54385e747fe41af8a397e78b7fa010000000863acac6a51ab00ac0d2e9b9d049b8173010000000007ac53526a650063ba9b7e010000000008526a00525263acac0ab3fd030000000000ea8a0303000000000200aca61a97b9", "", 1, -1276952681, "b6ed4a3721be3c3c7305a5128c9d418efa58e419580cec0d83f133a93e3a22c5"],
+ ["a7721d94021652d90c79aaf5022d98219337d50f836382403ed313adb1116ba507ac28b0b0010000000551ac6300ab89e6d64a7aa81fb9595368f04d1b36d7020e7adf5807535c80d015f994cce29554fe869b01000000065353ab636500ffffffff024944c90100000000046300635369df9f01000000000000000000", "656a536551ab", 0, -1740151687, "935892c6f02948f3b08bcd463b6acb769b02c1912be4450126768b055e8f183a"],
+ ["2f7353dd02e395b0a4d16da0f7472db618857cd3de5b9e2789232952a9b154d249102245fd030000000151617fd88f103280b85b0a198198e438e7cab1a4c92ba58409709997cc7a65a619eb9eec3c0200000003636aabffffffff0397481c0200000000045300636a0dc97803000000000009d389030000000003ac6a53134007bb", "0000536552526a", 0, -1912746174, "30c4cd4bd6b291f7e9489cc4b4440a083f93a7664ea1f93e77a9597dab8ded9c"],
+ ["7d95473604fd5267d0e1bb8c9b8be06d7e83ff18ad597e7a568a0aa033fa5b4e1e2b6f1007020000000465006a6affffffffaee008503bfc5708bd557c7e78d2eab4878216a9f19daa87555f175490c40aaf000000000263abffffffffabd74f0cff6e7ceb9acc2ee25e65af1abcebb50c08306e6c78fa8171c37613dd010000000552acacababffffffff54a3069393f7930fa1b331cdff0cb945ec21c11d4605d8eedba1d3e094c6ae1f01000000026300ffffffff0182edeb050000000009526353ab5153530065a247e8cd", "51516aab00", 2, -426210430, "2707ca714af09494bb4cf0794abe33c6cba5f29891d619e76070269d1fa8e690"],
+ ["221d4718023d9ca9fe1af178dbfce02b2b369bf823ea3f43f00891b7fef98e215c06b94fdd000000000951005153ab000051acffffffffb1c7ad1c64b7441bf5e70cd0f6eb4ec96821d67fc4997d9e6dfdceadecd36dde01000000070051536a635153ffffffff04e883cd00000000000851ab536553ab0052bbb2f70400000000002f1b2e03000000000165259fcb00000000000010dbde99", "ab", 1, 665721280, "4abce77432a86dfe608e7c1646c18b5253a373392ff962e288e3ab96bba1ba1d"],
+ ["6f66c0b3013e6ae6aabae9382a4326df31c981eac169b6bc4f746edaa7fc1f8c796ef4e374000000000665ab6aabac6affffffff0191c8d6030000000002525300000000", "6a5352516a635352ab", 0, -1299629906, "48411efeb133c6b7fec4e7bdbe613f827093cb06ea0dbcc2ffcfde3a9ac4356c"],
+ ["89e7928c04363cb520eff4465251fd8e41550cbd0d2cdf18c456a0be3d634382abcfd4a2130200000006ac516a6a656355042a796061ed72db52ae47d1607b1ceef6ca6aea3b7eea48e7e02429f382b378c4e51901000000085351ab6352ab5252ffffffff53631cbda79b40183000d6ede011c778f70147dc6fa1aed3395d4ce9f7a8e69701000000096a6553ab52516a52abad0de418d80afe059aab5da73237e0beb60af4ac490c3394c12d66665d1bac13bdf29aa8000000000153f2b59ab6027a33eb040000000007005351ac5100ac88b941030000000003ab0052e1e8a143", "63656a", 0, 1258533326, "b575a04b0bb56e38bbf26e1a396a76b99fb09db01527651673a073a75f0a7a34"],
+ ["ca356e2004bea08ec2dd2df203dc275765dc3f6073f55c46513a588a7abcc4cbde2ff011c7020000000553525100003aefec4860ef5d6c1c6be93e13bd2d2a40c6fb7361694136a7620b020ecbaca9413bcd2a030000000965ac00536352535100ace4289e00e97caaea741f2b89c1143060011a1f93090dc230bee3f05e34fbd8d8b6c399010000000365526affffffff48fc444238bda7a757cb6a98cb89fb44338829d3e24e46a60a36d4e24ba05d9002000000026a53ffffffff03d70b440200000000056a6a526aac853c97010000000002515335552202000000000351635300000000", "0052", 3, -528192467, "fc93cc056c70d5e033933d730965f36ad81ef64f1762e57f0bc5506c5b507e24"],
+ ["82d4fa65017958d53e562fac073df233ab154bd0cf6e5a18f57f4badea8200b217975e31030200000004636aab51ac0891a204227cc9050000000006635200655365bfef8802000000000865650051635252acfc2d09050000000006ab65ac51516380195e030000000007ac52525352510063d50572", "53", 0, -713567171, "e095003ca82af89738c1863f0f5488ec56a96fb81ea7df334f9344fcb1d0cf40"],
+ ["75f6949503e0e47dd70426ef32002d6cdb564a45abedc1575425a18a8828bf385fa8e808e600000000036aabab82f9fd14e9647d7a1b5284e6c55169c8bd228a7ea335987cef0195841e83da45ec28aa2e0300000002516350dc6fe239d150efdb1b51aa288fe85f9b9f741c72956c11d9dcd176889963d699abd63f0000000001ab429a63f502777d20010000000007abac52ac516a53d081d9020000000003acac630c3cc3a8", "535152516551510000", 1, 973814968, "c6ec1b7cb5c16a1bfd8a3790db227d2acc836300534564252b57bd66acf95092"],
+ ["24f24cd90132b2162f938f1c22d3ca5e7daa83515883f31a61a5177aebf99d7db6bdfc398c010000000163ffffffff01d5562d0100000000016300000000", "5265ac5165ac5252ab", 0, 1055129103, "5eeb03e03806cd7bfd44bbba69c30f84c2c5120df9e68cd8facc605fcfbc9693"],
+ ["5ff2cac201423064a4d87a96b88f1669b33adddc6fa9acdc840c0d8a243671e0e6de49a5b00300000005ac6353655353b91db50180db5a03000000000663535151006a047a3aff", "52ab51ab5365005163", 0, -1336626596, "b8db8d57fe40ab3a99cf2f8ed57da7a65050fcc1d34d4280e25faf10108d3110"],
+ ["10011f150220ad76a50ccc7bb1a015eda0ff987e64cd447f84b0afb8dc3060bdae5b36a6900200000000ffffffff1e92dd814dfafa830187bc8e5b9258de2445ec07b02c420ee5181d0b203bb334000000000565ab536a65ffffffff0124e65401000000000800ab636553ab53ac00000000", "53abab0051", 0, 440222748, "c6675bf229737e005b5c8ffa6f81d9e2c4396840921b6151316f67c4315a4270"],
+ ["8b95ec900456648d820a9b8df1d8f816db647df8a8dc9f6e7151ebf6079d90ee3f6861352a02000000085200ab00ac535151ffffffff039b10b845f961225ac0bcaac4f5fe1991029a051aa3d06a3811b5762977a67403000000035252abffffffff8559d65f40d5e261f45aec8aad3d2c56c6114b22b26f7ee54a06f0881be3a7f5010000000765635252536363ffffffff38f8b003b50f6412feb2322b06b270197f81ad69c36af02ca5008b94eee5f650020000000165ffffffff01ae2b00010000000001638eb153a2", "0053ab5300ac53", 2, 1266056769, "205f3653f0142b35ce3ef39625442efebae98cde8cbf0516b97b51073bb0479f"],
+ ["babbb7ea01ab5d584727cb44393b17cf66521606dc81e25d85273be0d57bad43e8f6b6d43501000000036a656aba83a68803fb0f4a000000000005536353ab633fcfe4020000000009ac00acab6351006a65182a0c03000000000453ac5363bee74f44", "536a6a6a6365ac51ab", 0, -799187625, "3275e98dca37243b977525a07b5d8e369d6c3bdc08cb948029a635547d0d1a4e"],
+ ["e86a24bc03e4fae784cdf81b24d120348cb5e52d937cd9055402fdba7e43281e482e77a1c100000000046363006affffffffa5447e9bdcdab22bd20d88b19795d4c8fb263fbbf7ce8f4f9a85f865953a6325020000000663ac53535253ffffffff9f8b693bc84e0101fc73748e0513a8cecdc264270d8a4ee1a1b6717607ee1eaa00000000026a513417bf980158d82c020000000009005253005351acac5200000000", "6353516365536a6a", 2, -563792735, "508129278ef07b43112ac32faf00170ad38a500eed97615a860fd58baaad174b"],
+ ["53bd749603798ed78798ef0f1861b498fc61dcee2ee0f2b37cddb115b118e73bc6a5a47a0201000000096a63656a6aab6a000007ff674a0d74f8b4be9d2e8e654840e99d533263adbdd0cf083fa1d5dd38e44d2d163d900100000007abab5251ac6a51c8b6b63f744a9b9273ccfdd47ceb05d3be6400c1ed0f7283d32b34a7f4f0889cccf06be30000000009516a52636551ab516a9ac1fe63030c677e05000000000027bc610000000000086565636a635100526e2dc60200000000015300000000", "6552536a515351ab", 1, -1617066878, "fe516df92299e995b8e6489be824c6839543071ec5e9286060b2600935bf1f20"],
+ ["691bf9fc028ca3099020b79184e70039cf53b3c7b3fe695d661fd62d7b433e65feda2150610000000003ac63abffffffff2c814c15b142bc944192bddccb90a392cd05b968b599c1d8cd99a55a28a243fd0100000009ab5300526a5200abac98516a5803dfd3540500000000046552ac522838120100000000040053ab6a4409a903000000000665636a5300658759621b", "65ac5165ab", 0, -359941441, "d582c442e0ecc400c7ba33a56c93ad9c8cfd45af820350a13623594b793486f0"],
+ ["536bc5e60232eb60954587667d6bcdd19a49048d67a027383cc0c2a29a48b960dc38c5a0370300000005ac636300abffffffff8f1cfc102f39b1c9348a2195d496e602c77d9f57e0769dabde7eaaedf9c69e250100000006acabab6a6351ffffffff0432f56f0400000000046a5365517fd54b0400000000035265539484e4050000000003536a5376dc25020000000008ac536aab6aab536ab978e686", "ac0051006a006a006a", 0, -273074082, "f151f1ec305f698d9fdce18ea292b145a58d931f1518cf2a4c83484d9a429638"],
+ ["74606eba01c2f98b86c29ba5a32dc7a7807c2abe6ed8d89435b3da875d87c12ae05329e6070200000003510052ffffffff02a1e2c4020000000006516563526a63c68bae04000000000952ab6363ab00006363fe19ae4f", "63ababacac5365", 0, 112323400, "d1b1d79001b4a0324962607b739972d6f39c1493c4500ce814fd3bd72d32a5a0"],
+ ["2ed805e20399e52b5bcc9dc075dad5cf19049ff5d7f3de1a77aee9288e59c5f4986751483f020000000165ffffffff967531a5726e7a653a9db75bd3d5208fa3e2c5e6cd5970c4d3aba84eb644c72c0300000000ffffffffd79030d20c65e5f8d3c55b5692e5bdaa2ae78cfa1935a0282efb97515feac43f030000000400006365261ab88c02bdf66a000000000003ab6351d6ad8b000000000005525152abac00000000", "630053ab5265", 0, 2072814938, "1d25d16d84d5793be1ad5cda2de9c9cf70e04a66c3dae618f1a7ca4026198e7f"],
+ ["fab796ee03f737f07669160d1f1c8bf0800041157e3ac7961fea33a293f976d79ce49c02ab0200000003ac5252eb097ea1a6d1a7ae9dace338505ba559e579a1ee98a2e9ad96f30696d6337adcda5a85f403000000096500abab656a6a656396d5d41a9b11f571d91e4242ddc0cf2420eca796ad4882ef1251e84e42b930398ec69dd80100000005526551ac6a8e5d0de804f763bb0400000000015288271a010000000001acf2bf2905000000000300ab51c9641500000000000952655363636365ac5100000000", "00ac536552", 0, -1854521113, "f3bbab70b759fe6cfae1bf349ce10716dbc64f6e9b32916904be4386eb461f1f"],
+ ["f2b539a401e4e8402869d5e1502dbc3156dbce93583f516a4947b333260d5af1a34810c6a00200000003525363ffffffff01d305e2000000000005acab535200a265fe77", "", 0, -1435650456, "41617b27321a830c712638dbb156dae23d4ef181c7a06728ccbf3153ec53d7dd"],
+ ["9f10b1d8033aee81ac04d84ceee0c03416a784d1017a2af8f8a34d2f56b767aea28ff88c8f02000000025352ffffffff748cb29843bea8e9c44ed5ff258df1faf55fbb9146870b8d76454786c4549de100000000016a5ba089417305424d05112c0ca445bc7107339083e7da15e430050d578f034ec0c589223b0200000007abac53ac6565abffffffff025a4ecd010000000006636563ab65ab40d2700000000000056a6553526333fa296c", "", 0, -395044364, "20fd0eee5b5716d6cbc0ddf852614b686e7a1534693570809f6719b6fcb0a626"],
+ ["ab81755f02b325cbd2377acd416374806aa51482f9cc5c3b72991e64f459a25d0ddb52e66703000000036a00ab8727056d48c00cc6e6222be6608c721bc2b1e69d0ffbadd51d131f05ec54bcd83003aac5000000000003f2cdb60454630e020000000007526aac63000000e9e25c040000000003516a0088c97e0000000000076a535265655263771b5805000000000851ab00ac6565515100000000", "5151ab00ac", 0, -230931127, "ba0a2c987fcdd74b6915f6462f62c3f126a0750aa70048f7aa20f70726e6a20b"],
+ ["7a17e0ef0378dab4c601240639139335da3b7d684600fa682f59b7346ef39386fe9abd69350000000004ac5252ab807f26fb3249326813e18260a603b9ad66f41f05eaa8146f66bcca452162a502aac4aa8b02000000026a534ea460faa7e3d7854ec6c70d7e797025697b547ec500b2c09c873b4d5517767d3f3720660300000000ffffffff01b12e7a02000000000900ab006aab65656a63991c03e2", "6aab6a", 1, -1577994103, "62cd3413d9d819fb7355336365cf8a2a997f7436cc050a7143972044343b3281"],
+ ["ff2ecc09041b4cf5abb7b760e910b775268abee2792c7f21cc5301dd3fecc1b4233ee70a2c0200000009acac5300006a51526affffffffeb39c195a5426afff38379fc85369771e4933587218ef4968f3f05c51d6b7c92000000000165453a5f039b8dbef7c1ffdc70ac383b481f72f99f52b0b3a5903c825c45cfa5d2c0642cd50200000001654b5038e6c49daea8c0a9ac8611cfe904fc206dad03a41fb4e5b1d6d85b1ecad73ecd4c0102000000096a51000053ab656565bdb5548302cc719200000000000452655265214a3603000000000300ab6a00000000", "52516a006a63", 1, -2113289251, "37ed6fae36fcb3360c69cac8b359daa62230fc1419b2cf992a32d8f3e079dcff"],
+ ["70a8577804e553e462a859375957db68cfdf724d68caeacf08995e80d7fa93db7ebc04519d02000000045352ab53619f4f2a428109c5fcf9fee634a2ab92f4a09dc01a5015e8ecb3fc0d9279c4a77fb27e900000000006ab6a51006a6affffffff3ed1a0a0d03f25c5e8d279bb5d931b7eb7e99c8203306a6c310db113419a69ad010000000565516300abffffffff6bf668d4ff5005ef73a1b0c51f32e8235e67ab31fe019bf131e1382050b39a630000000004536a6563ffffffff02faf0bb00000000000163cf2b4b05000000000752ac635363acac15ab369f", "ac", 0, -1175809030, "1c9d6816c20865849078f9777544b5ddf37c8620fe7bd1618e4b72fb72dddca1"],
+ ["a3604e5304caa5a6ba3c257c20b45dcd468f2c732a8ca59016e77b6476ac741ce8b16ca8360200000004acac6553ffffffff695e7006495517e0b79bd4770f955040610e74d35f01e41c9932ab8ccfa3b55d0300000007ac5253515365acffffffff6153120efc5d73cd959d72566fc829a4eb00b3ef1a5bd3559677fb5aae116e38000000000400abab52c29e7abd06ff98372a3a06227386609adc7665a602e511cadcb06377cc6ac0b8f63d4fdb03000000055100acabacffffffff04209073050000000009ab5163ac525253ab6514462e05000000000952abacab636300656a20672c0400000000025153b276990000000000056565ab6a5300000000", "5351", 0, 1460890590, "249c4513a49076c6618aabf736dfd5ae2172be4311844a62cf313950b4ba94be"],
+ ["c6a72ed403313b7d027f6864e705ec6b5fa52eb99169f8ea7cd884f5cdb830a150cebade870100000009ac63ab516565ab6a51ffffffff398d5838735ff43c390ca418593dbe43f3445ba69394a6d665b5dc3b4769b5d700000000075265acab515365ffffffff7ee5616a1ee105fd18189806a477300e2a9cf836bf8035464e8192a0d785eea3030000000700ac6a51516a52ffffffff018075fd0000000000015100000000", "005251acac5252", 2, -656067295, "2cc1c7514fdc512fd45ca7ba4f7be8a9fe6d3318328bc1a61ae6e7675047e654"],
+ ["93c12cc30270fc4370c960665b8f774e07942a627c83e58e860e38bd6b0aa2cb7a2c1e060901000000036300abffffffff4d9b618035f9175f564837f733a2b108c0f462f28818093372eec070d9f0a5440300000001acffffffff039c2137020000000001525500990100000000055265ab636a07980e0300000000005ba0e9d1", "656a5100", 1, 18954182, "6beca0e0388f824ca33bf3589087a3c8ad0857f9fe7b7609ae3704bef0eb83e2"],
+ ["97bddc63015f1767619d56598ad0eb5c7e9f880b24a928fea1e040e95429c930c1dc653bdb0100000008ac53acac00005152aaa94eb90235ed10040000000000287bdd0400000000016a8077673a", "acac6a536352655252", 0, -813649781, "5990b139451847343c9bb89cdba0e6daee6850b60e5b7ea505b04efba15f5d92"],
+ ["cc3c9dd303637839fb727270261d8e9ddb8a21b7f6cbdcf07015ba1e5cf01dc3c3a327745d0300000000d2d7804fe20a9fca9659a0e49f258800304580499e8753046276062f69dbbde85d17cd2201000000096352536a520000acabffffffffbc75dfa9b5f81f3552e4143e08f485dfb97ae6187330e6cd6752de6c21bdfd21030000000600ab53650063ffffffff0313d0140400000000096565515253526aacac167f0a040000000008acab00535263536a9a52f8030000000006abab5151ab63f75b66f2", "6a635353636a65ac65", 1, 377286607, "dbc7935d718328d23d73f8a6dc4f53a267b8d4d9816d0091f33823bd1f0233e9"],
+ ["236f91b702b8ffea3b890700b6f91af713480769dda5a085ae219c8737ebae90ff25915a3203000000056300ac6300811a6a10230f12c9faa28dae5be2ebe93f37c06a79e76214feba49bb017fb25305ff84eb020000000100ffffffff041e351703000000000351ac004ff53e050000000003ab53636c1460010000000000cb55f701000000000651520051ab0000000000", "acac636a6aac5300", 0, 406448919, "793a3d3c37f6494fab79ff10c16702de002f63e34be25dd8561f424b0ea938c4"],
+ ["22e10d2003ab4ea9849a2801921113583b7c35c3710ff49a6003489395789a7cfb1e6051900100000006526a65535151ffffffff82f21e249ec60db33831d33b9ead0d56f6496db64337dcb7f1c3327c47729c4a020000000253abffffffff138f098f0e6a4cf51dc3e7a3b749f487d1ebde71b73b731d1d02ad1180ac7b8c02000000036563acda215011027a9484020000000007635165530000ac4bf6cb0400000000066aacabab65ab3ce3f32c", "ab0052ab", 2, 1136359457, "b5bd080bbcb8cd652f440484311d7a3cb6a973cd48f03c5c00fd6beb52dfc061"],
+ ["c47d5ad60485cb2f7a825587b95ea665a593769191382852f3514a486d7a7a11d220b62c54000000000663655253acab8c3cf32b0285b040e50dcf6987ddf7c385b3665048ad2f9317b9e0c5ba0405d8fde4129b00000000095251ab00ac65635300ffffffff549fe963ee410d6435bb2ed3042a7c294d0c7382a83edefba8582a2064af3265000000000152fffffffff7737a85e0e94c2d19cd1cde47328ece04b3e33cd60f24a8a345da7f2a96a6d0000000000865ab6a0051656aab28ff30d5049613ea020000000005ac51000063f06df1050000000008ac63516aabac5153afef5901000000000700656500655253688bc00000000000086aab5352526a53521ff1d5ff", "51ac52", 2, -1296011911, "0c1fd44476ff28bf603ad4f306e8b6c7f0135a441dc3194a6f227cb54598642a"],
+ ["0b43f122032f182366541e7ee18562eb5f39bc7a8e5e0d3c398f7e306e551cdef773941918030000000863006351ac51acabffffffffae586660c8ff43355b685dfa8676a370799865fbc4b641c5a962f0849a13d8250100000005abab63acabffffffff0b2b6b800d8e77807cf130de6286b237717957658443674df047a2ab18e413860100000008ab6aac655200ab63ffffffff04f1dbca03000000000800635253ab656a52a6eefd0300000000036365655d8ca90200000000005a0d530400000000015300000000", "65ac65acac", 0, 351448685, "86f26e23822afd1bdfc9fff92840fc1e60089f12f54439e3ab9e5167d0361dcf"],
+ ["4b0ecc0c03ba35700d2a30a71f28e432ff6ac7e357533b49f4e97cf28f1071119ad6b97f3e0300000008acab516363ac63acffffffffcd6a2019d99b5c2d639ddca0b1aa5ea7c1326a071255ea226960bd88f45ca57d00000000085253655363005353ffffffffba257635191c9f216de3277be548cb5a2313114cb1a4c563b03b4ef6c0f4f7040300000001abda542edf0495cdc40100000000026353c049e903000000000752516a53ab65512b0f9304000000000963ab516aac65516552fa9ece050000000009acab6500005152530000000000", "65ab51525352510052", 1, -1355414590, "3cd85f84aae6d702436f3f9b8980adcc1f8f202e957759540a27da0a32fc6c87"],
+ ["adaac0a803f66811346271c733036d6e0d45e15a9b602092e2e04ad93564f196e7f020b088000000000600526a636a00700ec3f9db07a3a6ce910bf318c7ec87a876e1f2a3366cc69f20cde09203b99c1cb9d15800000000050000ac636a4d0de554ebe95c6cc14faf5ff6361d1deba9474b8b0fd3b93c011cd96aec783abb3f36830200000005ab65005251ffffffff0464eb10050000000007520000ab6a65ab1beaa80300000000005a2f31050000000006526aab65ac52ba7db10000000000045251ab6a0cfb46e7", "ab0051ac52636a", 1, -184733716, "961ff413850336d3987c550404fc1d923266ca36cc9ffee7113edb3a9fea7f30"],
+ ["af1c4ab301ec462f76ee69ba419b1b2557b7ded639f3442a3522d4f9170b2d6859765c3df402000000016affffffff01a5ca6c000000000008ab52536aab00005300000000", "6a6351", 0, 110304602, "e88ed2eea9143f2517b15c03db00767eb01a5ce12193b99b964a35700607e5f4"],
+ ["0bfd34210451c92cdfa02125a62ba365448e11ff1db3fb8bc84f1c7e5615da40233a8cd368010000000252ac9a070cd88dec5cf9aed1eab10d19529720e12c52d3a21b92c6fdb589d056908e43ea910e0200000009ac516a52656a6a5165ffffffffc3edcca8d2f61f34a5296c405c5f6bc58276416c720c956ff277f1fb81541ddd00000000030063abffffffff811247905cdfc973d179c03014c01e37d44e78f087233444dfdce1d1389d97c302000000065163000063ab1724a26e02ca37c902000000000851ab53525352ac529012a90100000000085200525253535353fa32575b", "5352ac6351", 1, -1087700448, "b8f1e1f35e3e1368bd17008c756e59cced216b3c699bcd7bebdb5b6c8eec4697"],
+ ["2c84c0640487a4a695751d3e4be48019dbaea85a6e854f796881697383ea455347d2b2769001000000055265526500ffffffff6aac176d8aa00778d496a7231eeb7d3334f20c512d3db1683276402100d98de5030000000700536a5263526ac1ee9ceb171c0c984ebaf12c234fd1487fbf3b3d73aa0756907f26837efba78d1bed33200300000001ab4d9e8ec0bed837cb929bbed76ee848959cec59de44bd7667b7631a744f880d5c71a20cfd0100000007005363515300abffffffff023753fb0000000000036565532d3873050000000009005152ab6a63acab5200000000", "ab650053ab", 0, -877941183, "c49af297dffe2d80deddf10ceea84b99f8554bd2d55bbdc34e449728c31f0835"],
+ ["1f7e4b1b045d3efa6cd7a11d7873a8bab886c19bd11fcb6712f0948f2db3a7be76ff76c8f100000000095265ab6a0065ac5363ffffffffdaafcfa6029336c997680a541725190f09a6f6da21e54560eca4b5b8ae987da1000000000952ac52acac52515165ffffffff825a38d3b1e5bb4d10f33653ab3ab6882c7abdaec74460257d1528ce7be3f98e0100000007526a006a656a63c14adc8f04953a5d3d3f89237f38b857dd357713896d36215f7e8b77b11d98ea3cdc93df02000000015212484f6104bfafae0300000000025263a2b0120000000000056563ab00516c4d2605000000000653ac6500655301cc93030000000002acab14643b1f", "63acac53ab", 0, 333824258, "18da6ceb011cd36f15ad7dd6c55ef07e6f6ed48881ce3bb31416d3c290d9a0e9"],
+ ["467a3e7602e6d1a7a531106791845ec3908a29b833598e41f610ef83d02a7da3a1900bf2960000000005ab6a636353ffffffff031db6dac6f0bafafe723b9199420217ad2c94221b6880654f2b35114f44b1df010000000965ab52636a63ac6352ffffffff02b3b95c0100000000026300703216030000000001ab3261c0aa", "6a", 0, 2110869267, "3078b1d1a7713c6d101c64afe35adfae0977a5ab4c7e07a0b170b041258adbf2"],
+ ["8713bc4f01b411149d575ebae575f5dd7e456198d61d238695df459dd9b86c4e3b2734b62e0300000004abac6363ffffffff03b58049050000000002ac653c714c04000000000953656a005151526a527b5a9e03000000000652ac5100525300000000", "52", 0, -647281251, "0e0bed1bf2ff255aef6e5c587f879ae0be6222ab33bd75ee365ec6fbb8acbe38"],
+ ["f2ba8a8701b9c401efe3dd0695d655e20532b90ac0142768cee4a3bb0a89646758f544aa8102000000036a52527899f4e4040c6f0b030000000008636565ab530051ab52b60c000000000009515200ab630053ac53a49c5f040000000008ab53ab516300ab63fa27340300000000015100000000", "ac63abab5251", 0, -1328936437, "ab61497afd39e61fe06bc5677326919716f9b20083c9f3417dcea905090e0411"],
+ ["b5a7df6102107beded33ae7f1dec0531d4829dff7477260925aa2cba54119b7a07d92d5a1d02000000046a516a52803b625c334c1d2107a326538a3db92c6c6ae3f7c3516cd90a09b619ec6f58d10e77bd6703000000056563006a63ffffffff0117484b03000000000853acab52526a65abc1b548a1", "ac006a525100", 0, 2074359913, "680336db57347d8183b8898cd27a83f1ba5884155aeae5ce20b4840b75e12871"],
+ ["278cb16204b9dadf400266106392c4aa9df01ba03af988c8139dae4c1818ac009f13fc5f1a00000000065200ac656a52ffffffffd006bbebd8cbd7bdead24cddc9badfcc6bc0c2e63c037e5c29aa858f5d0f3e7d01000000046a0051acffffffffbc62a5f57e58da0b67956003ae81ac97cb4cbd1d694c914fc41515c008c4d8fd020000000165e329c844bcc16164be64b64a81cbf4ffd41ed2934e0daa0040ccb8365bab0b2a9e401c180300000003ab52abffffffff02588460030000000000a25a12030000000005535100005300000000", "6553ab6a5300acab51", 3, 989407546, "1c29f110576f4a3b257f67454d99dfc0dee62ef5517ca702848ce4bd2ea1a1d7"],
+ ["49eb2178020a04fca08612c34959fd41447319c190fb7ffed9f71c235aa77bec28703aa1820200000003ac6353abaff326071f07ec6b77fb651af06e8e8bd171068ec96b52ed584de1d71437fed186aecf0300000001acffffffff03da3dbe02000000000652ac63ac6aab8f3b680400000000096a536a65636a53516a5175470100000000016500000000", "6a536365", 0, 1283691249, "c670219a93234929f662ecb9aa148a85a2d281e83f4e53d10509461cdea47979"],
+ ["0f96cea9019b4b3233c0485d5b1bad770c246fe8d4a58fb24c3b7dfdb3b0fd90ea4e8e947f0300000006006a5163515303571e1e01906956030000000005ab635353abadc0fbbe", "acac", 0, -1491469027, "716a8180e417228f769dcb49e0491e3fda63badf3d5ea0ceeac7970d483dd7e2"],
+ ["9a7d858604577171f5fe3f3fd3e5e039c4b0a06717a5381e9977d80e9f53e025e0f16d2877020000000752636565536353ffffffff5862bd028e8276e63f044be1dddcbb8d0c3fa097678308abf2b0f45104a93dbd0100000001531200667ba8fdd3b28e98a35da73d3ddfe51e210303d8eb580f923de988ee632d77793892030000000752526363526563ffffffffe9744eb44db2658f120847c77f47786d268c302120d269e6004455aa3ea5f5e20200000009ab6300636aab656551ffffffff03c61a3c020000000009ab516a6aab6aab53ab737f1a05000000000853acabab655365ab92a4a00400000000016367edf6c8", "535352ab", 3, 659348595, "d36ee79fc80db2e63e05cdc50357d186181b40ae20e3720878284228a13ee8b3"],
+ ["148e68480196eb52529af8e83e14127cbfdbd4a174e60a86ac2d86eac9665f46f4447cf7aa01000000045200ac538f8f871401cf240c0300000000065252ab52656a5266cf61", "", 0, -344314825, "eacc47c5a53734d6ae3aedbc6a7c0a75a1565310851b29ef0342dc4745ceb607"],
+ ["e2bc29d4013660631ba14ecf75c60ec5e9bed7237524d8c10f66d0675daa66d1492cb834530200000004ac510065e42d0c9e04f2b26c01000000000951525152acac65ababa35b7504000000000953ac6aac00650053ab94688c0400000000056365526553a1bced0300000000016a00000000", "65ab0063655353", 0, -888431789, "59a34b3ed3a1cce0b104de8f7d733f2d386ffc7445efae67680cd90bc915f7e0"],
+ ["0c8a70d70494dca6ab05b2bc941b5b431c43a292bd8f2f02eab5e240a408ca73a676044a4103000000056a51ab006affffffff84496004e54836c035821f14439149f22e1db834f315b24588ba2f031511926c0100000000ffffffffbbc5e70ed1c3060ba1bfe99c1656a3158a7307c3ce8eb362ec32c668596d2bd30000000009636563635351abab00b039344c6fc4f9bec24322e45407af271b2d3dfec5f259ee2fc7227bc5285e22b3be85b40100000009ac00ab53abac6a5352e5ddfcff02d50231020000000005006a51536ab086d9020000000006ababac51ac6a00000000", "abab636565acac6a", 3, 241546088, "643a7b4c8d832e14d5c10762e74ec84f2c3f7ed96c03053157f1bed226614911"],
+ ["f98f79cf0274b745e1d6f36da7cbe205a79132a7ad462bdc434cfb1dcd62a6977c3d2a5dbc010000000553516a5365ffffffff4f89f485b53cdad7fb80cc1b7e314b9735b9383bc92c1248bb0e5c6173a55c0d010000000353655293f9b014045ad96d02000000000963ac526a53ac636365f4c27904000000000952536563635152526a2788f0030000000002516aff5add01000000000863530051655351abd04716ba", "ab6552536a53", 1, -2128899945, "56d29f5e300ddfed2cd8dcce5d79826e193981d0b70dc7487772c8a0b3b8d7b1"],
+ ["6c7913f902aa3f5f939dd1615114ce961beda7c1e0dd195be36a2f0d9d047c28ac62738c3a020000000453abac00ffffffff477bf2c5b5c6733881447ac1ecaff3a6f80d7016eee3513f382ad7f554015b970100000007ab6563acab5152ffffffff04e58fe1040000000009ab00526aabab526553e59790010000000002ab525a834b03000000000035fdaf0200000000086551ac65515200ab00000000", "63ac53", 1, 1285478169, "1536da582a0b6de017862445e91ba14181bd6bf953f4de2f46b040d351a747c9"],
+ ["4624aa9204584f06a8a325c84e3b108cafb97a387af62dc9eab9afd85ae5e2c71e593a3b690200000003636a005eb2b44eabbaeca6257c442fea00107c80e32e8715a1293cc164a42e62ce14fea146220c020000000090b9ee38106e3310037bfc519fd209bdbd21c588522a0e96df5fba4e979392bc993bfe9f01000000086363636a635353ab6f1907d218ef6f3c729d9200e23c1dbff2df58b8b1282c6717b26cf760ee4c880d23f4d100000000086a516a536a525163ffffffff01d6f162050000000000ebbab208", "525365ab0053", 1, -1515409325, "6cf9cd409b7185b1f118171f0a34217af5b612ea54195ea186505b667c19337f"],
+ ["16562fc503f1cf9113987040c408bfd4523f1512da699a2ca6ba122dc65677a4c9bf7763830000000003636552ffffffff1ec1fab5ff099d1c8e6b068156f4e39b5543286bab53c6d61e2582d1e07c96cf02000000045163656affffffffd0ef40003524d54c08cb4d13a5ee61c84fbb28cde9eca7a6d11ba3a9335d8c620100000007635153536a6300fbb84fc2012003a601000000000363ab6a00000000", "63636a006a6aab", 0, -1310262675, "1efbf3d37a92bc03d9eb950b792f307e95504f7c4998f668aa250707ebb752ac"],
+ ["531665d701f86bacbdb881c317ef60d9cd1baeffb2475e57d3b282cd9225e2a3bf9cbe0ded01000000086300ac515263acabffffffff0453a8500100000000086353acab516a6565e5e9200500000000026a52a44caa00000000000453ac000065e41b0500000000076500ac0065526ab4476f4d", "006563006aab00636a", 0, 1770013777, "0898b26dd3ca08632a5131fa48eb55b44386d0c5070c24d6e329673d5e3693b8"],
+ ["0f1227a20140655a3da36e413b9b5d108a866f6f147eb4940f032f5a89854eae6d7c3a91600100000009525363515153515253e37a79480161ab61020000000001ab00000000", "ab65005200", 0, -1996383599, "979782dc3f36d908d37d7e4046a38d306b4b08ddc60a5eba355fe3d6da1b29a9"],
+ ["063ff6eb01aff98d0d2a6db224475010edb634c2f3b46257084676adeb84165a4ff8558d7601000000066353006a5165deb3262c042d109c0000000000076363ab52ac005200b9c4050000000007516300ac510063cfffc800000000000200639e815501000000000700526a52ac6365ac7b07b8", "656552abac6500", 0, -1559847112, "674a4bcb04247f8dc98780f1792cac86b8aee41a800fc1e6f5032f6e1dccde65"],
+ ["3320f6730132f830c4681d0cae542188e4177cad5d526fae84565c60ceb5c0118e844f90bd030000000163ffffffff0257ec5a040000000005525251ac6538344d000000000002515200000000", "5352656a53ac516a65", 0, 788050308, "3afacaca0ef6be9d39e71d7b1b118994f99e4ea5973c9107ca687d28d8eba485"],
+ ["c13aa4b702eedd7cde09d0416e649a890d40e675aa9b5b6d6912686e20e9b9e10dbd40abb1000000000863ab6353515351ac11d24dc4cc22ded7cdbc13edd3f87bd4b226eda3e4408853a57bcd1becf2df2a1671fd1600000000045165516affffffff01baea300100000000076aab52ab53005300000000", "0065", 0, -1195908377, "241a23e7b1982d5f78917ed97a8678087acbbffe7f624b81df78a5fe5e41e754"],
+ ["d9a6f20e019dd1b5fae897fb472843903f9c3c2293a0ffb59cff2b413bae6eceab574aaf9d030000000663ab006a515102f54939032df5100100000000056a51ab65530ec28f010000000004ac5100007e874905000000000651005265ac6a00000000", "abacab63acacabab", 0, 271463254, "1326a46f4c21e7619f30a992719a905aa1632aaf481a57e1cbd7d7c22139b41e"],
+ ["157c81bf0490432b3fcb3f9a5b79e5f91f67f05efb89fa1c8740a3fe7e9bdc18d7cb6acd2203000000026351ffffffff912e48e72bbcf8a540b693cf8b028e532a950e6e63a28801f6eaad1afcc52ad00000000000b1a4b170a2b9e60e0cad88a0085137309f6807d25d5afb5c1e1d32aa10ba1cdf7df596dd0000000009525165656a51ab65ab3674fba32a76fe09b273618d5f14124465933f4190ba4e0fd09d838daafc6223b31642ac00000000086a53536551ac6565ffffffff01fe9fb6030000000008ab51656a5165636a00000000", "ab00ab6a6551", 3, -64357617, "1ddaab7f973551d71f16bd70c4c4edbf7225e64e784a6da0ee7f7a9fe4f12a0b"],
+ ["a2692fff03b2387f5bacd5640c86ba7df574a0ee9ed7f66f22c73cccaef3907eae791cbd230200000004536363abffffffff4d9fe7e5b375de88ba48925d9b2005447a69ea2e00495a96eafb2f144ad475b40000000008000053000052636537259bee3cedd3dcc07c8f423739690c590dc195274a7d398fa196af37f3e9b4a1413f810000000006ac63acac52abffffffff04c65fe60200000000075151536365ab657236fc020000000009005263ab00656a6a5195b8b6030000000007ac5165636aac6a7d7b66010000000002acab00000000", "51", 2, -826546582, "925037c7dc7625f3f12dc83904755a37016560de8e1cdd153c88270a7201cf15"],
+ ["2c5b003201b88654ac2d02ff6762446cb5a4af77586f05e65ee5d54680cea13291efcf930d0100000005ab536a006a37423d2504100367000000000004536a515335149800000000000152166aeb03000000000452510063226c8e03000000000000000000", "635251", 0, 1060344799, "7e058ca5dd07640e4aae7dea731cfb7d7fef1bfd0d6d7b6ce109d041f4ca2a31"],
+ ["f981b9e104acb93b9a7e2375080f3ea0e7a94ce54cd8fb25c57992fa8042bdf4378572859f0100000002630008604febba7e4837da77084d5d1b81965e0ea0deb6d61278b6be8627b0d9a2ecd7aeb06a0300000005ac5353536a42af3ef15ce7a2cd60482fc0d191c4236e66b4b48c9018d7dbe4db820f5925aad0e8b52a0300000008ab0063510052516301863715efc8608bf69c0343f18fb81a8b0c720898a3563eca8fe630736c0440a179129d03000000086aac6a52ac6a63ac44fec4c00408320a03000000000062c21c030000000007ac6a655263006553835f0100000000015303cd60000000000005535263536558b596e0", "00", 0, -2140385880, "49870a961263354c9baf108c6979b28261f99b374e97605baa532d9fa3848797"],
+ ["e7416df901269b7af14a13d9d0507709b3cd751f586ce9d5da8d16a121e1bd481f5a086e1103000000056aab005200ffffffff01aa269c040000000006acac6a6a5263ee718de6", "ab525363", 0, 1309186551, "eea7d2212bda2d408fff146f9ae5e85e6b640a93b9362622bb9d5e6e36798389"],
+ ["402a815902193073625ab13d876190d1bbb72aecb0ea733c3330f2a4c2fe6146f322d8843a0300000008656aab0000535363fffffffff9dccdec5d8509d9297d26dfcb1e789cf02236c77dc4b90ebccbf94d1b5821150300000001510bf1f96a03c5c145000000000002ac6ae11b1c0100000000055163516a5239c8a600000000000365636300000000", "63536aacab", 0, -1811424955, "0090803a20102a778ab967a74532faee13e03b702083b090b1497bc2267ee2fe"],
+ ["c4b702e502f1a54f235224f0e6de961d2e53b506ab45b9a40805d1dacd35148f0acf24ca5e00000000085200ac65ac53acabf34ba6099135658460de9d9b433b84a8562032723635baf21ca1db561dce1c13a06f4407000000000851ac006a63516aabffffffff02a853a603000000000163d17a67030000000005ab63006a5200000000", "ac5363515153", 1, 480734903, "5c46f7ac3d6460af0da28468fcc5b3c87f2b9093d0f837954b7c8174b4d7b6e7"],
+ ["9b83f78704f492b9b353a3faad8d93f688e885030c274856e4037818848b99e490afef27770200000000ffffffff36b60675a5888c0ef4d9e11744ecd90d9fe9e6d8abb4cff5666c898fdce98d9e00000000056aab656352596370fca7a7c139752971e169a1af3e67d7656fc4fc7fd3b98408e607c2f2c836c9f27c030000000653ac51ab6300a0761de7e158947f401b3595b7dc0fe7b75fa9c833d13f1af57b9206e4012de0c41b8124030000000953656a53ab53510052242e5f5601bf83b301000000000465516a6300000000", "63515200ac656365", 3, -150879312, "9cf05990421ea853782e4a2c67118e03434629e7d52ab3f1d55c37cf7d72cdc4"],
+ ["f492a9da04f80b679708c01224f68203d5ea2668b1f442ebba16b1aa4301d2fe5b4e2568f3010000000953005351525263ab65ffffffff93b34c3f37d4a66df255b514419105b56d7d60c24bf395415eda3d3d8aa5cd0101000000020065ffffffff9dba34dabdc4f1643b372b6b77fdf2b482b33ed425914bb4b1a61e4fad33cf390000000002ab52ffffffffbbf3dc82f397ef3ee902c5146c8a80d9a1344fa6e38b7abce0f157be7adaefae0000000009515351005365006a51ffffffff021359ba010000000000403fea0200000000095200ac6353abac635300000000", "00ac51acacac", 0, -2115078404, "fd44fc98639ca32c927929196fc3f3594578f4c4bd248156a25c04a65bf3a9f3"],
+ ["2f73e0b304f154d3a00fde2fdd40e791295e28d6cb76af9c0fd8547acf3771a02e3a92ba37030000000852ac6351ab6565639aa95467b065cec61b6e7dc4d6192b5536a7c569315fb43f470078b31ed22a55dab8265f02000000080065636a6aab6a53ffffffff9e3addbff52b2aaf9fe49c67017395198a9b71f0aa668c5cb354d06c295a691a0100000000ffffffff45c2b4019abaf05c5e484df982a4a07459204d1343a6ee5badade358141f8f990300000007ac516a6aacac6308655cd601f3bc2f0000000000015200000000", "", 0, -2082053939, "9a95e692e1f78efd3e46bb98f178a1e3a0ef60bd0301d9f064c0e5703dc879c2"],
+ ["5a60b9b503553f3c099f775db56af3456330f1e44e67355c4ab290d22764b9144a7b5f959003000000030052acbd63e0564decc8659aa53868be48c1bfcda0a8c9857b0db32a217bc8b46d9e7323fe9649020000000553ac6551abd0ecf806211db989bead96c09c7f3ec5f73c1411d3329d47d12f9e46678f09bac0dc383e0200000000ffffffff01494bb202000000000500516551ac00000000", "ac", 0, 1169947809, "62a36c6e8da037202fa8aeae03e533665376d5a4e0a854fc4624a75ec52e4eb1"],
+ ["7e98d353045569c52347ca0ff2fdba608829e744f61eb779ffdb5830aae0e6d6857ab2690e03000000075365acab656352ffffffffa890dd37818776d12da8dca53d02d243ef23b4535c67016f4c58103eed85360f030000000093dbacdc25ca65d2951e047d6102c4a7da5e37f3d5e3c8b87c29b489360725dcd117ee2003000000056a6300ac53c7e99fa1dc2b8b51733034e6555f6d6de47dbbf1026effac7db80cb2080678687380dc1e02000000075352005263516affffffff04423272040000000008ab6353ab65510051e0f53b0500000000086300516552635152f74a5f04000000000853acab0053ab52ab0e8e5f00000000000951ac5363516a6aabab00000000", "6a5163ab52", 3, 890006103, "476868cecd1763c91dade98f17defa42d31049547df45acffa1cc5ae5c3d75d6"],
+ ["e3649aa40405e6ffe377dbb1bbbb672a40d8424c430fa6512c6165273a2b9b6afa9949ec430200000007630052ab655153a365f62f2792fa90c784efe3f0981134d72aac0b1e1578097132c7f0406671457c332b84020000000353ab6ad780f40cf51be22bb4ff755434779c7f1def4999e4f289d2bd23d142f36b66fbe5cfbb4b01000000076a5252abac52ab1430ffdc67127c9c0fc97dcd4b578dab64f4fb9550d2b59d599773962077a563e8b6732c02000000016affffffff04cb2687000000000002ab636e320904000000000252acf70e9401000000000100dc3393050000000006ab0063536aacbc231765", "65520053", 3, -2016196547, "f64f805f0ff7f237359fa6b0e58085f3c766d1859003332223444fd29144112a"],
+ ["1d033569040700441686672832b531ab55db89b50dc1f9fc00fb72218b652da9dcfbc83be901000000066551ac526a632b390f9ad068e5fdee6563e88e2a8e4e09763c861072713dc069893dc6bbc9db3f00e26502000000096a5363526565525252ffffffff8a36bdd0aaf38f6707592d203e14476ca9f259021e487135c7e8324244057ed90300000000ed3fb2a3dfd4d46b5f3603fe0148653911988457bd0ed7f742b07c452f5476c228ff9f600200000007526aac00525152ffffffff04b88e48030000000000c753d602000000000853510000006553518fda2603000000000853ac52acac5263534839f1030000000006ac006aacac5300000000", "516553635300ab0052", 1, 2075958316, "c2cefaec2293134acbcf6d2a8bf2b3eb42e4ec04ee8f8bf30ff23e65680677c1"],
+ ["4c4be7540344050e3044f0f1d628039a334a7c1f7b4573469cfea46101d6888bb6161fe9710200000000ffffffffac85a4fdad641d8e28523f78cf5b0f4dc74e6c5d903c10b358dd13a5a1fd8a06000000000163e0ae75d05616b72467b691dc207fe2e65ea35e2eadb7e06ea442b2adb9715f212c0924f10200000000ffffffff0194ddfe02000000000265ac00000000", "00006500", 1, -479922562, "d66924d49f03a6960d3ca479f3415d638c45889ce9ab05e25b65ac260b51d634"],
+ ["202c18eb012bc0a987e69e205aea63f0f0c089f96dd8f0e9fcde199f2f37892b1d4e6da90302000000055352ac6565ffffffff0257e5450100000000025300ad257203000000000000000000", "520052ac6a005265", 0, 168054797, "502967a6f999f7ee25610a443caf8653dda288e6d644a77537bcc115a8a29894"],
+ ["32fa0b0804e6ea101e137665a041cc2350b794e59bf42d9b09088b01cde806ec1bbea077df0200000008515153650000006506a11c55904258fa418e57b88b12724b81153260d3f4c9f080439789a391ab147aabb0fa0000000007000052ac51ab510986f2a15c0d5e05d20dc876dd2dafa435276d53da7b47c393f20900e55f163b97ce0b800000000008ab526a520065636a8087df7d4d9c985fb42308fb09dce704650719140aa6050e8955fa5d2ea46b464a333f870000000009636300636a6565006affffffff01994a0d040000000002536500000000", "516563530065", 2, -163068286, "f58637277d2bc42e18358dc55f7e87e7043f5e33f4ce1fc974e715ef0d3d1c2a"],
+ ["ae23424d040cd884ebfb9a815d8f17176980ab8015285e03fdde899449f4ae71e04275e9a80100000007ab006553530053ffffffff018e06db6af519dadc5280c07791c0fd33251500955e43fe4ac747a4df5c54df020000000251ac330e977c0fec6149a1768e0d312fdb53ed9953a3737d7b5d06aad4d86e9970346a4feeb5030000000951ab51ac6563ab526a67cabc431ee3d8111224d5ecdbb7d717aa8fe82ce4a63842c9bd1aa848f111910e5ae1eb0100000004ac515300bfb7e0d7048acddc030000000009636a5253636a655363a3428e040000000001525b99c6050000000004655265ab717e6e020000000000d99011eb", "ac6a6a516565", 1, -716251549, "b098eb9aff1bbd375c70a0cbb9497882ab51f3abfebbf4e1f8d74c0739dc7717"],
+ ["030f44fc01b4a9267335a95677bd190c1c12655e64df74addc53b753641259af1a54146baa020000000152e004b56c04ba11780300000000026a53f125f001000000000251acd2cc7c03000000000763536563655363c9b9e50500000000015200000000", "ac", 0, -1351818298, "19dd32190ed2a37be22f0224a9b55b91e37290577c6c346d36d32774db0219a3"],
+ ["c05f448f02817740b30652c5681a3b128322f9dc97d166bd4402d39c37c0b14506d8adb5890300000003536353ffffffffa188b430357055ba291c648f951cd2f9b28a2e76353bef391b71a889ba68d5fc02000000056565526a6affffffff02745f73010000000001ab3ec34c0400000000036aac5200000000", "516551510053", 0, -267877178, "3a1c6742d4c374f061b1ebe330b1e169a113a19792a1fdde979b53e094cc4a3c"],
+ ["163ba45703dd8c2c5a1c1f8b806afdc710a2a8fc40c0138e2d83e329e0e02a9b6c837ff6b8000000000700655151ab6a522b48b8f134eb1a7e6f5a6fa319ce9d11b36327ba427b7d65ead3b4a6a69f85cda8bbcd22030000000563656552acffffffffdbcf4955232bd11eef0cc6954f3f6279675b2956b9bcc24f08c360894027a60201000000066500006500abffffffff04d0ce9d0200000000008380650000000000015233f360040000000003006aabedcf0801000000000000000000", "000065006500ac", 0, 216965323, "9afe3f4978df6a86e9a8ebd62ef6a9d48a2203f02629349f1864ef2b8b92fd55"],
+ ["07f7f5530453a12ad0c7eb8fbc3f140c7ab6818144d67d2d8752600ca5d9a9358e2dff87d4000000000663526aab526a9e599c379d455e2da36d0cde88d931a863a3e97e01e93b9edb65856f3d958dc08b92b720000000000165bbc8d66dae3b1b170a6e2457f5b161465cb8706e0e6ffc6af55deb918365f14c5f40d4890100000000a7bd77c069ee4b48638e2363fcf2a86b02bea022047bd9fcb16d2b94ad068308d19b31cb00000000066aab5300ab529672aa8f01dbd8a205000000000663536353006a02e99901", "ac006351006a63ab63", 1, 119789359, "6629a1e75c6ae8f4f9d5f734246b6a71682a5ea57246040ef0584f6b97916175"],
+ ["fe647f950311bf8f3a4d90afd7517df306e04a344d2b2a2fea368935faf11fa6882505890d0000000005ab5100516affffffff43c140947d9778718919c49c0535667fc6cc727f5876851cb8f7b6460710c7f60100000000ffffffffce4aa5d90d7ab93cbec2e9626a435afcf2a68dd693c15b0e1ece81a9fcbe025e0300000000ffffffff02f34806020000000002515262e54403000000000965635151ac655363636de5ce24", "6a005100ac516351", 2, 989643518, "818a7ceaf963f52b5c48a7f01681ac6653c26b63a9f491856f090d9d60f2ffe3"],
+ ["a1050f8604d0f9d2feefcdb5051ae0052f38e21bf39daf583fd0c3900faa3eab5d431c0bbe030000000653536a005151683d27e5c6e0da8f22125823f32d5d98477d8098ef36263b9694d61d4d85d3f2ac02b7570200000007000052005165abffffffff0cad981542bcb54a87d9400aa63e514c7c6fab7158c2b1fb37821ea755eb162a0200000000b94feb5100e5ef3bf8ed8d43356c8a8d5ac6c7e80d7ff6040f4f0aa19abbe783f4f461240200000007636500000052655686fd70042be3ad02000000000465ab636a15680b000000000004acac53511277c705000000000452635252d27a0102000000000000000000", "6a6aacab65655251", 1, -982144648, "dfcf484111801989eb6df8dc2bafb944d7365ffeb36a575a08f3270d3ef24c9f"],
+ ["cef7316804c3e77fe67fc6207a1ea6ae6eb06b3bf1b3a4010a45ae5c7ad677bb8a4ebd16d90200000009ac536a5152ac5263005301ab8a0da2b3e0654d31a30264f9356ba1851c820a403be2948d35cafc7f9fe67a06960300000006526a63636a53ffffffffbada0d85465199fa4232c6e4222df790470c5b7afd54704595a48eedd7a4916b030000000865ab63ac006a006ab28dba4ad55e58b5375053f78b8cdf4879f723ea4068aed3dd4138766cb4d80aab0aff3d0300000003ac6a00ffffffff010f5dd6010000000006ab006aab51ab00000000", "", 1, 889284257, "d0f32a6db43378af84b063a6706d614e2d647031cf066997c48c04de3b493a94"],
+ ["7b3ff28004ba3c7590ed6e36f45453ebb3f16636fe716acb2418bb2963df596a50ed954d2e03000000065251515265abffffffff706ee16e32e22179400c9841013971645dabf63a3a6d2d5feb42f83aa468983e030000000653ac51ac5152ffffffffa03a16e5e5de65dfa848b9a64ee8bf8656cc1f96b06a15d35bd5f3d32629876e020000000043c1a3965448b3b46f0f0689f1368f3b2981208a368ec5c30defb35595ef9cf95ffd10e902000000036aac65253a5bbe042e907204000000000800006565656352634203b4020000000002656336b3b7010000000001ab7a063f0100000000026500a233cb76", "006551636a53ac5251", 1, -1144216171, "68c7bd717b399b1ee33a6562a916825a2fed3019cdf4920418bb72ffd7403c8c"],
+ ["d5c1b16f0248c60a3ddccf7ebd1b3f260360bbdf2230577d1c236891a1993725e262e1b6cb000000000363636affffffff0a32362cfe68d25b243a015fc9aa172ea9c6b087c9e231474bb01824fd6bd8bc0300000005ab52ab516affffffff0420d9a70200000000045152656a45765d0000000000055252536a5277bad100000000000252ab3f3f3803000000000463acac5200000000", "52636a52ab65", 1, 1305123906, "978dc178ecd03d403b048213d904653979d11c51730381c96c4208e3ea24243a"],
+ ["1be8ee5604a9937ebecffc832155d9ba7860d0ca451eaced58ca3688945a31d93420c27c460100000006abac5300535288b65458af2f17cbbf7c5fbcdcfb334ffd84c1510d5500dc7d25a43c36679b702e850f7c0200000003005300ffffffff7c237281cb859653eb5bb0a66dbb7aeb2ac11d99ba9ed0f12c766a8ae2a2157203000000086aabac526365acabfffffffff09d3d6639849f442a6a52ad10a5d0e4cb1f4a6b22a98a8f442f60280c9e5be80200000007ab00ab6565ab52ffffffff0398fe83030000000005526aababacbdd6ec010000000005535252ab6a82c1e6040000000001652b71c40c", "6563526353656351", 2, -853634888, "0d936cceda2f56c7bb87d90a7b508f6208577014ff280910a710580357df25f3"],
+ ["9e0f99c504fbca858c209c6d9371ddd78985be1ab52845db0720af9ae5e2664d352f5037d4010000000552ac53636affffffff0e0ce866bc3f5b0a49748f597c18fa47a2483b8a94cef1d7295d9a5d36d31ae7030000000663515263ac635bb5d1698325164cdd3f7f3f7831635a3588f26d47cc30bf0fefd56cd87dc4e84f162ab702000000036a6365ffffffff85c2b1a61de4bcbd1d5332d5f59f338dd5e8accbc466fd860f96eef1f54c28ec030000000165ffffffff04f5cabd010000000007000052ac526563c18f1502000000000465510051dc9157050000000008655363ac525253ac506bb600000000000865656a53ab63006a00000000", "006a6a0052", 0, 1186324483, "2f9b7348600336512686e7271c53015d1cb096ab1a5e0bce49acd35bceb42bc8"],
+ ["11ce51f90164b4b54b9278f0337d95c50d16f6828fcb641df9c7a041a2b274aa70b1250f2b0000000008ab6a6a65006551524c9fe7f604af44be050000000005525365006521f79a0300000000015306bb4e04000000000265ac99611a05000000000765acab656500006dc866d0", "", 0, -1710478768, "cfa4b7573559b3b199478880c8013fa713ca81ca8754a3fd68a6d7ee6147dc5a"],
+ ["86bc233e02ba3c647e356558e7252481a7769491fb46e883dd547a4ce9898fc9a1ca1b77790000000006ab5351abab51f0c1d09c37696d5c7c257788f5dff5583f4700687bcb7d4acfb48521dc953659e325fa390300000003acac5280f29523027225af03000000000963abac0065ab65acab7e59d90400000000016549dac846", "53006aac52acac", 0, 711159875, "880330ccde00991503ea598a6dfd81135c6cda9d317820352781417f89134d85"],
+ ["beac155d03a853bf18cd5c490bb2a245b3b2a501a3ce5967945b0bf388fec2ba9f04c03d68030000000012fe96283aec4d3aafed8f888b0f1534bd903f9cd1af86a7e64006a2fa0d2d30711af770010000000163ffffffffd963a19d19a292104b9021c535d3e302925543fb3b5ed39fb2124ee23a9db00302000000056500ac63acffffffff01ad67f503000000000300ac5189f78db2", "53536a636500", 2, 748992863, "bde3dd0575164d7ece3b5783ce0783ffddb7df98f178fe6468683230314f285a"],
+ ["81dab34a039c9e225ba8ef421ec8e0e9d46b5172e892058a9ade579fe0eb239f7d9c97d45b0300000009ac65655351ab526363ffffffff10c0faaf7f597fc8b00bbc67c3fd4c6b70ca6b22718d15946bf6b032e62dae570000000005536a00ab6a02cddec3acf985bbe62c96fccf17012a87026ed63fc6756fa39e286eb4c2dd79b59d37400300000002516affffffff04f18b8d03000000000753abab5152636564411c02000000000400ab6300e965750300000000001bd2cf02000000000565ab526aab00000000", "006551ab", 0, -1488174485, "a3d65a8cd0c1eea8558d01396b929520a2221c29d9f25f29035b8abae874447f"],
+ ["489ebbf10478e260ba88c0168bd7509a651b36aaee983e400c7063da39c93bf28100011f280100000004abab63ab2fc856f05f59b257a4445253e0d91b6dffe32302d520ac8e7f6f2467f7f6b4b65f2f59e903000000096353abacab6351656affffffff0122d9480db6c45a2c6fd68b7bc57246edffbf6330c39ccd36aa3aa45ec108fc030000000265ab9a7e78a69aadd6b030b12602dff0739bbc346b466c7c0129b34f50ae1f61e634e11e9f3d0000000006516a53525100ffffffff011271070000000000086563ab6353536352c4dd0e2c", "", 0, -293358504, "4eba3055bc2b58765593ec6e11775cea4b6493d8f785e28d01e2d5470ea71575"],
+ ["6911195d04f449e8eade3bc49fd09b6fb4b7b7ec86529918b8593a9f6c34c2f2d301ec378b000000000263ab49162266af054643505b572c24ff6f8e4c920e601b23b3c42095881857d00caf56b28acd030000000565525200ac3ac4d24cb59ee8cfec0950312dcdcc14d1b360ab343e834004a5628d629642422f3c5acc02000000035100accf99b663e3c74787aba1272129a34130668a877cc6516bfb7574af9fa6d07f9b4197303400000000085351ab5152635252ffffffff042b3c95000000000000ff92330200000000046a5252ab884a2402000000000853530065520063000d78be03000000000953abab52ab53ac65aba72cb34b", "6a", 2, -637739405, "6b80d74eb0e7ee59d14f06f30ba7d72a48d3a8ff2d68d3b99e770dec23e9284f"],
+ ["746347cf03faa548f4c0b9d2bd96504d2e780292730f690bf0475b188493fb67ca58dcca4f0000000002005336e3521bfb94c254058e852a32fc4cf50d99f9cc7215f7c632b251922104f638aa0b9d080100000008656aac5351635251ffffffff4da22a678bb5bb3ad1a29f97f6f7e5b5de11bb80bcf2f7bb96b67b9f1ac44d09030000000365ababffffffff036f02b30000000000076353ab6aac63ac50b72a050000000002acaba8abf804000000000663006a6a6353797eb999", "acac5100", 1, -1484493812, "164c32a263f357e385bd744619b91c3f9e3ce6c256d6a827d6defcbdff38fa75"],
+ ["e17149010239dd33f847bf1f57896db60e955117d8cf013e7553fae6baa9acd3d0f1412ad90200000006516500516500cb7b32a8a67d58dddfb6ceb5897e75ef1c1ff812d8cd73875856487826dec4a4e2d2422a0100000004ac525365196dbb69039229270400000000070000535351636a8b7596020000000006ab51ac52655131e99d040000000003516551ee437f5c", "ac656a53", 1, 1102662601, "8858bb47a042243f369f27d9ab4a9cd6216adeac1c1ac413ed0890e46f23d3f3"],
+ ["144971940223597a2d1dec49c7d4ec557e4f4bd207428618bafa3c96c411752d494249e1fb0100000004526a5151ffffffff340a545b1080d4f7e2225ff1c9831f283a7d4ca4d3d0a29d12e07d86d6826f7f0200000003006553ffffffff03c36965000000000000dfa9af00000000000451636aac7f7d140300000000016300000000", "", 1, -108117779, "c84fcaf9d779df736a26cc3cabd04d0e61150d4d5472dd5358d6626e610be57f"],
+ ["b11b6752044e650b9c4744fb9c930819227d2ac4040d8c91a133080e090b042a142e93906e0000000003650053ffffffff6b9ce7e29550d3c1676b702e5e1537567354b002c8b7bb3d3535e63ad03b50ea01000000055100516300fffffffffcf7b252fea3ad5a108af3640a9bc2cd724a7a3ce22a760fba95496e88e2f2e801000000036a00ac7c58df5efba193d33d9549547f6ca839f93e14fa0e111f780c28c60cc938f785b363941b000000000863ab51516552ac5265e51fcd0308e9830400000000036a00abab72190300000000016a63d0710000000000050051ab6a6300000000", "53005165ac51ab65", 0, 229563932, "e562579d1a2b10d1c5e45c06513456002a6bec157d7eb42511d30b118103c052"],
+ ["2aee6b9a02172a8288e02fac654520c9dd9ab93cf514d73163701f4788b4caeeb9297d2e250300000004ab6363008fb36695528d7482710ea2926412f877a3b20acae31e9d3091406bfa6b62ebf9d9d2a6470100000009535165536a63520065ffffffff03f7b560050000000003acab6a9a8338050000000000206ce90000000000056552516a5100000000", "5252", 1, -1102319963, "fa4676c374ae3a417124b4c970d1ed3319dc3ac91fb36efca1aa9ed981a8aa1b"],
+ ["9554595203ad5d687f34474685425c1919e3d2cd05cf2dac89d5f33cd3963e5bb43f8706480100000000ffffffff9de2539c2fe3000d59afbd376cb46cefa8bd01dbc43938ff6089b63d68acdc2b02000000096553655251536a6500fffffffff9695e4016cd4dfeb5f7dadf00968e6a409ef048f81922cec231efed4ac78f5d010000000763abab6a5365006caaf0070162cc640200000000045163ab5100000000", "", 0, -1105256289, "e8e10ed162b1a43bfd23bd06b74a6c2f138b8dc1ab094ffb2fa11d5b22869bee"],
+ ["04f51f2a0484cba53d63de1cb0efdcb222999cdf2dd9d19b3542a896ca96e23a643dfc45f00200000007acac53510063002b091fd0bfc0cfb386edf7b9e694f1927d7a3cf4e1d2ce937c1e01610313729ef6419ae7030000000165a3372a913c59b8b3da458335dc1714805c0db98992fd0d93f16a7f28c55dc747fe66a5b503000000095351ab65ab52536351ffffffff5650b318b3e236802a4e41ed9bc0a19c32b7aa3f9b2cda1178f84499963a0cde000000000165ffffffff0383954f04000000000553ac536363a8fc90030000000000a2e315000000000005acab00ab5100000000", "0053", 2, -1424653648, "a5bc0356f56b2b41a2314ec05bee7b91ef57f1074bcd2efc4da442222269d1a3"],
+ ["5e4fab42024a27f0544fe11abc781f46596f75086730be9d16ce948b04cc36f86db7ad50fd01000000026a00613330f4916285b5305cc2d3de6f0293946aa6362fc087727e5203e558c676b314ef8dd401000000001af590d202ba496f040000000001009e3c9604000000000351ac51943d64d3", "51acabab5100ab52", 1, -129301207, "556c3f90aa81f9b4df5b92a23399fe6432cf8fecf7bba66fd8fdb0246440036c"],
+ ["a115284704b88b45a5f060af429a3a8eab10b26b7c15ed421258f5320fa22f4882817d6c2b0300000003005300ffffffff4162f4d738e973e5d26991452769b2e1be4b2b5b7e8cbeab79b9cf9df2882c040000000006636aac63ac5194abc8aa22f8ddc8a7ab102a58e39671683d1891799d19bd1308d24ea6d365e571172f1e030000000700515352515153ffffffff4da7ad75ce6d8541acbb0226e9818a1784e9c97c54b7d1ff82f791df1c6578f60000000000ffffffff01b1f265040000000009ab0051ac656a516a5300000000", "51abab6352535265", 0, -1269106800, "0ef7b6e87c782fa33fe109aab157a2d9cddc4472864f629510a1c92fa1fe7fc1"],
+ ["f3f771ae02939752bfe309d6c652c0d271b7cab14107e98032f269d92b2a8c8853ab057da8010000000563ab6a6365670c305c38f458e30a7c0ab45ee9abd9a8dc03bae1860f965ffced879cb2e5d0bb156821020000000153ffffffff025dc619050000000002ac51ec0d250100000000076a5200636a6363333aecd8", "650053ac515100ab", 1, 1812404608, "a7aa34bf8a5644f03c6dd8801f9b15ba2e07e07256dbf1e02dad59f0d3e17ea9"],
+ ["fd3e267203ae7d6d3975e738ca84f12540229bb237dd228d5f688e9d5ba53fce4302b0334d01000000026353ffffffff602a3ab75af7aa951d93093e345ef0037a2863f3f580a9b1a575fffe68e677450300000000239e476d1e8f81e8b6313880d8a49b27c1b00af467f29756e76f675f084a5676539636ab030000000765ab6351acac52d9217747044d773204000000000752ac51526353acc33e45050000000005516500005115d889040000000004ab5163510cbbbd0200000000016500000000", "65ac526aac6a53ab52", 2, -886179388, "bc46f3f83058ddf5bebd9e1f2c117a673847c4dc5e31cfb24bac91adf30877cf"],
+ ["f380ae23033646af5dfc186f6599098015139e961919aea28502ea2d69474413d94a555ea2000000000853635265abacac5314da394b99b07733341ddba9e86022637be3b76492992fb0f58f23c915098979250a96620300000003ab6300ffffffff4bb6d1c0a0d84eac7f770d3ad0fdc5369ae42a21bbe4c06e0b5060d5990776220300000000ffffffff0486fd70020000000007ac6500635252acf3fd72010000000005656a6a6551212de90500000000096365006a63635153000fa33100000000000600535151656300000000", "ab52", 2, -740890152, "f804fc4d81f039009ed1f2cccb5c91da797543f235ac71b214c20e763a6d86d7"],
+ ["5c45d09801bb4d8e7679d857b86b97697472d514f8b76d862460e7421e8617b15a2df217c6010000000863acacab6565006affffffff01156dbc03000000000952ac63516551ac6aac00000000", "6aabac", 0, 1310125891, "270445ab77258ced2e5e22a6d0d8c36ac7c30fff9beefa4b3e981867b03fa0ad"],
+ ["4ecc6bde030ca0f83c0ed3d4b777f94c0c88708c6c933fe1df6874f296d425cac95355c23d0000000006ac6a51536a52f286a0969d6170e20f2a8000193807f5bc556770e9d82341ef8e17b0035eace89c76edd50200000007ac65525100656affffffff5bade6e462fac1927f078d69d3a981f5b4c1e59311a38efcb9a910aa436afaa80000000007ac6a006352ab52ffffffff0331e58902000000000763ac53636352abb8b3ca000000000001637a1d26040000000009535263ac6a5352ab655ae34a39", "6a65ab", 2, 2142728517, "4a3415eb1677ae4e0c939644a4cfd5dc6299780b55cd0dc735967057b6b1526a"],
+ ["a59484b501eb50114be0fc79e72ab9bc9f4a5f7acdf274a56d6b68684eb68cf8b07ec5d1c2000000000765abab00ab00639e09aa940141e3530200000000046500ac6500000000", "00516565ab", 0, -1561622405, "d60bbadd2cc0674100baa08d0e0493ee4248f0304b3eb778da942041f503a896"],
+ ["53dc1a88046531c7b57a35f4d9adf101d068bf8d63fbbedaf4741dba8bc5e92c8725def571030000000453655251fcdf116a226b3ec240739c4c7493800e4edfe67275234e371a227721eac43d3d9ecaf1b50300000003ac0052ffffffff2c9279ffeea4718d167e9499bd067600715c14484e373ef93ae4a31d2f5671ab0000000009516553ac636a6a65001977752eeba95a8f16b88c571a459c2f2a204e23d48cc7090e4f4cc35846ca7fc0a455ce00000000055165ac0063188143f80205972902000000000765ac63ac516353c7b6a50000000000036a510000000000", "655351536a", 0, 103806788, "b276584d3514e5b4e058167c41dc02915b9d97f6795936a51f40e894ed8508bc"],
+ ["53f8959f01ddb36afdcd20167edcbb75a63d18654fdcf10bc0004c761ab450fe236d79cb2702000000065151650063653435003a033a5e34050000000009ac52516a630000516ab86db3030000000002006344ac090500000000046363ab00f3644537", "5263abab63ac656353", 0, -218513553, "f1f2a489682e42a6fc20025dfc89584d17f150b2d7ae3ddedd2bf43d5e24f37f"],
+ ["5a06cb4602dcfc85f49b8d14513f33c48f67146f2ee44959bbca092788e6823b2719f3160b0200000001ab3c013f2518035b9ea635f9a1c74ec1a3fb7496a160f46aae2e09bfc5cd5111a0f20969e003000000015158c89ab7049f20d6010000000008ac6a52abac53515349765e00000000000300ab638292630100000000045351ab0086da09010000000006656a6365525300000000", "526a63", 1, 1502936586, "bdfaff8a4e775379c5dc26e024968efa805f923de53fa8272dd53ec582afa0c5"],
+ ["ca9d84fa0129011e1bf27d7cb71819650b59fb292b053d625c6f02b0339249b498ff7fd4b601000000025352ffffffff032173a0040000000008525253abab5152639473bb030000000009005153526a53535151d085bd0000000000086a5365ab5165655300000000", "005152ac51", 0, 580353445, "c629d93b02037f40aa110e46d903edb34107f64806aa0c418d435926feef68b8"],
+ ["e3cdbfb4014d90ae6a4401e85f7ac717adc2c035858bf6ff48979dd399d155bce1f150daea0300000002ac51a67a0d39017f6c71040000000005535200535200000000", "", 0, -1899950911, "c1c7df8206e661d593f6455db1d61a364a249407f88e99ecad05346e495b38d7"],
+ ["b2b6b9ab0283d9d73eeae3d847f41439cd88279c166aa805e44f8243adeb3b09e584efb1df00000000026300ffffffff7dfe653bd67ca094f8dab51007c6adaced09de2af745e175b9714ca1f5c68d050000000003ac6500aa8e596903fd3f3204000000000553ac6a6a533a2e210500000000075253acabab526392d0ee020000000008520065635200ab5200000000", "65acacac65005365", 0, 28298553, "39c2aaa2496212b3ab120ab7d7f37c5e852bfe38d20f5226413a2268663eeae8"],
+ ["f30c5c3d01a6edb9e10fafaf7e85db14e7fec558b9dca4a80b05d7c3a2944d282c5018f4680200000003005263ffffffff04aac3530300000000026551bc2419010000000009005163acab6a5100658e7085050000000000c5e4ec050000000007656a6a635365ab2d8e8882", "abac53ab005251ac52", 0, -490287546, "877e347ec7487497769e2581142276d1a8d813b652e4483cf9cc993d16354417"],
+ ["4314339e01de40faabcb1b970245a7f19eedbc17c507dac86cf986c2973715035cf95736ae0200000007abababababab65bde67b900151510b04000000000853ac00655200535300000000", "52", 0, 399070095, "47585dc25469d04ff3a60939d0a03779e3e81a411bf0ca18b91bb925ebd30718"],
+ ["2d4cf4e9031b3e175b2ff18cd933151379d9cfac4713d8bd0e63b70bd4a92277aa7af901ab000000000565515353abffffffff557666c7f3be9cdecdad44c3df206eb63a2da4ed1f159d21193882a9f0340081020000000963ab53ab5252ac63abffffffff8a8c897bdb87e93886aad5ded9d82a13101d5476554386373646ca5e23612e450300000009006a526552abab6a635ac03fc00198bb02040000000009525100526a6563636a1d052834", "ab52ac00acac6a", 0, -1469882480, "09ed6563a454814ab7e3b4c28d56d8751162b77df1825b37ba66c6147750b2a3"],
+ ["f063171b03e1830fdc1d685a30a377537363ccafdc68b42bf2e3acb908dac61ee24b37595c020000000765ac5100ab6aacf447bc8e037b89d6cadd62d960cc442d5ced901d188867b5122b42a862929ce45e7b628d010000000253aba009a1ba42b00f1490b0b857052820976c675f335491cda838fb7934d5eea0257684a2a202000000001e83cf2401a7f777030000000008ab6553526a53526a00000000", "", 2, 1984790332, "c19caada8e71535e29a86fa29cfd9b74a0c7412003fc722a121005e461e01636"],
+ ["cf7bdc250249e22cbe23baf6b648328d31773ea0e771b3b76a48b4748d7fbd390e88a004d30000000003ac536a4ab8cce0e097136c90b2037f231b7fde2063017facd40ed4e5896da7ad00e9c71dd70ae600000000096a0063516352525365ffffffff01b71e3e00000000000300536a00000000", "", 1, 546970113, "6a815ba155270af102322c882f26d22da11c5330a751f520807936b320b9af5d"],
+ ["ac7a125a0269d35f5dbdab9948c48674616e7507413cd10e1acebeaf85b369cd8c88301b7c030000000963656aac6a530053abffffffffed94c39a582e1a46ce4c6bffda2ccdb16cda485f3a0d94b06206066da12aecfe010000000752abab63536363ef71dcfb02ee07fa0400000000016a6908c802000000000751656a6551abac688c2c2d", "6a6351526551", 0, 858400684, "552ff97d7924f51cda6d1b94be53483153ef725cc0a3a107adbef220c753f9a6"],
+ ["3a1f454a03a4591e46cf1f7605a3a130b631bf4dfd81bd2443dc4fac1e0a224e74112884fe0000000005516aac6a53a87e78b55548601ffc941f91d75eab263aa79cd498c88c37fdf275a64feff89fc1710efe03000000016a39d7ef6f2a52c00378b4f8f8301853b61c54792c0f1c4e2cd18a08cb97a7668caa008d970200000002656affffffff017642b20100000000096a63535253abac6a6528271998", "51", 2, 1459585400, "e9a7f21fc2d38be7be47095fbc8f1bf8923660aa4d71df6d797ae0ba5ca4d5b0"],
+ ["f59366cc0114c2a18e6bd1347ed9470f2522284e9e835dd5c5f7ef243639ebea95d9b232b6020000000153474b62eb045c00170500000000096352ab516352ab5200038a520400000000086aab5253656a63005b968904000000000963536353ac0053635387106002000000000000000000", "ab52526300ab51", 0, 1834116153, "cdf51f6e3a9dc2be5a59ea4c00f5aac1e1426a5202c325e6cf2567d07d8d8de4"],
+ ["6269e0fa0173e76e89657ca495913f1b86af5b8f1c1586bcd6c960aede9bc759718dfd5044000000000352ac530e2c7bd90219849b000000000007ab00ab6a53006319f281000000000007ab00515165ac5200000000", "6a", 0, -2039568300, "62094f98234a05bf1b9c7078c5275ed085656856fb5bdfd1b48090e86b53dd85"],
+ ["eb2bc00604815b9ced1c604960d54beea4a3a74b5c0035d4a8b6bfec5d0c9108f143c0e99a0000000000ffffffff22645b6e8da5f11d90e5130fd0a0df8cf79829b2647957471d881c2372c527d8010000000263acffffffff1179dbaf17404109f706ae27ad7ba61e860346f63f0c81cb235d2b05d14f2c1003000000025300264cb23aaffdc4d6fa8ec0bb94eff3a2e50a83418a8e9473a16aaa4ef8b855625ed77ef40100000003ac51acf8414ad404dd328901000000000652526500006ab6261c000000000002526a72a4c9020000000006ac526500656586d2e7000000000006656aac00ac5279cd8908", "51", 1, -399279379, "d37532e7b2b8e7db5c7c534197600397ebcc15a750e3af07a3e2d2e4f84b024f"],
+ ["dc9fe6a8038b84209bbdae5d848e8c040433237f415437592907aa798bf30d9dbbddf0ff85010000000153ffffffff23269a7ea29fcf788db483b8d4c4b35669e582608644259e950ce152b0fa6e050000000003acababffffffff65de94857897ae9ea3aa0b938ba6e5adf374d48469922d2b36dbb83d3b8c8261010000000452ac5200ffffffff02856e9b0300000000026a51980c8e02000000000365ab63d2648db4", "00ab0051ac526565", 2, 1562581941, "5cef9d8e18a2d5a70448f17b465d411a19dab78f0ddf1672ffd518b188f52433"],
+ ["eba8b0de04ac276293c272d0d3636e81400b1aaa60db5f11561480592f99e6f6fa13ad387002000000070053acab536563bebb23d66fd17d98271b182019864a90e60a54f5a615e40b643a54f8408fa8512cfac927030000000963ac6a6aabac65ababffffffff890a72192bc01255058314f376bab1dc72b5fea104c154a15d6faee75dfa5dba020000000100592b3559b0085387ac7575c05b29b1f35d9a2c26a0c27903cc0f43e7e6e37d5a60d8305a030000000252abffffffff0126518f05000000000000000000", "005300635252635351", 1, 664344756, "26dc2cba4bd5334e5c0b3a520b44cc1640c6b923d10e576062f1197171724097"],
+ ["91bd040802c92f6fe97411b159df2cd60fb9571764b001f31657f2d616964637605875c2a901000000055263006a65ffffffff3651df372645f50cf4e32fdf6e61c766e912e16335db2b40c5d52fe89eefe7cd00000000040065ab65ffffffff03ca8625030000000009ab51ac63530052ab52c6bf14020000000006ab00ab52005167d270000000000007ab53525351636a00000000", "5151ab63005252ac", 1, 1983087664, "3e5aa0200248d8d86ede3b315ca1b857018b89184a4bd023bd88ab12e499f6e1"],
+ ["185cda1a01ecf7a8a8c28466725b60431545fc7a3367ab68e34d486e8ea85ee3128e0d8384000000000465ac63abec88b7bb031c56eb04000000000965636a51005252006a7c78d5040000000007acac63abac51ac3024a40500000000086300526a51abac51464c0e8c", "0065535265515352", 0, 1594558917, "b5280b9610c0625a65b36a8c2402a95019a7bbb9dd3de77f7c3cb1d82c3263ba"],
+ ["a9531f07034091668b65fea8b1a79700d586ac9e2f42ca0455a26abe41f9e1805d009a0f5702000000096365516365ac5263ab3619bac643a9e28ee47855118cf80c3a74531cdf198835d206d0fe41804e325a4f9f105e03000000016a58e3ab0d46375d98994daf0fa7c600d2bb4669e726fca0e3a3f21ea0d9e777396740328f0100000008636a5363ab526a538d3ea7700304cb66030000000007515163ab52ab510184030500000000085353636565ac0051d9cff402000000000751ab52ab5352abf0e36254", "ab5353ac5365acab", 2, 1633101834, "04c9ef72f33668ca449c0415becf62cc0b8e0c75f9c8813852d42a58acf107c8"],
+ ["6b5ecc7903fe0ba37ea551df92a59e12bad0a3065846ba69179a8f4a741a2b4fcf679aac810200000004535263529a3d343293b99ab425e7ef8529549d84f480bcd92472bab972ea380a302128ae14dfcd0200000000025163ffffffff24636e4545cab9bf87009119b7fc3ec4d5ee9e206b90f35d1df8a563b6cd097a010000000852abac53005153abc64467860406e832020000000009526300006a53ac6352ac1395010000000002ac53b117f300000000000863655351acab00651edf02030000000008ab51ac6353535252628ef71d", "ab63ab6a52ac526563", 2, -1559697626, "8f07ece7d65e509f1e0780584ef8d271c1c61a13b10335d5faafc7afc8b5b8ec"],
+ ["92c9fb780138abc472e589d5b59489303f234acc838ca66ffcdf0164517a8679bb622a4267020000000153468e373d04de03fa020000000009ac006a5265ab5163006af649050000000007515153006a00658ceb59030000000001ac36afa0020000000009ab53006351ab51000000000000", "6a", 0, 2059357502, "e2358dfb51831ee81d7b0bc602a65287d6cd2dbfacf55106e2bf597e22a4b573"],
+ ["6f62138301436f33a00b84a26a0457ccbfc0f82403288b9cbae39986b34357cb2ff9b889b302000000045253655335a7ff6701bac9960400000000086552ab656352635200000000", "6aac51", 0, 1444414211, "502a2435fd02898d2ff3ab08a3c19078414b32ec9b73d64a944834efc9dae10c"],
+ ["9981143a040a88c2484ac3abe053849e72d04862120f424f373753161997dd40505dcb4783030000000700536365536565a2e10da3f4b1c1ad049d97b33f0ae0ea48c5d7c30cc8810e144ad93be97789706a5ead180100000003636a00ffffffffbdcbac84c4bcc87f03d0ad83fbe13b369d7e42ddb3aecf40870a37e814ad8bb5010000000963536a5100636a53abffffffff883609905a80e34202101544f69b58a0b4576fb7391e12a769f890eef90ffb72020000000651656352526affffffff04243660000000000004ab5352534a9ce001000000000863656363ab6a53652df19d030000000003ac65acedc51700000000000000000000", "ac6300acac", 2, 293672388, "7ba99b289c04718a7283f150d831175ed6303081e191a0608ea81f78926c5bdf"],
+ ["a2bb630b01989bc5d643f2da4fb9b55c0cdf846ba06d1dbe372893024dbbe5b9b8a1900af802000000055265ac63aca7a68d2f04916c74010000000003abac007077f0040000000001007d4127010000000005ac516aac000f31e8030000000000571079c9", "65ab0051ac", 0, -1103627693, "92d53b4390262e6b288e8a32e0cfc36cd5adfdfabfe96c7bfd4a19d65e233761"],
+ ["49f7d0b6037bba276e910ad3cd74966c7b3bc197ffbcfefd6108d6587006947e97789835ea0300000008526a52006a650053ffffffff8d7b6c07cd10f4c4010eac7946f61aff7fb5f3920bdf3467e939e58a1d4100ab03000000076aac63ac535351ffffffff8f48c3ba2d52ad67fbcdc90d8778f3c8a3894e3c35b9730562d7176b81af23c80100000003ab5265ffffffff0301e3ef0300000000046a525353e899ac0500000000075153ab6a65abac259bea0400000000007b739972", "53516aacac6aac", 1, 955403557, "5d366a7f4346ae18aeb7c9fc4dab5af71173184aa20ed22fcb4ea8511ad25449"],
+ ["58a4fed801fbd8d92db9dfcb2e26b6ff10b120204243fee954d7dcb3b4b9b53380e7bb8fb60100000003006351ffffffff02a0795b050000000006536351ac6aac2718d00200000000075151acabac515354d21ba1", "005363515351", 0, -1322430665, "bbee941bbad950424bf40e3623457db47f60ed29deaa43c99dec702317cb3326"],
+ ["32765a0b02e455793d9ce530e9f6a44bcbc612e893a875b5da61d822dc56d8245166c398b403000000085353abac6300006a6bdee2a78d0d0b6a5ea666eed70b9bfea99d1d612ba3878f615c4da10d4a521cba27155002000000035363abffffffff043cd42401000000000551656a53653685320100000000030000511881bc0500000000065165abab636a20169f010000000007acab656aac63acdb0706a8", "65ac53ab53", 0, 1936499176, "5c5a9c3a5de7dc7a82bc171c9d3505913b8bcc450bc8b2d11772c1a1d781210b"],
+ ["17fad0d303da0d764fedf9f2887a91ea625331b28704940f41e39adf3903d8e75683ef6d46020000000151ffffffffff376eea4e880bcf0f03d33999104aafed2b3daf4907950bb06496af6b51720a020000000900636a63525253525196521684f3b08497bad2c660b00b43a6a517edc58217876eb5e478aa3b5fda0f29ee1bea00000000046aacab6affffffff03dde8e2050000000007ac5365ac51516a14772e000000000005630000abacbbb360010000000006ab5251ab656a50f180f0", "0053", 0, -1043701251, "a3bdf8771c8990971bff9b4e7d59b7829b067ed0b8d3ac1ec203429811384668"],
+ ["236c32850300045e292c84ede2b9ab5733ba08315a2bb09ab234c4b4e8894808edbdac0d3b020000000653635363abacffffffffd3f696bb31fdd18a72f3fc2bb9ae54b416a253fc37c1a0f0180b52d35bad49440100000004650053abffffffffa85c75a2406d82a93b12e555b66641c1896a4e83ae41ef1038218311e38ace060200000006abab006a51ac104b5e6701e2842c04000000000800630051ac0000ab00000000", "ab63ac6a516a", 1, -1709887524, "8c29ea8ef60c5a927fccdba8ea385db6b6b84d98e891db45f5d4ee3148d3f5a7"],
+ ["b78d5fd601345f3100af494cdf447e7d4076179f940035b0ebe8962587d4d0c9c6c9fc34ee0300000003516a6affffffff03dc5c890100000000085353ac53ac6a52534ac941040000000007ac63656a51ab51d4266b0100000000036aacac70731f2d", "005351ab0053", 0, -1789071265, "d5f1c1cb35956a5711d67bfb4cedbc67e77c089b912d688ad440ff735adb390d"],
+ ["5a2257df03554550b774e677f348939b37f8e765a212e566ce6b60b4ea8fed4c9504b7f7d1000000000653655265ab5258b67bb931df15b041177cf9599b0604160b79e30f3d7a594e7826bae2c29700f6d8f8f40300000005515300ac6a159cf8808a41f504eb5c2e0e8a9279f3801a5b5d7bc6a70515fbf1c5edc875bb4c9ffac500000000050063510052ffffffff0422a90105000000000965006a650000516a006417d2020000000006526363ab00524d969d0100000000035153acc4f077040000000005ac5200636500000000", "6a52", 1, -1482463464, "37b794b05d0687c9b93d5917ab068f6b2f0e38406ff04e7154d104fc1fb14cdc"],
+ ["e0032ad601269154b3fa72d3888a3151da0aed32fb2e1a15b3ae7bee57c3ddcffff76a1321010000000100110d93ae03f5bd080100000000075263516a6551002871e60100000000046a005252eaa753040000000004ab6aab526e325c71", "630052", 0, -1857873018, "ea117348e94de86381bb8ad1c7f93b8c623f0272104341701bb54e6cb433596c"],
+ ["014b2a5304d46764817aca180dca50f5ab25f2e0d5749f21bb74a2f8bf6b8b7b3fa8189cb7030000000965ac5165ab6a51ac6360ecd91e8abc7e700a4c36c1a708a494c94bb20cbe695c408543146566ab22be43beae9103000000045163ab00ffffffffffa48066012829629a9ec06ccd4905a05df0e2b745b966f6a269c9c8e13451fc00000000026565ffffffffc40ccadc21e65fe8a4b1e072f4994738ccaf4881ae6fede2a2844d7da4d199ab02000000065152ab536aabffffffff01b6e054030000000004515352ab3e063432", "", 0, 1056459916, "a7aff48f3b8aeb7a4bfe2e6017c80a84168487a69b69e46681e0d0d8e63a84b6"],
+ ["c4ef04c103c5dde65410fced19bf6a569549ecf01ceb0db4867db11f2a3a3eef0320c9e8e001000000085100536a53516aabffffffff2a0354fa5bd96f1e28835ffe30f52e19bd7d5150c687d255021a6bec03cf4cfd03000000056a006300514900c5b01d3d4ae1b97370ff1155b9dd0510e198d266c356d6168109c54c11b4c283dca00300000002ababffffffff02e19e3003000000000451655351fa5c0003000000000163ef1fc64b", "51636a51ab630065", 1, -1754709177, "0a281172d306b6a32e166e6fb2a2cc52c505c5d60ea448e9ba7029aa0a2211e1"],
+ ["29083fe00398bd2bb76ceb178f22c51b49b5c029336a51357442ed1bac35b67e1ae6fdf13100000000066a6500acab51ffffffffe4ca45c9dc84fd2c9c47c7281575c2ba4bf33b0b45c7eca8a2a483f9e3ebe4b3010000000200abffffffffdf47ad2b8c263fafb1e3908158b18146357c3a6e0832f718cd464518a219d18303000000096352ac656351ac0052daddfb3b0231c36f00000000000400526a5275c7e0020000000001ab00000000", "acab536aac52", 2, 300802386, "82ebc07b16cff0077e9c1a279373185b3494e39d08fd3194aae6a4a019377509"],
+ ["1201ab5d04f89f07c0077abd009762e59db4bb0d86048383ba9e1dad2c9c2ad96ef660e6d00200000007ab6a65ac5200652466fa5143ab13d55886b6cdc3d0f226f47ec1c3020c1c6e32602cd3428aceab544ef43e00000000086a6a6a526a6a5263ffffffffd5be0b0be13ab75001243749c839d779716f46687e2e9978bd6c9e2fe457ee48020000000365abab1e1bac0f72005cf638f71a3df2e3bbc0fa35bf00f32d9c7dc9c39a5e8909f7d53170c8ae0200000008ab6a51516363516affffffff02f0a6210500000000036300ac867356010000000009acab65ac6353536a659356d367", "ac53535252", 0, 917543338, "418acc156c2bc76a5d7baa58db29f1b4cf6c266c9222ed167ef5b4d47f0e0f41"],
+ ["344fa11e01c19c4dd232c77742f0dd0aeb3695f18f76da627628741d0ee362b0ea1fb3a2180200000007635151005100529bab25af01937c1f0500000000055153ab53656e7630af", "6351005163ac51", 0, -629732125, "228ca52a0a376fe0527a61cfa8da6d7baf87486bba92d49dfd3899cac8a1034f"],
+ ["b2fda1950191358a2b855f5626a0ebc830ab625bea7480f09f9cd3b388102e35c0f303124c030000000565ac65ab53ffffffff03f9c5ec04000000000765ab51516551650e2b9f0500000000045365525284e8f6040000000001ac00000000", "ac51655253", 0, 1433027632, "d2fa7e13c34cecda5105156bd2424c9b84ee0a07162642b0706f83243ff811a8"],
+ ["a4a6bbd201aa5d882957ac94f2c74d4747ae32d69fdc765add4acc2b68abd1bdb8ee333d6e0300000008516a6552515152abffffffff02c353cb040000000007ac6351ab51536588bd320500000000066552525253ac00000000", "", 0, 1702060459, "499da7d74032388f820645191ac3c8d20f9dba8e8ded7fa3a5401ea2942392a1"],
+ ["584e8d6c035a6b2f9dac2791b980a485994bf38e876d9dda9b77ad156eee02fa39e19224a60300000003ab636529db326cc8686a339b79ab6b6e82794a18e0aabc19d9ad13f31dee9d7aad8eff38288588020000000452530052ffffffff09a41f07755c16cea1c7e193c765807d18cadddca6ec1c2ed7f5dcdca99e90e80000000001acffffffff01cba62305000000000451ac63acccdf1f67", "ab536a6363", 2, -27393461, "1125645b49202dca2df2d76dae51877387903a096a9d3f66b5ac80e042c95788"],
+ ["83a583d204d926f2ee587a83dd526cf1e25a44bb668e45370798f91a2907d184f7cddcbbc7030000000700ab6565536a539f71d3776300dffdfa0cdd1c3784c9a1f773e34041ca400193612341a9c42df64e3f550e01000000050052515251ffffffff52dab2034ab0648553a1bb8fc4e924b2c89ed97c18dfc8a63e248b454035564b01000000015139ab54708c7d4d2c2886290f08a5221cf69592a810fd1979d7b63d35c271961e710424fd0300000005ac65ac5251ffffffff01168f7c030000000000a85e5fb0", "6a536353656a00", 0, 179595345, "5350a31ac954a0b49931239d0ecafbf34d035a537fd0c545816b8fdc355e9961"],
+ ["ffd35d51042f290108fcb6ea49a560ba0a6560f9181da7453a55dfdbdfe672dc800b39e7320200000006630065516a65f2166db2e3827f44457e86dddfd27a8af3a19074e216348daa0204717d61825f198ec0030100000006ab51abab00abffffffffdf41807adb7dff7db9f14d95fd6dc4e65f8402c002d009a3f1ddedf6f4895fc8030000000500ab006a65a5a848345052f860620abd5fcd074195548ce3bd0839fa9ad8642ed80627bf43a0d47dbd010000000765ab006a656a53b38cdd6502a186da05000000000765ab00ab006a53527c0e0100000000085365ab51acacac52534bd1b1", "6a635253ac0000", 0, 1095082149, "3c05473a816621a3613f0e903faa1a1e44891dd40862b029e41fc520776350fa"],
+ ["6c9a4b98013c8f1cae1b1df9f0f2de518d0c50206a0ab871603ac682155504c0e0ce946f460100000000ffffffff04e9266305000000000753535100ac6aacded39e04000000000365ac6ab93ccd010000000002515397bf3d050000000003ab636300000000", "63520052ac656353", 0, -352633155, "936eff8cdfd771be24124da87c7b24feb48da7cbc2c25fb5ba13d1a23255d902"],
+ ["e01dc7f0021dc07928906b2946ca3e9ac95f14ad4026887101e2d722c26982c27dc2b59fdb0000000005ac5200516ab5a31ffadcbe74957a5a3f97d7f1475cc6423fc6dbc4f96471bd44c70cc736e7dec0d1ea020000000951636a526a52abac53ffffffff04bc2edd05000000000252ab528c7b02000000000952ac51526500525353324820040000000002005380c713000000000009630065ab00ac525252451bbb48", "53ab65ac", 0, -552384418, "69c0b30f4c630a6c878fde6ea6b74dae94f4eb3bcfbde2dc3649e1a9ada00757"],
+ ["009046a1023f266d0113556d604931374d7932b4d6a7952d08fbd9c9b87cbd83f4f4c178b4030000000452ac526346e73b438c4516c60edd5488023131f07acb5f9ea1540b3e84de92f4e3c432289781ea4900000000046500655357dfd6da02baef910100000000026a007d101703000000000800516500abacac5100000000", "6aab6553ac", 0, -802456605, "f8757fbb4448ca34e0cd41b997685b37238d331e70316659a9cc9087d116169d"],
+ ["df76ec0801a3fcf3d18862c5f686b878266dd5083f16cf655facab888b4cb3123b3ce5db7e01000000010010e7ac6a0233c83803000000000365ac51faf14a040000000004ac51655100000000", "6353acab", 0, 15705861, "e7d873aa079a19ec712b269a37d2670f60d8cb334c4f97e2e3fd10eeb8ee5f5e"],
+ ["828fd3e0031084051ccef9cfdd97fae4d9cc50c0dae36bd22a3ff332881f17e9756c3e288e0200000004ab535363961a2ccccaf0218ec6a16ba0c1d8b5e93cfd025c95b6e72bc629ec0a3f47da7a4c396dad01000000025353ffffffff19ad28747fb32b4caf7b5dbd9b2da5a264bedb6c86d3a4805cd294ae53a86ac40200000009ab53535351ab6551abffffffff04a41650030000000005656aab6aab8331a304000000000700516365ac516a0d2a47010000000007abac516353abacdebc19040000000006ab5300636a6300000000", "51ab52ab53ac52", 0, 1866105980, "311094b4d73e31aefc77e97859ef07ca2f07a7b7e4d7def80c69d3f5d58527e5"],
+ ["c4b80f850323022205b3e1582f1ed097911a81be593471a8dce93d5c3a7bded92ef6c7c1260100000002006affffffff70294d62f37c3da7c5eae5d67dce6e1b28fedd7316d03f4f48e1829f78a88ae801000000096a5200530000516351f6b7b544f7c39189d3a2106ca58ce4130605328ce7795204be592a90acd81bef517d6f170200000000ffffffff012ab8080000000000075100006365006335454c1e", "53ac6a536aacac", 0, -1124103895, "06277201504e6bf8b8c94136fad81b6e3dadacb9d4a2c21a8e10017bfa929e0e"],
+ ["8ab69ed50351b47b6e04ac05e12320984a63801716739ed7a940b3429c9c9fed44d3398ad40300000006536a516a52638171ef3a46a2adb8025a4884b453889bc457d63499971307a7e834b0e76eec69c943038a0300000000ffffffff566bb96f94904ed8d43d9d44a4a6301073cef2c011bf5a12a89bedbaa03e4724030000000265acb606affd01edea38050000000008515252516aacac6300000000", "65000000006365ac53", 0, -1338942849, "7912573937824058103cb921a59a7f910a854bf2682f4116a393a2045045a8c3"],
+ ["2484991e047f1cf3cfe38eab071f915fe86ebd45d111463b315217bf9481daf0e0d10902a402000000006e71a424eb1347ffa638363604c0d5eccbc90447ff371e000bf52fc743ec832851bb564a0100000001abffffffffef7d014fad3ae7927948edbbb3afe247c1bcbe7c4c8f5d6cf97c799696412612020000000851536a5353006a001dfee0d7a0dd46ada63b925709e141863f7338f34f7aebde85d39268ae21b77c3068c01d0000000008535151ab00636563ffffffff018478070200000000095200635365ac52ab5341b08cd3", "", 3, 265623923, "24cb420a53b4f8bb477f7cbb293caabfd2fc47cc400ce37dbbab07f92d3a9575"],
+ ["54839ef9026f65db30fc9cfcb71f5f84d7bb3c48731ab9d63351a1b3c7bc1e7da22bbd508e0300000000442ad138f170e446d427d1f64040016032f36d8325c3b2f7a4078766bdd8fb106e52e8d20000000003656500ffffffff02219aa101000000000851ababac52ab00659646bd02000000000552acacabac24c394a5", "ac", 0, 906807497, "69264faadcd1a581f7000570a239a0a26b82f2ad40374c5b9c1f58730514de96"],
+ ["5036d7080434eb4eef93efda86b9131b0b4c6a0c421e1e5feb099a28ff9dd8477728639f77030000000951516aab535152ab5391429be9cce85d9f3d358c5605cf8c3666f034af42740e94d495e28b9aaa1001ba0c87580300000008006552ab00ab006affffffffd838978e10c0c78f1cd0a0830d6815f38cdcc631408649c32a25170099669daa0000000002acab8984227e804ad268b5b367285edcdf102d382d027789250a2c0641892b480c21bf84e3fb0100000000b518041e023d8653010000000001004040fb0100000000080051ac5200636a6300000000", "52ac", 0, 366357656, "bd0e88829afa6bdc1e192bb8b2d9d14db69298a4d81d464cbd34df0302c634c6"],
+ ["9ad5ccf503fa4facf6a27b538bc910cce83c118d6dfd82f3fb1b8ae364a1aff4dcefabd38f03000000096365655263ac655300807c48130c5937190a996105a69a8eba585e0bd32fadfc57d24029cbed6446d30ebc1f100100000004000053650f0ccfca1356768df7f9210cbf078a53c72e0712736d9a7a238e0115faac0ca383f219d0010000000600ab536552002799982b0221b8280000000000000c41320000000000086552ac6365636a6595f233a3", "6a5152", 2, 553208588, "f99c29a79f1d73d2a69c59abbb5798e987639e36d4c44125d8dc78a94ddcfb13"],
+ ["669538a204047214ce058aed6a07ca5ad4866c821c41ac1642c7d63ed0054f84677077a84f030000000853abacab6a655353ffffffff70c2a071c115282924e3cb678b13800c1d29b6a028b3c989a598c491bc7c76c5030000000752ac52ac5163ac80420e8a6e43d39af0163271580df6b936237f15de998e9589ec39fe717553d415ac02a4030000000463635153184ad8a5a4e69a8969f71288c331aff3c2b7d1b677d2ebafad47234840454b624bf7ac1d03000000056a63abab63df38c24a02fbc63a040000000002ab535ec3dc050000000002536500000000", "635153", 3, -190399351, "9615541884dfb1feeb08073a6a6aa73ef694bc5076e52187fdf4138a369f94d9"],
+ ["a7f139e502af5894be88158853b7cbea49ba08417fbbca876ca6614b5a41432be34499987b000000000765635165abac63ffffffff8b8d70e96c7f54eb70da0229b548ced438e1ca2ba5ddd648a027f72277ee1efc0100000001abffffffff044f2c4204000000000165e93f550100000000050000526a6a94550304000000000365536aadc21c0300000000016300000000", "6aacac6363ab5265ac", 1, 2143189425, "6e3f97955490d93d6a107c18d7fe402f1cada79993bb0ff0d096357261b3a724"],
+ ["3b94438f0366f9f53579a9989b86a95d134256ce271da63ca7cd16f7dd5e4bffa17d35133f010000000100ffffffff1aaad0c721e06ec00d07e61a84fb6dc840b9a968002ce7e142f943f06fd143a10100000008535151ac51ab0053b68b8e9c672daf66041332163e04db3f6048534bd718e1940b3fc3811c4eef5b7a56888b01000000001d58e38c012e38e700000000000852ab53ac6365536a00000000", "ab655352", 1, -935223304, "b3b336de141d4f071313a2207b2a0c7cf54a070dd8d234a511b7f1d13e23b0c4"],
+ ["e5dca8a20456de0a67e185fa6ea94085ceae478d2c15c73cb931a500db3a1b6735dd1649ec0200000005ab536aabab32d11bbdcb81361202681df06a6b824b12b5cb40bb1a672cf9af8f2a836e4d95b7839327030000000951005365ab65abacabb345085932939eef0c724adef8a57f9e1bf5813852d957c039b6a12d9c2f201ea520fb030000000009ac5352005165acac6a5efc6072f1a421dc7dc714fc6368f6d763a5d76d0278b95fc0503b9268ccfadb48213a2500000000026a53ffffffff039ee1c4020000000009ac5353ab6353535163184018000000000005655265526a9a4a8a050000000001ac00000000", "65ab53ab6a00ab6553", 2, 1902561212, "7928ae8e86c0b0cad1b2c120ea313087437974382ee6d46443ca5ac3f5878b88"],
+ ["972128b904e7b673517e96e98d80c0c8ceceae76e2f5c126d63da77ffd7893fb53308bb2da0300000006ac6552ab52acffffffff4cac767c797d297c079a93d06dc8569f016b4bf7a7d79b605c526e1d36a40e2202000000095365ab636aac6a6a6a69928d2eddc836133a690cfb72ec2d3115bf50fb3b0d10708fa5d2ebb09b4810c426a1db01000000060052526300001e8e89585da7e77b2dd2e30625887f0660accdf29e53a614d23cf698e6fc8ab03310e87700000000076a520051acac6555231ddb0330ec2d03000000000200abfaf457040000000004ab6a6352bdc42400000000000153d6dd2f04", "", 0, 209234698, "4a92fec1eb03f5bd754ee9bfd70707dc4420cc13737374f4675f48529be518e4"],
+ ["1fb4085b022c6cfb848f8af7ba3ba8d21bd23ffa9f0bfd181cb68bcaaf2074e66d4974a31602000000090000006a6a6500acab6c12c07d9f3dbd2d93295c3a49e3757119767097e7fd5371f7d1ba9ba32f1a67a5a426f00000000000ffffffff018fd2fc04000000000363ac5100000000", "65ab006a6aab526a", 0, 1431502299, "8b7dd0ff12ca0d8f4dbf9abf0abba00e897c2f6fd3b92c79f5f6a534e0b33b32"],
+ ["5374f0c603d727f63006078bd6c3dce48bd5d0a4b6ea00a47e5832292d86af258ea0825c260000000009655353636352526a6af2221067297d42a9f8933dfe07f61a574048ff9d3a44a3535cd8eb7de79fb7c45b6f47320200000003ac006affffffff153d917c447d367e75693c5591e0abf4c94bbdd88a98ab8ad7f75bfe69a08c470200000005ac65516365ffffffff037b5b7b000000000001515dc4d904000000000004bb26010000000004536a6aac00000000", "516552516352ac", 2, 328538756, "8bb7a0129eaf4b8fc23e911c531b9b7637a21ab11a246352c6c053ff6e93fcb6"],
+ ["c441132102cc82101b6f31c1025066ab089f28108c95f18fa67db179610247086350c163bd010000000651525263ab00ffffffff9b8d56b1f16746f075249b215bdb3516cbbe190fef6292c75b1ad8a8988897c3000000000751ab6553abab00ffffffff02f9078b000000000009ab0053ac51ac00ab51c0422105000000000651006563525200000000", "ac51", 0, -197051790, "55acd8293ed0be6792150a3d7ced6c5ccd153ca7daf09cee035c1b0dac92bb96"],
+ ["ab82ad3b04545bd86b3bb937eb1af304d3ef1a6d1343ed809b4346cafb79b7297c09e1648202000000086351ac5200535353ffffffff95d32795bbaaf5977a81c2128a9ec0b3c7551b9b1c3d952876fcb423b2dfb9e80000000005515363acac47a7d050ec1a603627ce6cd606b3af314fa7964abcc579d92e19c7aba00cf6c3090d6d4601000000056a516551633e794768bfe39277ebc0db18b5afb5f0c8117dde9b4dfd5697e9027210eca76a9be20d63000000000700520063ab6aacffffffff01ec2ddc050000000008ac52ac65ac65ac5100000000", "536300abab", 1, -2070209841, "b362da5634f20be7267de78b545d81773d711b82fe9310f23cd0414a8280801d"],
+ ["8bff9d170419fa6d556c65fa227a185fe066efc1decf8a1c490bc5cbb9f742d68da2ab7f320100000007ab000053525365a7a43a80ab9593b9e8b6130a7849603b14b5c9397a190008d89d362250c3a2257504eb810200000007acabacac00ab51ee141be418f003e75b127fd3883dbf4e8c3f6cd05ca4afcaac52edd25dd3027ae70a62a00000000008ac52526a5200536affffffffb8058f4e1d7f220a1d1fa17e96d81dfb9a304a2de4e004250c9a576963a586ae0300000005abacac5363b9bc856c039c01d804000000000951656aac53005365acb0724e00000000000565abab63acea7c7a0000000000036a00ac00000000", "6565", 1, -1349282084, "2b822737c2affeefae13451d7c9db22ff98e06490005aba57013f6b9bbc97250"],
+ ["0e1633b4041c50f656e882a53fde964e7f0c853b0ada0964fc89ae124a2b7ffc5bc97ea6230100000006ac6aacacabacffffffff2e35f4dfcad2d53ea1c8ada8041d13ea6c65880860d96a14835b025f76b1fbd9000000000351515121270867ef6bf63a91adbaf790a43465c61a096acc5a776b8e5215d4e5cd1492e611f761000000000600ac6aab5265ffffffff63b5fc39bcac83ca80ac36124abafc5caee608f9f63a12479b68473bd4bae769000000000965ac52acac5263acabffffffff0163153e020000000008ab005165ab65515300000000", "6a6aac00", 0, -968477862, "20732d5073805419f275c53784e78db45e53332ee618a9fcf60a3417a6e2ca69"],
+ ["2b052c24022369e956a8d318e38780ef73b487ba6a8f674a56bdb80a9a63634c6110fb5154010000000251acffffffff48fe138fb7fdaa014d67044bc05940f4127e70c113c6744fbd13f8d51d45143e01000000005710db3804e01aa9030000000008acac6a516a5152abfd55aa01000000000751ab510000ac636d6026010000000000b97da9000000000000fddf3b53", "006552", 0, 595461670, "685d67d84755906d67a007a7d4fa311519467b9bdc6a351913246a41e082a29f"],
+ ["073bc856015245f03b2ea2da62ccedc44ecb99e4250c7042f596bcb23b294c9dc92cfceb6b02000000095163abab52abab636afe292fb303b7c3f001000000000352636af3c49502000000000400ac6a535851850100000000066aac6553ab6500000000", "ab6aab53006aab52", 0, 247114317, "123916c6485cf23bfea95654a8815fbf04ce4d21a3b7f862805c241472906658"],
+ ["7888b71403f6d522e414d4ca2e12786247acf3e78f1918f6d727d081a79813d129ee8befce0100000009ab516a6353ab6365abffffffff4a882791bf6400fda7a8209fb2c83c6eef51831bdf0f5dacde648859090797ec030000000153ffffffffbb08957d59fa15303b681bad19ccf670d7d913697a2f4f51584bf85fcf91f1f30200000008526565ac52ac63acffffffff0227c0e8050000000001ac361dc801000000000800515165ab00ab0000000000", "656a", 2, 1869281295, "f43378a0b7822ad672773944884e866d7a46579ee34f9afc17b20afc1f6cf197"],
+ ["cc4dda57047bd0ca6806243a6a4b108f7ced43d8042a1acaa28083c9160911cf47eab910c40200000007526a0000ab6a63e4154e581fcf52567836c9a455e8b41b162a78c85906ccc1c2b2b300b4c69caaaa2ba0230300000008ab5152ac5100ab65ffffffff69696b523ed4bd41ecd4d65b4af73c9cf77edf0e066138712a8e60a04614ea1c0300000004ab6a000016c9045c7df7836e05ac4b2e397e2dd72a5708f4a8bf6d2bc36adc5af3cacefcf074b8b403000000065352ac5252acffffffff01d7e380050000000000cf4e699a", "525163656351", 1, -776533694, "ff18c5bffd086e00917c2234f880034d24e7ea2d1e1933a28973d134ca9e35d2"],
+ ["b7877f82019c832707a60cf14fba44cfa254d787501fdd676bd58c744f6e951dbba0b3b77f0200000009ac515263ac53525300a5a36e500148f89c0500000000085265ac6a6a65acab00000000", "6563", 0, -1785108415, "cb6e4322955af12eb29613c70e1a00ddbb559c887ba844df0bcdebed736dffbd"],
+ ["aeb14046045a28cc59f244c2347134d3434faaf980961019a084f7547218785a2bd03916f3000000000165f852e6104304955bda5fa0b75826ee176211acc4a78209816bbb4419feff984377b2352200000000003a94a5032df1e0d60390715b4b188c330e4bb7b995f07cdef11ced9d17ee0f60bb7ffc8e0100000002516513e343a5c1dc1c80cd4561e9dddad22391a2dbf9c8d2b6048e519343ca1925a9c6f0800a020000000665516365ac513180144a0290db27000000000006ab655151ab5138b187010000000007ab5363abac516a9e5cd98a", "53ac", 0, 478591320, "e8d89a302ae626898d4775d103867a8d9e81f4fd387af07212adab99946311ef"],
+ ["c9270fe004c7911b791a00999d108ce42f9f1b19ec59143f7b7b04a67400888808487bd59103000000066a0052ac6565b905e76687be2dd7723b22c5e8269bc0f2000a332a289cfc40bc0d617cfe3214a61a85a30300000007ac63ac00635251560871209f21eb0268f175b8b4a06edd0b04162a974cf8b5dada43e499a1f22380d35ede0300000000792213fc58b6342cc8100079f9f5f046fb89f2d92cf0a2cb6d07304d32d9da858757037c0000000008abab51636565516affffffff02c72a8b03000000000452acac530dfb9f05000000000096f94307", "5253ab536351", 3, 543688436, "0278adbcc476d135493ae9bdcd7b3c2002df17f2d81c17d631c50c73e546c264"],
+ ["57a5a04c0278c8c8e243d2df4bb716f81d41ac41e2df153e7096f5682380c4f441888d9d260300000004ab63ab6afdbe4203525dff42a7b1e628fe22bccaa5edbb34d8ab02faff198e085580ea5fcdb0c61b0000000002ac6affffffff03375e6c05000000000663ab516a6a513cb6260400000000007ca328020000000006516a636a52ab94701cc7", "0053ac5152", 0, -550925626, "b7ca991ab2e20d0158168df2d3dd842a57ab4a3b67cca8f45b07c4b7d1d11126"],
+ ["072b75a504ad2550c2e9a02614bc9b2a2f50b5b553af7b87c0ef07c64ddc8d8934c96d216401000000036aabaca1387242a5bcd21099b016ad6045bed7dce603472757d9822cc5f602caa4ae20414d378b02000000026a63e4ac816734acdc969538d6f70b8ab43a2589f55e0177a4dc471bdd0eb61d59f0f46f6bb801000000065351526aab52d9f2977be76a492c3a7617b7a16dc29a3b0a7618f328c2f7d4fd9bafe760dc427a5066ef000000000465635165ffffffff02c5793600000000000165296820050000000002ac6300000000", "53006a6aac0052ab", 2, 66084636, "437e89bb6f70fd2ed2feef33350b6f6483b891305e574da03e580b3efd81ae13"],
+ ["7e27c42d0279c1a05eeb9b9faedcc9be0cab6303bde351a19e5cbb26dd0d594b9d74f40d2b020000000200518c8689a08a01e862d5c4dcb294a2331912ff11c13785be7dce3092f154a005624970f84e0200000000500cf5a601e74c1f0000000000076aab52636a6a5200000000", "6500006a5351", 0, 449533391, "535ba819d74770d4d613ee19369001576f98837e18e1777b8246238ff2381dd0"],
+ ["11414de403d7f6c0135a9df01cb108c1359b8d4e105be50a3dcba5e6be595c8817217490b20000000003005263ffffffff0c6becb9c3ad301c8dcd92f5cbc07c8bed7973573806d1489316fc77a829da03030000000700005253535352ffffffff2346d74ff9e12e5111aa8779a2025981850d4bf788a48de72baa2e321e4bc9ca00000000056352acab63cc585b64045e0385050000000009ab5253ab516aacac00efa9cf0300000000065200635151acbe80330400000000070063635100ab000be159050000000007525300655300ac00000000", "51656a0051ab", 0, 683137826, "d4737f3b58f3e5081b35f36f91acde89dda00a6a09d447e516b523e7a99264d5"],
+ ["1c6b5f29033fc139338658237a42456123727c8430019ca25bd71c6168a9e35a2bf54538d80100000008536aac52ac6a6a52ffffffff3fb36be74036ff0c940a0247c451d923c65f826793d0ac2bb3f01ecbec8033290100000007ab000051ab6363ffffffff5d9eca0cf711685105bd060bf7a67321eaef95367acffab36ce8dedddd632ee2000000000652ac6a63ac517167319e032d26de040000000003516363dc38fb010000000000b37b00000000000006ab520051ac534baba51f", "636300ababac6563", 0, -2049129935, "3282a2ec6b8c87c9303e6060c17b421687db1bd35fbfa0345b48f2490e15b6cc"],
+ ["978b9dad0214cfc7ce392d74d9dcc507350dc34007d72e4125861c63071ebf2cc0a6fd4856020000000651ac6a6aab52ffffffff47f20734e3370e733f87a6edab95a7a268ae44db7a8974e255614836b22938720200000008635265ac51516553ffffffff0137b2560100000000035252ac2f3363e9", "006aab6352", 1, 2014249801, "55611a5fb1483bce4c14c33ed15198130e788b72cd8929b2ceef4dd68b1806bf"],
+ ["442f1c8703ab39876153c241ab3d69f432ba6db4732bea5002be45c8ca10c3a2356fe0e9590300000001accb2b679cab7c58a660cb6d4b3452c21cd7251a1b77a52c300f655f5baeb6fa27ff5b79880300000003005252e5ccf55712bc8ed6179f6726f8a78f3018a7a0391594b7e286ef5ee99efdcde302a102cc0200000009006352526351536a63ffffffff04443f63030000000006536a63ab63651405fb020000000009ac535351525300ab6a9f172b000000000004ab535263ad5c50050000000008656a65ab630000ac00000000", "65636aab006552", 2, 2125838294, "b3ff10f21e71ebc8b25fe058c4074c42f08617e0dcc03f9e75d20539d3242644"],
+ ["2b3470dd028083910117f86614cdcfb459ee56d876572510be4df24c72e8f58c70d5f5948b03000000066aab65635265da2c3aac9d42c9baafd4b655c2f3efc181784d8cba5418e053482132ee798408ba43ccf90300000000ffffffff047dda4703000000000765516a52ac53009384a603000000000651636a63ab6a8cf57a03000000000352ab6a8cf6a405000000000952636a6a6565525100661e09cb", "ac520063ac6a6a52", 1, 1405647183, "9b360c3310d55c845ef537125662b9fe56840c72136891274e9fedfef56f9bb5"],
+ ["d74282b501be95d3c19a5d9da3d49c8a88a7049c573f3788f2c42fc6fa594f59715560b9b00000000009655353525265ac52ac9772121f028f8303030000000003510065af5f47040000000007ac516a6551630000000000", "acab53006363ac", 0, -1113209770, "2f482b97178f17286f693796a756f4d7bd2dfcdbecd4142528eec1c7a3e5101a"],
+ ["3a5644a9010f199f253f858d65782d3caec0ac64c3262b56893022b9796086275c9d4d097b02000000009d168f7603a67b30050000000007ac51536a0053acd9d88a050000000007655363535263ab3cf1f403000000000352ac6a00000000", "005363536565acac6a", 0, -1383947195, "6390ab0963cf611e0cea35a71dc958b494b084e6fd71d22217fdc5524787ade6"],
+ ["67b3cc43049d13007485a8133b90d94648bcf30e83ba174f5486ab42c9107c69c5530c5e1f0000000003005100ffffffff9870ebb65c14263282ea8d41e4f4f40df16b565c2cf86f1d22a9494cad03a67f01000000016a5a121bee5e359da548e808ae1ad6dfccae7c67cbb8898d811638a1f455a671e822f228ef030000000151c1fcc9f9825f27c0dde27ea709da62a80a2ff9f6b1b86a5874c50d6c37d39ae31fb6c8a0030000000163553b8786020ca74a00000000000665635153ab5275c0760000000000020052e659b05d", "636aab6a6a", 0, -342795451, "f77c3322c97b1681c17b1eba461fa27b07e04c1534e8aaf735a49cab72c7c2e2"],
+ ["bda1ff6804a3c228b7a12799a4c20917301dd501c67847d35da497533a606701ad31bf9d5e0300000001ac16a6c5d03cf516cd7364e4cbbf5aeccd62f8fd03cb6675883a0636a7daeb650423cb1291010000000500656553ac4a63c30b6a835606909c9efbae1b2597e9db020c5ecfc0642da6dc583fba4e84167539a8020000000865525353515200acffffffff990807720a5803c305b7da08a9f24b92abe343c42ac9e917a84e1f335aad785d00000000026a52ffffffff04981f20030000000001ab8c762200000000000253ab690b9605000000000151ce88b301000000000753526a6a51006500000000", "000052ac52530000", 1, -1809193140, "5299b0fb7fc16f40a5d6b337e71fcd1eb04d2600aefd22c06fe9c71fe0b0ba54"],
+ ["2ead28ff0243b3ab285e5d1067f0ec8724224402b21b9cef9be962a8b0d153d401be99bbee0000000004ac635153ffffffff6985987b7c1360c9fa8406dd6e0a61141709f0d5195f946da55ed83be4e3895301000000020053ffffffff016503d20500000000085251ac6a65656a6a00000000", "51abab", 1, 1723793403, "67483ee62516be17a2431a163e96fd88a08ff2ce8634a52e42c1bc04e30f3f8a"],
+ ["db4904e6026b6dd8d898f278c6428a176410d1ffbde75a4fa37cda12263108ccd4ca6137440100000007656a0000515263ffffffff1db7d5005c1c40da0ed17b74cf6b2a6ee2c33c9e0bacda76c0da2017dcac2fc70200000004abab6a53ffffffff0454cf2103000000000153463aef000000000009ab6a630065ab52636387e0ed050000000000e8d16f05000000000352ac63e4521b22", "", 1, 1027042424, "48315a95e49277ab6a2d561ee4626820b7bab919eea372b6bf4e9931ab221d04"],
+ ["dca31ad10461ead74751e83d9a81dcee08db778d3d79ad9a6d079cfdb93919ac1b0b61871102000000086500525365ab51ac7f7e9aed78e1ef8d213d40a1c50145403d196019985c837ffe83836222fe3e5955e177e70100000006525152525300ffffffff5e98482883cc08a6fe946f674cca479822f0576a43bf4113de9cbf414ca628060100000006ac53516a5253ffffffff07490b0b898198ec16c23b75d606e14fa16aa3107ef9818594f72d5776805ec502000000036a0052ffffffff01932a2803000000000865ab6551ac6a516a2687aa06", "635300ac", 2, -1880362326, "74d6a2fa7866fd8b74b2e34693e2d6fd690410384b7afdcd6461b1ae71d265ce"],
+ ["e14e1a9f0442ab44dfc5f6d945ad1ff8a376bc966aad5515421e96ddbe49e529614995cafc03000000055165515165fffffffff97582b8290e5a5cfeb2b0f018882dbe1b43f60b7f45e4dd21dbd3a8b0cfca3b0200000000daa267726fe075db282d694b9fee7d6216d17a8c1f00b2229085495c5dc5b260c8f8cd5d000000000363ac6affffffffaab083d22d0465471c896a438c6ac3abf4d383ae79420617a8e0ba8b9baa872b010000000963526563ac5363ababd948b5ce022113440200000000076a636552006a53229017040000000000e6f62ac8", "526353636a65", 3, -485265025, "1bc8ad76f9b7c366c5d052dc479d6a8a2015566d3a42e93ab12f727692c89d65"],
+ ["720d4693025ca3d347360e219e9bc746ef8f7bc88e8795162e5e2f0b0fc99dc17116fc937100000000046353520045cb1fd79824a100d30b6946eab9b219daea2b0cdca6c86367c0c36af98f19ac64f3575002000000008a1c881003ed16f3050000000008536a63630000abac45e0e704000000000151f6551a05000000000963536565515363abab00000000", "6553ab6a6a510000ab", 1, 1249091393, "a575fa4f59a8e90cd07de012c78fe8f981183bb170b9c50fcc292b8c164cbc3b"],
+ ["69df842a04c1410bfca10896467ce664cfa31c681a5dac10106b34d4b9d4d6d0dc1eac01c1000000000551536a5165269835ca4ad7268667b16d0a2df154ec81e304290d5ed69e0069b43f8c89e673328005e200000000076a5153006aacabffffffffc9314bd80b176488f3d634360fcba90c3a659e74a52e100ac91d3897072e3509010000000765abac51636363ffffffff0e0768b13f10f0fbd2fa3f68e4b4841809b3b5ba0e53987c3aaffcf09eee12bf0300000008ac535263526a53ac514f4c2402da8fab0400000000001ef15201000000000451526a52d0ec9aca", "525365ac52", 1, 313967049, "a72a760b361af41832d2c667c7488dc9702091918d11e344afc234a4aea3ec44"],
+ ["adf2340d03af5c589cb5d28c06635ac07dd0757b884d4777ba85a6a7c410408ad5efa8b19001000000045100ab00ffffffff808dc0231c96e6667c04786865727013922bcb7db20739b686f0c17f5ba70e8f0300000000fd2332a654b580881a5e2bfec8313f5aa878ae94312f37441bf2d226e7fc953dcf0c77ab000000000163aa73dc580412f8c2050000000005636aacac63da02d502000000000153e74b52020000000001536b293d030000000009636552ababacab526500000000", "000052ab52ababab", 0, -568651175, "2c45d021db545df7167ac03c9ee56473f2398d9b2b739cf3ff3e074501d324f8"],
+ ["e4fec9f10378a95199c1dd23c6228732c9de0d7997bf1c83918a5cfd36012476c0c3cba24002000000085165536500ac0000ad08ab93fb49d77d12a7ccdbb596bc5110876451b53a79fdce43104ff1c316ad63501de801000000046a6352ab76af9908463444aeecd32516a04dd5803e02680ed7f16307242a794024d93287595250f4000000000089807279041a82e603000000000200521429100200000000055253636a63f20b940400000000004049ed04000000000500ab5265ab43dfaf7d", "6563526aac", 2, -1923470368, "32f3c012eca9a823bebb9b282240aec40ca65df9f38da43b1dcfa0cac0c0df7e"],
+ ["4000d3600100b7a3ff5b41ec8d6ccdc8b2775ad034765bad505192f05d1f55d2bc39d0cbe10100000007ab5165ac6a5163ffffffff034949150100000000026a6a92c9f6000000000008ab6553ab6aab635200e697040000000007636a5353525365237ae7d2", "52000063", 0, -880046683, "c76146f68f43037289aaeb2bacf47408cddc0fb326b350eb4f5ef6f0f8564793"],
+ ["eabc0aa701fe489c0e4e6222d72b52f083166b49d63ad1410fb98caed027b6a71c02ab830c03000000075253ab63530065ffffffff01a5dc0b05000000000253533e820177", "", 0, 954499283, "1d849b92eedb9bf26bd4ced52ce9cb0595164295b0526842ab1096001fcd31b1"],
+ ["d48d55d304aad0139783b44789a771539d052db565379f668def5084daba0dfd348f7dcf6b00000000006826f59e5ffba0dd0ccbac89c1e2d69a346531d7f995dea2ca6d7e6d9225d81aec257c6003000000096a655200ac656552acffffffffa188ffbd5365cae844c8e0dea6213c4d1b2407274ae287b769ab0bf293e049eb0300000005ac6a6aab51ad1c407c5b116ca8f65ed496b476183f85f072c5f8a0193a4273e2015b1cc288bf03e9e2030000000252abffffffff04076f44040000000006655353abab53be6500050000000003ac65ac3c15040500000000095100ab536353516a52ed3aba04000000000900ac53ab53636aabac00000000", "5253526563acac", 2, -1506108646, "bbee17c8582514744bab5df50012c94b0db4aff5984d2e13a8d09421674404e2"],
+ ["9746f45b039bfe723258fdb6be77eb85917af808211eb9d43b15475ee0b01253d33fc3bfc502000000065163006a655312b12562dc9c54e11299210266428632a7d0ee31d04dfc7375dcad2da6e9c11947ced0e000000000009074095a5ac4df057554566dd04740c61490e1d3826000ad9d8f777a93373c8dddc4918a00000000025351ffffffff01287564030000000004636a00ab00000000", "52", 2, -1380411075, "84af1623366c4db68d81f452b86346832344734492b9c23fbb89015e516c60b2"],
+ ["8731b64903d735ba16da64af537eaf487b57d73977f390baac57c7b567cb2770dfa2ef65870100000001635aedd990c42645482340eacb0bfa4a0a9e888057389c728b5b6a8691cdeb1a6a67b45e140200000008ac53526a52516551ffffffff45c4f567c47b8d999916fd49642cbc5d10d43c304b99e32d044d35091679cb860100000003006a51ffffffff0176d6c200000000000000000000", "ab6a65ab53", 2, -1221546710, "ccfdba36d9445f4451fb7cbf0752cc89c23d4fc6fff0f3930d20e116f9db0b95"],
+ ["f5cfc52f016209ab1385e890c2865a74e93076595d1ca77cbe8fbf2022a2f2061a90fb0f3e010000000253acffffffff027de73f0200000000085252ac510052acac49cd6a020000000000e6c2cb56", "516552535300ab63", 0, -1195302704, "5532717402a2da01a1da912d824964024185ca7e8d4ad1748659dc393a14182b"],
+ ["df0a32ae01c4672fd1abd0b2623aae0a1a8256028df57e532f9a472d1a9ceb194267b6ee190200000009536a6a51516a525251b545f9e803469a2302000000000465526500810631040000000000441f5b050000000006530051006aaceb183c76", "536a635252ac6a", 0, 1601138113, "9a0435996cc58bdba09643927fe48c1fc908d491a050abbef8daec87f323c58f"],
+ ["d102d10c028b9c721abb259fe70bc68962f6cae384dabd77477c59cbeb1fb26266e091ba3e0100000002516affffffffe8d7305a74f43e30c772109849f4cd6fb867c7216e6d92e27605e69a0818899700000000026a65ecf82d58027db4620500000000026552c28ed3010000000001ab00000000", "0051ab515365", 1, -131815460, "1d1757a782cb5860302128bcbe9398243124a2f82d671a113f74f8e582c7a182"],
+ ["cef930ed01c36fcb1d62ceef931bef57098f27a77a4299904cc0cbb44504802d535fb11557010000000153ffffffff02c8657403000000000863ac655253520063d593380400000000046aab536a00000000", "656a0051ab6365ab53", 0, -351313308, "e69dba3efb5c02af2ab1087d0a990678784671f4744d01ca097d71aec14dd8e9"],
+ ["b1c0b71804dff30812b92eefb533ac77c4b9fdb9ab2f77120a76128d7da43ad70c20bbfb990200000002536392693e6001bc59411aebf15a3dc62a6566ec71a302141b0c730a3ecc8de5d76538b30f55010000000665535252ac514b740c6271fb9fe69fdf82bf98b459a7faa8a3b62f3af34943ad55df4881e0d93d3ce0ac0200000000c4158866eb9fb73da252102d1e64a3ce611b52e873533be43e6883137d0aaa0f63966f060000000001abffffffff04a605b604000000000851006a656a630052f49a0300000000000252515a94e1050000000009abac65ab0052abab00fd8dd002000000000651535163526a2566852d", "ac5363", 0, -1718831517, "b0dc030661783dd9939e4bf1a6dfcba809da2017e1b315a6312e5942d714cf05"],
+ ["6a270ee404ebc8d137cfd4bb6b92aa3702213a3139a579c1fc6f56fbc7edd9574ef17b13f30100000009ab00ab656565ababacffffffffaa65b1ab6c6d87260d9e27a472edceb7dd212483e72d90f08857abf1dbfd46d10100000000fffffffff93c4c9c84c4dbbe8a912b99a2830cfe3401aebc919041de063d660e585fc9f002000000096aabacab52ac6a53acfa6dcef3f28355a8d98eee53839455445eeee83eecd2c854e784efa53cee699dbfecaebd0100000003ab6a51ffffffff04f7d71b050000000009ac6a536aac6a6365513c37650500000000065265abab6a53fa742002000000000039ed82030000000009516aac635165ab51ab2fdabd17", "ab535252526563", 1, -1326210506, "1dec0d5eb921bf5b2df39c8576e19c38d0c17254a4a0b78ac4b5422bcc426258"],
+ ["3657e4260304ccdc19936e47bdf058d36167ee3d4eb145c52b224eff04c9eb5d1b4e434dfc0000000001ab58aefe57707c66328d3cceef2e6f56ab6b7465e587410c5f73555a513ace2b232793a74400000000036a006522e69d3a785b61ad41a635d59b3a06b2780a92173f85f8ed428491d0aaa436619baa9c4501000000046351abab2609629902eb7793050000000000a1b967040000000003525353a34d6192", "516a", 0, -1761874713, "0a2ff41f6d155d8d0e37cd9438f3b270df9f9214cda8e95c76d5a239ca189df2"],
+ ["a0eb6dc402994e493c787b45d1f946d267b09c596c5edde043e620ce3d59e95b2b5b93d43002000000096a5252526aac63ab6555694287a279e29ee491c177a801cd685b8744a2eab83824255a3bcd08fc0e3ea13fb8820000000009abab6365ab52ab0063ffffffff029e424a040000000008acab53ab516a636a23830f0400000000016adf49c1f9", "ac0065ac6500005252", 1, 669294500, "e05e3d383631a7ed1b78210c13c2eb26564e5577db7ddfcea2583c7c014091d4"],
+ ["6e67c0d3027701ef71082204c85ed63c700ef1400c65efb62ce3580d187fb348376a23e9710200000001655b91369d3155ba916a0bc6fe4f5d94cad461d899bb8aaac3699a755838bfc229d6828920010000000765536353526a52ffffffff04c0c792000000000005650052535372f79e000000000001527fc0ee010000000005ac5300ab65d1b3e902000000000251aba942b278", "6a5151", 0, 1741407676, "e657e2c8ec4ebc769ddd3198a83267b47d4f2a419fc737e813812acefad92ff7"],
+ ["8f53639901f1d643e01fc631f632b7a16e831d846a0184cdcda289b8fa7767f0c292eb221a00000000046a53abacffffffff037a2daa01000000000553ac6a6a51eac349020000000005ac526552638421b3040000000007006a005100ac63048a1492", "ac65", 0, 1033685559, "da86c260d42a692358f46893d6f91563985d86eeb9ea9e21cd38c2d8ffcfcc4d"],
+ ["491f99cb01bdfba1aa235e5538dac081fae9ce55f9622de483afe7e65105c2b0db75d360d200000000045251636340b60f0f041421330300000000096351ac000051636553ce2822040000000005516a00ac5180c8e40300000000025100caa8570400000000020000cfdc8da6", "6a5100516aab655365", 0, -953727341, "397c68803b7ce953666830b0221a5e2bcf897aa2ded8e36a6b76c497dcb1a2e1"],
+ ["b3cad3a7041c2c17d90a2cd994f6c37307753fa3635e9ef05ab8b1ff121ca11239a0902e700300000009ab635300006aac5163ffffffffcec91722c7468156dce4664f3c783afef147f0e6f80739c83b5f09d5a09a57040200000004516a6552ffffffff969d1c6daf8ef53a70b7cdf1b4102fb3240055a8eaeaed2489617cd84cfd56cf020000000352ab53ffffffff46598b6579494a77b593681c33422a99559b9993d77ca2fa97833508b0c169f80200000009655300655365516351ffffffff04d7ddf800000000000853536a65ac6351ab09f3420300000000056aab65abac33589d04000000000952656a65655151acac944d6f0400000000006a8004ba", "005165", 1, 1035865506, "fe1dc9e8554deecf8f50c417c670b839cc9d650722ebaaf36572418756075d58"],
+ ["e1cfd73b0125add9e9d699f5a45dca458355af175a7bd4486ebef28f1928d87864384d02df02000000036a0051ffffffff0357df030100000000036a5365777e2d04000000000763ab6a00005265f434a601000000000351655100000000", "ab53ab", 0, -1936500914, "950f4b4f72ccdf8a6a0f381265d6c8842fdb7e8b3df3e9742905f643b2432b69"],
+ ["cf781855040a755f5ba85eef93837236b34a5d3daeb2dbbdcf58bb811828d806ed05754ab8010000000351ac53ffffffffda1e264727cf55c67f06ebcc56dfe7fa12ac2a994fecd0180ce09ee15c480f7d00000000096351516a51acac00ab53dd49ff9f334befd6d6f87f1a832cddfd826a90b78fd8cf19a52cb8287788af94e939d6020000000700525251ac526310d54a7e8900ed633f0f6f0841145aae7ee0cbbb1e2a0cae724ee4558dbabfdc58ba6855010000000552536a53abfd1b101102c51f910500000000096300656a525252656a300bee010000000009ac52005263635151abe19235c9", "53005365", 2, 1422854188, "d5981bd4467817c1330da72ddb8760d6c2556cd809264b2d85e6d274609fc3a3"],
+ ["fea256ce01272d125e577c0a09570a71366898280dda279b021000db1325f27edda41a53460100000002ab53c752c21c013c2b3a01000000000000000000", "65", 0, 1145543262, "076b9f844f6ae429de228a2c337c704df1652c292b6c6494882190638dad9efd"]
+]
diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json
new file mode 100644
index 0000000000..d22175d660
--- /dev/null
+++ b/src/test/data/tx_invalid.json
@@ -0,0 +1,392 @@
+[
+["The following are deserialized transactions which are invalid."],
+["They are in the form"],
+["[[[prevout hash, prevout index, prevout scriptPubKey, amount?], [input 2], ...],"],
+["serializedTransaction, verifyFlags]"],
+["Objects that are only a single string (like this one) are ignored"],
+
+["0e1b5688cf179cd9f7cbda1fac0090f6e684bbf8cd946660120197c3f3681809 but with extra junk appended to the end of the scriptPubKey"],
+[[["6ca7ec7b1847f6bdbd737176050e6a08d66ccd55bb94ad24f4018024107a5827", 0, "0x41 0x043b640e983c9690a14c039a2037ecc3467b27a0dcd58f19d76c7bc118d09fec45adc5370a1c5bf8067ca9f5557a4cf885fdb0fe0dcc9c3a7137226106fbc779a5 CHECKSIG VERIFY 1"]],
+"010000000127587a10248001f424ad94bb55cd6cd6086a0e05767173bdbdf647187beca76c000000004948304502201b822ad10d6adc1a341ae8835be3f70a25201bbff31f59cbb9c5353a5f0eca18022100ea7b2f7074e9aa9cf70aa8d0ffee13e6b45dddabf1ab961bda378bcdb778fa4701ffffffff0100f2052a010000001976a914fc50c5907d86fed474ba5ce8b12a66e0a4c139d888ac00000000", "P2SH"],
+
+["This is the nearly-standard transaction with CHECKSIGVERIFY 1 instead of CHECKSIG from tx_valid.json"],
+["but with the signature duplicated in the scriptPubKey with a non-standard pushdata prefix"],
+["See FindAndDelete, which will only remove if it uses the same pushdata prefix as is standard"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x4c 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]],
+"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", "P2SH"],
+
+["Same as above, but with the sig in the scriptSig also pushed with the same non-standard OP_PUSHDATA"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x4c 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]],
+"01000000010001000000000000000000000000000000000000000000000000000000000000000000006b4c473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", "P2SH"],
+
+["This is the nearly-standard transaction with CHECKSIGVERIFY 1 instead of CHECKSIG from tx_valid.json"],
+["but with the signature duplicated in the scriptPubKey with a different hashtype suffix"],
+["See FindAndDelete, which will only remove if the signature, including the hash type, matches"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a81"]],
+"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", "P2SH"],
+
+["An invalid P2SH Transaction"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", "P2SH"],
+
+["Tests for CheckTransaction()"],
+["No outputs"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x05ab9e14d983742513f0f451e105ffb4198d1dd4 EQUAL"]],
+"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022100f16703104aab4e4088317c862daec83440242411b039d14280e03dd33b487ab802201318a7be236672c5c56083eb7a5a195bc57a40af7923ff8545016cd3b571e2a601232103c40e5d339df3f30bf753e7e04450ae4ef76c9e45587d1d993bdc4cd06f0651c7acffffffff0000000000", "P2SH"],
+
+["Negative output"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xae609aca8061d77c5e111f6bb62501a6bbe2bfdb EQUAL"]],
+"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d4830450220063222cbb128731fc09de0d7323746539166544d6c1df84d867ccea84bcc8903022100bf568e8552844de664cd41648a031554327aa8844af34b4f27397c65b92c04de0123210243ec37dee0e2e053a9c976f43147e79bc7d9dc606ea51010af1ac80db6b069e1acffffffff01ffffffffffffffff015100000000", "P2SH"],
+
+["MAX_MONEY + 1 output"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x32afac281462b822adbec5094b8d4d337dd5bd6a EQUAL"]],
+"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010140075af0750700015100000000", "P2SH"],
+
+["MAX_MONEY output + 1 output"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xb558cbf4930954aa6a344363a15668d7477ae716 EQUAL"]],
+"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510001000000000000015100000000", "P2SH"],
+
+["Duplicate inputs"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x236d0639db62b0773fd8ac34dc85ae19e9aba80a EQUAL"]],
+"01000000020001000000000000000000000000000000000000000000000000000000000000000000006c47304402204bb1197053d0d7799bf1b30cd503c44b58d6240cccbdc85b6fe76d087980208f02204beeed78200178ffc6c74237bb74b3f276bbb4098b5605d814304fe128bf1431012321039e8815e15952a7c3fada1905f8cf55419837133bd7756c0ef14fc8dfe50c0deaacffffffff0001000000000000000000000000000000000000000000000000000000000000000000006c47304402202306489afef52a6f62e90bf750bbcdf40c06f5c6b138286e6b6b86176bb9341802200dba98486ea68380f47ebb19a7df173b99e6bc9c681d6ccf3bde31465d1f16b3012321039e8815e15952a7c3fada1905f8cf55419837133bd7756c0ef14fc8dfe50c0deaacffffffff010000000000000000015100000000", "P2SH"],
+
+["Coinbase of size 1"],
+["Note the input is just required to make the tester happy"],
+[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]],
+"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0151ffffffff010000000000000000015100000000", "P2SH"],
+
+["Coinbase of size 101"],
+["Note the input is just required to make the tester happy"],
+[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]],
+"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff655151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151ffffffff010000000000000000015100000000", "P2SH"],
+
+["Null txin, but without being a coinbase (because there are two inputs)"],
+[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"],
+ ["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]],
+"01000000020000000000000000000000000000000000000000000000000000000000000000ffffffff00ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff010000000000000000015100000000", "P2SH"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"],
+ ["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]],
+"010000000200010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0000000000000000000000000000000000000000000000000000000000000000ffffffff00ffffffff010000000000000000015100000000", "P2SH"],
+
+["Same as the transactions in valid with one input SIGHASH_ALL and one SIGHASH_ANYONECANPAY, but we set the _ANYONECANPAY sequence number, invalidating the SIGHASH_ALL signature"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"],
+ ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]],
+ "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df10101000000000200000000000000000000000000000000000000000000000000000000000000000000484730440220201dc2d030e380e8f9cfb41b442d930fa5a685bb2c8db5906671f865507d0670022018d9e7a8d4c8d86a73c2a724ee38ef983ec249827e0e464841735955c707ece98101000000010100000000000000015100000000", "P2SH"],
+
+["CHECKMULTISIG with incorrect signature order"],
+["Note the input is just required to make the tester happy"],
+[[["b3da01dd4aae683c7aee4d5d8b52a540a508e1115f77cd7fa9a291243f501223", 0, "HASH160 0x14 0xb1ce99298d5f07364b57b1e5c9cc00be0b04a954 EQUAL"]],
+"01000000012312503f2491a2a97fcd775f11e108a540a5528b5d4dee7a3c68ae4add01dab300000000fdfe000048304502207aacee820e08b0b174e248abd8d7a34ed63b5da3abedb99934df9fddd65c05c4022100dfe87896ab5ee3df476c2655f9fbe5bd089dccbef3e4ea05b5d121169fe7f5f401483045022100f6649b0eddfdfd4ad55426663385090d51ee86c3481bdc6b0c18ea6c0ece2c0b0220561c315b07cffa6f7dd9df96dbae9200c2dee09bf93cc35ca05e6cdf613340aa014c695221031d11db38972b712a9fe1fc023577c7ae3ddb4a3004187d41c45121eecfdbb5b7210207ec36911b6ad2382860d32989c7b8728e9489d7bbc94a6b5509ef0029be128821024ea9fac06f666a4adc3fc1357b7bec1fd0bdece2b9d08579226a8ebde53058e453aeffffffff0180380100000000001976a914c9b99cddf847d10685a4fabaa0baf505f7c3dfab88ac00000000", "P2SH"],
+
+
+["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"],
+["It is an OP_CHECKMULTISIG with the dummy value missing"],
+[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]],
+"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004847304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"],
+
+
+["CHECKMULTISIG SCRIPT_VERIFY_NULLDUMMY tests:"],
+
+["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"],
+["It is an OP_CHECKMULTISIG with the dummy value set to something other than an empty string"],
+[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]],
+"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004a010047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"],
+
+["As above, but using an OP_1"],
+[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]],
+"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000495147304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"],
+
+["As above, but using an OP_1NEGATE"],
+[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]],
+"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000494f47304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"],
+
+["As above, but with the dummy byte missing"],
+[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]],
+"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004847304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"],
+
+
+["Empty stack when we try to run CHECKSIG"],
+[[["ad503f72c18df5801ee64d76090afe4c607fb2b822e9b7b63c5826c50e22fc3b", 0, "0x21 0x027c3a97665bf283a102a587a62a30a0c102d4d3b141015e2cae6f64e2543113e5 CHECKSIG NOT"]],
+"01000000013bfc220ec526583cb6b7e922b8b27f604cfe0a09764de61e80f58dc1723f50ad0000000000ffffffff0101000000000000002321027c3a97665bf283a102a587a62a30a0c102d4d3b141015e2cae6f64e2543113e5ac00000000", "P2SH"],
+
+
+["Inverted versions of tx_valid CODESEPARATOR IF block tests"],
+
+["CODESEPARATOR in an unexecuted IF block does not change what is hashed"],
+[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]],
+"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a48304502207a6974a77c591fa13dff60cabbb85a0de9e025c09c65a4b2285e47ce8e22f761022100f0efaac9ff8ac36b10721e0aae1fb975c90500b50c56e8a0cc52b0403f0425dd0151ffffffff010000000000000000016a00000000", "P2SH"],
+
+["As above, with the IF block executed"],
+[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]],
+"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a483045022100fa4a74ba9fd59c59f46c3960cf90cbe0d2b743c471d24a3d5d6db6002af5eebb02204d70ec490fd0f7055a7c45f86514336e3a7f03503dacecabb247fc23f15c83510100ffffffff010000000000000000016a00000000", "P2SH"],
+
+["CHECKLOCKTIMEVERIFY tests"],
+
+["By-height locks, with argument just beyond tx nLockTime"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1 CHECKLOCKTIMEVERIFY 1"]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 CHECKLOCKTIMEVERIFY 1"]],
+"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000fe64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
+
+["By-time locks, with argument just beyond tx nLockTime (but within numerical boundaries)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000001 CHECKLOCKTIMEVERIFY 1"]],
+"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKLOCKTIMEVERIFY 1"]],
+"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000feffffff", "P2SH,CHECKLOCKTIMEVERIFY"],
+
+["Argument missing"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "CHECKLOCKTIMEVERIFY 1"]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000001b1010000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
+
+["Argument negative with by-blockheight nLockTime=0"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 CHECKLOCKTIMEVERIFY 1"]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
+
+["Argument negative with by-blocktime nLockTime=500,000,000"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 CHECKLOCKTIMEVERIFY 1"]],
+"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000004005194b1010000000100000000000000000002000000", "P2SH,CHECKLOCKTIMEVERIFY"],
+
+["Input locked"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKLOCKTIMEVERIFY 1"]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0"]],
+"01000000010001000000000000000000000000000000000000000000000000000000000000000000000251b1ffffffff0100000000000000000002000000", "P2SH,CHECKLOCKTIMEVERIFY"],
+
+["Another input being unlocked isn't sufficient; the CHECKLOCKTIMEVERIFY-using input must be unlocked"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKLOCKTIMEVERIFY 1"] ,
+ ["0000000000000000000000000000000000000000000000000000000000000200", 1, "1"]],
+"010000000200010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00020000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
+
+["Argument/tx height/time mismatch, both versions"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKLOCKTIMEVERIFY 1"]],
+"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0"]],
+"01000000010001000000000000000000000000000000000000000000000000000000000000000000000251b100000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 CHECKLOCKTIMEVERIFY 1"]],
+"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 CHECKLOCKTIMEVERIFY 1"]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 CHECKLOCKTIMEVERIFY 1"]],
+"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ff64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
+
+["Argument 2^32 with nLockTime=2^32-1"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967296 CHECKLOCKTIMEVERIFY 1"]],
+"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffffff", "P2SH,CHECKLOCKTIMEVERIFY"],
+
+["Same, but with nLockTime=2^31-1"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKLOCKTIMEVERIFY 1"]],
+"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffff7f", "P2SH,CHECKLOCKTIMEVERIFY"],
+
+["6 byte non-minimally-encoded arguments are invalid even if their contents are valid"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x06 0x000000000000 CHECKLOCKTIMEVERIFY 1"]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
+
+["Failure due to failing CHECKLOCKTIMEVERIFY in scriptSig"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]],
+"01000000010001000000000000000000000000000000000000000000000000000000000000000000000251b1000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
+
+["Failure due to failing CHECKLOCKTIMEVERIFY in redeemScript"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xc5b93064159b3b2d6ab506a41b1f50463771b988 EQUAL"]],
+"0100000001000100000000000000000000000000000000000000000000000000000000000000000000030251b1000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
+
+["A transaction with a non-standard DER signature."],
+[[["b1dbc81696c8a9c0fccd0693ab66d7c368dbc38c0def4e800685560ddd1b2132", 0, "DUP HASH160 0x14 0x4b3bd7eba3bc0284fd3007be7f3be275e94f5826 EQUALVERIFY CHECKSIG"]],
+"010000000132211bdd0d568506804eef0d8cc3db68c3d766ab9306cdfcc0a9c89616c8dbb1000000006c493045022100c7bb0faea0522e74ff220c20c022d2cb6033f8d167fb89e75a50e237a35fd6d202203064713491b1f8ad5f79e623d0219ad32510bfaa1009ab30cbee77b59317d6e30001210237af13eb2d84e4545af287b919c2282019c9691cc509e78e196a9d8274ed1be0ffffffff0100000000000000001976a914f1b3ed2eda9a2ebe5a9374f692877cdf87c0f95b88ac00000000", "P2SH,DERSIG"],
+
+["CHECKSEQUENCEVERIFY tests"],
+
+["By-height locks, with argument just beyond txin.nSequence"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000feff40000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["By-time locks, with argument just beyond txin.nSequence (but within numerical boundaries)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194305 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000feff40000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Argument missing"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Argument negative with by-blockheight txin.nSequence=0"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Argument negative with by-blocktime txin.nSequence=CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Argument/tx height/time mismatch, both versions"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["6 byte non-minimally-encoded arguments are invalid even if their contents are valid"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x06 0x000000000000 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff00000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Failure due to failing CHECKSEQUENCEVERIFY in scriptSig"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]],
+"02000000010001000000000000000000000000000000000000000000000000000000000000000000000251b2000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Failure due to failing CHECKSEQUENCEVERIFY in redeemScript"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7c17aff532f22beb54069942f9bf567a66133eaf EQUAL"]],
+"0200000001000100000000000000000000000000000000000000000000000000000000000000000000030251b2000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Failure due to insufficient tx.nVersion (<2)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKSEQUENCEVERIFY 1"]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 CHECKSEQUENCEVERIFY 1"]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Unknown witness program version (with DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x60 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b00000000000001510002483045022100a3cec69b52cba2d2de623ffffffffff1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"],
+
+["Unknown length for witness program v0"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x15 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3fff", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff04b60300000000000001519e070000000000000151860b0000000000000100960000000000000001510002473044022022fceb54f62f8feea77faac7083c3b56c4676a78f93745adc8a35800bc36adfa022026927df9abcf0a8777829bcfcce3ff0a385fa54c3f9df577405e3ef24ee56479022103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash Single|AnyoneCanPay (same index output value changed)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e80300000000000001516c070000000000000151b80b0000000000000151000248304502210092f4777a0f17bf5aeb8ae768dec5f2c14feabf9d1fe2c89c78dfed0f13fdb86902206da90a86042e252bcd1e80a168c719e4a1ddcc3cebea24b9812c5453c79107e9832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash None|AnyoneCanPay (input sequence changed)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff000100000000000000000000000000000000000000000000000000000000000001000000000100000000010000000000000000000000000000000000000000000000000000000000000200000000ffffffff00000248304502210091b32274295c2a3fa02f5bce92fb2789e3fc6ea947fbe1a76e52ea3f4ef2381a022079ad72aefa3837a2e0c033a8652a59731da05fa4a813f4fc48e87c075037256b822103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash All|AnyoneCanPay (third output value changed)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151540b00000000000001510002483045022100a3cec69b52cba2d2de623eeef89e0ba1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with a push of 521 bytes"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x20 0x33198a9bfef674ebddb9ffaa52928017b8472791e54c609cb95f278ac6b1e349", 1000]],
+"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff010000000000000000015102fd0902000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002755100000000", "P2SH,WITNESS"],
+
+["Witness with unknown version which push false on the stack should be invalid (even without DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x02 0x0000", 2000]],
+"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff010000000000000000015101010100000000", "P2SH,WITNESS"],
+
+["Witness program should leave clean stack"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x20 0x2f04a3aa051f1f60d695f6c44c0c3d383973dfd446ace8962664a76bb10e31a8", 2000]],
+"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01000000000000000001510102515100000000", "P2SH,WITNESS"],
+
+["Witness v0 with a push of 2 bytes"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x02 0x0001", 2000]],
+"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff010000000000000000015101040002000100000000", "P2SH,WITNESS"],
+
+["Unknown witness version with non empty scriptSig"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x02 0x0001", 2000]],
+"01000000010001000000000000000000000000000000000000000000000000000000000000000000000151ffffffff010000000000000000015100000000", "P2SH,WITNESS"],
+
+["Non witness Single|AnyoneCanPay hash input's position (permutation)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x03596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71 CHECKSIG", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x21 0x03596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71 CHECKSIG", 1001]],
+"010000000200010000000000000000000000000000000000000000000000000000000000000100000049483045022100acb96cfdbda6dc94b489fd06f2d720983b5f350e31ba906cdbd800773e80b21c02200d74ea5bdf114212b4bbe9ed82c36d2e369e302dff57cb60d01c428f0bd3daab83ffffffff0001000000000000000000000000000000000000000000000000000000000000000000004847304402202a0b4b1294d70540235ae033d78e64b4897ec859c7b6f1b2b1d8a02e1d46006702201445e756d2254b0f1dfda9ab8e1e1bc26df9668077403204f32d16a49a36eb6983ffffffff02e9030000000000000151e803000000000000015100000000", "P2SH,WITNESS"],
+
+["P2WSH with a redeem representing a witness scriptPubKey should fail"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x20 0x34b6c399093e06cf9f0f7f660a1abcfe78fcf7b576f43993208edd9518a0ae9b", 1000]],
+"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0001045102010100000000", "P2SH,WITNESS"],
+
+["33 bytes push should be considered a witness scriptPubKey"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x21 0xff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3dbff", 1000]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"],
+
+["FindAndDelete tests"],
+["This is a test of FindAndDelete. The first tx is a spend of normal scriptPubKey and the second tx is a spend of bare P2WSH."],
+["The redeemScript/witnessScript is CHECKSIGVERIFY <0x30450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e01>."],
+["The signature is <0x30450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e01> <pubkey>,"],
+["where the pubkey is obtained through key recovery with sig and the wrong sighash."],
+["This is to show that FindAndDelete is applied only to non-segwit scripts"],
+["To show that the tests are 'correctly wrong', they should pass by modifying OP_CHECKSIG under interpreter.cpp"],
+["by replacing (sigversion == SigVersion::BASE) with (sigversion != SigVersion::BASE)"],
+["Non-segwit: wrong sighash (without FindAndDelete) = 1ba1fe3bc90c5d1265460e684ce6774e324f0fabdf67619eda729e64e8b6bc08"],
+[[["f18783ace138abac5d3a7a5cf08e88fe6912f267ef936452e0c27d090621c169", 7000, "HASH160 0x14 0x0c746489e2d83cdbb5b90b432773342ba809c134 EQUAL", 200000]],
+"010000000169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1ac8387f1581b0000b64830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e012103b12a1ec8428fc74166926318c15e17408fea82dbb157575e16a8c365f546248f4aad4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e01ffffffff0101000000000000000000000000", "P2SH,WITNESS"],
+["BIP143: wrong sighash (with FindAndDelete) = 71c9cd9b2869b9c70b01b1f0360c148f42dee72297db312638df136f43311f23"],
+[[["f18783ace138abac5d3a7a5cf08e88fe6912f267ef936452e0c27d090621c169", 7500, "0x00 0x20 0x9e1be07558ea5cc8e02ed1d80c0911048afad949affa36d5c3951e3159dbea19", 200000]],
+"0100000000010169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1ac8387f14c1d000000ffffffff01010000000000000000034830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e012102a9d7ed6e161f0e255c10bbfcca0128a9e2035c2c8da58899c54d22d3a31afdef4aad4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0100000000", "P2SH,WITNESS"],
+["This is multisig version of the FindAndDelete tests"],
+["Script is 2 CHECKMULTISIGVERIFY <sig1> <sig2> DROP"],
+["52af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c0395960175"],
+["Signature is 0 <sig1> <sig2> 2 <key1> <key2>"],
+["Should pass by replacing (sigversion == SigVersion::BASE) with (sigversion != SigVersion::BASE) under OP_CHECKMULTISIG"],
+["Non-segwit: wrong sighash (without FindAndDelete) = 4bc6a53e8e16ef508c19e38bba08831daba85228b0211f323d4cb0999cf2a5e8"],
+[[["9628667ad48219a169b41b020800162287d2c0f713c04157e95c484a8dcb7592", 7000, "HASH160 0x14 0x5748407f5ca5cdca53ba30b79040260770c9ee1b EQUAL", 200000]],
+"01000000019275cb8d4a485ce95741c013f7c0d28722160008021bb469a11982d47a662896581b0000fd6f01004830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c039596015221023fd5dd42b44769c5653cbc5947ff30ab8871f240ad0c0e7432aefe84b5b4ff3421039d52178dbde360b83f19cf348deb04fa8360e1bf5634577be8e50fafc2b0e4ef4c9552af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c0395960175ffffffff0101000000000000000000000000", "P2SH,WITNESS"],
+["BIP143: wrong sighash (with FindAndDelete) = 17c50ec2181ecdfdc85ca081174b248199ba81fff730794d4f69b8ec031f2dce"],
+[[["9628667ad48219a169b41b020800162287d2c0f713c04157e95c484a8dcb7592", 7500, "0x00 0x20 0x9b66c15b4e0b4eb49fa877982cafded24859fe5b0e2dbfbe4f0df1de7743fd52", 200000]],
+"010000000001019275cb8d4a485ce95741c013f7c0d28722160008021bb469a11982d47a6628964c1d000000ffffffff0101000000000000000007004830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c03959601010221023cb6055f4b57a1580c5a753e19610cafaedf7e0ff377731c77837fd666eae1712102c1b1db303ac232ffa8e5e7cc2cf5f96c6e40d3e6914061204c0541cb2043a0969552af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c039596017500000000", "P2SH,WITNESS"],
+
+["SCRIPT_VERIFY_CONST_SCRIPTCODE tests"],
+["All transactions are copied from OP_CODESEPARATOR tests in tx_valid.json"],
+
+[[["bc7fd132fcf817918334822ee6d9bd95c889099c96e07ca2c1eb2cc70db63224", 0, "CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIG"]],
+ "01000000012432b60dc72cebc1a27ce0969c0989c895bdd9e62e8234839117f8fc32d17fbc000000004a493046022100a576b52051962c25e642c0fd3d77ee6c92487048e5d90818bcf5b51abaccd7900221008204f8fb121be4ec3b24483b1f92d89b1b0548513a134e345c5442e86e8617a501ffffffff010000000000000000016a00000000", "P2SH,CONST_SCRIPTCODE"],
+[[["83e194f90b6ef21fa2e3a365b63794fb5daa844bdc9b25de30899fcfe7b01047", 0, "CODESEPARATOR CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIG"]],
+ "01000000014710b0e7cf9f8930de259bdc4b84aa5dfb9437b665a3e3a21ff26e0bf994e183000000004a493046022100a166121a61b4eeb19d8f922b978ff6ab58ead8a5a5552bf9be73dc9c156873ea02210092ad9bc43ee647da4f6652c320800debcf08ec20a094a0aaf085f63ecb37a17201ffffffff010000000000000000016a00000000", "P2SH,CONST_SCRIPTCODE"],
+
+[[["326882a7f22b5191f1a0cc9962ca4b878cd969cf3b3a70887aece4d801a0ba5e", 0, "0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CODESEPARATOR CHECKSIG"]],
+ "01000000015ebaa001d8e4ec7a88703a3bcf69d98c874bca6299cca0f191512bf2a7826832000000004948304502203bf754d1c6732fbf87c5dcd81258aefd30f2060d7bd8ac4a5696f7927091dad1022100f5bcb726c4cf5ed0ed34cc13dadeedf628ae1045b7cb34421bc60b89f4cecae701ffffffff010000000000000000016a00000000", "P2SH,CONST_SCRIPTCODE"],
+
+[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIGVERIFY CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIGVERIFY CODESEPARATOR 1"]],
+ "010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a900000000924830450221009c0a27f886a1d8cb87f6f595fbc3163d28f7a81ec3c4b252ee7f3ac77fd13ffa02203caa8dfa09713c8c4d7ef575c75ed97812072405d932bd11e6a1593a98b679370148304502201e3861ef39a526406bad1e20ecad06be7375ad40ddb582c9be42d26c3a0d7b240221009d0a3985e96522e59635d19cc4448547477396ce0ef17a58e7d74c3ef464292301ffffffff010000000000000000016a00000000", "P2SH,CONST_SCRIPTCODE"],
+
+["CODESEPARATOR in an unexecuted IF block is still invalid"],
+[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]],
+ "010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a48304502207a6974a77c591fa13dff60cabbb85a0de9e025c09c65a4b2285e47ce8e22f761022100f0efaac9ff8ac36b10721e0aae1fb975c90500b50c56e8a0cc52b0403f0425dd0100ffffffff010000000000000000016a00000000", "P2SH,CONST_SCRIPTCODE"],
+
+["CODESEPARATOR in an executed IF block is invalid"],
+[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]],
+ "010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a483045022100fa4a74ba9fd59c59f46c3960cf90cbe0d2b743c471d24a3d5d6db6002af5eebb02204d70ec490fd0f7055a7c45f86514336e3a7f03503dacecabb247fc23f15c83510151ffffffff010000000000000000016a00000000", "P2SH,CONST_SCRIPTCODE"],
+
+
+["Using CHECKSIG with signatures in scriptSigs will trigger FindAndDelete, which is invalid"],
+[[["ccf7f4053a02e653c36ac75c891b7496d0dc5ce5214f6c913d9cf8f1329ebee0", 0, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]],
+ "0100000001e0be9e32f1f89c3d916c4f21e55cdcd096741b895cc76ac353e6023a05f4f7cc00000000d86149304602210086e5f736a2c3622ebb62bd9d93d8e5d76508b98be922b97160edc3dcca6d8c47022100b23c312ac232a4473f19d2aeb95ab7bdf2b65518911a0d72d50e38b5dd31dc820121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac4730440220508fa761865c8abd81244a168392876ee1d94e8ed83897066b5e2df2400dad24022043f5ee7538e87e9c6aef7ef55133d3e51da7cc522830a9c4d736977a76ef755c0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH,CONST_SCRIPTCODE"],
+
+["OP_CODESEPARATOR in scriptSig is invalid"],
+[[["10c9f0effe83e97f80f067de2b11c6a00c3088a4bce42c5ae761519af9306f3c", 1, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]],
+ "01000000013c6f30f99a5161e75a2ce4bca488300ca0c6112bde67f0807fe983feeff0c91001000000e608646561646265656675ab61493046022100ce18d384221a731c993939015e3d1bcebafb16e8c0b5b5d14097ec8177ae6f28022100bcab227af90bab33c3fe0a9abfee03ba976ee25dc6ce542526e9b2e56e14b7f10121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac493046022100c3b93edcc0fd6250eb32f2dd8a0bba1754b0f6c3be8ed4100ed582f3db73eba2022100bf75b5bd2eff4d6bf2bda2e34a40fcc07d4aa3cf862ceaa77b47b81eff829f9a01ab21038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH,CONST_SCRIPTCODE"],
+
+["Again, FindAndDelete() in scriptSig"],
+[[["6056ebd549003b10cbbd915cea0d82209fe40b8617104be917a26fa92cbe3d6f", 0, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]],
+ "01000000016f3dbe2ca96fa217e94b1017860be49f20820dea5c91bdcb103b0049d5eb566000000000fd1d0147304402203989ac8f9ad36b5d0919d97fa0a7f70c5272abee3b14477dc646288a8b976df5022027d19da84a066af9053ad3d1d7459d171b7e3a80bc6c4ef7a330677a6be548140147304402203989ac8f9ad36b5d0919d97fa0a7f70c5272abee3b14477dc646288a8b976df5022027d19da84a066af9053ad3d1d7459d171b7e3a80bc6c4ef7a330677a6be548140121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac47304402203757e937ba807e4a5da8534c17f9d121176056406a6465054bdd260457515c1a02200f02eccf1bec0f3a0d65df37889143c2e88ab7acec61a7b6f5aa264139141a2b0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH,CONST_SCRIPTCODE"],
+
+[[["5a6b0021a6042a686b6b94abc36b387bef9109847774e8b1e51eb8cc55c53921", 1, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]],
+ "01000000012139c555ccb81ee5b1e87477840991ef7b386bc3ab946b6b682a04a621006b5a01000000fdb40148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f2204148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390175ac4830450220646b72c35beeec51f4d5bc1cbae01863825750d7f490864af354e6ea4f625e9c022100f04b98432df3a9641719dbced53393022e7249fb59db993af1118539830aab870148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a580039017521038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH,CONST_SCRIPTCODE"],
+
+["FindAndDelete() in redeemScript"],
+[[["b5b598de91787439afd5938116654e0b16b7a0d0f82742ba37564219c5afcbf9", 0, "DUP HASH160 0x14 0xf6f365c40f0739b61de827a44751e5e99032ed8f EQUALVERIFY CHECKSIG"],
+ ["ab9805c6d57d7070d9a42c5176e47bb705023e6b67249fb6760880548298e742", 0, "HASH160 0x14 0xd8dacdadb7462ae15cd906f1878706d0da8660e6 EQUAL"]],
+ "0100000002f9cbafc519425637ba4227f8d0a0b7160b4e65168193d5af39747891de98b5b5000000006b4830450221008dd619c563e527c47d9bd53534a770b102e40faa87f61433580e04e271ef2f960220029886434e18122b53d5decd25f1f4acb2480659fea20aabd856987ba3c3907e0121022b78b756e2258af13779c1a1f37ea6800259716ca4b7f0b87610e0bf3ab52a01ffffffff42e7988254800876b69f24676b3e0205b77be476512ca4d970707dd5c60598ab00000000fd260100483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a53034930460221008431bdfa72bc67f9d41fe72e94c88fb8f359ffa30b33c72c121c5a877d922e1002210089ef5fc22dd8bfc6bf9ffdb01a9862d27687d424d1fefbab9e9c7176844a187a014c9052483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c7153aeffffffff01a08601000000000017a914d8dacdadb7462ae15cd906f1878706d0da8660e68700000000", "P2SH,CONST_SCRIPTCODE"],
+
+["FindAndDelete() in bare CHECKMULTISIG"],
+[[["ceafe58e0f6e7d67c0409fbbf673c84c166e3c5d3c24af58f7175b18df3bb3db", 0, "DUP HASH160 0x14 0xf6f365c40f0739b61de827a44751e5e99032ed8f EQUALVERIFY CHECKSIG"],
+ ["ceafe58e0f6e7d67c0409fbbf673c84c166e3c5d3c24af58f7175b18df3bb3db", 1, "2 0x48 0x3045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 3 CHECKMULTISIG"]],
+ "0100000002dbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce000000006b4830450221009627444320dc5ef8d7f68f35010b4c050a6ed0d96b67a84db99fda9c9de58b1e02203e4b4aaa019e012e65d69b487fdf8719df72f488fa91506a80c49a33929f1fd50121022b78b756e2258af13779c1a1f37ea6800259716ca4b7f0b87610e0bf3ab52a01ffffffffdbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce010000009300483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303ffffffff01a0860100000000001976a9149bc0bbdd3024da4d0c38ed1aecf5c68dd1d3fa1288ac00000000", "P2SH,CONST_SCRIPTCODE"],
+
+["Make diffs cleaner by leaving a comment here without comma at the end"]
+]
diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json
new file mode 100644
index 0000000000..4a1c77166d
--- /dev/null
+++ b/src/test/data/tx_valid.json
@@ -0,0 +1,524 @@
+[
+["The following are deserialized transactions which are valid."],
+["They are in the form"],
+["[[[prevout hash, prevout index, prevout scriptPubKey, amount?], [input 2], ...],"],
+["serializedTransaction, verifyFlags]"],
+["Objects that are only a single string (like this one) are ignored"],
+
+["The following is 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"],
+["It is of particular interest because it contains an invalidly-encoded signature which OpenSSL accepts"],
+["See http://r6.ca/blog/20111119T211504Z.html"],
+["It is also the first OP_CHECKMULTISIG transaction in standard form"],
+[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]],
+"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000490047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"],
+
+["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"],
+["It is an OP_CHECKMULTISIG with an arbitrary extra byte stuffed into the signature at pos length - 2"],
+["The dummy byte is fine however, so the NULLDUMMY flag should be happy"],
+[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]],
+"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004a0048304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2bab01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"],
+
+["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"],
+["It is an OP_CHECKMULTISIG with the dummy value set to something other than an empty string"],
+[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]],
+"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004a01ff47304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"],
+
+["As above, but using an OP_1"],
+[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]],
+"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000495147304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"],
+
+["As above, but using an OP_1NEGATE"],
+[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]],
+"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000494f47304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"],
+
+["The following is c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73"],
+["It is of interest because it contains a 0-sequence as well as a signature of SIGHASH type 0 (which is not a real type)"],
+[[["406b2b06bcd34d3c8733e6b79f7a394c8a431fbf4ff5ac705c93f4076bb77602", 0, "DUP HASH160 0x14 0xdc44b1164188067c3a32d4780f5996fa14a4f2d9 EQUALVERIFY CHECKSIG"]],
+"01000000010276b76b07f4935c70acf54fbf1f438a4c397a9fb7e633873c4dd3bc062b6b40000000008c493046022100d23459d03ed7e9511a47d13292d3430a04627de6235b6e51a40f9cd386f2abe3022100e7d25b080f0bb8d8d5f878bba7d54ad2fda650ea8d158a33ee3cbd11768191fd004104b0e2c879e4daf7b9ab68350228c159766676a14f5815084ba166432aab46198d4cca98fa3e9981d0a90b2effc514b76279476550ba3663fdcaff94c38420e9d5000000000100093d00000000001976a9149a7b0f3b80c6baaeedce0a0842553800f832ba1f88ac00000000", "P2SH"],
+
+["A nearly-standard transaction with CHECKSIGVERIFY 1 instead of CHECKSIG"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1"]],
+"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", "P2SH"],
+
+["Same as above, but with the signature duplicated in the scriptPubKey with the proper pushdata prefix"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]],
+"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", "P2SH"],
+
+["The following is f7fdd091fa6d8f5e7a8c2458f5c38faffff2d3f1406b6e4fe2c99dcc0d2d1cbb"],
+["It caught a bug in the workaround for 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63 in an overly simple implementation. In a signature, it contains an ASN1 integer which isn't strict-DER conformant due to being negative, which doesn't make sense in a signature. Before BIP66 activated, it was a valid signature. After it activated, it's not valid any more."],
+[[["b464e85df2a238416f8bdae11d120add610380ea07f4ef19c5f9dfd472f96c3d", 0, "DUP HASH160 0x14 0xbef80ecf3a44500fda1bc92176e442891662aed2 EQUALVERIFY CHECKSIG"],
+["b7978cc96e59a8b13e0865d3f95657561a7f725be952438637475920bac9eb21", 1, "DUP HASH160 0x14 0xbef80ecf3a44500fda1bc92176e442891662aed2 EQUALVERIFY CHECKSIG"]],
+"01000000023d6cf972d4dff9c519eff407ea800361dd0a121de1da8b6f4138a2f25de864b4000000008a4730440220ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e022049cffa1cdc102a0b56e0e04913606c70af702a1149dc3b305ab9439288fee090014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff21ebc9ba20594737864352e95b727f1a565756f9d365083eb1a8596ec98c97b7010000008a4730440220503ff10e9f1e0de731407a4a245531c9ff17676eda461f8ceeb8c06049fa2c810220c008ac34694510298fa60b3f000df01caa244f165b727d4896eb84f81e46bcc4014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff01f0da5200000000001976a914857ccd42dded6df32949d4646dfa10a92458cfaa88ac00000000", "P2SH"],
+
+["The following tests for the presence of a bug in the handling of SIGHASH_SINGLE"],
+["It results in signing the constant 1, instead of something generated based on the transaction,"],
+["when the input doing the signing has an index greater than the maximum output index"],
+[[["0000000000000000000000000000000000000000000000000000000000000200", 0, "1"], ["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0xe52b482f2faa8ecbf0db344f93c84ac908557f33 EQUALVERIFY CHECKSIG"]],
+"01000000020002000000000000000000000000000000000000000000000000000000000000000000000151ffffffff0001000000000000000000000000000000000000000000000000000000000000000000006b483045022100c9cdd08798a28af9d1baf44a6c77bcc7e279f47dc487c8c899911bc48feaffcc0220503c5c50ae3998a733263c5c0f7061b483e2b56c4c41b456e7d2f5a78a74c077032102d5c25adb51b61339d2b05315791e21bbe80ea470a49db0135720983c905aace0ffffffff010000000000000000015100000000", "P2SH"],
+
+["The following tests SIGHASH_SINGLE|SIGHASHANYONECANPAY inputs"],
+[[["437a1002eb125dec0f93f635763e0ae45f28ff8e81d82945753d0107611cd390", 1, "DUP HASH160 0x14 0x383fb81cb0a3fc724b5e08cf8bbd404336d711f6 EQUALVERIFY CHECKSIG"],
+ ["2d48d32ccad087bcda0ac5b31555bd58d1d2568184cbc8e752dd2be2684af03f", 1, "DUP HASH160 0x14 0x275ec2a233e5b23d43fa19e7bf9beb0cb3996117 EQUALVERIFY CHECKSIG"],
+ ["c76168ef1a272a4f176e55e73157ecfce040cfad16a5272f6296eb7089dca846", 1, "DUP HASH160 0x14 0x34fea2c5a75414fd945273ae2d029ce1f28dafcf EQUALVERIFY CHECKSIG"]],
+"010000000390d31c6107013d754529d8818eff285fe40a3e7635f6930fec5d12eb02107a43010000006b483045022100f40815ae3c81a0dd851cc8d376d6fd226c88416671346a9033468cca2cdcc6c202204f764623903e6c4bed1b734b75d82c40f1725e4471a55ad4f51218f86130ac038321033d710ab45bb54ac99618ad23b3c1da661631aa25f23bfe9d22b41876f1d46e4effffffff3ff04a68e22bdd52e7c8cb848156d2d158bd5515b3c50adabc87d0ca2cd3482d010000006a4730440220598d263c107004008e9e26baa1e770be30fd31ee55ded1898f7c00da05a75977022045536bead322ca246779698b9c3df3003377090f41afeca7fb2ce9e328ec4af2832102b738b531def73020bd637f32935924cc88549c8206976226d968edd3a42fc2d7ffffffff46a8dc8970eb96622f27a516adcf40e0fcec5731e7556e174f2a271aef6861c7010000006b483045022100c5b90a777a9fdc90c208dbef7290d1fc1be651f47151ee4ccff646872a454cf90220640cfbc4550446968fbbe9d12528f3adf7d87b31541569c59e790db8a220482583210391332546e22bbe8fe3af54addfad6f8b83d05fa4f5e047593d4c07ae938795beffffffff028036be26000000001976a914ddfb29efad43a667465ac59ff14dc6442a1adfca88ac3d5cba01000000001976a914b64dde7a505a13ca986c40e86e984a8dc81368b688ac00000000", "P2SH"],
+
+["An invalid P2SH Transaction"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", "NONE"],
+
+["A valid P2SH Transaction using the standard transaction type put forth in BIP 16"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x8febbed40483661de6958d957412f82deed8e2f7 EQUAL"]],
+"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100c66c9cdf4c43609586d15424c54707156e316d88b0a1534c9e6b0d4f311406310221009c0fe51dbc9c4ab7cc25d3fdbeccf6679fe6827f08edf2b4a9f16ee3eb0e438a0123210338e8034509af564c62644c07691942e0c056752008a173c89f60ab2a88ac2ebfacffffffff010000000000000000015100000000", "P2SH"],
+
+["Tests for CheckTransaction()"],
+["MAX_MONEY output"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x32afac281462b822adbec5094b8d4d337dd5bd6a EQUAL"]],
+"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010040075af0750700015100000000", "P2SH"],
+
+["MAX_MONEY output + 0 output"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xb558cbf4930954aa6a344363a15668d7477ae716 EQUAL"]],
+"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510000000000000000015100000000", "P2SH"],
+
+["Coinbase of size 2"],
+["Note the input is just required to make the tester happy"],
+[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]],
+"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff025151ffffffff010000000000000000015100000000", "P2SH"],
+
+["Coinbase of size 100"],
+["Note the input is just required to make the tester happy"],
+[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]],
+"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6451515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151ffffffff010000000000000000015100000000", "P2SH"],
+
+["Simple transaction with first input is signed with SIGHASH_ALL, second with SIGHASH_ANYONECANPAY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"],
+ ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]],
+ "010000000200010000000000000000000000000000000000000000000000000000000000000000000049483045022100d180fd2eb9140aeb4210c9204d3f358766eb53842b2a9473db687fa24b12a3cc022079781799cd4f038b85135bbe49ec2b57f306b2bb17101b17f71f000fcab2b6fb01ffffffff0002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", "P2SH"],
+
+["Same as above, but we change the sequence number of the first input to check that SIGHASH_ANYONECANPAY is being followed"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"],
+ ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]],
+ "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df101010000000002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", "P2SH"],
+
+["afd9c17f8913577ec3509520bd6e5d63e9c0fd2a5f70c787993b097ba6ca9fae which has several SIGHASH_SINGLE signatures"],
+[[["63cfa5a09dc540bf63e53713b82d9ea3692ca97cd608c384f2aa88e51a0aac70", 0, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"],
+ ["04e8d0fcf3846c6734477b98f0f3d4badfb78f020ee097a0be5fe347645b817d", 1, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"],
+ ["ee1377aff5d0579909e11782e1d2f5f7b84d26537be7f5516dd4e43373091f3f", 1, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"]],
+ "010000000370ac0a1ae588aaf284c308d67ca92c69a39e2db81337e563bf40c59da0a5cf63000000006a4730440220360d20baff382059040ba9be98947fd678fb08aab2bb0c172efa996fd8ece9b702201b4fb0de67f015c90e7ac8a193aeab486a1f587e0f54d0fb9552ef7f5ce6caec032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff7d815b6447e35fbea097e00e028fb7dfbad4f3f0987b4734676c84f3fcd0e804010000006b483045022100c714310be1e3a9ff1c5f7cacc65c2d8e781fc3a88ceb063c6153bf950650802102200b2d0979c76e12bb480da635f192cc8dc6f905380dd4ac1ff35a4f68f462fffd032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff3f1f097333e4d46d51f5e77b53264db8f7f5d2e18217e1099957d0f5af7713ee010000006c493046022100b663499ef73273a3788dea342717c2640ac43c5a1cf862c9e09b206fcb3f6bb8022100b09972e75972d9148f2bdd462e5cb69b57c1214b88fc55ca638676c07cfc10d8032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff0380841e00000000001976a914bfb282c70c4191f45b5a6665cad1682f2c9cfdfb88ac80841e00000000001976a9149857cc07bed33a5cf12b9c5e0500b675d500c81188ace0fd1c00000000001976a91443c52850606c872403c0601e69fa34b26f62db4a88ac00000000", "P2SH"],
+
+ ["ddc454a1c0c35c188c98976b17670f69e586d9c0f3593ea879928332f0a069e7, which spends an input that pushes using a PUSHDATA1 that is negative when read as signed"],
+ [[["c5510a5dd97a25f43175af1fe649b707b1df8e1a41489bac33a23087027a2f48", 0, "0x4c 0xae 0x606563686f2022553246736447566b58312b5a536e587574356542793066794778625456415675534a6c376a6a334878416945325364667657734f53474f36633338584d7439435c6e543249584967306a486956304f376e775236644546673d3d22203e20743b206f70656e73736c20656e63202d7061737320706173733a5b314a564d7751432d707269766b65792d6865785d202d64202d6165732d3235362d636263202d61202d696e207460 DROP DUP HASH160 0x14 0xbfd7436b6265aa9de506f8a994f881ff08cc2872 EQUALVERIFY CHECKSIG"]],
+ "0100000001482f7a028730a233ac9b48411a8edfb107b749e61faf7531f4257ad95d0a51c5000000008b483045022100bf0bbae9bde51ad2b222e87fbf67530fbafc25c903519a1e5dcc52a32ff5844e022028c4d9ad49b006dd59974372a54291d5764be541574bb0c4dc208ec51f80b7190141049dd4aad62741dc27d5f267f7b70682eee22e7e9c1923b9c0957bdae0b96374569b460eb8d5b40d972e8c7c0ad441de3d94c4a29864b212d56050acb980b72b2bffffffff0180969800000000001976a914e336d0017a9d28de99d16472f6ca6d5a3a8ebc9988ac00000000", "P2SH"],
+
+["Correct signature order"],
+["Note the input is just required to make the tester happy"],
+[[["b3da01dd4aae683c7aee4d5d8b52a540a508e1115f77cd7fa9a291243f501223", 0, "HASH160 0x14 0xb1ce99298d5f07364b57b1e5c9cc00be0b04a954 EQUAL"]],
+"01000000012312503f2491a2a97fcd775f11e108a540a5528b5d4dee7a3c68ae4add01dab300000000fdfe0000483045022100f6649b0eddfdfd4ad55426663385090d51ee86c3481bdc6b0c18ea6c0ece2c0b0220561c315b07cffa6f7dd9df96dbae9200c2dee09bf93cc35ca05e6cdf613340aa0148304502207aacee820e08b0b174e248abd8d7a34ed63b5da3abedb99934df9fddd65c05c4022100dfe87896ab5ee3df476c2655f9fbe5bd089dccbef3e4ea05b5d121169fe7f5f4014c695221031d11db38972b712a9fe1fc023577c7ae3ddb4a3004187d41c45121eecfdbb5b7210207ec36911b6ad2382860d32989c7b8728e9489d7bbc94a6b5509ef0029be128821024ea9fac06f666a4adc3fc1357b7bec1fd0bdece2b9d08579226a8ebde53058e453aeffffffff0180380100000000001976a914c9b99cddf847d10685a4fabaa0baf505f7c3dfab88ac00000000", "P2SH"],
+
+["cc60b1f899ec0a69b7c3f25ddf32c4524096a9c5b01cbd84c6d0312a0c478984, which is a fairly strange transaction which relies on OP_CHECKSIG returning 0 when checking a completely invalid sig of length 0"],
+[[["cbebc4da731e8995fe97f6fadcd731b36ad40e5ecb31e38e904f6e5982fa09f7", 0, "0x2102085c6600657566acc2d6382a47bc3f324008d2aa10940dd7705a48aa2a5a5e33ac7c2103f5d0fb955f95dd6be6115ce85661db412ec6a08abcbfce7da0ba8297c6cc0ec4ac7c5379a820d68df9e32a147cffa36193c6f7c43a1c8c69cda530e1c6db354bfabdcfefaf3c875379a820f531f3041d3136701ea09067c53e7159c8f9b2746a56c3d82966c54bbc553226879a5479827701200122a59a5379827701200122a59a6353798277537982778779679a68"]],
+"0100000001f709fa82596e4f908ee331cb5e0ed46ab331d7dcfaf697fe95891e73dac4ebcb000000008c20ca42095840735e89283fec298e62ac2ddea9b5f34a8cbb7097ad965b87568100201b1b01dc829177da4a14551d2fc96a9db00c6501edfa12f22cd9cefd335c227f483045022100a9df60536df5733dd0de6bc921fab0b3eee6426501b43a228afa2c90072eb5ca02201c78b74266fac7d1db5deff080d8a403743203f109fbcabf6d5a760bf87386d20100ffffffff01c075790000000000232103611f9a45c18f28f06f19076ad571c344c82ce8fcfe34464cf8085217a2d294a6ac00000000", "P2SH"],
+
+["Empty pubkey"],
+[[["229257c295e7f555421c1bfec8538dd30a4b5c37c1c8810bbe83cafa7811652c", 0, "0x00 CHECKSIG NOT"]],
+"01000000012c651178faca83be0b81c8c1375c4b0ad38d53c8fe1b1c4255f5e795c25792220000000049483045022100d6044562284ac76c985018fc4a90127847708c9edb280996c507b28babdc4b2a02203d74eca3f1a4d1eea7ff77b528fde6d5dc324ec2dbfdb964ba885f643b9704cd01ffffffff010100000000000000232102c2410f8891ae918cab4ffc4bb4a3b0881be67c7a1e7faa8b5acf9ab8932ec30cac00000000", "P2SH"],
+
+["Empty signature"],
+[[["9ca93cfd8e3806b9d9e2ba1cf64e3cc6946ee0119670b1796a09928d14ea25f7", 0, "0x21 0x028a1d66975dbdf97897e3a4aef450ebeb5b5293e4a0b4a6d3a2daaa0b2b110e02 CHECKSIG NOT"]],
+"0100000001f725ea148d92096a79b1709611e06e94c63c4ef61cbae2d9b906388efd3ca99c000000000100ffffffff0101000000000000002321028a1d66975dbdf97897e3a4aef450ebeb5b5293e4a0b4a6d3a2daaa0b2b110e02ac00000000", "P2SH"],
+
+[[["444e00ed7840d41f20ecd9c11d3f91982326c731a02f3c05748414a4fa9e59be", 0, "1 0x00 0x21 0x02136b04758b0b6e363e7a6fbe83aaf527a153db2b060d36cc29f7f8309ba6e458 2 CHECKMULTISIG"]],
+"0100000001be599efaa4148474053c2fa031c7262398913f1dc1d9ec201fd44078ed004e44000000004900473044022022b29706cb2ed9ef0cb3c97b72677ca2dfd7b4160f7b4beb3ba806aa856c401502202d1e52582412eba2ed474f1f437a427640306fd3838725fab173ade7fe4eae4a01ffffffff010100000000000000232103ac4bba7e7ca3e873eea49e08132ad30c7f03640b6539e9b59903cf14fd016bbbac00000000", "P2SH"],
+
+[[["e16abbe80bf30c080f63830c8dbf669deaef08957446e95940227d8c5e6db612", 0, "1 0x21 0x03905380c7013e36e6e19d305311c1b81fce6581f5ee1c86ef0627c68c9362fc9f 0x00 2 CHECKMULTISIG"]],
+"010000000112b66d5e8c7d224059e946749508efea9d66bf8d0c83630f080cf30be8bb6ae100000000490047304402206ffe3f14caf38ad5c1544428e99da76ffa5455675ec8d9780fac215ca17953520220779502985e194d84baa36b9bd40a0dbd981163fa191eb884ae83fc5bd1c86b1101ffffffff010100000000000000232103905380c7013e36e6e19d305311c1b81fce6581f5ee1c86ef0627c68c9362fc9fac00000000", "P2SH"],
+
+[[["ebbcf4bfce13292bd791d6a65a2a858d59adbf737e387e40370d4e64cc70efb0", 0, "2 0x21 0x033bcaa0a602f0d44cc9d5637c6e515b0471db514c020883830b7cefd73af04194 0x21 0x03a88b326f8767f4f192ce252afe33c94d25ab1d24f27f159b3cb3aa691ffe1423 2 CHECKMULTISIG NOT"]],
+"0100000001b0ef70cc644e0d37407e387e73bfad598d852a5aa6d691d72b2913cebff4bceb000000004a00473044022068cd4851fc7f9a892ab910df7a24e616f293bcb5c5fbdfbc304a194b26b60fba022078e6da13d8cb881a22939b952c24f88b97afd06b4c47a47d7f804c9a352a6d6d0100ffffffff0101000000000000002321033bcaa0a602f0d44cc9d5637c6e515b0471db514c020883830b7cefd73af04194ac00000000", "P2SH"],
+
+[[["ba4cd7ae2ad4d4d13ebfc8ab1d93a63e4a6563f25089a18bf0fc68f282aa88c1", 0, "2 0x21 0x037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1 0x21 0x02edc823cd634f2c4033d94f5755207cb6b60c4b1f1f056ad7471c47de5f2e4d50 2 CHECKMULTISIG NOT"]],
+"0100000001c188aa82f268fcf08ba18950f263654a3ea6931dabc8bf3ed1d4d42aaed74cba000000004b0000483045022100940378576e069aca261a6b26fb38344e4497ca6751bb10905c76bb689f4222b002204833806b014c26fd801727b792b1260003c55710f87c5adbd7a9cb57446dbc9801ffffffff0101000000000000002321037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1ac00000000", "P2SH"],
+
+
+["OP_CODESEPARATOR tests"],
+
+["Test that SignatureHash() removes OP_CODESEPARATOR with FindAndDelete()"],
+[[["bc7fd132fcf817918334822ee6d9bd95c889099c96e07ca2c1eb2cc70db63224", 0, "CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIG"]],
+"01000000012432b60dc72cebc1a27ce0969c0989c895bdd9e62e8234839117f8fc32d17fbc000000004a493046022100a576b52051962c25e642c0fd3d77ee6c92487048e5d90818bcf5b51abaccd7900221008204f8fb121be4ec3b24483b1f92d89b1b0548513a134e345c5442e86e8617a501ffffffff010000000000000000016a00000000", "P2SH"],
+[[["83e194f90b6ef21fa2e3a365b63794fb5daa844bdc9b25de30899fcfe7b01047", 0, "CODESEPARATOR CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIG"]],
+"01000000014710b0e7cf9f8930de259bdc4b84aa5dfb9437b665a3e3a21ff26e0bf994e183000000004a493046022100a166121a61b4eeb19d8f922b978ff6ab58ead8a5a5552bf9be73dc9c156873ea02210092ad9bc43ee647da4f6652c320800debcf08ec20a094a0aaf085f63ecb37a17201ffffffff010000000000000000016a00000000", "P2SH"],
+
+["Hashed data starts at the CODESEPARATOR"],
+[[["326882a7f22b5191f1a0cc9962ca4b878cd969cf3b3a70887aece4d801a0ba5e", 0, "0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CODESEPARATOR CHECKSIG"]],
+"01000000015ebaa001d8e4ec7a88703a3bcf69d98c874bca6299cca0f191512bf2a7826832000000004948304502203bf754d1c6732fbf87c5dcd81258aefd30f2060d7bd8ac4a5696f7927091dad1022100f5bcb726c4cf5ed0ed34cc13dadeedf628ae1045b7cb34421bc60b89f4cecae701ffffffff010000000000000000016a00000000", "P2SH"],
+
+["But only if execution has reached it"],
+[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIGVERIFY CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIGVERIFY CODESEPARATOR 1"]],
+"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a900000000924830450221009c0a27f886a1d8cb87f6f595fbc3163d28f7a81ec3c4b252ee7f3ac77fd13ffa02203caa8dfa09713c8c4d7ef575c75ed97812072405d932bd11e6a1593a98b679370148304502201e3861ef39a526406bad1e20ecad06be7375ad40ddb582c9be42d26c3a0d7b240221009d0a3985e96522e59635d19cc4448547477396ce0ef17a58e7d74c3ef464292301ffffffff010000000000000000016a00000000", "P2SH"],
+
+["CODESEPARATOR in an unexecuted IF block does not change what is hashed"],
+[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]],
+"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a48304502207a6974a77c591fa13dff60cabbb85a0de9e025c09c65a4b2285e47ce8e22f761022100f0efaac9ff8ac36b10721e0aae1fb975c90500b50c56e8a0cc52b0403f0425dd0100ffffffff010000000000000000016a00000000", "P2SH"],
+
+["As above, with the IF block executed"],
+[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]],
+"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a483045022100fa4a74ba9fd59c59f46c3960cf90cbe0d2b743c471d24a3d5d6db6002af5eebb02204d70ec490fd0f7055a7c45f86514336e3a7f03503dacecabb247fc23f15c83510151ffffffff010000000000000000016a00000000", "P2SH"],
+
+
+["CHECKSIG is legal in scriptSigs"],
+[[["ccf7f4053a02e653c36ac75c891b7496d0dc5ce5214f6c913d9cf8f1329ebee0", 0, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]],
+"0100000001e0be9e32f1f89c3d916c4f21e55cdcd096741b895cc76ac353e6023a05f4f7cc00000000d86149304602210086e5f736a2c3622ebb62bd9d93d8e5d76508b98be922b97160edc3dcca6d8c47022100b23c312ac232a4473f19d2aeb95ab7bdf2b65518911a0d72d50e38b5dd31dc820121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac4730440220508fa761865c8abd81244a168392876ee1d94e8ed83897066b5e2df2400dad24022043f5ee7538e87e9c6aef7ef55133d3e51da7cc522830a9c4d736977a76ef755c0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"],
+
+["Same semantics for OP_CODESEPARATOR"],
+[[["10c9f0effe83e97f80f067de2b11c6a00c3088a4bce42c5ae761519af9306f3c", 1, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]],
+"01000000013c6f30f99a5161e75a2ce4bca488300ca0c6112bde67f0807fe983feeff0c91001000000e608646561646265656675ab61493046022100ce18d384221a731c993939015e3d1bcebafb16e8c0b5b5d14097ec8177ae6f28022100bcab227af90bab33c3fe0a9abfee03ba976ee25dc6ce542526e9b2e56e14b7f10121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac493046022100c3b93edcc0fd6250eb32f2dd8a0bba1754b0f6c3be8ed4100ed582f3db73eba2022100bf75b5bd2eff4d6bf2bda2e34a40fcc07d4aa3cf862ceaa77b47b81eff829f9a01ab21038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"],
+
+["Signatures are removed from the script they are in by FindAndDelete() in the CHECKSIG code; even multiple instances of one signature can be removed."],
+[[["6056ebd549003b10cbbd915cea0d82209fe40b8617104be917a26fa92cbe3d6f", 0, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]],
+"01000000016f3dbe2ca96fa217e94b1017860be49f20820dea5c91bdcb103b0049d5eb566000000000fd1d0147304402203989ac8f9ad36b5d0919d97fa0a7f70c5272abee3b14477dc646288a8b976df5022027d19da84a066af9053ad3d1d7459d171b7e3a80bc6c4ef7a330677a6be548140147304402203989ac8f9ad36b5d0919d97fa0a7f70c5272abee3b14477dc646288a8b976df5022027d19da84a066af9053ad3d1d7459d171b7e3a80bc6c4ef7a330677a6be548140121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac47304402203757e937ba807e4a5da8534c17f9d121176056406a6465054bdd260457515c1a02200f02eccf1bec0f3a0d65df37889143c2e88ab7acec61a7b6f5aa264139141a2b0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"],
+
+["That also includes ahead of the opcode being executed."],
+[[["5a6b0021a6042a686b6b94abc36b387bef9109847774e8b1e51eb8cc55c53921", 1, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]],
+"01000000012139c555ccb81ee5b1e87477840991ef7b386bc3ab946b6b682a04a621006b5a01000000fdb40148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f2204148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390175ac4830450220646b72c35beeec51f4d5bc1cbae01863825750d7f490864af354e6ea4f625e9c022100f04b98432df3a9641719dbced53393022e7249fb59db993af1118539830aab870148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a580039017521038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"],
+
+["Finally CHECKMULTISIG removes all signatures prior to hashing the script containing those signatures. In conjunction with the SIGHASH_SINGLE bug this lets us test whether or not FindAndDelete() is actually present in scriptPubKey/redeemScript evaluation by including a signature of the digest 0x01 We can compute in advance for our pubkey, embed it in the scriptPubKey, and then also using a normal SIGHASH_ALL signature. If FindAndDelete() wasn't run, the 'bugged' signature would still be in the hashed script, and the normal signature would fail."],
+
+["Here's an example on mainnet within a P2SH redeemScript. Remarkably it's a standard transaction in <0.9"],
+[[["b5b598de91787439afd5938116654e0b16b7a0d0f82742ba37564219c5afcbf9", 0, "DUP HASH160 0x14 0xf6f365c40f0739b61de827a44751e5e99032ed8f EQUALVERIFY CHECKSIG"],
+ ["ab9805c6d57d7070d9a42c5176e47bb705023e6b67249fb6760880548298e742", 0, "HASH160 0x14 0xd8dacdadb7462ae15cd906f1878706d0da8660e6 EQUAL"]],
+"0100000002f9cbafc519425637ba4227f8d0a0b7160b4e65168193d5af39747891de98b5b5000000006b4830450221008dd619c563e527c47d9bd53534a770b102e40faa87f61433580e04e271ef2f960220029886434e18122b53d5decd25f1f4acb2480659fea20aabd856987ba3c3907e0121022b78b756e2258af13779c1a1f37ea6800259716ca4b7f0b87610e0bf3ab52a01ffffffff42e7988254800876b69f24676b3e0205b77be476512ca4d970707dd5c60598ab00000000fd260100483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a53034930460221008431bdfa72bc67f9d41fe72e94c88fb8f359ffa30b33c72c121c5a877d922e1002210089ef5fc22dd8bfc6bf9ffdb01a9862d27687d424d1fefbab9e9c7176844a187a014c9052483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c7153aeffffffff01a08601000000000017a914d8dacdadb7462ae15cd906f1878706d0da8660e68700000000", "P2SH"],
+
+["Same idea, but with bare CHECKMULTISIG"],
+[[["ceafe58e0f6e7d67c0409fbbf673c84c166e3c5d3c24af58f7175b18df3bb3db", 0, "DUP HASH160 0x14 0xf6f365c40f0739b61de827a44751e5e99032ed8f EQUALVERIFY CHECKSIG"],
+ ["ceafe58e0f6e7d67c0409fbbf673c84c166e3c5d3c24af58f7175b18df3bb3db", 1, "2 0x48 0x3045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 3 CHECKMULTISIG"]],
+"0100000002dbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce000000006b4830450221009627444320dc5ef8d7f68f35010b4c050a6ed0d96b67a84db99fda9c9de58b1e02203e4b4aaa019e012e65d69b487fdf8719df72f488fa91506a80c49a33929f1fd50121022b78b756e2258af13779c1a1f37ea6800259716ca4b7f0b87610e0bf3ab52a01ffffffffdbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce010000009300483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303ffffffff01a0860100000000001976a9149bc0bbdd3024da4d0c38ed1aecf5c68dd1d3fa1288ac00000000", "P2SH"],
+
+
+["CHECKLOCKTIMEVERIFY tests"],
+
+["By-height locks, with argument == 0 and == tx nLockTime"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKLOCKTIMEVERIFY 1"]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 CHECKLOCKTIMEVERIFY 1"]],
+"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ff64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKLOCKTIMEVERIFY 1"]],
+"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ff64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
+
+["By-time locks, with argument just beyond tx nLockTime (but within numerical boundaries)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 CHECKLOCKTIMEVERIFY 1"]],
+"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKLOCKTIMEVERIFY 1"]],
+"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffffff", "P2SH,CHECKLOCKTIMEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 CHECKLOCKTIMEVERIFY 1"]],
+"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffffff", "P2SH,CHECKLOCKTIMEVERIFY"],
+
+["Any non-maxint nSequence is fine"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKLOCKTIMEVERIFY 1"]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
+
+["The argument can be calculated rather than created directly by a PUSHDATA"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 1ADD CHECKLOCKTIMEVERIFY 1"]],
+"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
+
+["Perhaps even by an ADD producing a 5-byte result that is out of bounds for other opcodes"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 2147483647 ADD CHECKLOCKTIMEVERIFY 1"]],
+"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000feffffff", "P2SH,CHECKLOCKTIMEVERIFY"],
+
+["5 byte non-minimally-encoded arguments are valid"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x05 0x0000000000 CHECKLOCKTIMEVERIFY 1"]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
+
+["Valid CHECKLOCKTIMEVERIFY in scriptSig"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]],
+"01000000010001000000000000000000000000000000000000000000000000000000000000000000000251b1000000000100000000000000000001000000", "P2SH,CHECKLOCKTIMEVERIFY"],
+
+["Valid CHECKLOCKTIMEVERIFY in redeemScript"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xc5b93064159b3b2d6ab506a41b1f50463771b988 EQUAL"]],
+"0100000001000100000000000000000000000000000000000000000000000000000000000000000000030251b1000000000100000000000000000001000000", "P2SH,CHECKLOCKTIMEVERIFY"],
+
+["A transaction with a non-standard DER signature."],
+[[["b1dbc81696c8a9c0fccd0693ab66d7c368dbc38c0def4e800685560ddd1b2132", 0, "DUP HASH160 0x14 0x4b3bd7eba3bc0284fd3007be7f3be275e94f5826 EQUALVERIFY CHECKSIG"]],
+"010000000132211bdd0d568506804eef0d8cc3db68c3d766ab9306cdfcc0a9c89616c8dbb1000000006c493045022100c7bb0faea0522e74ff220c20c022d2cb6033f8d167fb89e75a50e237a35fd6d202203064713491b1f8ad5f79e623d0219ad32510bfaa1009ab30cbee77b59317d6e30001210237af13eb2d84e4545af287b919c2282019c9691cc509e78e196a9d8274ed1be0ffffffff0100000000000000001976a914f1b3ed2eda9a2ebe5a9374f692877cdf87c0f95b88ac00000000", "P2SH"],
+
+["CHECKSEQUENCEVERIFY tests"],
+
+["By-height locks, with argument == 0 and == txin.nSequence"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff00000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["By-time locks, with argument == 0 and == txin.nSequence"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff40000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Upper sequence with upper sequence is fine"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000800100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000800100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Argument 2^31 with various nSequence"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Argument 2^32-1 with various nSequence"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Argument 3<<31 with various nSequence"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["5 byte non-minimally-encoded operandss are valid"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x05 0x0000000000 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["The argument can be calculated rather than created directly by a PUSHDATA"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194303 1ADD CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 1SUB CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff00000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["An ADD producing a 5-byte result that sets CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 65536 CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 4259840 ADD CHECKSEQUENCEVERIFY 1"]],
+"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Valid CHECKSEQUENCEVERIFY in scriptSig"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]],
+"02000000010001000000000000000000000000000000000000000000000000000000000000000000000251b2010000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Valid CHECKSEQUENCEVERIFY in redeemScript"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7c17aff532f22beb54069942f9bf567a66133eaf EQUAL"]],
+"0200000001000100000000000000000000000000000000000000000000000000000000000000000000030251b2010000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
+
+["Valid P2WPKH (Private key of segwit tests is L5AQtV2HDm4xGsseLokK2VAT2EtYKcTm3c7HwqnJBFt9LdaQULsM)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000]],
+"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100cfb07164b36ba64c1b1e8c7720a56ad64d96f6ef332d3d37f9cb3c96477dc44502200a464cd7a9cf94cd70f66ce4f4f0625ef650052c7afcfe29d7d7e01830ff91ed012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000", "P2SH,WITNESS"],
+
+["Valid P2WSH"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x20 0xff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3db", 1000]],
+"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100aa5d8aa40a90f23ce2c3d11bc845ca4a12acd99cbea37de6b9f6d86edebba8cb022022dedc2aa0a255f74d04c0b76ece2d7c691f9dd11a64a8ac49f62a99c3a05f9d01232103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ac00000000", "P2SH,WITNESS"],
+
+["Valid P2SH(P2WPKH)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xfe9c7dacc9fcfbf7e3b7d5ad06aa2b28c5a7b7e3 EQUAL", 1000]],
+"01000000000101000100000000000000000000000000000000000000000000000000000000000000000000171600144c9c3dfac4207d5d8cb89df5722cb3d712385e3fffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100cfb07164b36ba64c1b1e8c7720a56ad64d96f6ef332d3d37f9cb3c96477dc44502200a464cd7a9cf94cd70f66ce4f4f0625ef650052c7afcfe29d7d7e01830ff91ed012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000", "P2SH,WITNESS"],
+
+["Valid P2SH(P2WSH)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x2135ab4f0981830311e35600eebc7376dce3a914 EQUAL", 1000]],
+"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000023220020ff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3dbffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100aa5d8aa40a90f23ce2c3d11bc845ca4a12acd99cbea37de6b9f6d86edebba8cb022022dedc2aa0a255f74d04c0b76ece2d7c691f9dd11a64a8ac49f62a99c3a05f9d01232103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ac00000000", "P2SH,WITNESS"],
+
+["Witness with SigHash Single|AnyoneCanPay"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3100],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1100],
+["0000000000000000000000000000000000000000000000000000000000000100", 3, "0x51", 4100]],
+"0100000000010400010000000000000000000000000000000000000000000000000000000000000200000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000300000000ffffffff05540b0000000000000151d0070000000000000151840300000000000001513c0f00000000000001512c010000000000000151000248304502210092f4777a0f17bf5aeb8ae768dec5f2c14feabf9d1fe2c89c78dfed0f13fdb86902206da90a86042e252bcd1e80a168c719e4a1ddcc3cebea24b9812c5453c79107e9832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71000000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash Single|AnyoneCanPay (same signature as previous)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b0000000000000151000248304502210092f4777a0f17bf5aeb8ae768dec5f2c14feabf9d1fe2c89c78dfed0f13fdb86902206da90a86042e252bcd1e80a168c719e4a1ddcc3cebea24b9812c5453c79107e9832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash Single"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff0484030000000000000151d0070000000000000151540b0000000000000151c800000000000000015100024730440220699e6b0cfe015b64ca3283e6551440a34f901ba62dd4c72fe1cb815afb2e6761022021cc5e84db498b1479de14efda49093219441adc6c543e5534979605e273d80b032103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash Single (same signature as previous)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b000000000000015100024730440220699e6b0cfe015b64ca3283e6551440a34f901ba62dd4c72fe1cb815afb2e6761022021cc5e84db498b1479de14efda49093219441adc6c543e5534979605e273d80b032103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash None|AnyoneCanPay"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3100],
+["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1100],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 3, "0x51", 4100]],
+"0100000000010400010000000000000000000000000000000000000000000000000000000000000200000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000300000000ffffffff04b60300000000000001519e070000000000000151860b00000000000001009600000000000000015100000248304502210091b32274295c2a3fa02f5bce92fb2789e3fc6ea947fbe1a76e52ea3f4ef2381a022079ad72aefa3837a2e0c033a8652a59731da05fa4a813f4fc48e87c075037256b822103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash None|AnyoneCanPay (same signature as previous)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b0000000000000151000248304502210091b32274295c2a3fa02f5bce92fb2789e3fc6ea947fbe1a76e52ea3f4ef2381a022079ad72aefa3837a2e0c033a8652a59731da05fa4a813f4fc48e87c075037256b822103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash None"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff04b60300000000000001519e070000000000000151860b0000000000000100960000000000000001510002473044022022fceb54f62f8feea77faac7083c3b56c4676a78f93745adc8a35800bc36adfa022026927df9abcf0a8777829bcfcce3ff0a385fa54c3f9df577405e3ef24ee56479022103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash None (same signature as previous)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b00000000000001510002473044022022fceb54f62f8feea77faac7083c3b56c4676a78f93745adc8a35800bc36adfa022026927df9abcf0a8777829bcfcce3ff0a385fa54c3f9df577405e3ef24ee56479022103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash None (same signature, only sequences changed)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"01000000000103000100000000000000000000000000000000000000000000000000000000000000000000000200000000010000000000000000000000000000000000000000000000000000000000000100000000ffffffff000100000000000000000000000000000000000000000000000000000000000002000000000200000003e8030000000000000151d0070000000000000151b80b00000000000001510002473044022022fceb54f62f8feea77faac7083c3b56c4676a78f93745adc8a35800bc36adfa022026927df9abcf0a8777829bcfcce3ff0a385fa54c3f9df577405e3ef24ee56479022103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash All|AnyoneCanPay"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3100],
+["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1100],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 3, "0x51", 4100]],
+"0100000000010400010000000000000000000000000000000000000000000000000000000000000200000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000300000000ffffffff03e8030000000000000151d0070000000000000151b80b0000000000000151000002483045022100a3cec69b52cba2d2de623eeef89e0ba1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with SigHash All|AnyoneCanPay (same signature as previous)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b00000000000001510002483045022100a3cec69b52cba2d2de623eeef89e0ba1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Unknown witness program version (without DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x60 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
+"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b00000000000001510002483045022100a3cec69b52cba2d2de623ffffffffff1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Witness with a push of 520 bytes"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x20 0x33198a9bfef674ebddb9ffaa52928017b8472791e54c609cb95f278ac6b1e349", 1000]],
+"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff010000000000000000015102fd08020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002755100000000", "P2SH,WITNESS"],
+
+["Transaction mixing all SigHash, segwit and normal inputs"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1001],
+["0000000000000000000000000000000000000000000000000000000000000100", 2, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1002],
+["0000000000000000000000000000000000000000000000000000000000000100", 3, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1003],
+["0000000000000000000000000000000000000000000000000000000000000100", 4, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1004],
+["0000000000000000000000000000000000000000000000000000000000000100", 5, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1005],
+["0000000000000000000000000000000000000000000000000000000000000100", 6, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1006],
+["0000000000000000000000000000000000000000000000000000000000000100", 7, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1007],
+["0000000000000000000000000000000000000000000000000000000000000100", 8, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1008],
+["0000000000000000000000000000000000000000000000000000000000000100", 9, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1009],
+["0000000000000000000000000000000000000000000000000000000000000100", 10, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1010],
+["0000000000000000000000000000000000000000000000000000000000000100", 11, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1011]],
+"0100000000010c00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff0001000000000000000000000000000000000000000000000000000000000000020000006a473044022026c2e65b33fcd03b2a3b0f25030f0244bd23cc45ae4dec0f48ae62255b1998a00220463aa3982b718d593a6b9e0044513fd67a5009c2fdccc59992cffc2b167889f4012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000030000006a4730440220008bd8382911218dcb4c9f2e75bf5c5c3635f2f2df49b36994fde85b0be21a1a02205a539ef10fb4c778b522c1be852352ea06c67ab74200977c722b0bc68972575a012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000040000006b483045022100d9436c32ff065127d71e1a20e319e4fe0a103ba0272743dbd8580be4659ab5d302203fd62571ee1fe790b182d078ecfd092a509eac112bea558d122974ef9cc012c7012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000050000006a47304402200e2c149b114ec546015c13b2b464bbcb0cdc5872e6775787527af6cbc4830b6c02207e9396c6979fb15a9a2b96ca08a633866eaf20dc0ff3c03e512c1d5a1654f148012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000060000006b483045022100b20e70d897dc15420bccb5e0d3e208d27bdd676af109abbd3f88dbdb7721e6d6022005836e663173fbdfe069f54cde3c2decd3d0ea84378092a5d9d85ec8642e8a41012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff00010000000000000000000000000000000000000000000000000000000000000700000000ffffffff00010000000000000000000000000000000000000000000000000000000000000800000000ffffffff00010000000000000000000000000000000000000000000000000000000000000900000000ffffffff00010000000000000000000000000000000000000000000000000000000000000a00000000ffffffff00010000000000000000000000000000000000000000000000000000000000000b0000006a47304402206639c6e05e3b9d2675a7f3876286bdf7584fe2bbd15e0ce52dd4e02c0092cdc60220757d60b0a61fc95ada79d23746744c72bac1545a75ff6c2c7cdb6ae04e7e9592012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0ce8030000000000000151e9030000000000000151ea030000000000000151eb030000000000000151ec030000000000000151ed030000000000000151ee030000000000000151ef030000000000000151f0030000000000000151f1030000000000000151f2030000000000000151f30300000000000001510248304502210082219a54f61bf126bfc3fa068c6e33831222d1d7138c6faa9d33ca87fd4202d6022063f9902519624254d7c2c8ea7ba2d66ae975e4e229ae38043973ec707d5d4a83012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7102473044022017fb58502475848c1b09f162cb1688d0920ff7f142bed0ef904da2ccc88b168f02201798afa61850c65e77889cbcd648a5703b487895517c88f85cdd18b021ee246a012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000000247304402202830b7926e488da75782c81a54cd281720890d1af064629ebf2e31bf9f5435f30220089afaa8b455bbeb7d9b9c3fe1ed37d07685ade8455c76472cda424d93e4074a012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7102473044022026326fcdae9207b596c2b05921dbac11d81040c4d40378513670f19d9f4af893022034ecd7a282c0163b89aaa62c22ec202cef4736c58cd251649bad0d8139bcbf55012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71024730440220214978daeb2f38cd426ee6e2f44131a33d6b191af1c216247f1dd7d74c16d84a02205fdc05529b0bc0c430b4d5987264d9d075351c4f4484c16e91662e90a72aab24012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710247304402204a6e9f199dc9672cf2ff8094aaa784363be1eb62b679f7ff2df361124f1dca3302205eeb11f70fab5355c9c8ad1a0700ea355d315e334822fa182227e9815308ee8f012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
+
+["Unknown version witness program with empty witness"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS"],
+
+["Witness SIGHASH_SINGLE with output out of bound"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x20 0x4d6c2a32c87821d68fc016fca70797abdb80df6cd84651d40a9300c6bad79e62", 1000]],
+"0100000000010200010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff01d00700000000000001510003483045022100e078de4e96a0e05dcdc0a414124dd8475782b5f3f0ed3f607919e9a5eeeb22bf02201de309b3a3109adb3de8074b3610d4cf454c49b61247a2779a0bcbf31c889333032103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc711976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac00000000", "P2SH,WITNESS"],
+
+["1 byte push should not be considered a witness scriptPubKey"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x01 0x01", 1000]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"],
+
+["41 bytes push should not be considered a witness scriptPubKey"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x29 0xff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3dbff0000000000000000", 1000]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"],
+
+["The witness version must use OP_1 to OP_16 only"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x01 0x10 0x02 0x0001", 1000]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"],
+
+["The witness program push must be canonical"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x4c02 0x0001", 1000]],
+"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"],
+
+["Witness Single|AnyoneCanPay does not hash input's position"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1001]],
+"0100000000010200010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff02e8030000000000000151e90300000000000001510247304402206d59682663faab5e4cb733c562e22cdae59294895929ec38d7c016621ff90da0022063ef0af5f970afe8a45ea836e3509b8847ed39463253106ac17d19c437d3d56b832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710248304502210085001a820bfcbc9f9de0298af714493f8a37b3b354bfd21a7097c3e009f2018c022050a8b4dbc8155d4d04da2f5cdd575dcf8dd0108de8bec759bd897ea01ecb3af7832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000", "P2SH,WITNESS"],
+
+["Witness Single|AnyoneCanPay does not hash input's position (permutation)"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1001],
+["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000]],
+"0100000000010200010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff02e9030000000000000151e80300000000000001510248304502210085001a820bfcbc9f9de0298af714493f8a37b3b354bfd21a7097c3e009f2018c022050a8b4dbc8155d4d04da2f5cdd575dcf8dd0108de8bec759bd897ea01ecb3af7832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710247304402206d59682663faab5e4cb733c562e22cdae59294895929ec38d7c016621ff90da0022063ef0af5f970afe8a45ea836e3509b8847ed39463253106ac17d19c437d3d56b832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000", "P2SH,WITNESS"],
+
+["Non witness Single|AnyoneCanPay hash input's position"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x03596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71 CHECKSIG", 1000],
+["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x21 0x03596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71 CHECKSIG", 1001]],
+"01000000020001000000000000000000000000000000000000000000000000000000000000000000004847304402202a0b4b1294d70540235ae033d78e64b4897ec859c7b6f1b2b1d8a02e1d46006702201445e756d2254b0f1dfda9ab8e1e1bc26df9668077403204f32d16a49a36eb6983ffffffff00010000000000000000000000000000000000000000000000000000000000000100000049483045022100acb96cfdbda6dc94b489fd06f2d720983b5f350e31ba906cdbd800773e80b21c02200d74ea5bdf114212b4bbe9ed82c36d2e369e302dff57cb60d01c428f0bd3daab83ffffffff02e8030000000000000151e903000000000000015100000000", "P2SH,WITNESS"],
+
+["BIP143 examples: details and private keys are available in BIP143"],
+["BIP143 example: P2WSH with OP_CODESEPARATOR and out-of-range SIGHASH_SINGLE."],
+[[["6eb316926b1c5d567cd6f5e6a84fec606fc53d7b474526d1fff3948020c93dfe", 0, "0x21 0x036d5c20fa14fb2f635474c1dc4ef5909d4568e5569b79fc94d3448486e14685f8 CHECKSIG", 156250000],
+["f825690aee1b3dc247da796cacb12687a5e802429fd291cfd63e010f02cf1508", 0, "0x00 0x20 0x5d1b56b63d714eebe542309525f484b7e9d6f686b3781b6f61ef925d66d6f6a0", 4900000000]],
+"01000000000102fe3dc9208094f3ffd12645477b3dc56f60ec4fa8e6f5d67c565d1c6b9216b36e000000004847304402200af4e47c9b9629dbecc21f73af989bdaa911f7e6f6c2e9394588a3aa68f81e9902204f3fcf6ade7e5abb1295b6774c8e0abd94ae62217367096bc02ee5e435b67da201ffffffff0815cf020f013ed6cf91d29f4202e8a58726b1ac6c79da47c23d1bee0a6925f80000000000ffffffff0100f2052a010000001976a914a30741f8145e5acadf23f751864167f32e0963f788ac000347304402200de66acf4527789bfda55fc5459e214fa6083f936b430a762c629656216805ac0220396f550692cd347171cbc1ef1f51e15282e837bb2b30860dc77c8f78bc8501e503473044022027dc95ad6b740fe5129e7e62a75dd00f291a2aeb1200b84b09d9e3789406b6c002201a9ecd315dd6a0e632ab20bbb98948bc0c6fb204f2c286963bb48517a7058e27034721026dccc749adc2a9d0d89497ac511f760f45c47dc5ed9cf352a58ac706453880aeadab210255a9626aebf5e29c0e6538428ba0d1dcf6ca98ffdf086aa8ced5e0d0215ea465ac00000000", "P2SH,WITNESS,CONST_SCRIPTCODE"],
+
+["BIP143 example: P2WSH with unexecuted OP_CODESEPARATOR and SINGLE|ANYONECANPAY"],
+[[["01c0cf7fba650638e55eb91261b183251fbb466f90dff17f10086817c542b5e9", 0, "0x00 0x20 0xba468eea561b26301e4cf69fa34bde4ad60c81e70f059f045ca9a79931004a4d", 16777215],
+["1b2a9a426ba603ba357ce7773cb5805cb9c7c2b386d100d1fc9263513188e680", 0, "0x00 0x20 0xd9bbfbe56af7c4b7f960a70d7ea107156913d9e5a26b0a71429df5e097ca6537", 16777215]],
+"01000000000102e9b542c5176808107ff1df906f46bb1f2583b16112b95ee5380665ba7fcfc0010000000000ffffffff80e68831516392fcd100d186b3c2c7b95c80b53c77e77c35ba03a66b429a2a1b0000000000ffffffff0280969800000000001976a914de4b231626ef508c9a74a8517e6783c0546d6b2888ac80969800000000001976a9146648a8cd4531e1ec47f35916de8e259237294d1e88ac02483045022100f6a10b8604e6dc910194b79ccfc93e1bc0ec7c03453caaa8987f7d6c3413566002206216229ede9b4d6ec2d325be245c5b508ff0339bf1794078e20bfe0babc7ffe683270063ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac024730440220032521802a76ad7bf74d0e2c218b72cf0cbc867066e2e53db905ba37f130397e02207709e2188ed7f08f4c952d9d13986da504502b8c3be59617e043552f506c46ff83275163ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac00000000", "P2SH,WITNESS,CONST_SCRIPTCODE"],
+
+["BIP143 example: Same as the previous example with input-output pairs swapped"],
+[[["1b2a9a426ba603ba357ce7773cb5805cb9c7c2b386d100d1fc9263513188e680", 0, "0x00 0x20 0xd9bbfbe56af7c4b7f960a70d7ea107156913d9e5a26b0a71429df5e097ca6537", 16777215],
+["01c0cf7fba650638e55eb91261b183251fbb466f90dff17f10086817c542b5e9", 0, "0x00 0x20 0xba468eea561b26301e4cf69fa34bde4ad60c81e70f059f045ca9a79931004a4d", 16777215]],
+"0100000000010280e68831516392fcd100d186b3c2c7b95c80b53c77e77c35ba03a66b429a2a1b0000000000ffffffffe9b542c5176808107ff1df906f46bb1f2583b16112b95ee5380665ba7fcfc0010000000000ffffffff0280969800000000001976a9146648a8cd4531e1ec47f35916de8e259237294d1e88ac80969800000000001976a914de4b231626ef508c9a74a8517e6783c0546d6b2888ac024730440220032521802a76ad7bf74d0e2c218b72cf0cbc867066e2e53db905ba37f130397e02207709e2188ed7f08f4c952d9d13986da504502b8c3be59617e043552f506c46ff83275163ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac02483045022100f6a10b8604e6dc910194b79ccfc93e1bc0ec7c03453caaa8987f7d6c3413566002206216229ede9b4d6ec2d325be245c5b508ff0339bf1794078e20bfe0babc7ffe683270063ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac00000000", "P2SH,WITNESS,CONST_SCRIPTCODE"],
+
+["BIP143 example: P2SH-P2WSH 6-of-6 multisig signed with 6 different SIGHASH types"],
+[[["6eb98797a21c6c10aa74edf29d618be109f48a8e94c694f3701e08ca69186436", 1, "HASH160 0x14 0x9993a429037b5d912407a71c252019287b8d27a5 EQUAL", 987654321]],
+"0100000000010136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000023220020a16b5755f7f6f96dbd65f5f0d6ab9418b89af4b1f14a1bb8a09062c35f0dcb54ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac080047304402206ac44d672dac41f9b00e28f4df20c52eeb087207e8d758d76d92c6fab3b73e2b0220367750dbbe19290069cba53d096f44530e4f98acaa594810388cf7409a1870ce01473044022068c7946a43232757cbdf9176f009a928e1cd9a1a8c212f15c1e11ac9f2925d9002205b75f937ff2f9f3c1246e547e54f62e027f64eefa2695578cc6432cdabce271502473044022059ebf56d98010a932cf8ecfec54c48e6139ed6adb0728c09cbe1e4fa0915302e022007cd986c8fa870ff5d2b3a89139c9fe7e499259875357e20fcbb15571c76795403483045022100fbefd94bd0a488d50b79102b5dad4ab6ced30c4069f1eaa69a4b5a763414067e02203156c6a5c9cf88f91265f5a942e96213afae16d83321c8b31bb342142a14d16381483045022100a5263ea0553ba89221984bd7f0b13613db16e7a70c549a86de0cc0444141a407022005c360ef0ae5a5d4f9f2f87a56c1546cc8268cab08c73501d6b3be2e1e1a8a08824730440220525406a1482936d5a21888260dc165497a90a15669636d8edca6b9fe490d309c022032af0c646a34a44d1f4576bf6a4a74b67940f8faa84c7df9abe12a01a11e2b4783cf56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae00000000", "P2SH,WITNESS"],
+
+["FindAndDelete tests"],
+["This is a test of FindAndDelete. The first tx is a spend of normal P2SH and the second tx is a spend of bare P2WSH."],
+["The redeemScript/witnessScript is CHECKSIGVERIFY <0x30450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e01>."],
+["The signature is <0x30450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e01> <pubkey>,"],
+["where the pubkey is obtained through key recovery with sig and correct sighash."],
+["This is to show that FindAndDelete is applied only to non-segwit scripts"],
+["Non-segwit: correct sighash (with FindAndDelete) = 1ba1fe3bc90c5d1265460e684ce6774e324f0fabdf67619eda729e64e8b6bc08"],
+[[["f18783ace138abac5d3a7a5cf08e88fe6912f267ef936452e0c27d090621c169", 7000, "HASH160 0x14 0x0c746489e2d83cdbb5b90b432773342ba809c134 EQUAL", 200000]],
+"010000000169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1ac8387f1581b0000b64830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0121037a3fb04bcdb09eba90f69961ba1692a3528e45e67c85b200df820212d7594d334aad4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e01ffffffff0101000000000000000000000000", "P2SH,WITNESS"],
+["BIP143: correct sighash (without FindAndDelete) = 71c9cd9b2869b9c70b01b1f0360c148f42dee72297db312638df136f43311f23"],
+[[["f18783ace138abac5d3a7a5cf08e88fe6912f267ef936452e0c27d090621c169", 7500, "0x00 0x20 0x9e1be07558ea5cc8e02ed1d80c0911048afad949affa36d5c3951e3159dbea19", 200000]],
+"0100000000010169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1ac8387f14c1d000000ffffffff01010000000000000000034830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e012102a9781d66b61fb5a7ef00ac5ad5bc6ffc78be7b44a566e3c87870e1079368df4c4aad4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0100000000", "P2SH,WITNESS,CONST_SCRIPTCODE"],
+["This is multisig version of the FindAndDelete tests"],
+["Script is 2 CHECKMULTISIGVERIFY <sig1> <sig2> DROP"],
+["52af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c0395960175"],
+["Signature is 0 <sig1> <sig2> 2 <key1> <key2>"],
+["Non-segwit: correct sighash (with FindAndDelete) = 1d50f00ba4db2917b903b0ec5002e017343bb38876398c9510570f5dce099295"],
+[[["9628667ad48219a169b41b020800162287d2c0f713c04157e95c484a8dcb7592", 7000, "HASH160 0x14 0x5748407f5ca5cdca53ba30b79040260770c9ee1b EQUAL", 200000]],
+"01000000019275cb8d4a485ce95741c013f7c0d28722160008021bb469a11982d47a662896581b0000fd6f01004830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c03959601522102cd74a2809ffeeed0092bc124fd79836706e41f048db3f6ae9df8708cefb83a1c2102e615999372426e46fd107b76eaf007156a507584aa2cc21de9eee3bdbd26d36c4c9552af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c0395960175ffffffff0101000000000000000000000000", "P2SH,WITNESS"],
+["BIP143: correct sighash (without FindAndDelete) = c1628a1e7c67f14ca0c27c06e4fdeec2e6d1a73c7a91d7c046ff83e835aebb72"],
+[[["9628667ad48219a169b41b020800162287d2c0f713c04157e95c484a8dcb7592", 7500, "0x00 0x20 0x9b66c15b4e0b4eb49fa877982cafded24859fe5b0e2dbfbe4f0df1de7743fd52", 200000]],
+"010000000001019275cb8d4a485ce95741c013f7c0d28722160008021bb469a11982d47a6628964c1d000000ffffffff0101000000000000000007004830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c0395960101022102966f109c54e85d3aee8321301136cedeb9fc710fdef58a9de8a73942f8e567c021034ffc99dd9a79dd3cb31e2ab3e0b09e0e67db41ac068c625cd1f491576016c84e9552af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c039596017500000000", "P2SH,WITNESS,CONST_SCRIPTCODE"],
+
+["Test long outputs, which are streamed using length-prefixed bitcoin strings. This might be surprising."],
+[[["1111111111111111111111111111111111111111111111111111111111111111", 0, "0x00 0x14 0x751e76e8199196d454941c45d1b3a323f1433bd6", 5000000]],
+"0100000000010111111111111111111111111111111111111111111111111111111111111111110000000000ffffffff0130244c0000000000fd02014cdc1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111175210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac02483045022100c1a4a6581996a7fdfea77d58d537955a5655c1d619b6f3ab6874f28bb2e19708022056402db6fede03caae045a3be616a1a2d0919a475ed4be828dc9ff21f24063aa01210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179800000000", "P2SH,WITNESS"],
+
+["Make diffs cleaner by leaving a comment here without comma at the end"]
+]
diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp
new file mode 100644
index 0000000000..4dff1e5c72
--- /dev/null
+++ b/src/test/dbwrapper_tests.cpp
@@ -0,0 +1,322 @@
+// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <dbwrapper.h>
+#include <uint256.h>
+#include <random.h>
+#include <test/test_bitcoin.h>
+
+#include <memory>
+
+#include <boost/test/unit_test.hpp>
+
+// Test if a string consists entirely of null characters
+static bool is_null_key(const std::vector<unsigned char>& key) {
+ bool isnull = true;
+
+ for (unsigned int i = 0; i < key.size(); i++)
+ isnull &= (key[i] == '\x00');
+
+ return isnull;
+}
+
+BOOST_FIXTURE_TEST_SUITE(dbwrapper_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(dbwrapper)
+{
+ // Perform tests both obfuscated and non-obfuscated.
+ for (bool obfuscate : {false, true}) {
+ fs::path ph = SetDataDir(std::string("dbwrapper").append(obfuscate ? "_true" : "_false"));
+ CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
+ char key = 'k';
+ uint256 in = InsecureRand256();
+ uint256 res;
+
+ // Ensure that we're doing real obfuscation when obfuscate=true
+ BOOST_CHECK(obfuscate != is_null_key(dbwrapper_private::GetObfuscateKey(dbw)));
+
+ BOOST_CHECK(dbw.Write(key, in));
+ BOOST_CHECK(dbw.Read(key, res));
+ BOOST_CHECK_EQUAL(res.ToString(), in.ToString());
+ }
+}
+
+// Test batch operations
+BOOST_AUTO_TEST_CASE(dbwrapper_batch)
+{
+ // Perform tests both obfuscated and non-obfuscated.
+ for (bool obfuscate : {false, true}) {
+ fs::path ph = SetDataDir(std::string("dbwrapper_batch").append(obfuscate ? "_true" : "_false"));
+ CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
+
+ char key = 'i';
+ uint256 in = InsecureRand256();
+ char key2 = 'j';
+ uint256 in2 = InsecureRand256();
+ char key3 = 'k';
+ uint256 in3 = InsecureRand256();
+
+ uint256 res;
+ CDBBatch batch(dbw);
+
+ batch.Write(key, in);
+ batch.Write(key2, in2);
+ batch.Write(key3, in3);
+
+ // Remove key3 before it's even been written
+ batch.Erase(key3);
+
+ dbw.WriteBatch(batch);
+
+ BOOST_CHECK(dbw.Read(key, res));
+ BOOST_CHECK_EQUAL(res.ToString(), in.ToString());
+ BOOST_CHECK(dbw.Read(key2, res));
+ BOOST_CHECK_EQUAL(res.ToString(), in2.ToString());
+
+ // key3 should've never been written
+ BOOST_CHECK(dbw.Read(key3, res) == false);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(dbwrapper_iterator)
+{
+ // Perform tests both obfuscated and non-obfuscated.
+ for (bool obfuscate : {false, true}) {
+ fs::path ph = SetDataDir(std::string("dbwrapper_iterator").append(obfuscate ? "_true" : "_false"));
+ CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate);
+
+ // The two keys are intentionally chosen for ordering
+ char key = 'j';
+ uint256 in = InsecureRand256();
+ BOOST_CHECK(dbw.Write(key, in));
+ char key2 = 'k';
+ uint256 in2 = InsecureRand256();
+ BOOST_CHECK(dbw.Write(key2, in2));
+
+ std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper&>(dbw).NewIterator());
+
+ // Be sure to seek past the obfuscation key (if it exists)
+ it->Seek(key);
+
+ char key_res;
+ uint256 val_res;
+
+ it->GetKey(key_res);
+ it->GetValue(val_res);
+ BOOST_CHECK_EQUAL(key_res, key);
+ BOOST_CHECK_EQUAL(val_res.ToString(), in.ToString());
+
+ it->Next();
+
+ it->GetKey(key_res);
+ it->GetValue(val_res);
+ BOOST_CHECK_EQUAL(key_res, key2);
+ BOOST_CHECK_EQUAL(val_res.ToString(), in2.ToString());
+
+ it->Next();
+ BOOST_CHECK_EQUAL(it->Valid(), false);
+ }
+}
+
+// Test that we do not obfuscation if there is existing data.
+BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate)
+{
+ // We're going to share this fs::path between two wrappers
+ fs::path ph = SetDataDir("existing_data_no_obfuscate");
+ create_directories(ph);
+
+ // Set up a non-obfuscated wrapper to write some initial data.
+ std::unique_ptr<CDBWrapper> dbw = MakeUnique<CDBWrapper>(ph, (1 << 10), false, false, false);
+ char key = 'k';
+ uint256 in = InsecureRand256();
+ uint256 res;
+
+ BOOST_CHECK(dbw->Write(key, in));
+ BOOST_CHECK(dbw->Read(key, res));
+ BOOST_CHECK_EQUAL(res.ToString(), in.ToString());
+
+ // Call the destructor to free leveldb LOCK
+ dbw.reset();
+
+ // Now, set up another wrapper that wants to obfuscate the same directory
+ CDBWrapper odbw(ph, (1 << 10), false, false, true);
+
+ // Check that the key/val we wrote with unobfuscated wrapper exists and
+ // is readable.
+ uint256 res2;
+ BOOST_CHECK(odbw.Read(key, res2));
+ BOOST_CHECK_EQUAL(res2.ToString(), in.ToString());
+
+ BOOST_CHECK(!odbw.IsEmpty()); // There should be existing data
+ BOOST_CHECK(is_null_key(dbwrapper_private::GetObfuscateKey(odbw))); // The key should be an empty string
+
+ uint256 in2 = InsecureRand256();
+ uint256 res3;
+
+ // Check that we can write successfully
+ BOOST_CHECK(odbw.Write(key, in2));
+ BOOST_CHECK(odbw.Read(key, res3));
+ BOOST_CHECK_EQUAL(res3.ToString(), in2.ToString());
+}
+
+// Ensure that we start obfuscating during a reindex.
+BOOST_AUTO_TEST_CASE(existing_data_reindex)
+{
+ // We're going to share this fs::path between two wrappers
+ fs::path ph = SetDataDir("existing_data_reindex");
+ create_directories(ph);
+
+ // Set up a non-obfuscated wrapper to write some initial data.
+ std::unique_ptr<CDBWrapper> dbw = MakeUnique<CDBWrapper>(ph, (1 << 10), false, false, false);
+ char key = 'k';
+ uint256 in = InsecureRand256();
+ uint256 res;
+
+ BOOST_CHECK(dbw->Write(key, in));
+ BOOST_CHECK(dbw->Read(key, res));
+ BOOST_CHECK_EQUAL(res.ToString(), in.ToString());
+
+ // Call the destructor to free leveldb LOCK
+ dbw.reset();
+
+ // Simulate a -reindex by wiping the existing data store
+ CDBWrapper odbw(ph, (1 << 10), false, true, true);
+
+ // Check that the key/val we wrote with unobfuscated wrapper doesn't exist
+ uint256 res2;
+ BOOST_CHECK(!odbw.Read(key, res2));
+ BOOST_CHECK(!is_null_key(dbwrapper_private::GetObfuscateKey(odbw)));
+
+ uint256 in2 = InsecureRand256();
+ uint256 res3;
+
+ // Check that we can write successfully
+ BOOST_CHECK(odbw.Write(key, in2));
+ BOOST_CHECK(odbw.Read(key, res3));
+ BOOST_CHECK_EQUAL(res3.ToString(), in2.ToString());
+}
+
+BOOST_AUTO_TEST_CASE(iterator_ordering)
+{
+ fs::path ph = SetDataDir("iterator_ordering");
+ CDBWrapper dbw(ph, (1 << 20), true, false, false);
+ for (int x=0x00; x<256; ++x) {
+ uint8_t key = x;
+ uint32_t value = x*x;
+ if (!(x & 1)) BOOST_CHECK(dbw.Write(key, value));
+ }
+
+ // Check that creating an iterator creates a snapshot
+ std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper&>(dbw).NewIterator());
+
+ for (unsigned int x=0x00; x<256; ++x) {
+ uint8_t key = x;
+ uint32_t value = x*x;
+ if (x & 1) BOOST_CHECK(dbw.Write(key, value));
+ }
+
+ for (int seek_start : {0x00, 0x80}) {
+ it->Seek((uint8_t)seek_start);
+ for (unsigned int x=seek_start; x<255; ++x) {
+ uint8_t key;
+ uint32_t value;
+ BOOST_CHECK(it->Valid());
+ if (!it->Valid()) // Avoid spurious errors about invalid iterator's key and value in case of failure
+ break;
+ BOOST_CHECK(it->GetKey(key));
+ if (x & 1) {
+ BOOST_CHECK_EQUAL(key, x + 1);
+ continue;
+ }
+ BOOST_CHECK(it->GetValue(value));
+ BOOST_CHECK_EQUAL(key, x);
+ BOOST_CHECK_EQUAL(value, x*x);
+ it->Next();
+ }
+ BOOST_CHECK(!it->Valid());
+ }
+}
+
+struct StringContentsSerializer {
+ // Used to make two serialized objects the same while letting them have different lengths
+ // This is a terrible idea
+ std::string str;
+ StringContentsSerializer() {}
+ explicit StringContentsSerializer(const std::string& inp) : str(inp) {}
+
+ StringContentsSerializer& operator+=(const std::string& s) {
+ str += s;
+ return *this;
+ }
+ StringContentsSerializer& operator+=(const StringContentsSerializer& s) { return *this += s.str; }
+
+ ADD_SERIALIZE_METHODS;
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream& s, Operation ser_action) {
+ if (ser_action.ForRead()) {
+ str.clear();
+ char c = 0;
+ while (true) {
+ try {
+ READWRITE(c);
+ str.push_back(c);
+ } catch (const std::ios_base::failure& e) {
+ break;
+ }
+ }
+ } else {
+ for (size_t i = 0; i < str.size(); i++)
+ READWRITE(str[i]);
+ }
+ }
+};
+
+BOOST_AUTO_TEST_CASE(iterator_string_ordering)
+{
+ char buf[10];
+
+ fs::path ph = SetDataDir("iterator_string_ordering");
+ CDBWrapper dbw(ph, (1 << 20), true, false, false);
+ for (int x=0x00; x<10; ++x) {
+ for (int y = 0; y < 10; y++) {
+ snprintf(buf, sizeof(buf), "%d", x);
+ StringContentsSerializer key(buf);
+ for (int z = 0; z < y; z++)
+ key += key;
+ uint32_t value = x*x;
+ BOOST_CHECK(dbw.Write(key, value));
+ }
+ }
+
+ std::unique_ptr<CDBIterator> it(const_cast<CDBWrapper&>(dbw).NewIterator());
+ for (int seek_start : {0, 5}) {
+ snprintf(buf, sizeof(buf), "%d", seek_start);
+ StringContentsSerializer seek_key(buf);
+ it->Seek(seek_key);
+ for (unsigned int x=seek_start; x<10; ++x) {
+ for (int y = 0; y < 10; y++) {
+ snprintf(buf, sizeof(buf), "%d", x);
+ std::string exp_key(buf);
+ for (int z = 0; z < y; z++)
+ exp_key += exp_key;
+ StringContentsSerializer key;
+ uint32_t value;
+ BOOST_CHECK(it->Valid());
+ if (!it->Valid()) // Avoid spurious errors about invalid iterator's key and value in case of failure
+ break;
+ BOOST_CHECK(it->GetKey(key));
+ BOOST_CHECK(it->GetValue(value));
+ BOOST_CHECK_EQUAL(key.str, exp_key);
+ BOOST_CHECK_EQUAL(value, x*x);
+ it->Next();
+ }
+ }
+ BOOST_CHECK(!it->Valid());
+ }
+}
+
+
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp
new file mode 100644
index 0000000000..fdf7397bff
--- /dev/null
+++ b/src/test/denialofservice_tests.cpp
@@ -0,0 +1,415 @@
+// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+// Unit tests for denial-of-service detection/prevention code
+
+#include <chainparams.h>
+#include <keystore.h>
+#include <net.h>
+#include <net_processing.h>
+#include <pow.h>
+#include <script/sign.h>
+#include <serialize.h>
+#include <util.h>
+#include <validation.h>
+
+#include <test/test_bitcoin.h>
+
+#include <stdint.h>
+
+#include <boost/test/unit_test.hpp>
+
+// Tests these internal-to-net_processing.cpp methods:
+extern bool AddOrphanTx(const CTransactionRef& tx, NodeId peer);
+extern void EraseOrphansFor(NodeId peer);
+extern unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans);
+extern void Misbehaving(NodeId nodeid, int howmuch, const std::string& message="");
+
+struct COrphanTx {
+ CTransactionRef tx;
+ NodeId fromPeer;
+ int64_t nTimeExpire;
+};
+extern std::map<uint256, COrphanTx> mapOrphanTransactions;
+
+static CService ip(uint32_t i)
+{
+ struct in_addr s;
+ s.s_addr = i;
+ return CService(CNetAddr(s), Params().GetDefaultPort());
+}
+
+static NodeId id = 0;
+
+void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds);
+
+BOOST_FIXTURE_TEST_SUITE(denialofservice_tests, TestingSetup)
+
+// Test eviction of an outbound peer whose chain never advances
+// Mock a node connection, and use mocktime to simulate a peer
+// which never sends any headers messages. PeerLogic should
+// decide to evict that outbound peer, after the appropriate timeouts.
+// Note that we protect 4 outbound nodes from being subject to
+// this logic; this test takes advantage of that protection only
+// being applied to nodes which send headers with sufficient
+// work.
+BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
+{
+
+ // Mock an outbound peer
+ CAddress addr1(ip(0xa0b0c001), NODE_NONE);
+ CNode dummyNode1(id++, ServiceFlags(NODE_NETWORK|NODE_WITNESS), 0, INVALID_SOCKET, addr1, 0, 0, CAddress(), "", /*fInboundIn=*/ false);
+ dummyNode1.SetSendVersion(PROTOCOL_VERSION);
+
+ peerLogic->InitializeNode(&dummyNode1);
+ dummyNode1.nVersion = 1;
+ dummyNode1.fSuccessfullyConnected = true;
+
+ // This test requires that we have a chain with non-zero work.
+ {
+ LOCK(cs_main);
+ BOOST_CHECK(chainActive.Tip() != nullptr);
+ BOOST_CHECK(chainActive.Tip()->nChainWork > 0);
+ }
+
+ // Test starts here
+ {
+ LOCK2(cs_main, dummyNode1.cs_sendProcessing);
+ peerLogic->SendMessages(&dummyNode1); // should result in getheaders
+ }
+ {
+ LOCK2(cs_main, dummyNode1.cs_vSend);
+ BOOST_CHECK(dummyNode1.vSendMsg.size() > 0);
+ dummyNode1.vSendMsg.clear();
+ }
+
+ int64_t nStartTime = GetTime();
+ // Wait 21 minutes
+ SetMockTime(nStartTime+21*60);
+ {
+ LOCK2(cs_main, dummyNode1.cs_sendProcessing);
+ peerLogic->SendMessages(&dummyNode1); // should result in getheaders
+ }
+ {
+ LOCK2(cs_main, dummyNode1.cs_vSend);
+ BOOST_CHECK(dummyNode1.vSendMsg.size() > 0);
+ }
+ // Wait 3 more minutes
+ SetMockTime(nStartTime+24*60);
+ {
+ LOCK2(cs_main, dummyNode1.cs_sendProcessing);
+ peerLogic->SendMessages(&dummyNode1); // should result in disconnect
+ }
+ BOOST_CHECK(dummyNode1.fDisconnect == true);
+ SetMockTime(0);
+
+ bool dummy;
+ peerLogic->FinalizeNode(dummyNode1.GetId(), dummy);
+}
+
+static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerLogicValidation &peerLogic)
+{
+ CAddress addr(ip(GetRandInt(0xffffffff)), NODE_NONE);
+ vNodes.emplace_back(new CNode(id++, ServiceFlags(NODE_NETWORK|NODE_WITNESS), 0, INVALID_SOCKET, addr, 0, 0, CAddress(), "", /*fInboundIn=*/ false));
+ CNode &node = *vNodes.back();
+ node.SetSendVersion(PROTOCOL_VERSION);
+
+ peerLogic.InitializeNode(&node);
+ node.nVersion = 1;
+ node.fSuccessfullyConnected = true;
+
+ CConnmanTest::AddNode(node);
+}
+
+BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
+{
+ const Consensus::Params& consensusParams = Params().GetConsensus();
+ constexpr int nMaxOutbound = 8;
+ CConnman::Options options;
+ options.nMaxConnections = 125;
+ options.nMaxOutbound = nMaxOutbound;
+ options.nMaxFeeler = 1;
+
+ connman->Init(options);
+ std::vector<CNode *> vNodes;
+
+ // Mock some outbound peers
+ for (int i=0; i<nMaxOutbound; ++i) {
+ AddRandomOutboundPeer(vNodes, *peerLogic);
+ }
+
+ peerLogic->CheckForStaleTipAndEvictPeers(consensusParams);
+
+ // No nodes should be marked for disconnection while we have no extra peers
+ for (const CNode *node : vNodes) {
+ BOOST_CHECK(node->fDisconnect == false);
+ }
+
+ SetMockTime(GetTime() + 3*consensusParams.nPowTargetSpacing + 1);
+
+ // Now tip should definitely be stale, and we should look for an extra
+ // outbound peer
+ peerLogic->CheckForStaleTipAndEvictPeers(consensusParams);
+ BOOST_CHECK(connman->GetTryNewOutboundPeer());
+
+ // Still no peers should be marked for disconnection
+ for (const CNode *node : vNodes) {
+ BOOST_CHECK(node->fDisconnect == false);
+ }
+
+ // If we add one more peer, something should get marked for eviction
+ // on the next check (since we're mocking the time to be in the future, the
+ // required time connected check should be satisfied).
+ AddRandomOutboundPeer(vNodes, *peerLogic);
+
+ peerLogic->CheckForStaleTipAndEvictPeers(consensusParams);
+ for (int i=0; i<nMaxOutbound; ++i) {
+ BOOST_CHECK(vNodes[i]->fDisconnect == false);
+ }
+ // Last added node should get marked for eviction
+ BOOST_CHECK(vNodes.back()->fDisconnect == true);
+
+ vNodes.back()->fDisconnect = false;
+
+ // Update the last announced block time for the last
+ // peer, and check that the next newest node gets evicted.
+ UpdateLastBlockAnnounceTime(vNodes.back()->GetId(), GetTime());
+
+ peerLogic->CheckForStaleTipAndEvictPeers(consensusParams);
+ for (int i=0; i<nMaxOutbound-1; ++i) {
+ BOOST_CHECK(vNodes[i]->fDisconnect == false);
+ }
+ BOOST_CHECK(vNodes[nMaxOutbound-1]->fDisconnect == true);
+ BOOST_CHECK(vNodes.back()->fDisconnect == false);
+
+ bool dummy;
+ for (const CNode *node : vNodes) {
+ peerLogic->FinalizeNode(node->GetId(), dummy);
+ }
+
+ CConnmanTest::ClearNodes();
+}
+
+BOOST_AUTO_TEST_CASE(DoS_banning)
+{
+
+ connman->ClearBanned();
+ CAddress addr1(ip(0xa0b0c001), NODE_NONE);
+ CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 0, 0, CAddress(), "", true);
+ dummyNode1.SetSendVersion(PROTOCOL_VERSION);
+ peerLogic->InitializeNode(&dummyNode1);
+ dummyNode1.nVersion = 1;
+ dummyNode1.fSuccessfullyConnected = true;
+ {
+ LOCK(cs_main);
+ Misbehaving(dummyNode1.GetId(), 100); // Should get banned
+ }
+ {
+ LOCK2(cs_main, dummyNode1.cs_sendProcessing);
+ peerLogic->SendMessages(&dummyNode1);
+ }
+ BOOST_CHECK(connman->IsBanned(addr1));
+ BOOST_CHECK(!connman->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned
+
+ CAddress addr2(ip(0xa0b0c002), NODE_NONE);
+ CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, 1, 1, CAddress(), "", true);
+ dummyNode2.SetSendVersion(PROTOCOL_VERSION);
+ peerLogic->InitializeNode(&dummyNode2);
+ dummyNode2.nVersion = 1;
+ dummyNode2.fSuccessfullyConnected = true;
+ {
+ LOCK(cs_main);
+ Misbehaving(dummyNode2.GetId(), 50);
+ }
+ {
+ LOCK2(cs_main, dummyNode2.cs_sendProcessing);
+ peerLogic->SendMessages(&dummyNode2);
+ }
+ BOOST_CHECK(!connman->IsBanned(addr2)); // 2 not banned yet...
+ BOOST_CHECK(connman->IsBanned(addr1)); // ... but 1 still should be
+ {
+ LOCK(cs_main);
+ Misbehaving(dummyNode2.GetId(), 50);
+ }
+ {
+ LOCK2(cs_main, dummyNode2.cs_sendProcessing);
+ peerLogic->SendMessages(&dummyNode2);
+ }
+ BOOST_CHECK(connman->IsBanned(addr2));
+
+ bool dummy;
+ peerLogic->FinalizeNode(dummyNode1.GetId(), dummy);
+ peerLogic->FinalizeNode(dummyNode2.GetId(), dummy);
+}
+
+BOOST_AUTO_TEST_CASE(DoS_banscore)
+{
+
+ connman->ClearBanned();
+ gArgs.ForceSetArg("-banscore", "111"); // because 11 is my favorite number
+ CAddress addr1(ip(0xa0b0c001), NODE_NONE);
+ CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 3, 1, CAddress(), "", true);
+ dummyNode1.SetSendVersion(PROTOCOL_VERSION);
+ peerLogic->InitializeNode(&dummyNode1);
+ dummyNode1.nVersion = 1;
+ dummyNode1.fSuccessfullyConnected = true;
+ {
+ LOCK(cs_main);
+ Misbehaving(dummyNode1.GetId(), 100);
+ }
+ {
+ LOCK2(cs_main, dummyNode1.cs_sendProcessing);
+ peerLogic->SendMessages(&dummyNode1);
+ }
+ BOOST_CHECK(!connman->IsBanned(addr1));
+ {
+ LOCK(cs_main);
+ Misbehaving(dummyNode1.GetId(), 10);
+ }
+ {
+ LOCK2(cs_main, dummyNode1.cs_sendProcessing);
+ peerLogic->SendMessages(&dummyNode1);
+ }
+ BOOST_CHECK(!connman->IsBanned(addr1));
+ {
+ LOCK(cs_main);
+ Misbehaving(dummyNode1.GetId(), 1);
+ }
+ {
+ LOCK2(cs_main, dummyNode1.cs_sendProcessing);
+ peerLogic->SendMessages(&dummyNode1);
+ }
+ BOOST_CHECK(connman->IsBanned(addr1));
+ gArgs.ForceSetArg("-banscore", std::to_string(DEFAULT_BANSCORE_THRESHOLD));
+
+ bool dummy;
+ peerLogic->FinalizeNode(dummyNode1.GetId(), dummy);
+}
+
+BOOST_AUTO_TEST_CASE(DoS_bantime)
+{
+
+ connman->ClearBanned();
+ int64_t nStartTime = GetTime();
+ SetMockTime(nStartTime); // Overrides future calls to GetTime()
+
+ CAddress addr(ip(0xa0b0c001), NODE_NONE);
+ CNode dummyNode(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr, 4, 4, CAddress(), "", true);
+ dummyNode.SetSendVersion(PROTOCOL_VERSION);
+ peerLogic->InitializeNode(&dummyNode);
+ dummyNode.nVersion = 1;
+ dummyNode.fSuccessfullyConnected = true;
+
+ {
+ LOCK(cs_main);
+ Misbehaving(dummyNode.GetId(), 100);
+ }
+ {
+ LOCK2(cs_main, dummyNode.cs_sendProcessing);
+ peerLogic->SendMessages(&dummyNode);
+ }
+ BOOST_CHECK(connman->IsBanned(addr));
+
+ SetMockTime(nStartTime+60*60);
+ BOOST_CHECK(connman->IsBanned(addr));
+
+ SetMockTime(nStartTime+60*60*24+1);
+ BOOST_CHECK(!connman->IsBanned(addr));
+
+ bool dummy;
+ peerLogic->FinalizeNode(dummyNode.GetId(), dummy);
+}
+
+static CTransactionRef RandomOrphan()
+{
+ std::map<uint256, COrphanTx>::iterator it;
+ LOCK(cs_main);
+ it = mapOrphanTransactions.lower_bound(InsecureRand256());
+ if (it == mapOrphanTransactions.end())
+ it = mapOrphanTransactions.begin();
+ return it->second.tx;
+}
+
+BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
+{
+ CKey key;
+ key.MakeNewKey(true);
+ CBasicKeyStore keystore;
+ keystore.AddKey(key);
+
+ // 50 orphan transactions:
+ for (int i = 0; i < 50; i++)
+ {
+ CMutableTransaction tx;
+ tx.vin.resize(1);
+ tx.vin[0].prevout.n = 0;
+ tx.vin[0].prevout.hash = InsecureRand256();
+ tx.vin[0].scriptSig << OP_1;
+ tx.vout.resize(1);
+ tx.vout[0].nValue = 1*CENT;
+ tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());
+
+ AddOrphanTx(MakeTransactionRef(tx), i);
+ }
+
+ // ... and 50 that depend on other orphans:
+ for (int i = 0; i < 50; i++)
+ {
+ CTransactionRef txPrev = RandomOrphan();
+
+ CMutableTransaction tx;
+ tx.vin.resize(1);
+ tx.vin[0].prevout.n = 0;
+ tx.vin[0].prevout.hash = txPrev->GetHash();
+ tx.vout.resize(1);
+ tx.vout[0].nValue = 1*CENT;
+ tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());
+ SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL);
+
+ AddOrphanTx(MakeTransactionRef(tx), i);
+ }
+
+ // This really-big orphan should be ignored:
+ for (int i = 0; i < 10; i++)
+ {
+ CTransactionRef txPrev = RandomOrphan();
+
+ CMutableTransaction tx;
+ tx.vout.resize(1);
+ tx.vout[0].nValue = 1*CENT;
+ tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());
+ tx.vin.resize(2777);
+ 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, SIGHASH_ALL);
+ // 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;
+
+ BOOST_CHECK(!AddOrphanTx(MakeTransactionRef(tx), i));
+ }
+
+ LOCK(cs_main);
+ // Test EraseOrphansFor:
+ for (NodeId i = 0; i < 3; i++)
+ {
+ size_t sizeBefore = mapOrphanTransactions.size();
+ EraseOrphansFor(i);
+ BOOST_CHECK(mapOrphanTransactions.size() < sizeBefore);
+ }
+
+ // Test LimitOrphanTxSize() function:
+ LimitOrphanTxSize(40);
+ BOOST_CHECK(mapOrphanTransactions.size() <= 40);
+ LimitOrphanTxSize(10);
+ BOOST_CHECK(mapOrphanTransactions.size() <= 10);
+ LimitOrphanTxSize(0);
+ BOOST_CHECK(mapOrphanTransactions.empty());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/descriptor_tests.cpp b/src/test/descriptor_tests.cpp
new file mode 100644
index 0000000000..f189222be8
--- /dev/null
+++ b/src/test/descriptor_tests.cpp
@@ -0,0 +1,163 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <vector>
+#include <string>
+#include <script/sign.h>
+#include <script/standard.h>
+#include <test/test_bitcoin.h>
+#include <boost/test/unit_test.hpp>
+#include <script/descriptor.h>
+#include <utilstrencodings.h>
+
+namespace {
+
+void CheckUnparsable(const std::string& prv, const std::string& pub)
+{
+ FlatSigningProvider keys_priv, keys_pub;
+ auto parse_priv = Parse(prv, keys_priv);
+ auto parse_pub = Parse(pub, keys_pub);
+ BOOST_CHECK(!parse_priv);
+ BOOST_CHECK(!parse_pub);
+}
+
+constexpr int DEFAULT = 0;
+constexpr int RANGE = 1; // Expected to be ranged descriptor
+constexpr int HARDENED = 2; // Derivation needs access to private keys
+constexpr int UNSOLVABLE = 4; // This descriptor is not expected to be solvable
+constexpr int SIGNABLE = 8; // We can sign with this descriptor (this is not true when actual BIP32 derivation is used, as that's not integrated in our signing code)
+
+std::string MaybeUseHInsteadOfApostrophy(std::string ret)
+{
+ if (InsecureRandBool()) {
+ while (true) {
+ auto it = ret.find("'");
+ if (it != std::string::npos) {
+ ret[it] = 'h';
+ } else {
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
+void Check(const std::string& prv, const std::string& pub, int flags, const std::vector<std::vector<std::string>>& scripts)
+{
+ FlatSigningProvider keys_priv, keys_pub;
+
+ // Check that parsing succeeds.
+ auto parse_priv = Parse(MaybeUseHInsteadOfApostrophy(prv), keys_priv);
+ auto parse_pub = Parse(MaybeUseHInsteadOfApostrophy(pub), keys_pub);
+ BOOST_CHECK(parse_priv);
+ BOOST_CHECK(parse_pub);
+
+ // Check private keys are extracted from the private version but not the public one.
+ BOOST_CHECK(keys_priv.keys.size());
+ BOOST_CHECK(!keys_pub.keys.size());
+
+ // Check that both versions serialize back to the public version.
+ std::string pub1 = parse_priv->ToString();
+ std::string pub2 = parse_priv->ToString();
+ BOOST_CHECK_EQUAL(pub, pub1);
+ BOOST_CHECK_EQUAL(pub, pub2);
+
+ // Check that both can be serialized with private key back to the private version, but not without private key.
+ std::string prv1, prv2;
+ BOOST_CHECK(parse_priv->ToPrivateString(keys_priv, prv1));
+ BOOST_CHECK_EQUAL(prv, prv1);
+ BOOST_CHECK(!parse_priv->ToPrivateString(keys_pub, prv1));
+ BOOST_CHECK(parse_pub->ToPrivateString(keys_priv, prv1));
+ BOOST_CHECK_EQUAL(prv, prv1);
+ BOOST_CHECK(!parse_pub->ToPrivateString(keys_pub, prv1));
+
+ // Check whether IsRange on both returns the expected result
+ BOOST_CHECK_EQUAL(parse_pub->IsRange(), (flags & RANGE) != 0);
+ BOOST_CHECK_EQUAL(parse_priv->IsRange(), (flags & RANGE) != 0);
+
+
+ // Is not ranged descriptor, only a single result is expected.
+ if (!(flags & RANGE)) assert(scripts.size() == 1);
+
+ size_t max = (flags & RANGE) ? scripts.size() : 3;
+ for (size_t i = 0; i < max; ++i) {
+ const auto& ref = scripts[(flags & RANGE) ? i : 0];
+ for (int t = 0; t < 2; ++t) {
+ FlatSigningProvider key_provider = (flags & HARDENED) ? keys_priv : keys_pub;
+ FlatSigningProvider script_provider;
+ std::vector<CScript> spks;
+ BOOST_CHECK((t ? parse_priv : parse_pub)->Expand(i, key_provider, spks, script_provider));
+ BOOST_CHECK_EQUAL(spks.size(), ref.size());
+ for (size_t n = 0; n < spks.size(); ++n) {
+ BOOST_CHECK_EQUAL(ref[n], HexStr(spks[n].begin(), spks[n].end()));
+ BOOST_CHECK_EQUAL(IsSolvable(Merge(key_provider, script_provider), spks[n]), (flags & UNSOLVABLE) == 0);
+
+ if (flags & SIGNABLE) {
+ CMutableTransaction spend;
+ spend.vin.resize(1);
+ spend.vout.resize(1);
+ BOOST_CHECK_MESSAGE(SignSignature(Merge(keys_priv, script_provider), spks[n], spend, 0, 1, SIGHASH_ALL), prv);
+ }
+ }
+
+ }
+ }
+}
+
+}
+
+BOOST_FIXTURE_TEST_SUITE(descriptor_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(descriptor_test)
+{
+ // Basic single-key compressed
+ Check("combo(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac","76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac","00149a1c78a507689f6f54b847ad1cef1e614ee23f1e","a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}});
+ Check("pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac"}});
+ Check("pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac"}});
+ Check("wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)", SIGNABLE, {{"00149a1c78a507689f6f54b847ad1cef1e614ee23f1e"}});
+ Check("sh(wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a91484ab21b1b2fd065d4504ff693d832434b6108d7b87"}});
+
+ // Basic single-key uncompressed
+ Check("combo(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "combo(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac","76a914b5bd079c4d57cc7fc28ecf8213a6b791625b818388ac"}});
+ Check("pk(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac"}});
+ Check("pkh(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "pkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"76a914b5bd079c4d57cc7fc28ecf8213a6b791625b818388ac"}});
+ CheckUnparsable("wpkh(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "wpkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)"); // No uncompressed keys in witness
+ CheckUnparsable("wsh(pk(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss))", "wsh(pk(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235))"); // No uncompressed keys in witness
+ CheckUnparsable("sh(wpkh(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss))", "sh(wpkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235))"); // No uncompressed keys in witness
+
+ // Some unconventional single-key constructions
+ Check("sh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a9141857af51a5e516552b3086430fd8ce55f7c1a52487"}});
+ Check("sh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a9141a31ad23bf49c247dd531a623c2ef57da3c400c587"}});
+ Check("wsh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"00202e271faa2325c199d25d22e1ead982e45b64eeb4f31e73dbdf41bd4b5fec23fa"}});
+ Check("wsh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"0020338e023079b91c58571b20e602d7805fb808c22473cbc391a41b1bd3a192e75b"}});
+ Check("sh(wsh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", SIGNABLE, {{"a91472d0c5a3bfad8c3e7bd5303a72b94240e80b6f1787"}});
+ Check("sh(wsh(pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(wsh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))", SIGNABLE, {{"a914b61b92e2ca21bac1e72a3ab859a742982bea960a87"}});
+
+ // Versions with BIP32 derivations
+ Check("combo(xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc)", "combo(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL)", SIGNABLE, {{"2102d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0ac","76a91431a507b815593dfc51ffc7245ae7e5aee304246e88ac","001431a507b815593dfc51ffc7245ae7e5aee304246e","a9142aafb926eb247cb18240a7f4c07983ad1f37922687"}});
+ Check("pk(xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0)", "pk(xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0)", DEFAULT, {{"210379e45b3cf75f9c5f9befd8e9506fb962f6a9d185ac87001ec44a8d3df8d4a9e3ac"}});
+ Check("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0)", HARDENED, {{"76a914ebdc90806a9c4356c1c88e42216611e1cb4c1c1788ac"}});
+ Check("wpkh(xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*)", "wpkh(xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*)", RANGE, {{"0014326b2249e3a25d5dc60935f044ee835d090ba859"},{"0014af0bd98abc2f2cae66e36896a39ffe2d32984fb7"},{"00141fa798efd1cbf95cebf912c031b8a4a6e9fb9f27"}});
+ Check("sh(wpkh(xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "sh(wpkh(xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", RANGE | HARDENED, {{"a9149a4d9901d6af519b2a23d4a2f51650fcba87ce7b87"},{"a914bed59fc0024fae941d6e20a3b44a109ae740129287"},{"a9148483aa1116eb9c05c482a72bada4b1db24af654387"}});
+ Check("combo(xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/*)", "combo(xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV/*)", RANGE, {{"2102df12b7035bdac8e3bab862a3a83d06ea6b17b6753d52edecba9be46f5d09e076ac","76a914f90e3178ca25f2c808dc76624032d352fdbdfaf288ac","0014f90e3178ca25f2c808dc76624032d352fdbdfaf2","a91408f3ea8c68d4a7585bf9e8bda226723f70e445f087"},{"21032869a233c9adff9a994e4966e5b821fd5bac066da6c3112488dc52383b4a98ecac","76a914a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b788ac","0014a8409d1b6dfb1ed2a3e8aa5e0ef2ff26b15b75b7","a91473e39884cb71ae4e5ac9739e9225026c99763e6687"}});
+ CheckUnparsable("pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483648)", "pkh(xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483648)"); // BIP 32 path element overflow
+
+ // Multisig constructions
+ Check("multi(1,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)", "multi(1,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea23552ae"}});
+ Check("sh(multi(2,xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))", "sh(multi(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0))", DEFAULT, {{"a91445a9a622a8b0a1269944be477640eedc447bbd8487"}});
+ Check("wsh(multi(2,xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))", "wsh(multi(2,xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB/2147483647'/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*,xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8/10/20/30/40/*'))", HARDENED | RANGE, {{"0020b92623201f3bb7c3771d45b2ad1d0351ea8fbf8cfe0a0e570264e1075fa1948f"},{"002036a08bbe4923af41cf4316817c93b8d37e2f635dd25cfff06bd50df6ae7ea203"},{"0020a96e7ab4607ca6b261bfe3245ffda9c746b28d3f59e83d34820ec0e2b36c139c"}});
+ Check("sh(wsh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9)))","sh(wsh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232)))", SIGNABLE, {{"a9147fc63e13dc25e8a95a3cee3d9a714ac3afd96f1e87"}});
+ CheckUnparsable("sh(multi(16,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy,KwGNz6YCCQtYvFzMtrC6D3tKTKdBBboMrLTsjr2NYVBwapCkn7Mr,KxogYhiNfwxuswvXV66eFyKcCpm7dZ7TqHVqujHAVUjJxyivxQ9X,L2BUNduTSyZwZjwNHynQTF14mv2uz2NRq5n5sYWTb4FkkmqgEE9f,L1okJGHGn1kFjdXHKxXjwVVtmCMR2JA5QsbKCSpSb7ReQjezKeoD,KxDCNSST75HFPaW5QKpzHtAyaCQC7p9Vo3FYfi2u4dXD1vgMiboK,L5edQjFtnkcf5UWURn6UuuoFrabgDQUHdheKCziwN42aLwS3KizU,KzF8UWFcEC7BYTq8Go1xVimMkDmyNYVmXV5PV7RuDicvAocoPB8i,L3nHUboKG2w4VSJ5jYZ5CBM97oeK6YuKvfZxrefdShECcjEYKMWZ,KyjHo36dWkYhimKmVVmQTq3gERv3pnqA4xFCpvUgbGDJad7eS8WE,KwsfyHKRUTZPQtysN7M3tZ4GXTnuov5XRgjdF2XCG8faAPmFruRF,KzCUbGhN9LJhdeFfL9zQgTJMjqxdBKEekRGZX24hXdgCNCijkkap,KzgpMBwwsDLwkaC5UrmBgCYaBD2WgZ7PBoGYXR8KT7gCA9UTN5a3,KyBXTPy4T7YG4q9tcAM3LkvfRpD1ybHMvcJ2ehaWXaSqeGUxEdkP,KzJDe9iwJRPtKP2F2AoN6zBgzS7uiuAwhWCfGdNeYJ3PC1HNJ8M8,L1xbHrxynrqLKkoYc4qtoQPx6uy5qYXR5ZDYVYBSRmCV5piU3JG9))","sh(multi(16,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600,0362a74e399c39ed5593852a30147f2959b56bb827dfa3e60e464b02ccf87dc5e8,0261345b53de74a4d721ef877c255429961b7e43714171ac06168d7e08c542a8b8,02da72e8b46901a65d4374fe6315538d8f368557dda3a1dcf9ea903f3afe7314c8,0318c82dd0b53fd3a932d16e0ba9e278fcc937c582d5781be626ff16e201f72286,0297ccef1ef99f9d73dec9ad37476ddb232f1238aff877af19e72ba04493361009,02e502cfd5c3f972fe9a3e2a18827820638f96b6f347e54d63deb839011fd5765d,03e687710f0e3ebe81c1037074da939d409c0025f17eb86adb9427d28f0f7ae0e9,02c04d3a5274952acdbc76987f3184b346a483d43be40874624b29e3692c1df5af,02ed06e0f418b5b43a7ec01d1d7d27290fa15f75771cb69b642a51471c29c84acd,036d46073cbb9ffee90473f3da429abc8de7f8751199da44485682a989a4bebb24,02f5d1ff7c9029a80a4e36b9a5497027ef7f3e73384a4a94fbfe7c4e9164eec8bc,02e41deffd1b7cce11cde209a781adcffdabd1b91c0ba0375857a2bfd9302419f3,02d76625f7956a7fc505ab02556c23ee72d832f1bac391bcd2d3abce5710a13d06,0399eb0a5487515802dc14544cf10b3666623762fbed2ec38a3975716e2c29c232))"); // P2SH does not fit 16 compressed pubkeys in a redeemscript
+
+ // Check for invalid nesting of structures
+ CheckUnparsable("sh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "sh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)"); // P2SH needs a script, not a key
+ CheckUnparsable("sh(combo(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "sh(combo(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))"); // Old must be top level
+ CheckUnparsable("wsh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)", "wsh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)"); // P2WSH needs a script, not a key
+ CheckUnparsable("wsh(wpkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))", "wsh(wpkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))"); // Cannot embed witness inside witness
+ CheckUnparsable("wsh(sh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "wsh(sh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))"); // Cannot embed P2SH inside P2WSH
+ CheckUnparsable("sh(sh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "sh(sh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))"); // Cannot embed P2SH inside P2SH
+ CheckUnparsable("wsh(wsh(pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)))", "wsh(wsh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)))"); // Cannot embed P2WSH inside P2WSH
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp
new file mode 100644
index 0000000000..eec7b38af7
--- /dev/null
+++ b/src/test/getarg_tests.cpp
@@ -0,0 +1,175 @@
+// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <util.h>
+#include <test/test_bitcoin.h>
+
+#include <string>
+#include <vector>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(getarg_tests, BasicTestingSetup)
+
+static void ResetArgs(const std::string& strArg)
+{
+ std::vector<std::string> vecArg;
+ if (strArg.size())
+ boost::split(vecArg, strArg, boost::is_space(), boost::token_compress_on);
+
+ // Insert dummy executable name:
+ vecArg.insert(vecArg.begin(), "testbitcoin");
+
+ // Convert to char*:
+ std::vector<const char*> vecChar;
+ for (std::string& s : vecArg)
+ vecChar.push_back(s.c_str());
+
+ std::string error;
+ gArgs.ParseParameters(vecChar.size(), vecChar.data(), error);
+}
+
+static void SetupArgs(const std::vector<std::string>& args)
+{
+ gArgs.ClearArgs();
+ for (const std::string& arg : args) {
+ gArgs.AddArg(arg, "", false, OptionsCategory::OPTIONS);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(boolarg)
+{
+ SetupArgs({"-foo"});
+ ResetArgs("-foo");
+ BOOST_CHECK(gArgs.GetBoolArg("-foo", false));
+ BOOST_CHECK(gArgs.GetBoolArg("-foo", true));
+
+ BOOST_CHECK(!gArgs.GetBoolArg("-fo", false));
+ BOOST_CHECK(gArgs.GetBoolArg("-fo", true));
+
+ BOOST_CHECK(!gArgs.GetBoolArg("-fooo", false));
+ BOOST_CHECK(gArgs.GetBoolArg("-fooo", true));
+
+ ResetArgs("-foo=0");
+ BOOST_CHECK(!gArgs.GetBoolArg("-foo", false));
+ BOOST_CHECK(!gArgs.GetBoolArg("-foo", true));
+
+ ResetArgs("-foo=1");
+ BOOST_CHECK(gArgs.GetBoolArg("-foo", false));
+ BOOST_CHECK(gArgs.GetBoolArg("-foo", true));
+
+ // New 0.6 feature: auto-map -nosomething to !-something:
+ ResetArgs("-nofoo");
+ BOOST_CHECK(!gArgs.GetBoolArg("-foo", false));
+ BOOST_CHECK(!gArgs.GetBoolArg("-foo", true));
+
+ ResetArgs("-nofoo=1");
+ BOOST_CHECK(!gArgs.GetBoolArg("-foo", false));
+ BOOST_CHECK(!gArgs.GetBoolArg("-foo", true));
+
+ ResetArgs("-foo -nofoo"); // -nofoo should win
+ BOOST_CHECK(!gArgs.GetBoolArg("-foo", false));
+ BOOST_CHECK(!gArgs.GetBoolArg("-foo", true));
+
+ ResetArgs("-foo=1 -nofoo=1"); // -nofoo should win
+ BOOST_CHECK(!gArgs.GetBoolArg("-foo", false));
+ BOOST_CHECK(!gArgs.GetBoolArg("-foo", true));
+
+ ResetArgs("-foo=0 -nofoo=0"); // -nofoo=0 should win
+ BOOST_CHECK(gArgs.GetBoolArg("-foo", false));
+ BOOST_CHECK(gArgs.GetBoolArg("-foo", true));
+
+ // New 0.6 feature: treat -- same as -:
+ ResetArgs("--foo=1");
+ BOOST_CHECK(gArgs.GetBoolArg("-foo", false));
+ BOOST_CHECK(gArgs.GetBoolArg("-foo", true));
+
+ ResetArgs("--nofoo=1");
+ BOOST_CHECK(!gArgs.GetBoolArg("-foo", false));
+ BOOST_CHECK(!gArgs.GetBoolArg("-foo", true));
+
+}
+
+BOOST_AUTO_TEST_CASE(stringarg)
+{
+ SetupArgs({"-foo", "-bar"});
+ ResetArgs("");
+ BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", ""), "");
+ BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", "eleven"), "eleven");
+
+ ResetArgs("-foo -bar");
+ BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", ""), "");
+ BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", "eleven"), "");
+
+ ResetArgs("-foo=");
+ BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", ""), "");
+ BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", "eleven"), "");
+
+ ResetArgs("-foo=11");
+ BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", ""), "11");
+ BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", "eleven"), "11");
+
+ ResetArgs("-foo=eleven");
+ BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", ""), "eleven");
+ BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", "eleven"), "eleven");
+
+}
+
+BOOST_AUTO_TEST_CASE(intarg)
+{
+ SetupArgs({"-foo", "-bar"});
+ ResetArgs("");
+ BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", 11), 11);
+ BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", 0), 0);
+
+ ResetArgs("-foo -bar");
+ BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", 11), 0);
+ BOOST_CHECK_EQUAL(gArgs.GetArg("-bar", 11), 0);
+
+ ResetArgs("-foo=11 -bar=12");
+ BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", 0), 11);
+ BOOST_CHECK_EQUAL(gArgs.GetArg("-bar", 11), 12);
+
+ ResetArgs("-foo=NaN -bar=NotANumber");
+ BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", 1), 0);
+ BOOST_CHECK_EQUAL(gArgs.GetArg("-bar", 11), 0);
+}
+
+BOOST_AUTO_TEST_CASE(doubledash)
+{
+ SetupArgs({"-foo", "-bar"});
+ ResetArgs("--foo");
+ BOOST_CHECK_EQUAL(gArgs.GetBoolArg("-foo", false), true);
+
+ ResetArgs("--foo=verbose --bar=1");
+ BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", ""), "verbose");
+ BOOST_CHECK_EQUAL(gArgs.GetArg("-bar", 0), 1);
+}
+
+BOOST_AUTO_TEST_CASE(boolargno)
+{
+ SetupArgs({"-foo", "-bar"});
+ ResetArgs("-nofoo");
+ BOOST_CHECK(!gArgs.GetBoolArg("-foo", true));
+ BOOST_CHECK(!gArgs.GetBoolArg("-foo", false));
+
+ ResetArgs("-nofoo=1");
+ BOOST_CHECK(!gArgs.GetBoolArg("-foo", true));
+ BOOST_CHECK(!gArgs.GetBoolArg("-foo", false));
+
+ ResetArgs("-nofoo=0");
+ BOOST_CHECK(gArgs.GetBoolArg("-foo", true));
+ BOOST_CHECK(gArgs.GetBoolArg("-foo", false));
+
+ ResetArgs("-foo --nofoo"); // --nofoo should win
+ BOOST_CHECK(!gArgs.GetBoolArg("-foo", true));
+ BOOST_CHECK(!gArgs.GetBoolArg("-foo", false));
+
+ ResetArgs("-nofoo -foo"); // foo always wins:
+ BOOST_CHECK(gArgs.GetBoolArg("-foo", true));
+ BOOST_CHECK(gArgs.GetBoolArg("-foo", false));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/hash_tests.cpp b/src/test/hash_tests.cpp
new file mode 100644
index 0000000000..6ed0209895
--- /dev/null
+++ b/src/test/hash_tests.cpp
@@ -0,0 +1,150 @@
+// Copyright (c) 2013-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <hash.h>
+#include <utilstrencodings.h>
+#include <test/test_bitcoin.h>
+
+#include <vector>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(hash_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(murmurhash3)
+{
+
+#define T(expected, seed, data) BOOST_CHECK_EQUAL(MurmurHash3(seed, ParseHex(data)), expected)
+
+ // Test MurmurHash3 with various inputs. Of course this is retested in the
+ // bloom filter tests - they would fail if MurmurHash3() had any problems -
+ // but is useful for those trying to implement Bitcoin libraries as a
+ // source of test data for their MurmurHash3() primitive during
+ // development.
+ //
+ // The magic number 0xFBA4C795 comes from CBloomFilter::Hash()
+
+ T(0x00000000U, 0x00000000, "");
+ T(0x6a396f08U, 0xFBA4C795, "");
+ T(0x81f16f39U, 0xffffffff, "");
+
+ T(0x514e28b7U, 0x00000000, "00");
+ T(0xea3f0b17U, 0xFBA4C795, "00");
+ T(0xfd6cf10dU, 0x00000000, "ff");
+
+ T(0x16c6b7abU, 0x00000000, "0011");
+ T(0x8eb51c3dU, 0x00000000, "001122");
+ T(0xb4471bf8U, 0x00000000, "00112233");
+ T(0xe2301fa8U, 0x00000000, "0011223344");
+ T(0xfc2e4a15U, 0x00000000, "001122334455");
+ T(0xb074502cU, 0x00000000, "00112233445566");
+ T(0x8034d2a0U, 0x00000000, "0011223344556677");
+ T(0xb4698defU, 0x00000000, "001122334455667788");
+
+#undef T
+}
+
+/*
+ SipHash-2-4 output with
+ k = 00 01 02 ...
+ and
+ in = (empty string)
+ in = 00 (1 byte)
+ in = 00 01 (2 bytes)
+ in = 00 01 02 (3 bytes)
+ ...
+ in = 00 01 02 ... 3e (63 bytes)
+
+ from: https://131002.net/siphash/siphash24.c
+*/
+uint64_t siphash_4_2_testvec[] = {
+ 0x726fdb47dd0e0e31, 0x74f839c593dc67fd, 0x0d6c8009d9a94f5a, 0x85676696d7fb7e2d,
+ 0xcf2794e0277187b7, 0x18765564cd99a68d, 0xcbc9466e58fee3ce, 0xab0200f58b01d137,
+ 0x93f5f5799a932462, 0x9e0082df0ba9e4b0, 0x7a5dbbc594ddb9f3, 0xf4b32f46226bada7,
+ 0x751e8fbc860ee5fb, 0x14ea5627c0843d90, 0xf723ca908e7af2ee, 0xa129ca6149be45e5,
+ 0x3f2acc7f57c29bdb, 0x699ae9f52cbe4794, 0x4bc1b3f0968dd39c, 0xbb6dc91da77961bd,
+ 0xbed65cf21aa2ee98, 0xd0f2cbb02e3b67c7, 0x93536795e3a33e88, 0xa80c038ccd5ccec8,
+ 0xb8ad50c6f649af94, 0xbce192de8a85b8ea, 0x17d835b85bbb15f3, 0x2f2e6163076bcfad,
+ 0xde4daaaca71dc9a5, 0xa6a2506687956571, 0xad87a3535c49ef28, 0x32d892fad841c342,
+ 0x7127512f72f27cce, 0xa7f32346f95978e3, 0x12e0b01abb051238, 0x15e034d40fa197ae,
+ 0x314dffbe0815a3b4, 0x027990f029623981, 0xcadcd4e59ef40c4d, 0x9abfd8766a33735c,
+ 0x0e3ea96b5304a7d0, 0xad0c42d6fc585992, 0x187306c89bc215a9, 0xd4a60abcf3792b95,
+ 0xf935451de4f21df2, 0xa9538f0419755787, 0xdb9acddff56ca510, 0xd06c98cd5c0975eb,
+ 0xe612a3cb9ecba951, 0xc766e62cfcadaf96, 0xee64435a9752fe72, 0xa192d576b245165a,
+ 0x0a8787bf8ecb74b2, 0x81b3e73d20b49b6f, 0x7fa8220ba3b2ecea, 0x245731c13ca42499,
+ 0xb78dbfaf3a8d83bd, 0xea1ad565322a1a0b, 0x60e61c23a3795013, 0x6606d7e446282b93,
+ 0x6ca4ecb15c5f91e1, 0x9f626da15c9625f3, 0xe51b38608ef25f57, 0x958a324ceb064572
+};
+
+BOOST_AUTO_TEST_CASE(siphash)
+{
+ CSipHasher hasher(0x0706050403020100ULL, 0x0F0E0D0C0B0A0908ULL);
+ BOOST_CHECK_EQUAL(hasher.Finalize(), 0x726fdb47dd0e0e31ull);
+ static const unsigned char t0[1] = {0};
+ hasher.Write(t0, 1);
+ BOOST_CHECK_EQUAL(hasher.Finalize(), 0x74f839c593dc67fdull);
+ static const unsigned char t1[7] = {1,2,3,4,5,6,7};
+ hasher.Write(t1, 7);
+ BOOST_CHECK_EQUAL(hasher.Finalize(), 0x93f5f5799a932462ull);
+ hasher.Write(0x0F0E0D0C0B0A0908ULL);
+ BOOST_CHECK_EQUAL(hasher.Finalize(), 0x3f2acc7f57c29bdbull);
+ static const unsigned char t2[2] = {16,17};
+ hasher.Write(t2, 2);
+ BOOST_CHECK_EQUAL(hasher.Finalize(), 0x4bc1b3f0968dd39cull);
+ static const unsigned char t3[9] = {18,19,20,21,22,23,24,25,26};
+ hasher.Write(t3, 9);
+ BOOST_CHECK_EQUAL(hasher.Finalize(), 0x2f2e6163076bcfadull);
+ static const unsigned char t4[5] = {27,28,29,30,31};
+ hasher.Write(t4, 5);
+ BOOST_CHECK_EQUAL(hasher.Finalize(), 0x7127512f72f27cceull);
+ hasher.Write(0x2726252423222120ULL);
+ BOOST_CHECK_EQUAL(hasher.Finalize(), 0x0e3ea96b5304a7d0ull);
+ hasher.Write(0x2F2E2D2C2B2A2928ULL);
+ BOOST_CHECK_EQUAL(hasher.Finalize(), 0xe612a3cb9ecba951ull);
+
+ BOOST_CHECK_EQUAL(SipHashUint256(0x0706050403020100ULL, 0x0F0E0D0C0B0A0908ULL, uint256S("1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100")), 0x7127512f72f27cceull);
+
+ // Check test vectors from spec, one byte at a time
+ CSipHasher hasher2(0x0706050403020100ULL, 0x0F0E0D0C0B0A0908ULL);
+ for (uint8_t x=0; x<ARRAYLEN(siphash_4_2_testvec); ++x)
+ {
+ BOOST_CHECK_EQUAL(hasher2.Finalize(), siphash_4_2_testvec[x]);
+ hasher2.Write(&x, 1);
+ }
+ // Check test vectors from spec, eight bytes at a time
+ CSipHasher hasher3(0x0706050403020100ULL, 0x0F0E0D0C0B0A0908ULL);
+ for (uint8_t x=0; x<ARRAYLEN(siphash_4_2_testvec); x+=8)
+ {
+ BOOST_CHECK_EQUAL(hasher3.Finalize(), siphash_4_2_testvec[x]);
+ hasher3.Write(uint64_t(x)|(uint64_t(x+1)<<8)|(uint64_t(x+2)<<16)|(uint64_t(x+3)<<24)|
+ (uint64_t(x+4)<<32)|(uint64_t(x+5)<<40)|(uint64_t(x+6)<<48)|(uint64_t(x+7)<<56));
+ }
+
+ CHashWriter ss(SER_DISK, CLIENT_VERSION);
+ CMutableTransaction tx;
+ // Note these tests were originally written with tx.nVersion=1
+ // and the test would be affected by default tx version bumps if not fixed.
+ tx.nVersion = 1;
+ ss << tx;
+ BOOST_CHECK_EQUAL(SipHashUint256(1, 2, ss.GetHash()), 0x79751e980c2a0a35ULL);
+
+ // Check consistency between CSipHasher and SipHashUint256[Extra].
+ FastRandomContext ctx;
+ for (int i = 0; i < 16; ++i) {
+ uint64_t k1 = ctx.rand64();
+ uint64_t k2 = ctx.rand64();
+ uint256 x = InsecureRand256();
+ uint32_t n = ctx.rand32();
+ uint8_t nb[4];
+ WriteLE32(nb, n);
+ CSipHasher sip256(k1, k2);
+ sip256.Write(x.begin(), 32);
+ CSipHasher sip288 = sip256;
+ sip288.Write(nb, 4);
+ BOOST_CHECK_EQUAL(SipHashUint256(k1, k2, x), sip256.Finalize());
+ BOOST_CHECK_EQUAL(SipHashUint256Extra(k1, k2, x, n), sip288.Finalize());
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/key_io_tests.cpp b/src/test/key_io_tests.cpp
new file mode 100644
index 0000000000..7e475ac610
--- /dev/null
+++ b/src/test/key_io_tests.cpp
@@ -0,0 +1,149 @@
+// Copyright (c) 2011-2017 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <test/data/key_io_invalid.json.h>
+#include <test/data/key_io_valid.json.h>
+
+#include <key.h>
+#include <key_io.h>
+#include <script/script.h>
+#include <utilstrencodings.h>
+#include <test/test_bitcoin.h>
+
+#include <boost/test/unit_test.hpp>
+
+#include <univalue.h>
+
+extern UniValue read_json(const std::string& jsondata);
+
+BOOST_FIXTURE_TEST_SUITE(key_io_tests, BasicTestingSetup)
+
+// Goal: check that parsed keys match test payload
+BOOST_AUTO_TEST_CASE(key_io_valid_parse)
+{
+ UniValue tests = read_json(std::string(json_tests::key_io_valid, json_tests::key_io_valid + sizeof(json_tests::key_io_valid)));
+ CKey privkey;
+ CTxDestination destination;
+ SelectParams(CBaseChainParams::MAIN);
+
+ for (unsigned int idx = 0; idx < tests.size(); idx++) {
+ UniValue test = tests[idx];
+ std::string strTest = test.write();
+ if (test.size() < 3) { // Allow for extra stuff (useful for comments)
+ BOOST_ERROR("Bad test: " << strTest);
+ continue;
+ }
+ std::string exp_base58string = test[0].get_str();
+ std::vector<unsigned char> exp_payload = ParseHex(test[1].get_str());
+ const UniValue &metadata = test[2].get_obj();
+ bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
+ SelectParams(find_value(metadata, "chain").get_str());
+ bool try_case_flip = find_value(metadata, "tryCaseFlip").isNull() ? false : find_value(metadata, "tryCaseFlip").get_bool();
+ if (isPrivkey) {
+ bool isCompressed = find_value(metadata, "isCompressed").get_bool();
+ // Must be valid private key
+ privkey = DecodeSecret(exp_base58string);
+ BOOST_CHECK_MESSAGE(privkey.IsValid(), "!IsValid:" + strTest);
+ BOOST_CHECK_MESSAGE(privkey.IsCompressed() == isCompressed, "compressed mismatch:" + strTest);
+ BOOST_CHECK_MESSAGE(privkey.size() == exp_payload.size() && std::equal(privkey.begin(), privkey.end(), exp_payload.begin()), "key mismatch:" + strTest);
+
+ // Private key must be invalid public key
+ destination = DecodeDestination(exp_base58string);
+ BOOST_CHECK_MESSAGE(!IsValidDestination(destination), "IsValid privkey as pubkey:" + strTest);
+ } else {
+ // Must be valid public key
+ destination = DecodeDestination(exp_base58string);
+ CScript script = GetScriptForDestination(destination);
+ BOOST_CHECK_MESSAGE(IsValidDestination(destination), "!IsValid:" + strTest);
+ BOOST_CHECK_EQUAL(HexStr(script), HexStr(exp_payload));
+
+ // Try flipped case version
+ for (char& c : exp_base58string) {
+ if (c >= 'a' && c <= 'z') {
+ c = (c - 'a') + 'A';
+ } else if (c >= 'A' && c <= 'Z') {
+ c = (c - 'A') + 'a';
+ }
+ }
+ destination = DecodeDestination(exp_base58string);
+ BOOST_CHECK_MESSAGE(IsValidDestination(destination) == try_case_flip, "!IsValid case flipped:" + strTest);
+ if (IsValidDestination(destination)) {
+ script = GetScriptForDestination(destination);
+ BOOST_CHECK_EQUAL(HexStr(script), HexStr(exp_payload));
+ }
+
+ // Public key must be invalid private key
+ privkey = DecodeSecret(exp_base58string);
+ BOOST_CHECK_MESSAGE(!privkey.IsValid(), "IsValid pubkey as privkey:" + strTest);
+ }
+ }
+}
+
+// Goal: check that generated keys match test vectors
+BOOST_AUTO_TEST_CASE(key_io_valid_gen)
+{
+ UniValue tests = read_json(std::string(json_tests::key_io_valid, json_tests::key_io_valid + sizeof(json_tests::key_io_valid)));
+
+ for (unsigned int idx = 0; idx < tests.size(); idx++) {
+ UniValue test = tests[idx];
+ std::string strTest = test.write();
+ if (test.size() < 3) // Allow for extra stuff (useful for comments)
+ {
+ BOOST_ERROR("Bad test: " << strTest);
+ continue;
+ }
+ std::string exp_base58string = test[0].get_str();
+ std::vector<unsigned char> exp_payload = ParseHex(test[1].get_str());
+ const UniValue &metadata = test[2].get_obj();
+ bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
+ SelectParams(find_value(metadata, "chain").get_str());
+ if (isPrivkey) {
+ bool isCompressed = find_value(metadata, "isCompressed").get_bool();
+ CKey key;
+ key.Set(exp_payload.begin(), exp_payload.end(), isCompressed);
+ assert(key.IsValid());
+ BOOST_CHECK_MESSAGE(EncodeSecret(key) == exp_base58string, "result mismatch: " + strTest);
+ } else {
+ CTxDestination dest;
+ CScript exp_script(exp_payload.begin(), exp_payload.end());
+ ExtractDestination(exp_script, dest);
+ std::string address = EncodeDestination(dest);
+
+ BOOST_CHECK_EQUAL(address, exp_base58string);
+ }
+ }
+
+ SelectParams(CBaseChainParams::MAIN);
+}
+
+
+// Goal: check that base58 parsing code is robust against a variety of corrupted data
+BOOST_AUTO_TEST_CASE(key_io_invalid)
+{
+ UniValue tests = read_json(std::string(json_tests::key_io_invalid, json_tests::key_io_invalid + sizeof(json_tests::key_io_invalid))); // Negative testcases
+ CKey privkey;
+ CTxDestination destination;
+
+ for (unsigned int idx = 0; idx < tests.size(); idx++) {
+ UniValue test = tests[idx];
+ std::string strTest = test.write();
+ if (test.size() < 1) // Allow for extra stuff (useful for comments)
+ {
+ BOOST_ERROR("Bad test: " << strTest);
+ continue;
+ }
+ std::string exp_base58string = test[0].get_str();
+
+ // must be invalid as public and as private key
+ for (auto chain : { CBaseChainParams::MAIN, CBaseChainParams::TESTNET, CBaseChainParams::REGTEST }) {
+ SelectParams(chain);
+ destination = DecodeDestination(exp_base58string);
+ BOOST_CHECK_MESSAGE(!IsValidDestination(destination), "IsValid pubkey in mainnet:" + strTest);
+ privkey = DecodeSecret(exp_base58string);
+ BOOST_CHECK_MESSAGE(!privkey.IsValid(), "IsValid privkey in mainnet:" + strTest);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp
new file mode 100644
index 0000000000..d9c3525b19
--- /dev/null
+++ b/src/test/key_tests.cpp
@@ -0,0 +1,155 @@
+// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <key.h>
+
+#include <key_io.h>
+#include <script/script.h>
+#include <uint256.h>
+#include <util.h>
+#include <utilstrencodings.h>
+#include <test/test_bitcoin.h>
+
+#include <string>
+#include <vector>
+
+#include <boost/test/unit_test.hpp>
+
+static const std::string strSecret1 = "5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHfmFiWtmAbrj";
+static const std::string strSecret2 = "5KC4ejrDjv152FGwP386VD1i2NYc5KkfSMyv1nGy1VGDxGHqVY3";
+static const std::string strSecret1C = "Kwr371tjA9u2rFSMZjTNun2PXXP3WPZu2afRHTcta6KxEUdm1vEw";
+static const std::string strSecret2C = "L3Hq7a8FEQwJkW1M2GNKDW28546Vp5miewcCzSqUD9kCAXrJdS3g";
+static const std::string addr1 = "1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ";
+static const std::string addr2 = "1F5y5E5FMc5YzdJtB9hLaUe43GDxEKXENJ";
+static const std::string addr1C = "1NoJrossxPBKfCHuJXT4HadJrXRE9Fxiqs";
+static const std::string addr2C = "1CRj2HyM1CXWzHAXLQtiGLyggNT9WQqsDs";
+
+static const std::string strAddressBad = "1HV9Lc3sNHZxwj4Zk6fB38tEmBryq2cBiF";
+
+
+BOOST_FIXTURE_TEST_SUITE(key_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(key_test1)
+{
+ CKey key1 = DecodeSecret(strSecret1);
+ BOOST_CHECK(key1.IsValid() && !key1.IsCompressed());
+ CKey key2 = DecodeSecret(strSecret2);
+ BOOST_CHECK(key2.IsValid() && !key2.IsCompressed());
+ CKey key1C = DecodeSecret(strSecret1C);
+ BOOST_CHECK(key1C.IsValid() && key1C.IsCompressed());
+ CKey key2C = DecodeSecret(strSecret2C);
+ BOOST_CHECK(key2C.IsValid() && key2C.IsCompressed());
+ CKey bad_key = DecodeSecret(strAddressBad);
+ BOOST_CHECK(!bad_key.IsValid());
+
+ CPubKey pubkey1 = key1. GetPubKey();
+ CPubKey pubkey2 = key2. GetPubKey();
+ CPubKey pubkey1C = key1C.GetPubKey();
+ CPubKey pubkey2C = key2C.GetPubKey();
+
+ BOOST_CHECK(key1.VerifyPubKey(pubkey1));
+ BOOST_CHECK(!key1.VerifyPubKey(pubkey1C));
+ BOOST_CHECK(!key1.VerifyPubKey(pubkey2));
+ BOOST_CHECK(!key1.VerifyPubKey(pubkey2C));
+
+ BOOST_CHECK(!key1C.VerifyPubKey(pubkey1));
+ BOOST_CHECK(key1C.VerifyPubKey(pubkey1C));
+ BOOST_CHECK(!key1C.VerifyPubKey(pubkey2));
+ BOOST_CHECK(!key1C.VerifyPubKey(pubkey2C));
+
+ BOOST_CHECK(!key2.VerifyPubKey(pubkey1));
+ BOOST_CHECK(!key2.VerifyPubKey(pubkey1C));
+ BOOST_CHECK(key2.VerifyPubKey(pubkey2));
+ BOOST_CHECK(!key2.VerifyPubKey(pubkey2C));
+
+ BOOST_CHECK(!key2C.VerifyPubKey(pubkey1));
+ BOOST_CHECK(!key2C.VerifyPubKey(pubkey1C));
+ BOOST_CHECK(!key2C.VerifyPubKey(pubkey2));
+ BOOST_CHECK(key2C.VerifyPubKey(pubkey2C));
+
+ BOOST_CHECK(DecodeDestination(addr1) == CTxDestination(pubkey1.GetID()));
+ BOOST_CHECK(DecodeDestination(addr2) == CTxDestination(pubkey2.GetID()));
+ BOOST_CHECK(DecodeDestination(addr1C) == CTxDestination(pubkey1C.GetID()));
+ BOOST_CHECK(DecodeDestination(addr2C) == CTxDestination(pubkey2C.GetID()));
+
+ for (int n=0; n<16; n++)
+ {
+ std::string strMsg = strprintf("Very secret message %i: 11", n);
+ uint256 hashMsg = Hash(strMsg.begin(), strMsg.end());
+
+ // normal signatures
+
+ std::vector<unsigned char> sign1, sign2, sign1C, sign2C;
+
+ BOOST_CHECK(key1.Sign (hashMsg, sign1));
+ BOOST_CHECK(key2.Sign (hashMsg, sign2));
+ BOOST_CHECK(key1C.Sign(hashMsg, sign1C));
+ BOOST_CHECK(key2C.Sign(hashMsg, sign2C));
+
+ BOOST_CHECK( pubkey1.Verify(hashMsg, sign1));
+ BOOST_CHECK(!pubkey1.Verify(hashMsg, sign2));
+ BOOST_CHECK( pubkey1.Verify(hashMsg, sign1C));
+ BOOST_CHECK(!pubkey1.Verify(hashMsg, sign2C));
+
+ BOOST_CHECK(!pubkey2.Verify(hashMsg, sign1));
+ BOOST_CHECK( pubkey2.Verify(hashMsg, sign2));
+ BOOST_CHECK(!pubkey2.Verify(hashMsg, sign1C));
+ BOOST_CHECK( pubkey2.Verify(hashMsg, sign2C));
+
+ BOOST_CHECK( pubkey1C.Verify(hashMsg, sign1));
+ BOOST_CHECK(!pubkey1C.Verify(hashMsg, sign2));
+ BOOST_CHECK( pubkey1C.Verify(hashMsg, sign1C));
+ BOOST_CHECK(!pubkey1C.Verify(hashMsg, sign2C));
+
+ BOOST_CHECK(!pubkey2C.Verify(hashMsg, sign1));
+ BOOST_CHECK( pubkey2C.Verify(hashMsg, sign2));
+ BOOST_CHECK(!pubkey2C.Verify(hashMsg, sign1C));
+ BOOST_CHECK( pubkey2C.Verify(hashMsg, sign2C));
+
+ // compact signatures (with key recovery)
+
+ std::vector<unsigned char> csign1, csign2, csign1C, csign2C;
+
+ BOOST_CHECK(key1.SignCompact (hashMsg, csign1));
+ BOOST_CHECK(key2.SignCompact (hashMsg, csign2));
+ BOOST_CHECK(key1C.SignCompact(hashMsg, csign1C));
+ BOOST_CHECK(key2C.SignCompact(hashMsg, csign2C));
+
+ CPubKey rkey1, rkey2, rkey1C, rkey2C;
+
+ BOOST_CHECK(rkey1.RecoverCompact (hashMsg, csign1));
+ BOOST_CHECK(rkey2.RecoverCompact (hashMsg, csign2));
+ BOOST_CHECK(rkey1C.RecoverCompact(hashMsg, csign1C));
+ BOOST_CHECK(rkey2C.RecoverCompact(hashMsg, csign2C));
+
+ BOOST_CHECK(rkey1 == pubkey1);
+ BOOST_CHECK(rkey2 == pubkey2);
+ BOOST_CHECK(rkey1C == pubkey1C);
+ BOOST_CHECK(rkey2C == pubkey2C);
+ }
+
+ // test deterministic signing
+
+ std::vector<unsigned char> detsig, detsigc;
+ std::string strMsg = "Very deterministic message";
+ uint256 hashMsg = Hash(strMsg.begin(), strMsg.end());
+ BOOST_CHECK(key1.Sign(hashMsg, detsig));
+ BOOST_CHECK(key1C.Sign(hashMsg, detsigc));
+ BOOST_CHECK(detsig == detsigc);
+ BOOST_CHECK(detsig == ParseHex("304402205dbbddda71772d95ce91cd2d14b592cfbc1dd0aabd6a394b6c2d377bbe59d31d022014ddda21494a4e221f0824f0b8b924c43fa43c0ad57dccdaa11f81a6bd4582f6"));
+ BOOST_CHECK(key2.Sign(hashMsg, detsig));
+ BOOST_CHECK(key2C.Sign(hashMsg, detsigc));
+ BOOST_CHECK(detsig == detsigc);
+ BOOST_CHECK(detsig == ParseHex("3044022052d8a32079c11e79db95af63bb9600c5b04f21a9ca33dc129c2bfa8ac9dc1cd5022061d8ae5e0f6c1a16bde3719c64c2fd70e404b6428ab9a69566962e8771b5944d"));
+ BOOST_CHECK(key1.SignCompact(hashMsg, detsig));
+ BOOST_CHECK(key1C.SignCompact(hashMsg, detsigc));
+ BOOST_CHECK(detsig == ParseHex("1c5dbbddda71772d95ce91cd2d14b592cfbc1dd0aabd6a394b6c2d377bbe59d31d14ddda21494a4e221f0824f0b8b924c43fa43c0ad57dccdaa11f81a6bd4582f6"));
+ BOOST_CHECK(detsigc == ParseHex("205dbbddda71772d95ce91cd2d14b592cfbc1dd0aabd6a394b6c2d377bbe59d31d14ddda21494a4e221f0824f0b8b924c43fa43c0ad57dccdaa11f81a6bd4582f6"));
+ BOOST_CHECK(key2.SignCompact(hashMsg, detsig));
+ BOOST_CHECK(key2C.SignCompact(hashMsg, detsigc));
+ BOOST_CHECK(detsig == ParseHex("1c52d8a32079c11e79db95af63bb9600c5b04f21a9ca33dc129c2bfa8ac9dc1cd561d8ae5e0f6c1a16bde3719c64c2fd70e404b6428ab9a69566962e8771b5944d"));
+ BOOST_CHECK(detsigc == ParseHex("2052d8a32079c11e79db95af63bb9600c5b04f21a9ca33dc129c2bfa8ac9dc1cd561d8ae5e0f6c1a16bde3719c64c2fd70e404b6428ab9a69566962e8771b5944d"));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/limitedmap_tests.cpp b/src/test/limitedmap_tests.cpp
new file mode 100644
index 0000000000..0788f75b04
--- /dev/null
+++ b/src/test/limitedmap_tests.cpp
@@ -0,0 +1,101 @@
+// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <limitedmap.h>
+
+#include <test/test_bitcoin.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(limitedmap_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(limitedmap_test)
+{
+ // create a limitedmap capped at 10 items
+ limitedmap<int, int> map(10);
+
+ // check that the max size is 10
+ BOOST_CHECK(map.max_size() == 10);
+
+ // check that it's empty
+ BOOST_CHECK(map.size() == 0);
+
+ // insert (-1, -1)
+ map.insert(std::pair<int, int>(-1, -1));
+
+ // make sure that the size is updated
+ BOOST_CHECK(map.size() == 1);
+
+ // make sure that the new item is in the map
+ BOOST_CHECK(map.count(-1) == 1);
+
+ // insert 10 new items
+ for (int i = 0; i < 10; i++) {
+ map.insert(std::pair<int, int>(i, i + 1));
+ }
+
+ // make sure that the map now contains 10 items...
+ BOOST_CHECK(map.size() == 10);
+
+ // ...and that the first item has been discarded
+ BOOST_CHECK(map.count(-1) == 0);
+
+ // iterate over the map, both with an index and an iterator
+ limitedmap<int, int>::const_iterator it = map.begin();
+ for (int i = 0; i < 10; i++) {
+ // make sure the item is present
+ BOOST_CHECK(map.count(i) == 1);
+
+ // use the iterator to check for the expected key and value
+ BOOST_CHECK(it->first == i);
+ BOOST_CHECK(it->second == i + 1);
+
+ // use find to check for the value
+ BOOST_CHECK(map.find(i)->second == i + 1);
+
+ // update and recheck
+ map.update(it, i + 2);
+ BOOST_CHECK(map.find(i)->second == i + 2);
+
+ it++;
+ }
+
+ // check that we've exhausted the iterator
+ BOOST_CHECK(it == map.end());
+
+ // resize the map to 5 items
+ map.max_size(5);
+
+ // check that the max size and size are now 5
+ BOOST_CHECK(map.max_size() == 5);
+ BOOST_CHECK(map.size() == 5);
+
+ // check that items less than 5 have been discarded
+ // and items greater than 5 are retained
+ for (int i = 0; i < 10; i++) {
+ if (i < 5) {
+ BOOST_CHECK(map.count(i) == 0);
+ } else {
+ BOOST_CHECK(map.count(i) == 1);
+ }
+ }
+
+ // erase some items not in the map
+ for (int i = 100; i < 1000; i += 100) {
+ map.erase(i);
+ }
+
+ // check that the size is unaffected
+ BOOST_CHECK(map.size() == 5);
+
+ // erase the remaining elements
+ for (int i = 5; i < 10; i++) {
+ map.erase(i);
+ }
+
+ // check that the map is now empty
+ BOOST_CHECK(map.empty());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/main_tests.cpp b/src/test/main_tests.cpp
new file mode 100644
index 0000000000..5b3f2bc578
--- /dev/null
+++ b/src/test/main_tests.cpp
@@ -0,0 +1,77 @@
+// Copyright (c) 2014-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <chainparams.h>
+#include <validation.h>
+#include <net.h>
+
+#include <test/test_bitcoin.h>
+
+#include <boost/signals2/signal.hpp>
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(main_tests, TestingSetup)
+
+static void TestBlockSubsidyHalvings(const Consensus::Params& consensusParams)
+{
+ int maxHalvings = 64;
+ CAmount nInitialSubsidy = 50 * COIN;
+
+ CAmount nPreviousSubsidy = nInitialSubsidy * 2; // for height == 0
+ BOOST_CHECK_EQUAL(nPreviousSubsidy, nInitialSubsidy * 2);
+ for (int nHalvings = 0; nHalvings < maxHalvings; nHalvings++) {
+ int nHeight = nHalvings * consensusParams.nSubsidyHalvingInterval;
+ CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams);
+ BOOST_CHECK(nSubsidy <= nInitialSubsidy);
+ BOOST_CHECK_EQUAL(nSubsidy, nPreviousSubsidy / 2);
+ nPreviousSubsidy = nSubsidy;
+ }
+ BOOST_CHECK_EQUAL(GetBlockSubsidy(maxHalvings * consensusParams.nSubsidyHalvingInterval, consensusParams), 0);
+}
+
+static void TestBlockSubsidyHalvings(int nSubsidyHalvingInterval)
+{
+ Consensus::Params consensusParams;
+ consensusParams.nSubsidyHalvingInterval = nSubsidyHalvingInterval;
+ TestBlockSubsidyHalvings(consensusParams);
+}
+
+BOOST_AUTO_TEST_CASE(block_subsidy_test)
+{
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
+ TestBlockSubsidyHalvings(chainParams->GetConsensus()); // As in main
+ TestBlockSubsidyHalvings(150); // As in regtest
+ TestBlockSubsidyHalvings(1000); // Just another interval
+}
+
+BOOST_AUTO_TEST_CASE(subsidy_limit_test)
+{
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
+ CAmount nSum = 0;
+ for (int nHeight = 0; nHeight < 14000000; nHeight += 1000) {
+ CAmount nSubsidy = GetBlockSubsidy(nHeight, chainParams->GetConsensus());
+ BOOST_CHECK(nSubsidy <= 50 * COIN);
+ nSum += nSubsidy * 1000;
+ BOOST_CHECK(MoneyRange(nSum));
+ }
+ BOOST_CHECK_EQUAL(nSum, CAmount{2099999997690000});
+}
+
+static bool ReturnFalse() { return false; }
+static bool ReturnTrue() { return true; }
+
+BOOST_AUTO_TEST_CASE(test_combiner_all)
+{
+ boost::signals2::signal<bool (), CombinerAll> Test;
+ BOOST_CHECK(Test());
+ Test.connect(&ReturnFalse);
+ BOOST_CHECK(!Test());
+ Test.connect(&ReturnTrue);
+ BOOST_CHECK(!Test());
+ Test.disconnect(&ReturnFalse);
+ BOOST_CHECK(Test());
+ Test.disconnect(&ReturnTrue);
+ BOOST_CHECK(Test());
+}
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/mempool_tests.cpp b/src/test/mempool_tests.cpp
new file mode 100644
index 0000000000..e416de098e
--- /dev/null
+++ b/src/test/mempool_tests.cpp
@@ -0,0 +1,752 @@
+// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <policy/policy.h>
+#include <txmempool.h>
+#include <util.h>
+
+#include <test/test_bitcoin.h>
+
+#include <boost/test/unit_test.hpp>
+#include <list>
+#include <vector>
+
+BOOST_FIXTURE_TEST_SUITE(mempool_tests, TestingSetup)
+
+BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
+{
+ // Test CTxMemPool::remove functionality
+
+ TestMemPoolEntryHelper entry;
+ // Parent transaction with three children,
+ // and three grand-children:
+ CMutableTransaction txParent;
+ txParent.vin.resize(1);
+ txParent.vin[0].scriptSig = CScript() << OP_11;
+ txParent.vout.resize(3);
+ for (int i = 0; i < 3; i++)
+ {
+ txParent.vout[i].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ txParent.vout[i].nValue = 33000LL;
+ }
+ CMutableTransaction txChild[3];
+ for (int i = 0; i < 3; i++)
+ {
+ txChild[i].vin.resize(1);
+ txChild[i].vin[0].scriptSig = CScript() << OP_11;
+ txChild[i].vin[0].prevout.hash = txParent.GetHash();
+ txChild[i].vin[0].prevout.n = i;
+ txChild[i].vout.resize(1);
+ txChild[i].vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ txChild[i].vout[0].nValue = 11000LL;
+ }
+ CMutableTransaction txGrandChild[3];
+ for (int i = 0; i < 3; i++)
+ {
+ txGrandChild[i].vin.resize(1);
+ txGrandChild[i].vin[0].scriptSig = CScript() << OP_11;
+ txGrandChild[i].vin[0].prevout.hash = txChild[i].GetHash();
+ txGrandChild[i].vin[0].prevout.n = 0;
+ txGrandChild[i].vout.resize(1);
+ txGrandChild[i].vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ txGrandChild[i].vout[0].nValue = 11000LL;
+ }
+
+
+ CTxMemPool testPool;
+ LOCK(testPool.cs);
+
+ // Nothing in pool, remove should do nothing:
+ unsigned int poolSize = testPool.size();
+ testPool.removeRecursive(txParent);
+ BOOST_CHECK_EQUAL(testPool.size(), poolSize);
+
+ // Just the parent:
+ testPool.addUnchecked(txParent.GetHash(), entry.FromTx(txParent));
+ poolSize = testPool.size();
+ testPool.removeRecursive(txParent);
+ BOOST_CHECK_EQUAL(testPool.size(), poolSize - 1);
+
+ // Parent, children, grandchildren:
+ testPool.addUnchecked(txParent.GetHash(), entry.FromTx(txParent));
+ for (int i = 0; i < 3; i++)
+ {
+ testPool.addUnchecked(txChild[i].GetHash(), entry.FromTx(txChild[i]));
+ testPool.addUnchecked(txGrandChild[i].GetHash(), entry.FromTx(txGrandChild[i]));
+ }
+ // Remove Child[0], GrandChild[0] should be removed:
+ poolSize = testPool.size();
+ testPool.removeRecursive(txChild[0]);
+ BOOST_CHECK_EQUAL(testPool.size(), poolSize - 2);
+ // ... make sure grandchild and child are gone:
+ poolSize = testPool.size();
+ testPool.removeRecursive(txGrandChild[0]);
+ BOOST_CHECK_EQUAL(testPool.size(), poolSize);
+ poolSize = testPool.size();
+ testPool.removeRecursive(txChild[0]);
+ BOOST_CHECK_EQUAL(testPool.size(), poolSize);
+ // Remove parent, all children/grandchildren should go:
+ poolSize = testPool.size();
+ testPool.removeRecursive(txParent);
+ BOOST_CHECK_EQUAL(testPool.size(), poolSize - 5);
+ BOOST_CHECK_EQUAL(testPool.size(), 0U);
+
+ // Add children and grandchildren, but NOT the parent (simulate the parent being in a block)
+ for (int i = 0; i < 3; i++)
+ {
+ testPool.addUnchecked(txChild[i].GetHash(), entry.FromTx(txChild[i]));
+ testPool.addUnchecked(txGrandChild[i].GetHash(), entry.FromTx(txGrandChild[i]));
+ }
+ // Now remove the parent, as might happen if a block-re-org occurs but the parent cannot be
+ // put into the mempool (maybe because it is non-standard):
+ poolSize = testPool.size();
+ testPool.removeRecursive(txParent);
+ BOOST_CHECK_EQUAL(testPool.size(), poolSize - 6);
+ BOOST_CHECK_EQUAL(testPool.size(), 0U);
+}
+
+template<typename name>
+static void CheckSort(CTxMemPool &pool, std::vector<std::string> &sortedOrder) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)
+{
+ BOOST_CHECK_EQUAL(pool.size(), sortedOrder.size());
+ typename CTxMemPool::indexed_transaction_set::index<name>::type::iterator it = pool.mapTx.get<name>().begin();
+ int count=0;
+ for (; it != pool.mapTx.get<name>().end(); ++it, ++count) {
+ BOOST_CHECK_EQUAL(it->GetTx().GetHash().ToString(), sortedOrder[count]);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(MempoolIndexingTest)
+{
+ CTxMemPool pool;
+ LOCK(pool.cs);
+ TestMemPoolEntryHelper entry;
+
+ /* 3rd highest fee */
+ CMutableTransaction tx1 = CMutableTransaction();
+ tx1.vout.resize(1);
+ tx1.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx1.vout[0].nValue = 10 * COIN;
+ pool.addUnchecked(tx1.GetHash(), entry.Fee(10000LL).FromTx(tx1));
+
+ /* highest fee */
+ CMutableTransaction tx2 = CMutableTransaction();
+ tx2.vout.resize(1);
+ tx2.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx2.vout[0].nValue = 2 * COIN;
+ pool.addUnchecked(tx2.GetHash(), entry.Fee(20000LL).FromTx(tx2));
+
+ /* lowest fee */
+ CMutableTransaction tx3 = CMutableTransaction();
+ tx3.vout.resize(1);
+ tx3.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx3.vout[0].nValue = 5 * COIN;
+ pool.addUnchecked(tx3.GetHash(), entry.Fee(0LL).FromTx(tx3));
+
+ /* 2nd highest fee */
+ CMutableTransaction tx4 = CMutableTransaction();
+ tx4.vout.resize(1);
+ tx4.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx4.vout[0].nValue = 6 * COIN;
+ pool.addUnchecked(tx4.GetHash(), entry.Fee(15000LL).FromTx(tx4));
+
+ /* equal fee rate to tx1, but newer */
+ CMutableTransaction tx5 = CMutableTransaction();
+ tx5.vout.resize(1);
+ tx5.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx5.vout[0].nValue = 11 * COIN;
+ entry.nTime = 1;
+ pool.addUnchecked(tx5.GetHash(), entry.Fee(10000LL).FromTx(tx5));
+ BOOST_CHECK_EQUAL(pool.size(), 5U);
+
+ std::vector<std::string> sortedOrder;
+ sortedOrder.resize(5);
+ sortedOrder[0] = tx3.GetHash().ToString(); // 0
+ sortedOrder[1] = tx5.GetHash().ToString(); // 10000
+ sortedOrder[2] = tx1.GetHash().ToString(); // 10000
+ sortedOrder[3] = tx4.GetHash().ToString(); // 15000
+ sortedOrder[4] = tx2.GetHash().ToString(); // 20000
+ CheckSort<descendant_score>(pool, sortedOrder);
+
+ /* low fee but with high fee child */
+ /* tx6 -> tx7 -> tx8, tx9 -> tx10 */
+ CMutableTransaction tx6 = CMutableTransaction();
+ tx6.vout.resize(1);
+ tx6.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx6.vout[0].nValue = 20 * COIN;
+ pool.addUnchecked(tx6.GetHash(), entry.Fee(0LL).FromTx(tx6));
+ BOOST_CHECK_EQUAL(pool.size(), 6U);
+ // Check that at this point, tx6 is sorted low
+ sortedOrder.insert(sortedOrder.begin(), tx6.GetHash().ToString());
+ CheckSort<descendant_score>(pool, sortedOrder);
+
+ CTxMemPool::setEntries setAncestors;
+ setAncestors.insert(pool.mapTx.find(tx6.GetHash()));
+ CMutableTransaction tx7 = CMutableTransaction();
+ tx7.vin.resize(1);
+ tx7.vin[0].prevout = COutPoint(tx6.GetHash(), 0);
+ tx7.vin[0].scriptSig = CScript() << OP_11;
+ tx7.vout.resize(2);
+ tx7.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx7.vout[0].nValue = 10 * COIN;
+ tx7.vout[1].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx7.vout[1].nValue = 1 * COIN;
+
+ CTxMemPool::setEntries setAncestorsCalculated;
+ std::string dummy;
+ BOOST_CHECK_EQUAL(pool.CalculateMemPoolAncestors(entry.Fee(2000000LL).FromTx(tx7), setAncestorsCalculated, 100, 1000000, 1000, 1000000, dummy), true);
+ BOOST_CHECK(setAncestorsCalculated == setAncestors);
+
+ pool.addUnchecked(tx7.GetHash(), entry.FromTx(tx7), setAncestors);
+ BOOST_CHECK_EQUAL(pool.size(), 7U);
+
+ // Now tx6 should be sorted higher (high fee child): tx7, tx6, tx2, ...
+ sortedOrder.erase(sortedOrder.begin());
+ sortedOrder.push_back(tx6.GetHash().ToString());
+ sortedOrder.push_back(tx7.GetHash().ToString());
+ CheckSort<descendant_score>(pool, sortedOrder);
+
+ /* low fee child of tx7 */
+ CMutableTransaction tx8 = CMutableTransaction();
+ tx8.vin.resize(1);
+ tx8.vin[0].prevout = COutPoint(tx7.GetHash(), 0);
+ tx8.vin[0].scriptSig = CScript() << OP_11;
+ tx8.vout.resize(1);
+ tx8.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx8.vout[0].nValue = 10 * COIN;
+ setAncestors.insert(pool.mapTx.find(tx7.GetHash()));
+ pool.addUnchecked(tx8.GetHash(), entry.Fee(0LL).Time(2).FromTx(tx8), setAncestors);
+
+ // Now tx8 should be sorted low, but tx6/tx both high
+ sortedOrder.insert(sortedOrder.begin(), tx8.GetHash().ToString());
+ CheckSort<descendant_score>(pool, sortedOrder);
+
+ /* low fee child of tx7 */
+ CMutableTransaction tx9 = CMutableTransaction();
+ tx9.vin.resize(1);
+ tx9.vin[0].prevout = COutPoint(tx7.GetHash(), 1);
+ tx9.vin[0].scriptSig = CScript() << OP_11;
+ tx9.vout.resize(1);
+ tx9.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx9.vout[0].nValue = 1 * COIN;
+ pool.addUnchecked(tx9.GetHash(), entry.Fee(0LL).Time(3).FromTx(tx9), setAncestors);
+
+ // tx9 should be sorted low
+ BOOST_CHECK_EQUAL(pool.size(), 9U);
+ sortedOrder.insert(sortedOrder.begin(), tx9.GetHash().ToString());
+ CheckSort<descendant_score>(pool, sortedOrder);
+
+ std::vector<std::string> snapshotOrder = sortedOrder;
+
+ setAncestors.insert(pool.mapTx.find(tx8.GetHash()));
+ setAncestors.insert(pool.mapTx.find(tx9.GetHash()));
+ /* tx10 depends on tx8 and tx9 and has a high fee*/
+ CMutableTransaction tx10 = CMutableTransaction();
+ tx10.vin.resize(2);
+ tx10.vin[0].prevout = COutPoint(tx8.GetHash(), 0);
+ tx10.vin[0].scriptSig = CScript() << OP_11;
+ tx10.vin[1].prevout = COutPoint(tx9.GetHash(), 0);
+ tx10.vin[1].scriptSig = CScript() << OP_11;
+ tx10.vout.resize(1);
+ tx10.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx10.vout[0].nValue = 10 * COIN;
+
+ setAncestorsCalculated.clear();
+ BOOST_CHECK_EQUAL(pool.CalculateMemPoolAncestors(entry.Fee(200000LL).Time(4).FromTx(tx10), setAncestorsCalculated, 100, 1000000, 1000, 1000000, dummy), true);
+ BOOST_CHECK(setAncestorsCalculated == setAncestors);
+
+ pool.addUnchecked(tx10.GetHash(), entry.FromTx(tx10), setAncestors);
+
+ /**
+ * tx8 and tx9 should both now be sorted higher
+ * Final order after tx10 is added:
+ *
+ * tx3 = 0 (1)
+ * tx5 = 10000 (1)
+ * tx1 = 10000 (1)
+ * tx4 = 15000 (1)
+ * tx2 = 20000 (1)
+ * tx9 = 200k (2 txs)
+ * tx8 = 200k (2 txs)
+ * tx10 = 200k (1 tx)
+ * tx6 = 2.2M (5 txs)
+ * tx7 = 2.2M (4 txs)
+ */
+ sortedOrder.erase(sortedOrder.begin(), sortedOrder.begin()+2); // take out tx9, tx8 from the beginning
+ sortedOrder.insert(sortedOrder.begin()+5, tx9.GetHash().ToString());
+ sortedOrder.insert(sortedOrder.begin()+6, tx8.GetHash().ToString());
+ sortedOrder.insert(sortedOrder.begin()+7, tx10.GetHash().ToString()); // tx10 is just before tx6
+ CheckSort<descendant_score>(pool, sortedOrder);
+
+ // there should be 10 transactions in the mempool
+ BOOST_CHECK_EQUAL(pool.size(), 10U);
+
+ // Now try removing tx10 and verify the sort order returns to normal
+ pool.removeRecursive(pool.mapTx.find(tx10.GetHash())->GetTx());
+ CheckSort<descendant_score>(pool, snapshotOrder);
+
+ pool.removeRecursive(pool.mapTx.find(tx9.GetHash())->GetTx());
+ pool.removeRecursive(pool.mapTx.find(tx8.GetHash())->GetTx());
+}
+
+BOOST_AUTO_TEST_CASE(MempoolAncestorIndexingTest)
+{
+ CTxMemPool pool;
+ LOCK(pool.cs);
+ TestMemPoolEntryHelper entry;
+
+ /* 3rd highest fee */
+ CMutableTransaction tx1 = CMutableTransaction();
+ tx1.vout.resize(1);
+ tx1.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx1.vout[0].nValue = 10 * COIN;
+ pool.addUnchecked(tx1.GetHash(), entry.Fee(10000LL).FromTx(tx1));
+
+ /* highest fee */
+ CMutableTransaction tx2 = CMutableTransaction();
+ tx2.vout.resize(1);
+ tx2.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx2.vout[0].nValue = 2 * COIN;
+ pool.addUnchecked(tx2.GetHash(), entry.Fee(20000LL).FromTx(tx2));
+ uint64_t tx2Size = GetVirtualTransactionSize(tx2);
+
+ /* lowest fee */
+ CMutableTransaction tx3 = CMutableTransaction();
+ tx3.vout.resize(1);
+ tx3.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx3.vout[0].nValue = 5 * COIN;
+ pool.addUnchecked(tx3.GetHash(), entry.Fee(0LL).FromTx(tx3));
+
+ /* 2nd highest fee */
+ CMutableTransaction tx4 = CMutableTransaction();
+ tx4.vout.resize(1);
+ tx4.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx4.vout[0].nValue = 6 * COIN;
+ pool.addUnchecked(tx4.GetHash(), entry.Fee(15000LL).FromTx(tx4));
+
+ /* equal fee rate to tx1, but newer */
+ CMutableTransaction tx5 = CMutableTransaction();
+ tx5.vout.resize(1);
+ tx5.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx5.vout[0].nValue = 11 * COIN;
+ pool.addUnchecked(tx5.GetHash(), entry.Fee(10000LL).FromTx(tx5));
+ BOOST_CHECK_EQUAL(pool.size(), 5U);
+
+ std::vector<std::string> sortedOrder;
+ sortedOrder.resize(5);
+ sortedOrder[0] = tx2.GetHash().ToString(); // 20000
+ sortedOrder[1] = tx4.GetHash().ToString(); // 15000
+ // tx1 and tx5 are both 10000
+ // Ties are broken by hash, not timestamp, so determine which
+ // hash comes first.
+ if (tx1.GetHash() < tx5.GetHash()) {
+ sortedOrder[2] = tx1.GetHash().ToString();
+ sortedOrder[3] = tx5.GetHash().ToString();
+ } else {
+ sortedOrder[2] = tx5.GetHash().ToString();
+ sortedOrder[3] = tx1.GetHash().ToString();
+ }
+ sortedOrder[4] = tx3.GetHash().ToString(); // 0
+
+ CheckSort<ancestor_score>(pool, sortedOrder);
+
+ /* low fee parent with high fee child */
+ /* tx6 (0) -> tx7 (high) */
+ CMutableTransaction tx6 = CMutableTransaction();
+ tx6.vout.resize(1);
+ tx6.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx6.vout[0].nValue = 20 * COIN;
+ uint64_t tx6Size = GetVirtualTransactionSize(tx6);
+
+ pool.addUnchecked(tx6.GetHash(), entry.Fee(0LL).FromTx(tx6));
+ BOOST_CHECK_EQUAL(pool.size(), 6U);
+ // Ties are broken by hash
+ if (tx3.GetHash() < tx6.GetHash())
+ sortedOrder.push_back(tx6.GetHash().ToString());
+ else
+ sortedOrder.insert(sortedOrder.end()-1,tx6.GetHash().ToString());
+
+ CheckSort<ancestor_score>(pool, sortedOrder);
+
+ CMutableTransaction tx7 = CMutableTransaction();
+ tx7.vin.resize(1);
+ tx7.vin[0].prevout = COutPoint(tx6.GetHash(), 0);
+ tx7.vin[0].scriptSig = CScript() << OP_11;
+ tx7.vout.resize(1);
+ tx7.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx7.vout[0].nValue = 10 * COIN;
+ uint64_t tx7Size = GetVirtualTransactionSize(tx7);
+
+ /* set the fee to just below tx2's feerate when including ancestor */
+ CAmount fee = (20000/tx2Size)*(tx7Size + tx6Size) - 1;
+
+ pool.addUnchecked(tx7.GetHash(), entry.Fee(fee).FromTx(tx7));
+ BOOST_CHECK_EQUAL(pool.size(), 7U);
+ sortedOrder.insert(sortedOrder.begin()+1, tx7.GetHash().ToString());
+ CheckSort<ancestor_score>(pool, sortedOrder);
+
+ /* after tx6 is mined, tx7 should move up in the sort */
+ std::vector<CTransactionRef> vtx;
+ vtx.push_back(MakeTransactionRef(tx6));
+ pool.removeForBlock(vtx, 1);
+
+ sortedOrder.erase(sortedOrder.begin()+1);
+ // Ties are broken by hash
+ if (tx3.GetHash() < tx6.GetHash())
+ sortedOrder.pop_back();
+ else
+ sortedOrder.erase(sortedOrder.end()-2);
+ sortedOrder.insert(sortedOrder.begin(), tx7.GetHash().ToString());
+ CheckSort<ancestor_score>(pool, sortedOrder);
+
+ // High-fee parent, low-fee child
+ // tx7 -> tx8
+ CMutableTransaction tx8 = CMutableTransaction();
+ tx8.vin.resize(1);
+ tx8.vin[0].prevout = COutPoint(tx7.GetHash(), 0);
+ tx8.vin[0].scriptSig = CScript() << OP_11;
+ tx8.vout.resize(1);
+ tx8.vout[0].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx8.vout[0].nValue = 10*COIN;
+
+ // Check that we sort by min(feerate, ancestor_feerate):
+ // set the fee so that the ancestor feerate is above tx1/5,
+ // but the transaction's own feerate is lower
+ pool.addUnchecked(tx8.GetHash(), entry.Fee(5000LL).FromTx(tx8));
+ sortedOrder.insert(sortedOrder.end()-1, tx8.GetHash().ToString());
+ CheckSort<ancestor_score>(pool, sortedOrder);
+}
+
+
+BOOST_AUTO_TEST_CASE(MempoolSizeLimitTest)
+{
+ CTxMemPool pool;
+ LOCK(pool.cs);
+ TestMemPoolEntryHelper entry;
+
+ CMutableTransaction tx1 = CMutableTransaction();
+ tx1.vin.resize(1);
+ tx1.vin[0].scriptSig = CScript() << OP_1;
+ tx1.vout.resize(1);
+ tx1.vout[0].scriptPubKey = CScript() << OP_1 << OP_EQUAL;
+ tx1.vout[0].nValue = 10 * COIN;
+ pool.addUnchecked(tx1.GetHash(), entry.Fee(10000LL).FromTx(tx1));
+
+ CMutableTransaction tx2 = CMutableTransaction();
+ tx2.vin.resize(1);
+ tx2.vin[0].scriptSig = CScript() << OP_2;
+ tx2.vout.resize(1);
+ tx2.vout[0].scriptPubKey = CScript() << OP_2 << OP_EQUAL;
+ tx2.vout[0].nValue = 10 * COIN;
+ pool.addUnchecked(tx2.GetHash(), entry.Fee(5000LL).FromTx(tx2));
+
+ pool.TrimToSize(pool.DynamicMemoryUsage()); // should do nothing
+ BOOST_CHECK(pool.exists(tx1.GetHash()));
+ BOOST_CHECK(pool.exists(tx2.GetHash()));
+
+ pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); // should remove the lower-feerate transaction
+ BOOST_CHECK(pool.exists(tx1.GetHash()));
+ BOOST_CHECK(!pool.exists(tx2.GetHash()));
+
+ pool.addUnchecked(tx2.GetHash(), entry.FromTx(tx2));
+ CMutableTransaction tx3 = CMutableTransaction();
+ tx3.vin.resize(1);
+ tx3.vin[0].prevout = COutPoint(tx2.GetHash(), 0);
+ tx3.vin[0].scriptSig = CScript() << OP_2;
+ tx3.vout.resize(1);
+ tx3.vout[0].scriptPubKey = CScript() << OP_3 << OP_EQUAL;
+ tx3.vout[0].nValue = 10 * COIN;
+ pool.addUnchecked(tx3.GetHash(), entry.Fee(20000LL).FromTx(tx3));
+
+ pool.TrimToSize(pool.DynamicMemoryUsage() * 3 / 4); // tx3 should pay for tx2 (CPFP)
+ BOOST_CHECK(!pool.exists(tx1.GetHash()));
+ BOOST_CHECK(pool.exists(tx2.GetHash()));
+ BOOST_CHECK(pool.exists(tx3.GetHash()));
+
+ pool.TrimToSize(GetVirtualTransactionSize(tx1)); // mempool is limited to tx1's size in memory usage, so nothing fits
+ BOOST_CHECK(!pool.exists(tx1.GetHash()));
+ BOOST_CHECK(!pool.exists(tx2.GetHash()));
+ BOOST_CHECK(!pool.exists(tx3.GetHash()));
+
+ CFeeRate maxFeeRateRemoved(25000, GetVirtualTransactionSize(tx3) + GetVirtualTransactionSize(tx2));
+ BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + 1000);
+
+ CMutableTransaction tx4 = CMutableTransaction();
+ tx4.vin.resize(2);
+ tx4.vin[0].prevout.SetNull();
+ tx4.vin[0].scriptSig = CScript() << OP_4;
+ tx4.vin[1].prevout.SetNull();
+ tx4.vin[1].scriptSig = CScript() << OP_4;
+ tx4.vout.resize(2);
+ tx4.vout[0].scriptPubKey = CScript() << OP_4 << OP_EQUAL;
+ tx4.vout[0].nValue = 10 * COIN;
+ tx4.vout[1].scriptPubKey = CScript() << OP_4 << OP_EQUAL;
+ tx4.vout[1].nValue = 10 * COIN;
+
+ CMutableTransaction tx5 = CMutableTransaction();
+ tx5.vin.resize(2);
+ tx5.vin[0].prevout = COutPoint(tx4.GetHash(), 0);
+ tx5.vin[0].scriptSig = CScript() << OP_4;
+ tx5.vin[1].prevout.SetNull();
+ tx5.vin[1].scriptSig = CScript() << OP_5;
+ tx5.vout.resize(2);
+ tx5.vout[0].scriptPubKey = CScript() << OP_5 << OP_EQUAL;
+ tx5.vout[0].nValue = 10 * COIN;
+ tx5.vout[1].scriptPubKey = CScript() << OP_5 << OP_EQUAL;
+ tx5.vout[1].nValue = 10 * COIN;
+
+ CMutableTransaction tx6 = CMutableTransaction();
+ tx6.vin.resize(2);
+ tx6.vin[0].prevout = COutPoint(tx4.GetHash(), 1);
+ tx6.vin[0].scriptSig = CScript() << OP_4;
+ tx6.vin[1].prevout.SetNull();
+ tx6.vin[1].scriptSig = CScript() << OP_6;
+ tx6.vout.resize(2);
+ tx6.vout[0].scriptPubKey = CScript() << OP_6 << OP_EQUAL;
+ tx6.vout[0].nValue = 10 * COIN;
+ tx6.vout[1].scriptPubKey = CScript() << OP_6 << OP_EQUAL;
+ tx6.vout[1].nValue = 10 * COIN;
+
+ CMutableTransaction tx7 = CMutableTransaction();
+ tx7.vin.resize(2);
+ tx7.vin[0].prevout = COutPoint(tx5.GetHash(), 0);
+ tx7.vin[0].scriptSig = CScript() << OP_5;
+ tx7.vin[1].prevout = COutPoint(tx6.GetHash(), 0);
+ tx7.vin[1].scriptSig = CScript() << OP_6;
+ tx7.vout.resize(2);
+ tx7.vout[0].scriptPubKey = CScript() << OP_7 << OP_EQUAL;
+ tx7.vout[0].nValue = 10 * COIN;
+ tx7.vout[1].scriptPubKey = CScript() << OP_7 << OP_EQUAL;
+ tx7.vout[1].nValue = 10 * COIN;
+
+ pool.addUnchecked(tx4.GetHash(), entry.Fee(7000LL).FromTx(tx4));
+ pool.addUnchecked(tx5.GetHash(), entry.Fee(1000LL).FromTx(tx5));
+ pool.addUnchecked(tx6.GetHash(), entry.Fee(1100LL).FromTx(tx6));
+ pool.addUnchecked(tx7.GetHash(), entry.Fee(9000LL).FromTx(tx7));
+
+ // we only require this to remove, at max, 2 txn, because it's not clear what we're really optimizing for aside from that
+ pool.TrimToSize(pool.DynamicMemoryUsage() - 1);
+ BOOST_CHECK(pool.exists(tx4.GetHash()));
+ BOOST_CHECK(pool.exists(tx6.GetHash()));
+ BOOST_CHECK(!pool.exists(tx7.GetHash()));
+
+ if (!pool.exists(tx5.GetHash()))
+ pool.addUnchecked(tx5.GetHash(), entry.Fee(1000LL).FromTx(tx5));
+ pool.addUnchecked(tx7.GetHash(), entry.Fee(9000LL).FromTx(tx7));
+
+ pool.TrimToSize(pool.DynamicMemoryUsage() / 2); // should maximize mempool size by only removing 5/7
+ BOOST_CHECK(pool.exists(tx4.GetHash()));
+ BOOST_CHECK(!pool.exists(tx5.GetHash()));
+ BOOST_CHECK(pool.exists(tx6.GetHash()));
+ BOOST_CHECK(!pool.exists(tx7.GetHash()));
+
+ pool.addUnchecked(tx5.GetHash(), entry.Fee(1000LL).FromTx(tx5));
+ pool.addUnchecked(tx7.GetHash(), entry.Fee(9000LL).FromTx(tx7));
+
+ std::vector<CTransactionRef> vtx;
+ SetMockTime(42);
+ SetMockTime(42 + CTxMemPool::ROLLING_FEE_HALFLIFE);
+ BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), maxFeeRateRemoved.GetFeePerK() + 1000);
+ // ... we should keep the same min fee until we get a block
+ pool.removeForBlock(vtx, 1);
+ SetMockTime(42 + 2*CTxMemPool::ROLLING_FEE_HALFLIFE);
+ BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), llround((maxFeeRateRemoved.GetFeePerK() + 1000)/2.0));
+ // ... then feerate should drop 1/2 each halflife
+
+ SetMockTime(42 + 2*CTxMemPool::ROLLING_FEE_HALFLIFE + CTxMemPool::ROLLING_FEE_HALFLIFE/2);
+ BOOST_CHECK_EQUAL(pool.GetMinFee(pool.DynamicMemoryUsage() * 5 / 2).GetFeePerK(), llround((maxFeeRateRemoved.GetFeePerK() + 1000)/4.0));
+ // ... with a 1/2 halflife when mempool is < 1/2 its target size
+
+ SetMockTime(42 + 2*CTxMemPool::ROLLING_FEE_HALFLIFE + CTxMemPool::ROLLING_FEE_HALFLIFE/2 + CTxMemPool::ROLLING_FEE_HALFLIFE/4);
+ BOOST_CHECK_EQUAL(pool.GetMinFee(pool.DynamicMemoryUsage() * 9 / 2).GetFeePerK(), llround((maxFeeRateRemoved.GetFeePerK() + 1000)/8.0));
+ // ... with a 1/4 halflife when mempool is < 1/4 its target size
+
+ SetMockTime(42 + 7*CTxMemPool::ROLLING_FEE_HALFLIFE + CTxMemPool::ROLLING_FEE_HALFLIFE/2 + CTxMemPool::ROLLING_FEE_HALFLIFE/4);
+ BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), 1000);
+ // ... but feerate should never drop below 1000
+
+ SetMockTime(42 + 8*CTxMemPool::ROLLING_FEE_HALFLIFE + CTxMemPool::ROLLING_FEE_HALFLIFE/2 + CTxMemPool::ROLLING_FEE_HALFLIFE/4);
+ BOOST_CHECK_EQUAL(pool.GetMinFee(1).GetFeePerK(), 0);
+ // ... unless it has gone all the way to 0 (after getting past 1000/2)
+
+ SetMockTime(0);
+}
+
+inline CTransactionRef make_tx(std::vector<CAmount>&& output_values, std::vector<CTransactionRef>&& inputs=std::vector<CTransactionRef>(), std::vector<uint32_t>&& input_indices=std::vector<uint32_t>())
+{
+ CMutableTransaction tx = CMutableTransaction();
+ tx.vin.resize(inputs.size());
+ tx.vout.resize(output_values.size());
+ for (size_t i = 0; i < inputs.size(); ++i) {
+ tx.vin[i].prevout.hash = inputs[i]->GetHash();
+ tx.vin[i].prevout.n = input_indices.size() > i ? input_indices[i] : 0;
+ }
+ for (size_t i = 0; i < output_values.size(); ++i) {
+ tx.vout[i].scriptPubKey = CScript() << OP_11 << OP_EQUAL;
+ tx.vout[i].nValue = output_values[i];
+ }
+ return MakeTransactionRef(tx);
+}
+
+
+BOOST_AUTO_TEST_CASE(MempoolAncestryTests)
+{
+ size_t ancestors, descendants;
+
+ CTxMemPool pool;
+ LOCK(pool.cs);
+ TestMemPoolEntryHelper entry;
+
+ /* Base transaction */
+ //
+ // [tx1]
+ //
+ CTransactionRef tx1 = make_tx(/* output_values */ {10 * COIN});
+ pool.addUnchecked(tx1->GetHash(), entry.Fee(10000LL).FromTx(tx1));
+
+ // Ancestors / descendants should be 1 / 1 (itself / itself)
+ pool.GetTransactionAncestry(tx1->GetHash(), ancestors, descendants);
+ BOOST_CHECK_EQUAL(ancestors, 1ULL);
+ BOOST_CHECK_EQUAL(descendants, 1ULL);
+
+ /* Child transaction */
+ //
+ // [tx1].0 <- [tx2]
+ //
+ CTransactionRef tx2 = make_tx(/* output_values */ {495 * CENT, 5 * COIN}, /* inputs */ {tx1});
+ pool.addUnchecked(tx2->GetHash(), entry.Fee(10000LL).FromTx(tx2));
+
+ // Ancestors / descendants should be:
+ // transaction ancestors descendants
+ // ============ =========== ===========
+ // tx1 1 (tx1) 2 (tx1,2)
+ // tx2 2 (tx1,2) 2 (tx1,2)
+ pool.GetTransactionAncestry(tx1->GetHash(), ancestors, descendants);
+ BOOST_CHECK_EQUAL(ancestors, 1ULL);
+ BOOST_CHECK_EQUAL(descendants, 2ULL);
+ pool.GetTransactionAncestry(tx2->GetHash(), ancestors, descendants);
+ BOOST_CHECK_EQUAL(ancestors, 2ULL);
+ BOOST_CHECK_EQUAL(descendants, 2ULL);
+
+ /* Grand-child 1 */
+ //
+ // [tx1].0 <- [tx2].0 <- [tx3]
+ //
+ CTransactionRef tx3 = make_tx(/* output_values */ {290 * CENT, 200 * CENT}, /* inputs */ {tx2});
+ pool.addUnchecked(tx3->GetHash(), entry.Fee(10000LL).FromTx(tx3));
+
+ // Ancestors / descendants should be:
+ // transaction ancestors descendants
+ // ============ =========== ===========
+ // tx1 1 (tx1) 3 (tx1,2,3)
+ // tx2 2 (tx1,2) 3 (tx1,2,3)
+ // tx3 3 (tx1,2,3) 3 (tx1,2,3)
+ pool.GetTransactionAncestry(tx1->GetHash(), ancestors, descendants);
+ BOOST_CHECK_EQUAL(ancestors, 1ULL);
+ BOOST_CHECK_EQUAL(descendants, 3ULL);
+ pool.GetTransactionAncestry(tx2->GetHash(), ancestors, descendants);
+ BOOST_CHECK_EQUAL(ancestors, 2ULL);
+ BOOST_CHECK_EQUAL(descendants, 3ULL);
+ pool.GetTransactionAncestry(tx3->GetHash(), ancestors, descendants);
+ BOOST_CHECK_EQUAL(ancestors, 3ULL);
+ BOOST_CHECK_EQUAL(descendants, 3ULL);
+
+ /* Grand-child 2 */
+ //
+ // [tx1].0 <- [tx2].0 <- [tx3]
+ // |
+ // \---1 <- [tx4]
+ //
+ CTransactionRef tx4 = make_tx(/* output_values */ {290 * CENT, 250 * CENT}, /* inputs */ {tx2}, /* input_indices */ {1});
+ pool.addUnchecked(tx4->GetHash(), entry.Fee(10000LL).FromTx(tx4));
+
+ // Ancestors / descendants should be:
+ // transaction ancestors descendants
+ // ============ =========== ===========
+ // tx1 1 (tx1) 4 (tx1,2,3,4)
+ // tx2 2 (tx1,2) 4 (tx1,2,3,4)
+ // tx3 3 (tx1,2,3) 4 (tx1,2,3,4)
+ // tx4 3 (tx1,2,4) 4 (tx1,2,3,4)
+ pool.GetTransactionAncestry(tx1->GetHash(), ancestors, descendants);
+ BOOST_CHECK_EQUAL(ancestors, 1ULL);
+ BOOST_CHECK_EQUAL(descendants, 4ULL);
+ pool.GetTransactionAncestry(tx2->GetHash(), ancestors, descendants);
+ BOOST_CHECK_EQUAL(ancestors, 2ULL);
+ BOOST_CHECK_EQUAL(descendants, 4ULL);
+ pool.GetTransactionAncestry(tx3->GetHash(), ancestors, descendants);
+ BOOST_CHECK_EQUAL(ancestors, 3ULL);
+ BOOST_CHECK_EQUAL(descendants, 4ULL);
+ pool.GetTransactionAncestry(tx4->GetHash(), ancestors, descendants);
+ BOOST_CHECK_EQUAL(ancestors, 3ULL);
+ BOOST_CHECK_EQUAL(descendants, 4ULL);
+
+ /* Make an alternate branch that is longer and connect it to tx3 */
+ //
+ // [ty1].0 <- [ty2].0 <- [ty3].0 <- [ty4].0 <- [ty5].0
+ // |
+ // [tx1].0 <- [tx2].0 <- [tx3].0 <- [ty6] --->--/
+ // |
+ // \---1 <- [tx4]
+ //
+ CTransactionRef ty1, ty2, ty3, ty4, ty5;
+ CTransactionRef* ty[5] = {&ty1, &ty2, &ty3, &ty4, &ty5};
+ CAmount v = 5 * COIN;
+ for (uint64_t i = 0; i < 5; i++) {
+ CTransactionRef& tyi = *ty[i];
+ tyi = make_tx(/* output_values */ {v}, /* inputs */ i > 0 ? std::vector<CTransactionRef>{*ty[i - 1]} : std::vector<CTransactionRef>{});
+ v -= 50 * CENT;
+ pool.addUnchecked(tyi->GetHash(), entry.Fee(10000LL).FromTx(tyi));
+ pool.GetTransactionAncestry(tyi->GetHash(), ancestors, descendants);
+ BOOST_CHECK_EQUAL(ancestors, i+1);
+ BOOST_CHECK_EQUAL(descendants, i+1);
+ }
+ CTransactionRef ty6 = make_tx(/* output_values */ {5 * COIN}, /* inputs */ {tx3, ty5});
+ pool.addUnchecked(ty6->GetHash(), entry.Fee(10000LL).FromTx(ty6));
+
+ // Ancestors / descendants should be:
+ // transaction ancestors descendants
+ // ============ =================== ===========
+ // tx1 1 (tx1) 5 (tx1,2,3,4, ty6)
+ // tx2 2 (tx1,2) 5 (tx1,2,3,4, ty6)
+ // tx3 3 (tx1,2,3) 5 (tx1,2,3,4, ty6)
+ // tx4 3 (tx1,2,4) 5 (tx1,2,3,4, ty6)
+ // ty1 1 (ty1) 6 (ty1,2,3,4,5,6)
+ // ty2 2 (ty1,2) 6 (ty1,2,3,4,5,6)
+ // ty3 3 (ty1,2,3) 6 (ty1,2,3,4,5,6)
+ // ty4 4 (y1234) 6 (ty1,2,3,4,5,6)
+ // ty5 5 (y12345) 6 (ty1,2,3,4,5,6)
+ // ty6 9 (tx123, ty123456) 6 (ty1,2,3,4,5,6)
+ pool.GetTransactionAncestry(tx1->GetHash(), ancestors, descendants);
+ BOOST_CHECK_EQUAL(ancestors, 1ULL);
+ BOOST_CHECK_EQUAL(descendants, 5ULL);
+ pool.GetTransactionAncestry(tx2->GetHash(), ancestors, descendants);
+ BOOST_CHECK_EQUAL(ancestors, 2ULL);
+ BOOST_CHECK_EQUAL(descendants, 5ULL);
+ pool.GetTransactionAncestry(tx3->GetHash(), ancestors, descendants);
+ BOOST_CHECK_EQUAL(ancestors, 3ULL);
+ BOOST_CHECK_EQUAL(descendants, 5ULL);
+ pool.GetTransactionAncestry(tx4->GetHash(), ancestors, descendants);
+ BOOST_CHECK_EQUAL(ancestors, 3ULL);
+ BOOST_CHECK_EQUAL(descendants, 5ULL);
+ pool.GetTransactionAncestry(ty1->GetHash(), ancestors, descendants);
+ BOOST_CHECK_EQUAL(ancestors, 1ULL);
+ BOOST_CHECK_EQUAL(descendants, 6ULL);
+ pool.GetTransactionAncestry(ty2->GetHash(), ancestors, descendants);
+ BOOST_CHECK_EQUAL(ancestors, 2ULL);
+ BOOST_CHECK_EQUAL(descendants, 6ULL);
+ pool.GetTransactionAncestry(ty3->GetHash(), ancestors, descendants);
+ BOOST_CHECK_EQUAL(ancestors, 3ULL);
+ BOOST_CHECK_EQUAL(descendants, 6ULL);
+ pool.GetTransactionAncestry(ty4->GetHash(), ancestors, descendants);
+ BOOST_CHECK_EQUAL(ancestors, 4ULL);
+ BOOST_CHECK_EQUAL(descendants, 6ULL);
+ pool.GetTransactionAncestry(ty5->GetHash(), ancestors, descendants);
+ BOOST_CHECK_EQUAL(ancestors, 5ULL);
+ BOOST_CHECK_EQUAL(descendants, 6ULL);
+ pool.GetTransactionAncestry(ty6->GetHash(), ancestors, descendants);
+ BOOST_CHECK_EQUAL(ancestors, 9ULL);
+ BOOST_CHECK_EQUAL(descendants, 6ULL);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp
new file mode 100644
index 0000000000..5e55ad6622
--- /dev/null
+++ b/src/test/merkle_tests.cpp
@@ -0,0 +1,252 @@
+// Copyright (c) 2015-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <consensus/merkle.h>
+#include <test/test_bitcoin.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(merkle_tests, TestingSetup)
+
+static uint256 ComputeMerkleRootFromBranch(const uint256& leaf, const std::vector<uint256>& vMerkleBranch, uint32_t nIndex) {
+ uint256 hash = leaf;
+ for (std::vector<uint256>::const_iterator it = vMerkleBranch.begin(); it != vMerkleBranch.end(); ++it) {
+ if (nIndex & 1) {
+ hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash));
+ } else {
+ hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it));
+ }
+ nIndex >>= 1;
+ }
+ return hash;
+}
+
+/* This implements a constant-space merkle root/path calculator, limited to 2^32 leaves. */
+static void MerkleComputation(const std::vector<uint256>& leaves, uint256* proot, bool* pmutated, uint32_t branchpos, std::vector<uint256>* pbranch) {
+ if (pbranch) pbranch->clear();
+ if (leaves.size() == 0) {
+ if (pmutated) *pmutated = false;
+ if (proot) *proot = uint256();
+ return;
+ }
+ bool mutated = false;
+ // count is the number of leaves processed so far.
+ uint32_t count = 0;
+ // inner is an array of eagerly computed subtree hashes, indexed by tree
+ // level (0 being the leaves).
+ // For example, when count is 25 (11001 in binary), inner[4] is the hash of
+ // the first 16 leaves, inner[3] of the next 8 leaves, and inner[0] equal to
+ // the last leaf. The other inner entries are undefined.
+ uint256 inner[32];
+ // Which position in inner is a hash that depends on the matching leaf.
+ int matchlevel = -1;
+ // First process all leaves into 'inner' values.
+ while (count < leaves.size()) {
+ uint256 h = leaves[count];
+ bool matchh = count == branchpos;
+ count++;
+ int level;
+ // For each of the lower bits in count that are 0, do 1 step. Each
+ // corresponds to an inner value that existed before processing the
+ // current leaf, and each needs a hash to combine it.
+ for (level = 0; !(count & (((uint32_t)1) << level)); level++) {
+ if (pbranch) {
+ if (matchh) {
+ pbranch->push_back(inner[level]);
+ } else if (matchlevel == level) {
+ pbranch->push_back(h);
+ matchh = true;
+ }
+ }
+ mutated |= (inner[level] == h);
+ CHash256().Write(inner[level].begin(), 32).Write(h.begin(), 32).Finalize(h.begin());
+ }
+ // Store the resulting hash at inner position level.
+ inner[level] = h;
+ if (matchh) {
+ matchlevel = level;
+ }
+ }
+ // Do a final 'sweep' over the rightmost branch of the tree to process
+ // odd levels, and reduce everything to a single top value.
+ // Level is the level (counted from the bottom) up to which we've sweeped.
+ int level = 0;
+ // As long as bit number level in count is zero, skip it. It means there
+ // is nothing left at this level.
+ while (!(count & (((uint32_t)1) << level))) {
+ level++;
+ }
+ uint256 h = inner[level];
+ bool matchh = matchlevel == level;
+ while (count != (((uint32_t)1) << level)) {
+ // If we reach this point, h is an inner value that is not the top.
+ // We combine it with itself (Bitcoin's special rule for odd levels in
+ // the tree) to produce a higher level one.
+ if (pbranch && matchh) {
+ pbranch->push_back(h);
+ }
+ CHash256().Write(h.begin(), 32).Write(h.begin(), 32).Finalize(h.begin());
+ // Increment count to the value it would have if two entries at this
+ // level had existed.
+ count += (((uint32_t)1) << level);
+ level++;
+ // And propagate the result upwards accordingly.
+ while (!(count & (((uint32_t)1) << level))) {
+ if (pbranch) {
+ if (matchh) {
+ pbranch->push_back(inner[level]);
+ } else if (matchlevel == level) {
+ pbranch->push_back(h);
+ matchh = true;
+ }
+ }
+ CHash256().Write(inner[level].begin(), 32).Write(h.begin(), 32).Finalize(h.begin());
+ level++;
+ }
+ }
+ // Return result.
+ if (pmutated) *pmutated = mutated;
+ if (proot) *proot = h;
+}
+
+static std::vector<uint256> ComputeMerkleBranch(const std::vector<uint256>& leaves, uint32_t position) {
+ std::vector<uint256> ret;
+ MerkleComputation(leaves, nullptr, nullptr, position, &ret);
+ return ret;
+}
+
+static std::vector<uint256> BlockMerkleBranch(const CBlock& block, uint32_t position)
+{
+ std::vector<uint256> leaves;
+ leaves.resize(block.vtx.size());
+ for (size_t s = 0; s < block.vtx.size(); s++) {
+ leaves[s] = block.vtx[s]->GetHash();
+ }
+ return ComputeMerkleBranch(leaves, position);
+}
+
+// Older version of the merkle root computation code, for comparison.
+static uint256 BlockBuildMerkleTree(const CBlock& block, bool* fMutated, std::vector<uint256>& vMerkleTree)
+{
+ vMerkleTree.clear();
+ vMerkleTree.reserve(block.vtx.size() * 2 + 16); // Safe upper bound for the number of total nodes.
+ for (std::vector<CTransactionRef>::const_iterator it(block.vtx.begin()); it != block.vtx.end(); ++it)
+ vMerkleTree.push_back((*it)->GetHash());
+ int j = 0;
+ bool mutated = false;
+ for (int nSize = block.vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
+ {
+ for (int i = 0; i < nSize; i += 2)
+ {
+ int i2 = std::min(i+1, nSize-1);
+ if (i2 == i + 1 && i2 + 1 == nSize && vMerkleTree[j+i] == vMerkleTree[j+i2]) {
+ // Two identical hashes at the end of the list at a particular level.
+ mutated = true;
+ }
+ vMerkleTree.push_back(Hash(vMerkleTree[j+i].begin(), vMerkleTree[j+i].end(),
+ vMerkleTree[j+i2].begin(), vMerkleTree[j+i2].end()));
+ }
+ j += nSize;
+ }
+ if (fMutated) {
+ *fMutated = mutated;
+ }
+ return (vMerkleTree.empty() ? uint256() : vMerkleTree.back());
+}
+
+// Older version of the merkle branch computation code, for comparison.
+static std::vector<uint256> BlockGetMerkleBranch(const CBlock& block, const std::vector<uint256>& vMerkleTree, int nIndex)
+{
+ std::vector<uint256> vMerkleBranch;
+ int j = 0;
+ for (int nSize = block.vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
+ {
+ int i = std::min(nIndex^1, nSize-1);
+ vMerkleBranch.push_back(vMerkleTree[j+i]);
+ nIndex >>= 1;
+ j += nSize;
+ }
+ return vMerkleBranch;
+}
+
+static inline int ctz(uint32_t i) {
+ if (i == 0) return 0;
+ int j = 0;
+ while (!(i & 1)) {
+ j++;
+ i >>= 1;
+ }
+ return j;
+}
+
+BOOST_AUTO_TEST_CASE(merkle_test)
+{
+ for (int i = 0; i < 32; i++) {
+ // Try 32 block sizes: all sizes from 0 to 16 inclusive, and then 15 random sizes.
+ int ntx = (i <= 16) ? i : 17 + (InsecureRandRange(4000));
+ // Try up to 3 mutations.
+ for (int mutate = 0; mutate <= 3; mutate++) {
+ int duplicate1 = mutate >= 1 ? 1 << ctz(ntx) : 0; // The last how many transactions to duplicate first.
+ if (duplicate1 >= ntx) break; // Duplication of the entire tree results in a different root (it adds a level).
+ int ntx1 = ntx + duplicate1; // The resulting number of transactions after the first duplication.
+ int duplicate2 = mutate >= 2 ? 1 << ctz(ntx1) : 0; // Likewise for the second mutation.
+ if (duplicate2 >= ntx1) break;
+ int ntx2 = ntx1 + duplicate2;
+ int duplicate3 = mutate >= 3 ? 1 << ctz(ntx2) : 0; // And for the third mutation.
+ if (duplicate3 >= ntx2) break;
+ int ntx3 = ntx2 + duplicate3;
+ // Build a block with ntx different transactions.
+ CBlock block;
+ block.vtx.resize(ntx);
+ for (int j = 0; j < ntx; j++) {
+ CMutableTransaction mtx;
+ mtx.nLockTime = j;
+ block.vtx[j] = MakeTransactionRef(std::move(mtx));
+ }
+ // Compute the root of the block before mutating it.
+ bool unmutatedMutated = false;
+ uint256 unmutatedRoot = BlockMerkleRoot(block, &unmutatedMutated);
+ BOOST_CHECK(unmutatedMutated == false);
+ // Optionally mutate by duplicating the last transactions, resulting in the same merkle root.
+ block.vtx.resize(ntx3);
+ for (int j = 0; j < duplicate1; j++) {
+ block.vtx[ntx + j] = block.vtx[ntx + j - duplicate1];
+ }
+ for (int j = 0; j < duplicate2; j++) {
+ block.vtx[ntx1 + j] = block.vtx[ntx1 + j - duplicate2];
+ }
+ for (int j = 0; j < duplicate3; j++) {
+ block.vtx[ntx2 + j] = block.vtx[ntx2 + j - duplicate3];
+ }
+ // Compute the merkle root and merkle tree using the old mechanism.
+ bool oldMutated = false;
+ std::vector<uint256> merkleTree;
+ uint256 oldRoot = BlockBuildMerkleTree(block, &oldMutated, merkleTree);
+ // Compute the merkle root using the new mechanism.
+ bool newMutated = false;
+ uint256 newRoot = BlockMerkleRoot(block, &newMutated);
+ BOOST_CHECK(oldRoot == newRoot);
+ BOOST_CHECK(newRoot == unmutatedRoot);
+ BOOST_CHECK((newRoot == uint256()) == (ntx == 0));
+ BOOST_CHECK(oldMutated == newMutated);
+ BOOST_CHECK(newMutated == !!mutate);
+ // If no mutation was done (once for every ntx value), try up to 16 branches.
+ if (mutate == 0) {
+ for (int loop = 0; loop < std::min(ntx, 16); loop++) {
+ // If ntx <= 16, try all branches. Otherwise, try 16 random ones.
+ int mtx = loop;
+ if (ntx > 16) {
+ mtx = InsecureRandRange(ntx);
+ }
+ std::vector<uint256> newBranch = BlockMerkleBranch(block, mtx);
+ std::vector<uint256> oldBranch = BlockGetMerkleBranch(block, merkleTree, mtx);
+ BOOST_CHECK(oldBranch == newBranch);
+ BOOST_CHECK(ComputeMerkleRootFromBranch(block.vtx[mtx]->GetHash(), newBranch, mtx) == oldRoot);
+ }
+ }
+ }
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/merkleblock_tests.cpp b/src/test/merkleblock_tests.cpp
new file mode 100644
index 0000000000..4978593285
--- /dev/null
+++ b/src/test/merkleblock_tests.cpp
@@ -0,0 +1,78 @@
+// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <merkleblock.h>
+#include <uint256.h>
+#include <test/test_bitcoin.h>
+
+#include <boost/test/unit_test.hpp>
+
+
+BOOST_FIXTURE_TEST_SUITE(merkleblock_tests, BasicTestingSetup)
+
+/**
+ * Create a CMerkleBlock using a list of txids which will be found in the
+ * given block.
+ */
+BOOST_AUTO_TEST_CASE(merkleblock_construct_from_txids_found)
+{
+ CBlock block = getBlock13b8a();
+
+ std::set<uint256> txids;
+
+ // Last txn in block.
+ uint256 txhash1 = uint256S("0x74d681e0e03bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20");
+
+ // Second txn in block.
+ uint256 txhash2 = uint256S("0xf9fc751cb7dc372406a9f8d738d5e6f8f63bab71986a39cf36ee70ee17036d07");
+
+ txids.insert(txhash1);
+ txids.insert(txhash2);
+
+ CMerkleBlock merkleBlock(block, txids);
+
+ BOOST_CHECK_EQUAL(merkleBlock.header.GetHash().GetHex(), block.GetHash().GetHex());
+
+ // vMatchedTxn is only used when bloom filter is specified.
+ BOOST_CHECK_EQUAL(merkleBlock.vMatchedTxn.size(), 0U);
+
+ std::vector<uint256> vMatched;
+ std::vector<unsigned int> vIndex;
+
+ BOOST_CHECK_EQUAL(merkleBlock.txn.ExtractMatches(vMatched, vIndex).GetHex(), block.hashMerkleRoot.GetHex());
+ BOOST_CHECK_EQUAL(vMatched.size(), 2U);
+
+ // Ordered by occurrence in depth-first tree traversal.
+ BOOST_CHECK_EQUAL(vMatched[0].ToString(), txhash2.ToString());
+ BOOST_CHECK_EQUAL(vIndex[0], 1U);
+
+ BOOST_CHECK_EQUAL(vMatched[1].ToString(), txhash1.ToString());
+ BOOST_CHECK_EQUAL(vIndex[1], 8U);
+}
+
+
+/**
+ * Create a CMerkleBlock using a list of txids which will not be found in the
+ * given block.
+ */
+BOOST_AUTO_TEST_CASE(merkleblock_construct_from_txids_not_found)
+{
+ CBlock block = getBlock13b8a();
+
+ std::set<uint256> txids2;
+ txids2.insert(uint256S("0xc0ffee00003bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20"));
+ CMerkleBlock merkleBlock(block, txids2);
+
+ BOOST_CHECK_EQUAL(merkleBlock.header.GetHash().GetHex(), block.GetHash().GetHex());
+ BOOST_CHECK_EQUAL(merkleBlock.vMatchedTxn.size(), 0U);
+
+ std::vector<uint256> vMatched;
+ std::vector<unsigned int> vIndex;
+
+ BOOST_CHECK_EQUAL(merkleBlock.txn.ExtractMatches(vMatched, vIndex).GetHex(), block.hashMerkleRoot.GetHex());
+ BOOST_CHECK_EQUAL(vMatched.size(), 0U);
+ BOOST_CHECK_EQUAL(vIndex.size(), 0U);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
new file mode 100644
index 0000000000..2da06b8d31
--- /dev/null
+++ b/src/test/miner_tests.cpp
@@ -0,0 +1,524 @@
+// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <chainparams.h>
+#include <coins.h>
+#include <consensus/consensus.h>
+#include <consensus/merkle.h>
+#include <consensus/tx_verify.h>
+#include <consensus/validation.h>
+#include <validation.h>
+#include <miner.h>
+#include <policy/policy.h>
+#include <pubkey.h>
+#include <script/standard.h>
+#include <txmempool.h>
+#include <uint256.h>
+#include <util.h>
+#include <utilstrencodings.h>
+
+#include <test/test_bitcoin.h>
+
+#include <memory>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(miner_tests, TestingSetup)
+
+// BOOST_CHECK_EXCEPTION predicates to check the specific validation error
+class HasReason {
+public:
+ HasReason(const std::string& reason) : m_reason(reason) {}
+ bool operator() (const std::runtime_error& e) const {
+ return std::string(e.what()).find(m_reason) != std::string::npos;
+ };
+private:
+ const std::string m_reason;
+};
+
+static CFeeRate blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE);
+
+static BlockAssembler AssemblerForTest(const CChainParams& params) {
+ BlockAssembler::Options options;
+
+ options.nBlockMaxWeight = MAX_BLOCK_WEIGHT;
+ options.blockMinFeeRate = blockMinFeeRate;
+ return BlockAssembler(params, options);
+}
+
+static
+struct {
+ unsigned char extranonce;
+ unsigned int nonce;
+} blockinfo[] = {
+ {4, 0xa4a3e223}, {2, 0x15c32f9e}, {1, 0x0375b547}, {1, 0x7004a8a5},
+ {2, 0xce440296}, {2, 0x52cfe198}, {1, 0x77a72cd0}, {2, 0xbb5d6f84},
+ {2, 0x83f30c2c}, {1, 0x48a73d5b}, {1, 0xef7dcd01}, {2, 0x6809c6c4},
+ {2, 0x0883ab3c}, {1, 0x087bbbe2}, {2, 0x2104a814}, {2, 0xdffb6daa},
+ {1, 0xee8a0a08}, {2, 0xba4237c1}, {1, 0xa70349dc}, {1, 0x344722bb},
+ {3, 0xd6294733}, {2, 0xec9f5c94}, {2, 0xca2fbc28}, {1, 0x6ba4f406},
+ {2, 0x015d4532}, {1, 0x6e119b7c}, {2, 0x43e8f314}, {2, 0x27962f38},
+ {2, 0xb571b51b}, {2, 0xb36bee23}, {2, 0xd17924a8}, {2, 0x6bc212d9},
+ {1, 0x630d4948}, {2, 0x9a4c4ebb}, {2, 0x554be537}, {1, 0xd63ddfc7},
+ {2, 0xa10acc11}, {1, 0x759a8363}, {2, 0xfb73090d}, {1, 0xe82c6a34},
+ {1, 0xe33e92d7}, {3, 0x658ef5cb}, {2, 0xba32ff22}, {5, 0x0227a10c},
+ {1, 0xa9a70155}, {5, 0xd096d809}, {1, 0x37176174}, {1, 0x830b8d0f},
+ {1, 0xc6e3910e}, {2, 0x823f3ca8}, {1, 0x99850849}, {1, 0x7521fb81},
+ {1, 0xaacaabab}, {1, 0xd645a2eb}, {5, 0x7aea1781}, {5, 0x9d6e4b78},
+ {1, 0x4ce90fd8}, {1, 0xabdc832d}, {6, 0x4a34f32a}, {2, 0xf2524c1c},
+ {2, 0x1bbeb08a}, {1, 0xad47f480}, {1, 0x9f026aeb}, {1, 0x15a95049},
+ {2, 0xd1cb95b2}, {2, 0xf84bbda5}, {1, 0x0fa62cd1}, {1, 0xe05f9169},
+ {1, 0x78d194a9}, {5, 0x3e38147b}, {5, 0x737ba0d4}, {1, 0x63378e10},
+ {1, 0x6d5f91cf}, {2, 0x88612eb8}, {2, 0xe9639484}, {1, 0xb7fabc9d},
+ {2, 0x19b01592}, {1, 0x5a90dd31}, {2, 0x5bd7e028}, {2, 0x94d00323},
+ {1, 0xa9b9c01a}, {1, 0x3a40de61}, {1, 0x56e7eec7}, {5, 0x859f7ef6},
+ {1, 0xfd8e5630}, {1, 0x2b0c9f7f}, {1, 0xba700e26}, {1, 0x7170a408},
+ {1, 0x70de86a8}, {1, 0x74d64cd5}, {1, 0x49e738a1}, {2, 0x6910b602},
+ {0, 0x643c565f}, {1, 0x54264b3f}, {2, 0x97ea6396}, {2, 0x55174459},
+ {2, 0x03e8779a}, {1, 0x98f34d8f}, {1, 0xc07b2b07}, {1, 0xdfe29668},
+ {1, 0x3141c7c1}, {1, 0xb3b595f4}, {1, 0x735abf08}, {5, 0x623bfbce},
+ {2, 0xd351e722}, {1, 0xf4ca48c9}, {1, 0x5b19c670}, {1, 0xa164bf0e},
+ {2, 0xbbbeb305}, {2, 0xfe1c810a},
+};
+
+static CBlockIndex CreateBlockIndex(int nHeight)
+{
+ CBlockIndex index;
+ index.nHeight = nHeight;
+ index.pprev = chainActive.Tip();
+ return index;
+}
+
+static bool TestSequenceLocks(const CTransaction &tx, int flags)
+{
+ LOCK(mempool.cs);
+ return CheckSequenceLocks(tx, flags);
+}
+
+// Test suite for ancestor feerate transaction selection.
+// Implemented as an additional function, rather than a separate test case,
+// to allow reusing the blockchain created in CreateNewBlock_validity.
+static void TestPackageSelection(const CChainParams& chainparams, const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) EXCLUSIVE_LOCKS_REQUIRED(::mempool.cs)
+{
+ // Test the ancestor feerate transaction selection.
+ TestMemPoolEntryHelper entry;
+
+ // Test that a medium fee transaction will be selected after a higher fee
+ // rate package with a low fee rate parent.
+ CMutableTransaction tx;
+ tx.vin.resize(1);
+ tx.vin[0].scriptSig = CScript() << OP_1;
+ tx.vin[0].prevout.hash = txFirst[0]->GetHash();
+ tx.vin[0].prevout.n = 0;
+ tx.vout.resize(1);
+ tx.vout[0].nValue = 5000000000LL - 1000;
+ // This tx has a low fee: 1000 satoshis
+ uint256 hashParentTx = tx.GetHash(); // save this txid for later use
+ mempool.addUnchecked(hashParentTx, entry.Fee(1000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
+
+ // This tx has a medium fee: 10000 satoshis
+ tx.vin[0].prevout.hash = txFirst[1]->GetHash();
+ tx.vout[0].nValue = 5000000000LL - 10000;
+ uint256 hashMediumFeeTx = tx.GetHash();
+ mempool.addUnchecked(hashMediumFeeTx, entry.Fee(10000).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
+
+ // This tx has a high fee, but depends on the first transaction
+ tx.vin[0].prevout.hash = hashParentTx;
+ tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 50k satoshi fee
+ uint256 hashHighFeeTx = tx.GetHash();
+ mempool.addUnchecked(hashHighFeeTx, entry.Fee(50000).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
+
+ std::unique_ptr<CBlockTemplate> pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
+ BOOST_CHECK(pblocktemplate->block.vtx[1]->GetHash() == hashParentTx);
+ BOOST_CHECK(pblocktemplate->block.vtx[2]->GetHash() == hashHighFeeTx);
+ BOOST_CHECK(pblocktemplate->block.vtx[3]->GetHash() == hashMediumFeeTx);
+
+ // Test that a package below the block min tx fee doesn't get included
+ tx.vin[0].prevout.hash = hashHighFeeTx;
+ tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 0 fee
+ uint256 hashFreeTx = tx.GetHash();
+ mempool.addUnchecked(hashFreeTx, entry.Fee(0).FromTx(tx));
+ size_t freeTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
+
+ // Calculate a fee on child transaction that will put the package just
+ // below the block min tx fee (assuming 1 child tx of the same size).
+ CAmount feeToUse = blockMinFeeRate.GetFee(2*freeTxSize) - 1;
+
+ tx.vin[0].prevout.hash = hashFreeTx;
+ tx.vout[0].nValue = 5000000000LL - 1000 - 50000 - feeToUse;
+ uint256 hashLowFeeTx = tx.GetHash();
+ mempool.addUnchecked(hashLowFeeTx, entry.Fee(feeToUse).FromTx(tx));
+ pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
+ // Verify that the free tx and the low fee tx didn't get selected
+ for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
+ BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashFreeTx);
+ BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashLowFeeTx);
+ }
+
+ // Test that packages above the min relay fee do get included, even if one
+ // of the transactions is below the min relay fee
+ // Remove the low fee transaction and replace with a higher fee transaction
+ mempool.removeRecursive(tx);
+ tx.vout[0].nValue -= 2; // Now we should be just over the min relay fee
+ hashLowFeeTx = tx.GetHash();
+ mempool.addUnchecked(hashLowFeeTx, entry.Fee(feeToUse+2).FromTx(tx));
+ pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
+ BOOST_CHECK(pblocktemplate->block.vtx[4]->GetHash() == hashFreeTx);
+ BOOST_CHECK(pblocktemplate->block.vtx[5]->GetHash() == hashLowFeeTx);
+
+ // Test that transaction selection properly updates ancestor fee
+ // calculations as ancestor transactions get included in a block.
+ // Add a 0-fee transaction that has 2 outputs.
+ tx.vin[0].prevout.hash = txFirst[2]->GetHash();
+ tx.vout.resize(2);
+ tx.vout[0].nValue = 5000000000LL - 100000000;
+ tx.vout[1].nValue = 100000000; // 1BTC output
+ uint256 hashFreeTx2 = tx.GetHash();
+ mempool.addUnchecked(hashFreeTx2, entry.Fee(0).SpendsCoinbase(true).FromTx(tx));
+
+ // This tx can't be mined by itself
+ tx.vin[0].prevout.hash = hashFreeTx2;
+ tx.vout.resize(1);
+ feeToUse = blockMinFeeRate.GetFee(freeTxSize);
+ tx.vout[0].nValue = 5000000000LL - 100000000 - feeToUse;
+ uint256 hashLowFeeTx2 = tx.GetHash();
+ mempool.addUnchecked(hashLowFeeTx2, entry.Fee(feeToUse).SpendsCoinbase(false).FromTx(tx));
+ pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
+
+ // Verify that this tx isn't selected.
+ for (size_t i=0; i<pblocktemplate->block.vtx.size(); ++i) {
+ BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashFreeTx2);
+ BOOST_CHECK(pblocktemplate->block.vtx[i]->GetHash() != hashLowFeeTx2);
+ }
+
+ // This tx will be mineable, and should cause hashLowFeeTx2 to be selected
+ // as well.
+ tx.vin[0].prevout.n = 1;
+ tx.vout[0].nValue = 100000000 - 10000; // 10k satoshi fee
+ mempool.addUnchecked(tx.GetHash(), entry.Fee(10000).FromTx(tx));
+ pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey);
+ BOOST_CHECK(pblocktemplate->block.vtx[8]->GetHash() == hashLowFeeTx2);
+}
+
+// NOTE: These tests rely on CreateNewBlock doing its own self-validation!
+BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
+{
+ // Note that by default, these tests run with size accounting enabled.
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
+ const CChainParams& chainparams = *chainParams;
+ CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
+ std::unique_ptr<CBlockTemplate> pblocktemplate;
+ CMutableTransaction tx;
+ CScript script;
+ uint256 hash;
+ TestMemPoolEntryHelper entry;
+ entry.nFee = 11;
+ entry.nHeight = 11;
+
+ fCheckpointsEnabled = false;
+
+ // Simple block creation, nothing special yet:
+ BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
+
+ // We can't make transactions until we have inputs
+ // Therefore, load 100 blocks :)
+ int baseheight = 0;
+ std::vector<CTransactionRef> txFirst;
+ for (unsigned int i = 0; i < sizeof(blockinfo)/sizeof(*blockinfo); ++i)
+ {
+ CBlock *pblock = &pblocktemplate->block; // pointer for convenience
+ {
+ LOCK(cs_main);
+ pblock->nVersion = 1;
+ pblock->nTime = chainActive.Tip()->GetMedianTimePast()+1;
+ CMutableTransaction txCoinbase(*pblock->vtx[0]);
+ txCoinbase.nVersion = 1;
+ txCoinbase.vin[0].scriptSig = CScript();
+ txCoinbase.vin[0].scriptSig.push_back(blockinfo[i].extranonce);
+ txCoinbase.vin[0].scriptSig.push_back(chainActive.Height());
+ txCoinbase.vout.resize(1); // Ignore the (optional) segwit commitment added by CreateNewBlock (as the hardcoded nonces don't account for this)
+ txCoinbase.vout[0].scriptPubKey = CScript();
+ pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase));
+ if (txFirst.size() == 0)
+ baseheight = chainActive.Height();
+ if (txFirst.size() < 4)
+ txFirst.push_back(pblock->vtx[0]);
+ pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
+ pblock->nNonce = blockinfo[i].nonce;
+ }
+ std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(*pblock);
+ BOOST_CHECK(ProcessNewBlock(chainparams, shared_pblock, true, nullptr));
+ pblock->hashPrevBlock = pblock->GetHash();
+ }
+
+ LOCK(cs_main);
+ LOCK(::mempool.cs);
+
+ // Just to make sure we can still make simple blocks
+ BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
+
+ const CAmount BLOCKSUBSIDY = 50*COIN;
+ const CAmount LOWFEE = CENT;
+ const CAmount HIGHFEE = COIN;
+ const CAmount HIGHERFEE = 4*COIN;
+
+ // block sigops > limit: 1000 CHECKMULTISIG + 1
+ tx.vin.resize(1);
+ // NOTE: OP_NOP is used to force 20 SigOps for the CHECKMULTISIG
+ tx.vin[0].scriptSig = CScript() << OP_0 << OP_0 << OP_0 << OP_NOP << OP_CHECKMULTISIG << OP_1;
+ tx.vin[0].prevout.hash = txFirst[0]->GetHash();
+ tx.vin[0].prevout.n = 0;
+ tx.vout.resize(1);
+ tx.vout[0].nValue = BLOCKSUBSIDY;
+ for (unsigned int i = 0; i < 1001; ++i)
+ {
+ tx.vout[0].nValue -= LOWFEE;
+ hash = tx.GetHash();
+ bool spendsCoinbase = i == 0; // only first tx spends coinbase
+ // If we don't set the # of sig ops in the CTxMemPoolEntry, template creation fails
+ mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx));
+ tx.vin[0].prevout.hash = hash;
+ }
+
+ BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-blk-sigops"));
+ mempool.clear();
+
+ tx.vin[0].prevout.hash = txFirst[0]->GetHash();
+ tx.vout[0].nValue = BLOCKSUBSIDY;
+ for (unsigned int i = 0; i < 1001; ++i)
+ {
+ tx.vout[0].nValue -= LOWFEE;
+ hash = tx.GetHash();
+ bool spendsCoinbase = i == 0; // only first tx spends coinbase
+ // If we do set the # of sig ops in the CTxMemPoolEntry, template creation passes
+ mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).SigOpsCost(80).FromTx(tx));
+ tx.vin[0].prevout.hash = hash;
+ }
+ BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
+ mempool.clear();
+
+ // block size > limit
+ tx.vin[0].scriptSig = CScript();
+ // 18 * (520char + DROP) + OP_1 = 9433 bytes
+ std::vector<unsigned char> vchData(520);
+ for (unsigned int i = 0; i < 18; ++i)
+ tx.vin[0].scriptSig << vchData << OP_DROP;
+ tx.vin[0].scriptSig << OP_1;
+ tx.vin[0].prevout.hash = txFirst[0]->GetHash();
+ tx.vout[0].nValue = BLOCKSUBSIDY;
+ for (unsigned int i = 0; i < 128; ++i)
+ {
+ tx.vout[0].nValue -= LOWFEE;
+ hash = tx.GetHash();
+ bool spendsCoinbase = i == 0; // only first tx spends coinbase
+ mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx));
+ tx.vin[0].prevout.hash = hash;
+ }
+ BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
+ mempool.clear();
+
+ // orphan in mempool, template creation fails
+ hash = tx.GetHash();
+ mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).FromTx(tx));
+ BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
+ mempool.clear();
+
+ // child with higher feerate than parent
+ tx.vin[0].scriptSig = CScript() << OP_1;
+ tx.vin[0].prevout.hash = txFirst[1]->GetHash();
+ tx.vout[0].nValue = BLOCKSUBSIDY-HIGHFEE;
+ hash = tx.GetHash();
+ mempool.addUnchecked(hash, entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
+ tx.vin[0].prevout.hash = hash;
+ tx.vin.resize(2);
+ tx.vin[1].scriptSig = CScript() << OP_1;
+ tx.vin[1].prevout.hash = txFirst[0]->GetHash();
+ tx.vin[1].prevout.n = 0;
+ tx.vout[0].nValue = tx.vout[0].nValue+BLOCKSUBSIDY-HIGHERFEE; //First txn output + fresh coinbase - new txn fee
+ hash = tx.GetHash();
+ mempool.addUnchecked(hash, entry.Fee(HIGHERFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
+ BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
+ mempool.clear();
+
+ // coinbase in mempool, template creation fails
+ tx.vin.resize(1);
+ tx.vin[0].prevout.SetNull();
+ tx.vin[0].scriptSig = CScript() << OP_0 << OP_1;
+ tx.vout[0].nValue = 0;
+ hash = tx.GetHash();
+ // give it a fee so it'll get mined
+ mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
+ // Should throw bad-cb-multiple
+ BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-cb-multiple"));
+ mempool.clear();
+
+ // double spend txn pair in mempool, template creation fails
+ tx.vin[0].prevout.hash = txFirst[0]->GetHash();
+ tx.vin[0].scriptSig = CScript() << OP_1;
+ tx.vout[0].nValue = BLOCKSUBSIDY-HIGHFEE;
+ tx.vout[0].scriptPubKey = CScript() << OP_1;
+ hash = tx.GetHash();
+ mempool.addUnchecked(hash, entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
+ tx.vout[0].scriptPubKey = CScript() << OP_2;
+ hash = tx.GetHash();
+ mempool.addUnchecked(hash, entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
+ BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
+ mempool.clear();
+
+ // subsidy changing
+ int nHeight = chainActive.Height();
+ // Create an actual 209999-long block chain (without valid blocks).
+ while (chainActive.Tip()->nHeight < 209999) {
+ CBlockIndex* prev = chainActive.Tip();
+ CBlockIndex* next = new CBlockIndex();
+ next->phashBlock = new uint256(InsecureRand256());
+ pcoinsTip->SetBestBlock(next->GetBlockHash());
+ next->pprev = prev;
+ next->nHeight = prev->nHeight + 1;
+ next->BuildSkip();
+ chainActive.SetTip(next);
+ }
+ BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
+ // Extend to a 210000-long block chain.
+ while (chainActive.Tip()->nHeight < 210000) {
+ CBlockIndex* prev = chainActive.Tip();
+ CBlockIndex* next = new CBlockIndex();
+ next->phashBlock = new uint256(InsecureRand256());
+ pcoinsTip->SetBestBlock(next->GetBlockHash());
+ next->pprev = prev;
+ next->nHeight = prev->nHeight + 1;
+ next->BuildSkip();
+ chainActive.SetTip(next);
+ }
+ BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
+
+ // invalid p2sh txn in mempool, template creation fails
+ tx.vin[0].prevout.hash = txFirst[0]->GetHash();
+ tx.vin[0].prevout.n = 0;
+ tx.vin[0].scriptSig = CScript() << OP_1;
+ tx.vout[0].nValue = BLOCKSUBSIDY-LOWFEE;
+ script = CScript() << OP_0;
+ tx.vout[0].scriptPubKey = GetScriptForDestination(CScriptID(script));
+ hash = tx.GetHash();
+ mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
+ tx.vin[0].prevout.hash = hash;
+ tx.vin[0].scriptSig = CScript() << std::vector<unsigned char>(script.begin(), script.end());
+ tx.vout[0].nValue -= LOWFEE;
+ hash = tx.GetHash();
+ mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
+ // Should throw block-validation-failed
+ BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("block-validation-failed"));
+ mempool.clear();
+
+ // Delete the dummy blocks again.
+ while (chainActive.Tip()->nHeight > nHeight) {
+ CBlockIndex* del = chainActive.Tip();
+ chainActive.SetTip(del->pprev);
+ pcoinsTip->SetBestBlock(del->pprev->GetBlockHash());
+ delete del->phashBlock;
+ delete del;
+ }
+
+ // non-final txs in mempool
+ SetMockTime(chainActive.Tip()->GetMedianTimePast()+1);
+ int flags = LOCKTIME_VERIFY_SEQUENCE|LOCKTIME_MEDIAN_TIME_PAST;
+ // height map
+ std::vector<int> prevheights;
+
+ // relative height locked
+ tx.nVersion = 2;
+ tx.vin.resize(1);
+ prevheights.resize(1);
+ tx.vin[0].prevout.hash = txFirst[0]->GetHash(); // only 1 transaction
+ tx.vin[0].prevout.n = 0;
+ tx.vin[0].scriptSig = CScript() << OP_1;
+ tx.vin[0].nSequence = chainActive.Tip()->nHeight + 1; // txFirst[0] is the 2nd block
+ prevheights[0] = baseheight + 1;
+ tx.vout.resize(1);
+ tx.vout[0].nValue = BLOCKSUBSIDY-HIGHFEE;
+ tx.vout[0].scriptPubKey = CScript() << OP_1;
+ tx.nLockTime = 0;
+ hash = tx.GetHash();
+ mempool.addUnchecked(hash, entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
+ BOOST_CHECK(CheckFinalTx(tx, flags)); // Locktime passes
+ BOOST_CHECK(!TestSequenceLocks(tx, flags)); // Sequence locks fail
+ BOOST_CHECK(SequenceLocks(tx, flags, &prevheights, CreateBlockIndex(chainActive.Tip()->nHeight + 2))); // Sequence locks pass on 2nd block
+
+ // relative time locked
+ tx.vin[0].prevout.hash = txFirst[1]->GetHash();
+ tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | (((chainActive.Tip()->GetMedianTimePast()+1-chainActive[1]->GetMedianTimePast()) >> CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) + 1); // txFirst[1] is the 3rd block
+ prevheights[0] = baseheight + 2;
+ hash = tx.GetHash();
+ mempool.addUnchecked(hash, entry.Time(GetTime()).FromTx(tx));
+ BOOST_CHECK(CheckFinalTx(tx, flags)); // Locktime passes
+ BOOST_CHECK(!TestSequenceLocks(tx, flags)); // Sequence locks fail
+
+ for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++)
+ chainActive.Tip()->GetAncestor(chainActive.Tip()->nHeight - i)->nTime += 512; //Trick the MedianTimePast
+ BOOST_CHECK(SequenceLocks(tx, flags, &prevheights, CreateBlockIndex(chainActive.Tip()->nHeight + 1))); // Sequence locks pass 512 seconds later
+ for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++)
+ chainActive.Tip()->GetAncestor(chainActive.Tip()->nHeight - i)->nTime -= 512; //undo tricked MTP
+
+ // absolute height locked
+ tx.vin[0].prevout.hash = txFirst[2]->GetHash();
+ tx.vin[0].nSequence = CTxIn::SEQUENCE_FINAL - 1;
+ prevheights[0] = baseheight + 3;
+ tx.nLockTime = chainActive.Tip()->nHeight + 1;
+ hash = tx.GetHash();
+ mempool.addUnchecked(hash, entry.Time(GetTime()).FromTx(tx));
+ BOOST_CHECK(!CheckFinalTx(tx, flags)); // Locktime fails
+ BOOST_CHECK(TestSequenceLocks(tx, flags)); // Sequence locks pass
+ BOOST_CHECK(IsFinalTx(tx, chainActive.Tip()->nHeight + 2, chainActive.Tip()->GetMedianTimePast())); // Locktime passes on 2nd block
+
+ // absolute time locked
+ tx.vin[0].prevout.hash = txFirst[3]->GetHash();
+ tx.nLockTime = chainActive.Tip()->GetMedianTimePast();
+ prevheights.resize(1);
+ prevheights[0] = baseheight + 4;
+ hash = tx.GetHash();
+ mempool.addUnchecked(hash, entry.Time(GetTime()).FromTx(tx));
+ BOOST_CHECK(!CheckFinalTx(tx, flags)); // Locktime fails
+ BOOST_CHECK(TestSequenceLocks(tx, flags)); // Sequence locks pass
+ BOOST_CHECK(IsFinalTx(tx, chainActive.Tip()->nHeight + 2, chainActive.Tip()->GetMedianTimePast() + 1)); // Locktime passes 1 second later
+
+ // mempool-dependent transactions (not added)
+ tx.vin[0].prevout.hash = hash;
+ prevheights[0] = chainActive.Tip()->nHeight + 1;
+ tx.nLockTime = 0;
+ tx.vin[0].nSequence = 0;
+ BOOST_CHECK(CheckFinalTx(tx, flags)); // Locktime passes
+ BOOST_CHECK(TestSequenceLocks(tx, flags)); // Sequence locks pass
+ tx.vin[0].nSequence = 1;
+ BOOST_CHECK(!TestSequenceLocks(tx, flags)); // Sequence locks fail
+ tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG;
+ BOOST_CHECK(TestSequenceLocks(tx, flags)); // Sequence locks pass
+ tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | 1;
+ BOOST_CHECK(!TestSequenceLocks(tx, flags)); // Sequence locks fail
+
+ BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
+
+ // None of the of the absolute height/time locked tx should have made
+ // it into the template because we still check IsFinalTx in CreateNewBlock,
+ // but relative locked txs will if inconsistently added to mempool.
+ // For now these will still generate a valid template until BIP68 soft fork
+ BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 3U);
+ // However if we advance height by 1 and time by 512, all of them should be mined
+ for (int i = 0; i < CBlockIndex::nMedianTimeSpan; i++)
+ chainActive.Tip()->GetAncestor(chainActive.Tip()->nHeight - i)->nTime += 512; //Trick the MedianTimePast
+ chainActive.Tip()->nHeight++;
+ SetMockTime(chainActive.Tip()->GetMedianTimePast() + 1);
+
+ BOOST_CHECK(pblocktemplate = AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey));
+ BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 5U);
+
+ chainActive.Tip()->nHeight--;
+ SetMockTime(0);
+ mempool.clear();
+
+ TestPackageSelection(chainparams, scriptPubKey, txFirst);
+
+ fCheckpointsEnabled = true;
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp
new file mode 100644
index 0000000000..61e579ed38
--- /dev/null
+++ b/src/test/multisig_tests.cpp
@@ -0,0 +1,217 @@
+// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <key.h>
+#include <keystore.h>
+#include <policy/policy.h>
+#include <script/script.h>
+#include <script/script_error.h>
+#include <script/interpreter.h>
+#include <script/sign.h>
+#include <script/ismine.h>
+#include <uint256.h>
+#include <test/test_bitcoin.h>
+
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(multisig_tests, BasicTestingSetup)
+
+static CScript
+sign_multisig(const CScript& scriptPubKey, const std::vector<CKey>& keys, const CTransaction& transaction, int whichIn)
+{
+ uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL, 0, SigVersion::BASE);
+
+ CScript result;
+ result << OP_0; // CHECKMULTISIG bug workaround
+ for (const CKey &key : keys)
+ {
+ std::vector<unsigned char> vchSig;
+ BOOST_CHECK(key.Sign(hash, vchSig));
+ vchSig.push_back((unsigned char)SIGHASH_ALL);
+ result << vchSig;
+ }
+ return result;
+}
+
+BOOST_AUTO_TEST_CASE(multisig_verify)
+{
+ unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
+
+ ScriptError err;
+ CKey key[4];
+ CAmount amount = 0;
+ for (int i = 0; i < 4; i++)
+ key[i].MakeNewKey(true);
+
+ CScript a_and_b;
+ a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
+
+ CScript a_or_b;
+ a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
+
+ CScript escrow;
+ escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
+
+ CMutableTransaction txFrom; // Funding transaction
+ txFrom.vout.resize(3);
+ txFrom.vout[0].scriptPubKey = a_and_b;
+ txFrom.vout[1].scriptPubKey = a_or_b;
+ txFrom.vout[2].scriptPubKey = escrow;
+
+ CMutableTransaction txTo[3]; // Spending transaction
+ for (int i = 0; i < 3; i++)
+ {
+ txTo[i].vin.resize(1);
+ txTo[i].vout.resize(1);
+ txTo[i].vin[0].prevout.n = i;
+ txTo[i].vin[0].prevout.hash = txFrom.GetHash();
+ txTo[i].vout[0].nValue = 1;
+ }
+
+ std::vector<CKey> keys;
+ CScript s;
+
+ // Test a AND b:
+ keys.assign(1,key[0]);
+ keys.push_back(key[1]);
+ s = sign_multisig(a_and_b, keys, txTo[0], 0);
+ BOOST_CHECK(VerifyScript(s, a_and_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
+
+ for (int i = 0; i < 4; i++)
+ {
+ keys.assign(1,key[i]);
+ s = sign_multisig(a_and_b, keys, txTo[0], 0);
+ BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err), strprintf("a&b 1: %d", i));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
+
+ keys.assign(1,key[1]);
+ keys.push_back(key[i]);
+ s = sign_multisig(a_and_b, keys, txTo[0], 0);
+ BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err), strprintf("a&b 2: %d", i));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
+ }
+
+ // Test a OR b:
+ for (int i = 0; i < 4; i++)
+ {
+ keys.assign(1,key[i]);
+ s = sign_multisig(a_or_b, keys, txTo[1], 0);
+ if (i == 0 || i == 1)
+ {
+ BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err), strprintf("a|b: %d", i));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
+ }
+ else
+ {
+ BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err), strprintf("a|b: %d", i));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
+ }
+ }
+ s.clear();
+ s << OP_0 << OP_1;
+ BOOST_CHECK(!VerifyScript(s, a_or_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err));
+
+
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++)
+ {
+ keys.assign(1,key[i]);
+ keys.push_back(key[j]);
+ s = sign_multisig(escrow, keys, txTo[2], 0);
+ if (i < j && i < 3 && j < 3)
+ {
+ BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, nullptr, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), &err), strprintf("escrow 1: %d %d", i, j));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
+ }
+ else
+ {
+ BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, nullptr, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), &err), strprintf("escrow 2: %d %d", i, j));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(multisig_IsStandard)
+{
+ CKey key[4];
+ for (int i = 0; i < 4; i++)
+ key[i].MakeNewKey(true);
+
+ txnouttype whichType;
+
+ CScript a_and_b;
+ a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
+ BOOST_CHECK(::IsStandard(a_and_b, whichType));
+
+ CScript a_or_b;
+ a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
+ BOOST_CHECK(::IsStandard(a_or_b, whichType));
+
+ CScript escrow;
+ escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
+ BOOST_CHECK(::IsStandard(escrow, whichType));
+
+ CScript one_of_four;
+ one_of_four << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << ToByteVector(key[3].GetPubKey()) << OP_4 << OP_CHECKMULTISIG;
+ BOOST_CHECK(!::IsStandard(one_of_four, whichType));
+
+ CScript malformed[6];
+ malformed[0] << OP_3 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
+ malformed[1] << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
+ malformed[2] << OP_0 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
+ malformed[3] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_0 << OP_CHECKMULTISIG;
+ malformed[4] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_CHECKMULTISIG;
+ malformed[5] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey());
+
+ for (int i = 0; i < 6; i++)
+ BOOST_CHECK(!::IsStandard(malformed[i], whichType));
+}
+
+BOOST_AUTO_TEST_CASE(multisig_Sign)
+{
+ // Test SignSignature() (and therefore the version of Solver() that signs transactions)
+ CBasicKeyStore keystore;
+ CKey key[4];
+ for (int i = 0; i < 4; i++)
+ {
+ key[i].MakeNewKey(true);
+ keystore.AddKey(key[i]);
+ }
+
+ CScript a_and_b;
+ a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
+
+ CScript a_or_b;
+ a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
+
+ CScript escrow;
+ escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
+
+ CMutableTransaction txFrom; // Funding transaction
+ txFrom.vout.resize(3);
+ txFrom.vout[0].scriptPubKey = a_and_b;
+ txFrom.vout[1].scriptPubKey = a_or_b;
+ txFrom.vout[2].scriptPubKey = escrow;
+
+ CMutableTransaction txTo[3]; // Spending transaction
+ for (int i = 0; i < 3; i++)
+ {
+ txTo[i].vin.resize(1);
+ txTo[i].vout.resize(1);
+ txTo[i].vin[0].prevout.n = i;
+ txTo[i].vin[0].prevout.hash = txFrom.GetHash();
+ txTo[i].vout[0].nValue = 1;
+ }
+
+ for (int i = 0; i < 3; i++)
+ {
+ BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i));
+ }
+}
+
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp
new file mode 100644
index 0000000000..4c56938ec9
--- /dev/null
+++ b/src/test/net_tests.cpp
@@ -0,0 +1,192 @@
+// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <addrman.h>
+#include <test/test_bitcoin.h>
+#include <string>
+#include <boost/test/unit_test.hpp>
+#include <hash.h>
+#include <serialize.h>
+#include <streams.h>
+#include <net.h>
+#include <netbase.h>
+#include <chainparams.h>
+#include <util.h>
+
+#include <memory>
+
+class CAddrManSerializationMock : public CAddrMan
+{
+public:
+ virtual void Serialize(CDataStream& s) const = 0;
+
+ //! Ensure that bucket placement is always the same for testing purposes.
+ void MakeDeterministic()
+ {
+ nKey.SetNull();
+ insecure_rand = FastRandomContext(true);
+ }
+};
+
+class CAddrManUncorrupted : public CAddrManSerializationMock
+{
+public:
+ void Serialize(CDataStream& s) const override
+ {
+ CAddrMan::Serialize(s);
+ }
+};
+
+class CAddrManCorrupted : public CAddrManSerializationMock
+{
+public:
+ void Serialize(CDataStream& s) const override
+ {
+ // Produces corrupt output that claims addrman has 20 addrs when it only has one addr.
+ unsigned char nVersion = 1;
+ s << nVersion;
+ s << ((unsigned char)32);
+ s << nKey;
+ s << 10; // nNew
+ s << 10; // nTried
+
+ int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30);
+ s << nUBuckets;
+
+ CService serv;
+ Lookup("252.1.1.1", serv, 7777, false);
+ CAddress addr = CAddress(serv, NODE_NONE);
+ CNetAddr resolved;
+ LookupHost("252.2.2.2", resolved, false);
+ CAddrInfo info = CAddrInfo(addr, resolved);
+ s << info;
+ }
+};
+
+static CDataStream AddrmanToStream(CAddrManSerializationMock& _addrman)
+{
+ CDataStream ssPeersIn(SER_DISK, CLIENT_VERSION);
+ ssPeersIn << Params().MessageStart();
+ ssPeersIn << _addrman;
+ std::string str = ssPeersIn.str();
+ std::vector<unsigned char> vchData(str.begin(), str.end());
+ return CDataStream(vchData, SER_DISK, CLIENT_VERSION);
+}
+
+BOOST_FIXTURE_TEST_SUITE(net_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(cnode_listen_port)
+{
+ // test default
+ unsigned short port = GetListenPort();
+ BOOST_CHECK(port == Params().GetDefaultPort());
+ // test set port
+ unsigned short altPort = 12345;
+ gArgs.SoftSetArg("-port", std::to_string(altPort));
+ port = GetListenPort();
+ BOOST_CHECK(port == altPort);
+}
+
+BOOST_AUTO_TEST_CASE(caddrdb_read)
+{
+ SetDataDir("caddrdb_read");
+ CAddrManUncorrupted addrmanUncorrupted;
+ addrmanUncorrupted.MakeDeterministic();
+
+ CService addr1, addr2, addr3;
+ Lookup("250.7.1.1", addr1, 8333, false);
+ Lookup("250.7.2.2", addr2, 9999, false);
+ Lookup("250.7.3.3", addr3, 9999, false);
+
+ // Add three addresses to new table.
+ CService source;
+ Lookup("252.5.1.1", source, 8333, false);
+ addrmanUncorrupted.Add(CAddress(addr1, NODE_NONE), source);
+ addrmanUncorrupted.Add(CAddress(addr2, NODE_NONE), source);
+ addrmanUncorrupted.Add(CAddress(addr3, NODE_NONE), source);
+
+ // Test that the de-serialization does not throw an exception.
+ CDataStream ssPeers1 = AddrmanToStream(addrmanUncorrupted);
+ bool exceptionThrown = false;
+ CAddrMan addrman1;
+
+ BOOST_CHECK(addrman1.size() == 0);
+ try {
+ unsigned char pchMsgTmp[4];
+ ssPeers1 >> pchMsgTmp;
+ ssPeers1 >> addrman1;
+ } catch (const std::exception& e) {
+ exceptionThrown = true;
+ }
+
+ BOOST_CHECK(addrman1.size() == 3);
+ BOOST_CHECK(exceptionThrown == false);
+
+ // Test that CAddrDB::Read creates an addrman with the correct number of addrs.
+ CDataStream ssPeers2 = AddrmanToStream(addrmanUncorrupted);
+
+ CAddrMan addrman2;
+ CAddrDB adb;
+ BOOST_CHECK(addrman2.size() == 0);
+ adb.Read(addrman2, ssPeers2);
+ BOOST_CHECK(addrman2.size() == 3);
+}
+
+
+BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted)
+{
+ SetDataDir("caddrdb_read_corrupted");
+ CAddrManCorrupted addrmanCorrupted;
+ addrmanCorrupted.MakeDeterministic();
+
+ // Test that the de-serialization of corrupted addrman throws an exception.
+ CDataStream ssPeers1 = AddrmanToStream(addrmanCorrupted);
+ bool exceptionThrown = false;
+ CAddrMan addrman1;
+ BOOST_CHECK(addrman1.size() == 0);
+ try {
+ unsigned char pchMsgTmp[4];
+ ssPeers1 >> pchMsgTmp;
+ ssPeers1 >> addrman1;
+ } catch (const std::exception& e) {
+ exceptionThrown = true;
+ }
+ // Even through de-serialization failed addrman is not left in a clean state.
+ BOOST_CHECK(addrman1.size() == 1);
+ BOOST_CHECK(exceptionThrown);
+
+ // Test that CAddrDB::Read leaves addrman in a clean state if de-serialization fails.
+ CDataStream ssPeers2 = AddrmanToStream(addrmanCorrupted);
+
+ CAddrMan addrman2;
+ CAddrDB adb;
+ BOOST_CHECK(addrman2.size() == 0);
+ adb.Read(addrman2, ssPeers2);
+ BOOST_CHECK(addrman2.size() == 0);
+}
+
+BOOST_AUTO_TEST_CASE(cnode_simple_test)
+{
+ SOCKET hSocket = INVALID_SOCKET;
+ NodeId id = 0;
+ int height = 0;
+
+ in_addr ipv4Addr;
+ ipv4Addr.s_addr = 0xa0b0c001;
+
+ CAddress addr = CAddress(CService(ipv4Addr, 7777), NODE_NETWORK);
+ std::string pszDest;
+ bool fInboundIn = false;
+
+ // Test that fFeeler is false by default.
+ std::unique_ptr<CNode> pnode1(new CNode(id++, NODE_NETWORK, height, hSocket, addr, 0, 0, CAddress(), pszDest, fInboundIn));
+ BOOST_CHECK(pnode1->fInbound == false);
+ BOOST_CHECK(pnode1->fFeeler == false);
+
+ fInboundIn = true;
+ std::unique_ptr<CNode> pnode2(new CNode(id++, NODE_NETWORK, height, hSocket, addr, 1, 1, CAddress(), pszDest, fInboundIn));
+ BOOST_CHECK(pnode2->fInbound == true);
+ BOOST_CHECK(pnode2->fFeeler == false);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp
new file mode 100644
index 0000000000..9c1af6bdf6
--- /dev/null
+++ b/src/test/netbase_tests.cpp
@@ -0,0 +1,305 @@
+// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <netbase.h>
+#include <test/test_bitcoin.h>
+#include <utilstrencodings.h>
+
+#include <string>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(netbase_tests, BasicTestingSetup)
+
+static CNetAddr ResolveIP(const char* ip)
+{
+ CNetAddr addr;
+ LookupHost(ip, addr, false);
+ return addr;
+}
+
+static CSubNet ResolveSubNet(const char* subnet)
+{
+ CSubNet ret;
+ LookupSubNet(subnet, ret);
+ return ret;
+}
+
+static CNetAddr CreateInternal(const char* host)
+{
+ CNetAddr addr;
+ addr.SetInternal(host);
+ return addr;
+}
+
+BOOST_AUTO_TEST_CASE(netbase_networks)
+{
+ BOOST_CHECK(ResolveIP("127.0.0.1").GetNetwork() == NET_UNROUTABLE);
+ BOOST_CHECK(ResolveIP("::1").GetNetwork() == NET_UNROUTABLE);
+ BOOST_CHECK(ResolveIP("8.8.8.8").GetNetwork() == NET_IPV4);
+ BOOST_CHECK(ResolveIP("2001::8888").GetNetwork() == NET_IPV6);
+ BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetNetwork() == NET_ONION);
+ BOOST_CHECK(CreateInternal("foo.com").GetNetwork() == NET_INTERNAL);
+
+}
+
+BOOST_AUTO_TEST_CASE(netbase_properties)
+{
+
+ BOOST_CHECK(ResolveIP("127.0.0.1").IsIPv4());
+ BOOST_CHECK(ResolveIP("::FFFF:192.168.1.1").IsIPv4());
+ BOOST_CHECK(ResolveIP("::1").IsIPv6());
+ BOOST_CHECK(ResolveIP("10.0.0.1").IsRFC1918());
+ BOOST_CHECK(ResolveIP("192.168.1.1").IsRFC1918());
+ BOOST_CHECK(ResolveIP("172.31.255.255").IsRFC1918());
+ BOOST_CHECK(ResolveIP("2001:0DB8::").IsRFC3849());
+ BOOST_CHECK(ResolveIP("169.254.1.1").IsRFC3927());
+ BOOST_CHECK(ResolveIP("2002::1").IsRFC3964());
+ BOOST_CHECK(ResolveIP("FC00::").IsRFC4193());
+ BOOST_CHECK(ResolveIP("2001::2").IsRFC4380());
+ BOOST_CHECK(ResolveIP("2001:10::").IsRFC4843());
+ BOOST_CHECK(ResolveIP("FE80::").IsRFC4862());
+ BOOST_CHECK(ResolveIP("64:FF9B::").IsRFC6052());
+ BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").IsTor());
+ BOOST_CHECK(ResolveIP("127.0.0.1").IsLocal());
+ BOOST_CHECK(ResolveIP("::1").IsLocal());
+ BOOST_CHECK(ResolveIP("8.8.8.8").IsRoutable());
+ BOOST_CHECK(ResolveIP("2001::1").IsRoutable());
+ BOOST_CHECK(ResolveIP("127.0.0.1").IsValid());
+ BOOST_CHECK(CreateInternal("FD6B:88C0:8724:edb1:8e4:3588:e546:35ca").IsInternal());
+ BOOST_CHECK(CreateInternal("bar.com").IsInternal());
+
+}
+
+bool static TestSplitHost(std::string test, std::string host, int port)
+{
+ std::string hostOut;
+ int portOut = -1;
+ SplitHostPort(test, portOut, hostOut);
+ return hostOut == host && port == portOut;
+}
+
+BOOST_AUTO_TEST_CASE(netbase_splithost)
+{
+ BOOST_CHECK(TestSplitHost("www.bitcoincore.org", "www.bitcoincore.org", -1));
+ BOOST_CHECK(TestSplitHost("[www.bitcoincore.org]", "www.bitcoincore.org", -1));
+ BOOST_CHECK(TestSplitHost("www.bitcoincore.org:80", "www.bitcoincore.org", 80));
+ BOOST_CHECK(TestSplitHost("[www.bitcoincore.org]:80", "www.bitcoincore.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(std::string src, std::string canon)
+{
+ CService addr(LookupNumeric(src.c_str(), 65535));
+ 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(":::", "[::]:0"));
+
+ // verify that an internal address fails to resolve
+ BOOST_CHECK(TestParse("[fd6b:88c0:8724:1:2:3:4:5]", "[::]:0"));
+ // and that a one-off resolves correctly
+ BOOST_CHECK(TestParse("[fd6c:88c0:8724:1:2:3:4:5]", "[fd6c:88c0:8724:1:2:3:4:5]:65535"));
+}
+
+BOOST_AUTO_TEST_CASE(onioncat_test)
+{
+
+ // values from https://web.archive.org/web/20121122003543/http://www.cypherpunk.at/onioncat/wiki/OnionCat
+ CNetAddr addr1(ResolveIP("5wyqrzbvrdsumnok.onion"));
+ CNetAddr addr2(ResolveIP("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_CASE(subnet_test)
+{
+
+ BOOST_CHECK(ResolveSubNet("1.2.3.0/24") == ResolveSubNet("1.2.3.0/255.255.255.0"));
+ BOOST_CHECK(ResolveSubNet("1.2.3.0/24") != ResolveSubNet("1.2.4.0/255.255.255.0"));
+ BOOST_CHECK(ResolveSubNet("1.2.3.0/24").Match(ResolveIP("1.2.3.4")));
+ BOOST_CHECK(!ResolveSubNet("1.2.2.0/24").Match(ResolveIP("1.2.3.4")));
+ BOOST_CHECK(ResolveSubNet("1.2.3.4").Match(ResolveIP("1.2.3.4")));
+ BOOST_CHECK(ResolveSubNet("1.2.3.4/32").Match(ResolveIP("1.2.3.4")));
+ BOOST_CHECK(!ResolveSubNet("1.2.3.4").Match(ResolveIP("5.6.7.8")));
+ BOOST_CHECK(!ResolveSubNet("1.2.3.4/32").Match(ResolveIP("5.6.7.8")));
+ BOOST_CHECK(ResolveSubNet("::ffff:127.0.0.1").Match(ResolveIP("127.0.0.1")));
+ BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:8").Match(ResolveIP("1:2:3:4:5:6:7:8")));
+ BOOST_CHECK(!ResolveSubNet("1:2:3:4:5:6:7:8").Match(ResolveIP("1:2:3:4:5:6:7:9")));
+ BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:0/112").Match(ResolveIP("1:2:3:4:5:6:7:1234")));
+ BOOST_CHECK(ResolveSubNet("192.168.0.1/24").Match(ResolveIP("192.168.0.2")));
+ BOOST_CHECK(ResolveSubNet("192.168.0.20/29").Match(ResolveIP("192.168.0.18")));
+ BOOST_CHECK(ResolveSubNet("1.2.2.1/24").Match(ResolveIP("1.2.2.4")));
+ BOOST_CHECK(ResolveSubNet("1.2.2.110/31").Match(ResolveIP("1.2.2.111")));
+ BOOST_CHECK(ResolveSubNet("1.2.2.20/26").Match(ResolveIP("1.2.2.63")));
+ // All-Matching IPv6 Matches arbitrary IPv4 and IPv6
+ BOOST_CHECK(ResolveSubNet("::/0").Match(ResolveIP("1:2:3:4:5:6:7:1234")));
+ BOOST_CHECK(ResolveSubNet("::/0").Match(ResolveIP("1.2.3.4")));
+ // All-Matching IPv4 does not Match IPv6
+ BOOST_CHECK(!ResolveSubNet("0.0.0.0/0").Match(ResolveIP("1:2:3:4:5:6:7:1234")));
+ // Invalid subnets Match nothing (not even invalid addresses)
+ BOOST_CHECK(!CSubNet().Match(ResolveIP("1.2.3.4")));
+ BOOST_CHECK(!ResolveSubNet("").Match(ResolveIP("4.5.6.7")));
+ BOOST_CHECK(!ResolveSubNet("bloop").Match(ResolveIP("0.0.0.0")));
+ BOOST_CHECK(!ResolveSubNet("bloop").Match(ResolveIP("hab")));
+ // Check valid/invalid
+ BOOST_CHECK(ResolveSubNet("1.2.3.0/0").IsValid());
+ BOOST_CHECK(!ResolveSubNet("1.2.3.0/-1").IsValid());
+ BOOST_CHECK(ResolveSubNet("1.2.3.0/32").IsValid());
+ BOOST_CHECK(!ResolveSubNet("1.2.3.0/33").IsValid());
+ BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:8/0").IsValid());
+ BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:8/33").IsValid());
+ BOOST_CHECK(!ResolveSubNet("1:2:3:4:5:6:7:8/-1").IsValid());
+ BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:8/128").IsValid());
+ BOOST_CHECK(!ResolveSubNet("1:2:3:4:5:6:7:8/129").IsValid());
+ BOOST_CHECK(!ResolveSubNet("fuzzy").IsValid());
+
+ //CNetAddr constructor test
+ BOOST_CHECK(CSubNet(ResolveIP("127.0.0.1")).IsValid());
+ BOOST_CHECK(CSubNet(ResolveIP("127.0.0.1")).Match(ResolveIP("127.0.0.1")));
+ BOOST_CHECK(!CSubNet(ResolveIP("127.0.0.1")).Match(ResolveIP("127.0.0.2")));
+ BOOST_CHECK(CSubNet(ResolveIP("127.0.0.1")).ToString() == "127.0.0.1/32");
+
+ CSubNet subnet = CSubNet(ResolveIP("1.2.3.4"), 32);
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/32");
+ subnet = CSubNet(ResolveIP("1.2.3.4"), 8);
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/8");
+ subnet = CSubNet(ResolveIP("1.2.3.4"), 0);
+ BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/0");
+
+ subnet = CSubNet(ResolveIP("1.2.3.4"), ResolveIP("255.255.255.255"));
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/32");
+ subnet = CSubNet(ResolveIP("1.2.3.4"), ResolveIP("255.0.0.0"));
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/8");
+ subnet = CSubNet(ResolveIP("1.2.3.4"), ResolveIP("0.0.0.0"));
+ BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/0");
+
+ BOOST_CHECK(CSubNet(ResolveIP("1:2:3:4:5:6:7:8")).IsValid());
+ BOOST_CHECK(CSubNet(ResolveIP("1:2:3:4:5:6:7:8")).Match(ResolveIP("1:2:3:4:5:6:7:8")));
+ BOOST_CHECK(!CSubNet(ResolveIP("1:2:3:4:5:6:7:8")).Match(ResolveIP("1:2:3:4:5:6:7:9")));
+ BOOST_CHECK(CSubNet(ResolveIP("1:2:3:4:5:6:7:8")).ToString() == "1:2:3:4:5:6:7:8/128");
+
+ subnet = ResolveSubNet("1.2.3.4/255.255.255.255");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/32");
+ subnet = ResolveSubNet("1.2.3.4/255.255.255.254");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/31");
+ subnet = ResolveSubNet("1.2.3.4/255.255.255.252");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/30");
+ subnet = ResolveSubNet("1.2.3.4/255.255.255.248");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/29");
+ subnet = ResolveSubNet("1.2.3.4/255.255.255.240");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/28");
+ subnet = ResolveSubNet("1.2.3.4/255.255.255.224");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/27");
+ subnet = ResolveSubNet("1.2.3.4/255.255.255.192");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/26");
+ subnet = ResolveSubNet("1.2.3.4/255.255.255.128");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/25");
+ subnet = ResolveSubNet("1.2.3.4/255.255.255.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/24");
+ subnet = ResolveSubNet("1.2.3.4/255.255.254.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.2.0/23");
+ subnet = ResolveSubNet("1.2.3.4/255.255.252.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/22");
+ subnet = ResolveSubNet("1.2.3.4/255.255.248.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/21");
+ subnet = ResolveSubNet("1.2.3.4/255.255.240.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/20");
+ subnet = ResolveSubNet("1.2.3.4/255.255.224.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/19");
+ subnet = ResolveSubNet("1.2.3.4/255.255.192.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/18");
+ subnet = ResolveSubNet("1.2.3.4/255.255.128.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/17");
+ subnet = ResolveSubNet("1.2.3.4/255.255.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/16");
+ subnet = ResolveSubNet("1.2.3.4/255.254.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/15");
+ subnet = ResolveSubNet("1.2.3.4/255.252.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/14");
+ subnet = ResolveSubNet("1.2.3.4/255.248.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/13");
+ subnet = ResolveSubNet("1.2.3.4/255.240.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/12");
+ subnet = ResolveSubNet("1.2.3.4/255.224.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/11");
+ subnet = ResolveSubNet("1.2.3.4/255.192.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/10");
+ subnet = ResolveSubNet("1.2.3.4/255.128.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/9");
+ subnet = ResolveSubNet("1.2.3.4/255.0.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/8");
+ subnet = ResolveSubNet("1.2.3.4/254.0.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/7");
+ subnet = ResolveSubNet("1.2.3.4/252.0.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/6");
+ subnet = ResolveSubNet("1.2.3.4/248.0.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/5");
+ subnet = ResolveSubNet("1.2.3.4/240.0.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/4");
+ subnet = ResolveSubNet("1.2.3.4/224.0.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/3");
+ subnet = ResolveSubNet("1.2.3.4/192.0.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/2");
+ subnet = ResolveSubNet("1.2.3.4/128.0.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/1");
+ subnet = ResolveSubNet("1.2.3.4/0.0.0.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/0");
+
+ subnet = ResolveSubNet("1:2:3:4:5:6:7:8/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1:2:3:4:5:6:7:8/128");
+ subnet = ResolveSubNet("1:2:3:4:5:6:7:8/ffff:0000:0000:0000:0000:0000:0000:0000");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1::/16");
+ subnet = ResolveSubNet("1:2:3:4:5:6:7:8/0000:0000:0000:0000:0000:0000:0000:0000");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "::/0");
+ subnet = ResolveSubNet("1.2.3.4/255.255.232.0");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/255.255.232.0");
+ subnet = ResolveSubNet("1:2:3:4:5:6:7:8/ffff:ffff:ffff:fffe:ffff:ffff:ffff:ff0f");
+ BOOST_CHECK_EQUAL(subnet.ToString(), "1:2:3:4:5:6:7:8/ffff:ffff:ffff:fffe:ffff:ffff:ffff:ff0f");
+
+}
+
+BOOST_AUTO_TEST_CASE(netbase_getgroup)
+{
+
+ BOOST_CHECK(ResolveIP("127.0.0.1").GetGroup() == std::vector<unsigned char>({0})); // Local -> !Routable()
+ BOOST_CHECK(ResolveIP("257.0.0.1").GetGroup() == std::vector<unsigned char>({0})); // !Valid -> !Routable()
+ BOOST_CHECK(ResolveIP("10.0.0.1").GetGroup() == std::vector<unsigned char>({0})); // RFC1918 -> !Routable()
+ BOOST_CHECK(ResolveIP("169.254.1.1").GetGroup() == std::vector<unsigned char>({0})); // RFC3927 -> !Routable()
+ BOOST_CHECK(ResolveIP("1.2.3.4").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // IPv4
+ BOOST_CHECK(ResolveIP("::FFFF:0:102:304").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC6145
+ BOOST_CHECK(ResolveIP("64:FF9B::102:304").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC6052
+ BOOST_CHECK(ResolveIP("2002:102:304:9999:9999:9999:9999:9999").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC3964
+ BOOST_CHECK(ResolveIP("2001:0:9999:9999:9999:9999:FEFD:FCFB").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV4, 1, 2})); // RFC4380
+ BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_ONION, 239})); // Tor
+ BOOST_CHECK(ResolveIP("2001:470:abcd:9999:9999:9999:9999:9999").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV6, 32, 1, 4, 112, 175})); //he.net
+ BOOST_CHECK(ResolveIP("2001:2001:9999:9999:9999:9999:9999:9999").GetGroup() == std::vector<unsigned char>({(unsigned char)NET_IPV6, 32, 1, 32, 1})); //IPv6
+
+ // baz.net sha256 hash: 12929400eb4607c4ac075f087167e75286b179c693eb059a01774b864e8fe505
+ std::vector<unsigned char> internal_group = {NET_INTERNAL, 0x12, 0x92, 0x94, 0x00, 0xeb, 0x46, 0x07, 0xc4, 0xac, 0x07};
+ BOOST_CHECK(CreateInternal("baz.net").GetGroup() == internal_group);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp
new file mode 100644
index 0000000000..5020192804
--- /dev/null
+++ b/src/test/pmt_tests.cpp
@@ -0,0 +1,126 @@
+// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <consensus/merkle.h>
+#include <merkleblock.h>
+#include <serialize.h>
+#include <streams.h>
+#include <uint256.h>
+#include <arith_uint256.h>
+#include <version.h>
+#include <test/test_bitcoin.h>
+
+#include <vector>
+
+#include <boost/test/unit_test.hpp>
+
+class CPartialMerkleTreeTester : public CPartialMerkleTree
+{
+public:
+ // flip one bit in one of the hashes - this should break the authentication
+ void Damage() {
+ unsigned int n = InsecureRandRange(vHash.size());
+ int bit = InsecureRandBits(8);
+ *(vHash[n].begin() + (bit>>3)) ^= 1<<(bit&7);
+ }
+};
+
+BOOST_FIXTURE_TEST_SUITE(pmt_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(pmt_test1)
+{
+ SeedInsecureRand(false);
+ static const unsigned int nTxCounts[] = {1, 4, 7, 17, 56, 100, 127, 256, 312, 513, 1000, 4095};
+
+ for (int i = 0; i < 12; i++) {
+ unsigned int nTx = nTxCounts[i];
+
+ // build a block with some dummy transactions
+ CBlock block;
+ for (unsigned int j=0; j<nTx; j++) {
+ CMutableTransaction tx;
+ tx.nLockTime = j; // actual transaction data doesn't matter; just make the nLockTime's unique
+ block.vtx.push_back(MakeTransactionRef(std::move(tx)));
+ }
+
+ // calculate actual merkle root and height
+ uint256 merkleRoot1 = BlockMerkleRoot(block);
+ std::vector<uint256> vTxid(nTx, uint256());
+ for (unsigned int j=0; j<nTx; j++)
+ vTxid[j] = block.vtx[j]->GetHash();
+ int nHeight = 1, nTx_ = nTx;
+ while (nTx_ > 1) {
+ nTx_ = (nTx_+1)/2;
+ nHeight++;
+ }
+
+ // check with random subsets with inclusion chances 1, 1/2, 1/4, ..., 1/128
+ for (int att = 1; att < 15; att++) {
+ // build random subset of txid's
+ std::vector<bool> vMatch(nTx, false);
+ std::vector<uint256> vMatchTxid1;
+ for (unsigned int j=0; j<nTx; j++) {
+ bool fInclude = InsecureRandBits(att / 2) == 0;
+ vMatch[j] = fInclude;
+ if (fInclude)
+ vMatchTxid1.push_back(vTxid[j]);
+ }
+
+ // build the partial merkle tree
+ CPartialMerkleTree pmt1(vTxid, vMatch);
+
+ // serialize
+ CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
+ ss << pmt1;
+
+ // verify CPartialMerkleTree's size guarantees
+ unsigned int n = std::min<unsigned int>(nTx, 1 + vMatchTxid1.size()*nHeight);
+ BOOST_CHECK(ss.size() <= 10 + (258*n+7)/8);
+
+ // deserialize into a tester copy
+ CPartialMerkleTreeTester pmt2;
+ ss >> pmt2;
+
+ // extract merkle root and matched txids from copy
+ std::vector<uint256> vMatchTxid2;
+ std::vector<unsigned int> vIndex;
+ uint256 merkleRoot2 = pmt2.ExtractMatches(vMatchTxid2, vIndex);
+
+ // check that it has the same merkle root as the original, and a valid one
+ BOOST_CHECK(merkleRoot1 == merkleRoot2);
+ BOOST_CHECK(!merkleRoot2.IsNull());
+
+ // check that it contains the matched transactions (in the same order!)
+ BOOST_CHECK(vMatchTxid1 == vMatchTxid2);
+
+ // check that random bit flips break the authentication
+ for (int j=0; j<4; j++) {
+ CPartialMerkleTreeTester pmt3(pmt2);
+ pmt3.Damage();
+ std::vector<uint256> vMatchTxid3;
+ uint256 merkleRoot3 = pmt3.ExtractMatches(vMatchTxid3, vIndex);
+ BOOST_CHECK(merkleRoot3 != merkleRoot1);
+ }
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(pmt_malleability)
+{
+ std::vector<uint256> vTxid = {
+ ArithToUint256(1), ArithToUint256(2),
+ ArithToUint256(3), ArithToUint256(4),
+ ArithToUint256(5), ArithToUint256(6),
+ ArithToUint256(7), ArithToUint256(8),
+ ArithToUint256(9), ArithToUint256(10),
+ ArithToUint256(9), ArithToUint256(10),
+ };
+ std::vector<bool> vMatch = {false, false, false, false, false, false, false, false, false, true, true, false};
+
+ CPartialMerkleTree tree(vTxid, vMatch);
+ std::vector<unsigned int> vIndex;
+ BOOST_CHECK(tree.ExtractMatches(vTxid, vIndex).IsNull());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp
new file mode 100644
index 0000000000..26a0b495d9
--- /dev/null
+++ b/src/test/policyestimator_tests.cpp
@@ -0,0 +1,183 @@
+// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <policy/policy.h>
+#include <policy/fees.h>
+#include <txmempool.h>
+#include <uint256.h>
+#include <util.h>
+
+#include <test/test_bitcoin.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(policyestimator_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(BlockPolicyEstimates)
+{
+ CBlockPolicyEstimator feeEst;
+ CTxMemPool mpool(&feeEst);
+ LOCK(mpool.cs);
+ TestMemPoolEntryHelper entry;
+ CAmount basefee(2000);
+ CAmount deltaFee(100);
+ std::vector<CAmount> feeV;
+
+ // Populate vectors of increasing fees
+ for (int j = 0; j < 10; j++) {
+ feeV.push_back(basefee * (j+1));
+ }
+
+ // Store the hashes of transactions that have been
+ // added to the mempool by their associate fee
+ // txHashes[j] is populated with transactions either of
+ // fee = basefee * (j+1)
+ std::vector<uint256> txHashes[10];
+
+ // Create a transaction template
+ CScript garbage;
+ for (unsigned int i = 0; i < 128; i++)
+ garbage.push_back('X');
+ CMutableTransaction tx;
+ tx.vin.resize(1);
+ tx.vin[0].scriptSig = garbage;
+ tx.vout.resize(1);
+ tx.vout[0].nValue=0LL;
+ CFeeRate baseRate(basefee, GetVirtualTransactionSize(tx));
+
+ // Create a fake block
+ std::vector<CTransactionRef> block;
+ int blocknum = 0;
+
+ // Loop through 200 blocks
+ // At a decay .9952 and 4 fee transactions per block
+ // This makes the tx count about 2.5 per bucket, well above the 0.1 threshold
+ while (blocknum < 200) {
+ for (int j = 0; j < 10; j++) { // For each fee
+ for (int k = 0; k < 4; k++) { // add 4 fee txs
+ tx.vin[0].prevout.n = 10000*blocknum+100*j+k; // make transaction unique
+ uint256 hash = tx.GetHash();
+ mpool.addUnchecked(hash, entry.Fee(feeV[j]).Time(GetTime()).Height(blocknum).FromTx(tx));
+ txHashes[j].push_back(hash);
+ }
+ }
+ //Create blocks where higher fee txs are included more often
+ for (int h = 0; h <= blocknum%10; h++) {
+ // 10/10 blocks add highest fee transactions
+ // 9/10 blocks add 2nd highest and so on until ...
+ // 1/10 blocks add lowest fee transactions
+ while (txHashes[9-h].size()) {
+ CTransactionRef ptx = mpool.get(txHashes[9-h].back());
+ if (ptx)
+ block.push_back(ptx);
+ txHashes[9-h].pop_back();
+ }
+ }
+ mpool.removeForBlock(block, ++blocknum);
+ block.clear();
+ // Check after just a few txs that combining buckets works as expected
+ if (blocknum == 3) {
+ // At this point we should need to combine 3 buckets to get enough data points
+ // So estimateFee(1) should fail and estimateFee(2) should return somewhere around
+ // 9*baserate. estimateFee(2) %'s are 100,100,90 = average 97%
+ BOOST_CHECK(feeEst.estimateFee(1) == CFeeRate(0));
+ BOOST_CHECK(feeEst.estimateFee(2).GetFeePerK() < 9*baseRate.GetFeePerK() + deltaFee);
+ BOOST_CHECK(feeEst.estimateFee(2).GetFeePerK() > 9*baseRate.GetFeePerK() - deltaFee);
+ }
+ }
+
+ std::vector<CAmount> origFeeEst;
+ // Highest feerate is 10*baseRate and gets in all blocks,
+ // second highest feerate is 9*baseRate and gets in 9/10 blocks = 90%,
+ // third highest feerate is 8*base rate, and gets in 8/10 blocks = 80%,
+ // so estimateFee(1) would return 10*baseRate but is hardcoded to return failure
+ // Second highest feerate has 100% chance of being included by 2 blocks,
+ // so estimateFee(2) should return 9*baseRate etc...
+ for (int i = 1; i < 10;i++) {
+ origFeeEst.push_back(feeEst.estimateFee(i).GetFeePerK());
+ if (i > 2) { // Fee estimates should be monotonically decreasing
+ BOOST_CHECK(origFeeEst[i-1] <= origFeeEst[i-2]);
+ }
+ int mult = 11-i;
+ if (i % 2 == 0) { //At scale 2, test logic is only correct for even targets
+ BOOST_CHECK(origFeeEst[i-1] < mult*baseRate.GetFeePerK() + deltaFee);
+ BOOST_CHECK(origFeeEst[i-1] > mult*baseRate.GetFeePerK() - deltaFee);
+ }
+ }
+ // Fill out rest of the original estimates
+ for (int i = 10; i <= 48; i++) {
+ origFeeEst.push_back(feeEst.estimateFee(i).GetFeePerK());
+ }
+
+ // Mine 50 more blocks with no transactions happening, estimates shouldn't change
+ // We haven't decayed the moving average enough so we still have enough data points in every bucket
+ while (blocknum < 250)
+ mpool.removeForBlock(block, ++blocknum);
+
+ BOOST_CHECK(feeEst.estimateFee(1) == CFeeRate(0));
+ for (int i = 2; i < 10;i++) {
+ BOOST_CHECK(feeEst.estimateFee(i).GetFeePerK() < origFeeEst[i-1] + deltaFee);
+ BOOST_CHECK(feeEst.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee);
+ }
+
+
+ // Mine 15 more blocks with lots of transactions happening and not getting mined
+ // Estimates should go up
+ while (blocknum < 265) {
+ for (int j = 0; j < 10; j++) { // For each fee multiple
+ for (int k = 0; k < 4; k++) { // add 4 fee txs
+ tx.vin[0].prevout.n = 10000*blocknum+100*j+k;
+ uint256 hash = tx.GetHash();
+ mpool.addUnchecked(hash, entry.Fee(feeV[j]).Time(GetTime()).Height(blocknum).FromTx(tx));
+ txHashes[j].push_back(hash);
+ }
+ }
+ mpool.removeForBlock(block, ++blocknum);
+ }
+
+ for (int i = 1; i < 10;i++) {
+ BOOST_CHECK(feeEst.estimateFee(i) == CFeeRate(0) || feeEst.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee);
+ }
+
+ // Mine all those transactions
+ // Estimates should still not be below original
+ for (int j = 0; j < 10; j++) {
+ while(txHashes[j].size()) {
+ CTransactionRef ptx = mpool.get(txHashes[j].back());
+ if (ptx)
+ block.push_back(ptx);
+ txHashes[j].pop_back();
+ }
+ }
+ mpool.removeForBlock(block, 266);
+ block.clear();
+ BOOST_CHECK(feeEst.estimateFee(1) == CFeeRate(0));
+ for (int i = 2; i < 10;i++) {
+ BOOST_CHECK(feeEst.estimateFee(i) == CFeeRate(0) || feeEst.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee);
+ }
+
+ // Mine 400 more blocks where everything is mined every block
+ // Estimates should be below original estimates
+ while (blocknum < 665) {
+ for (int j = 0; j < 10; j++) { // For each fee multiple
+ for (int k = 0; k < 4; k++) { // add 4 fee txs
+ tx.vin[0].prevout.n = 10000*blocknum+100*j+k;
+ uint256 hash = tx.GetHash();
+ mpool.addUnchecked(hash, entry.Fee(feeV[j]).Time(GetTime()).Height(blocknum).FromTx(tx));
+ CTransactionRef ptx = mpool.get(hash);
+ if (ptx)
+ block.push_back(ptx);
+
+ }
+ }
+ mpool.removeForBlock(block, ++blocknum);
+ block.clear();
+ }
+ BOOST_CHECK(feeEst.estimateFee(1) == CFeeRate(0));
+ for (int i = 2; i < 9; i++) { // At 9, the original estimate was already at the bottom (b/c scale = 2)
+ BOOST_CHECK(feeEst.estimateFee(i).GetFeePerK() < origFeeEst[i-1] - deltaFee);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp
new file mode 100644
index 0000000000..1ac9adc740
--- /dev/null
+++ b/src/test/pow_tests.cpp
@@ -0,0 +1,86 @@
+// Copyright (c) 2015-2018 The Bitcoin Core developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <chain.h>
+#include <chainparams.h>
+#include <pow.h>
+#include <random.h>
+#include <util.h>
+#include <test/test_bitcoin.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(pow_tests, BasicTestingSetup)
+
+/* Test calculation of next difficulty target with no constraints applying */
+BOOST_AUTO_TEST_CASE(get_next_work)
+{
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
+ int64_t nLastRetargetTime = 1261130161; // Block #30240
+ CBlockIndex pindexLast;
+ pindexLast.nHeight = 32255;
+ pindexLast.nTime = 1262152739; // Block #32255
+ pindexLast.nBits = 0x1d00ffff;
+ BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1d00d86aU);
+}
+
+/* Test the constraint on the upper bound for next work */
+BOOST_AUTO_TEST_CASE(get_next_work_pow_limit)
+{
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
+ int64_t nLastRetargetTime = 1231006505; // Block #0
+ CBlockIndex pindexLast;
+ pindexLast.nHeight = 2015;
+ pindexLast.nTime = 1233061996; // Block #2015
+ pindexLast.nBits = 0x1d00ffff;
+ BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1d00ffffU);
+}
+
+/* Test the constraint on the lower bound for actual time taken */
+BOOST_AUTO_TEST_CASE(get_next_work_lower_limit_actual)
+{
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
+ int64_t nLastRetargetTime = 1279008237; // Block #66528
+ CBlockIndex pindexLast;
+ pindexLast.nHeight = 68543;
+ pindexLast.nTime = 1279297671; // Block #68543
+ pindexLast.nBits = 0x1c05a3f4;
+ BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1c0168fdU);
+}
+
+/* Test the constraint on the upper bound for actual time taken */
+BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual)
+{
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
+ int64_t nLastRetargetTime = 1263163443; // NOTE: Not an actual block time
+ CBlockIndex pindexLast;
+ pindexLast.nHeight = 46367;
+ pindexLast.nTime = 1269211443; // Block #46367
+ pindexLast.nBits = 0x1c387f6f;
+ BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1d00e1fdU);
+}
+
+BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test)
+{
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
+ std::vector<CBlockIndex> blocks(10000);
+ for (int i = 0; i < 10000; i++) {
+ blocks[i].pprev = i ? &blocks[i - 1] : nullptr;
+ blocks[i].nHeight = i;
+ blocks[i].nTime = 1269211443 + i * chainParams->GetConsensus().nPowTargetSpacing;
+ blocks[i].nBits = 0x207fffff; /* target 0x7fffff000... */
+ blocks[i].nChainWork = i ? blocks[i - 1].nChainWork + GetBlockProof(blocks[i - 1]) : arith_uint256(0);
+ }
+
+ for (int j = 0; j < 1000; j++) {
+ CBlockIndex *p1 = &blocks[InsecureRandRange(10000)];
+ CBlockIndex *p2 = &blocks[InsecureRandRange(10000)];
+ CBlockIndex *p3 = &blocks[InsecureRandRange(10000)];
+
+ int64_t tdiff = GetBlockProofEquivalentTime(*p1, *p2, *p3, chainParams->GetConsensus());
+ BOOST_CHECK_EQUAL(tdiff, p1->GetBlockTime() - p2->GetBlockTime());
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp
new file mode 100644
index 0000000000..c488d3edcf
--- /dev/null
+++ b/src/test/prevector_tests.cpp
@@ -0,0 +1,267 @@
+// Copyright (c) 2015-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <vector>
+#include <prevector.h>
+
+#include <reverse_iterator.h>
+#include <serialize.h>
+#include <streams.h>
+
+#include <test/test_bitcoin.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(prevector_tests, TestingSetup)
+
+template<unsigned int N, typename T>
+class prevector_tester {
+ typedef std::vector<T> realtype;
+ realtype real_vector;
+ realtype real_vector_alt;
+
+ typedef prevector<N, T> pretype;
+ pretype pre_vector;
+ pretype pre_vector_alt;
+
+ typedef typename pretype::size_type Size;
+ bool passed = true;
+ FastRandomContext rand_cache;
+ uint256 rand_seed;
+
+
+ template <typename A, typename B>
+ void local_check_equal(A a, B b)
+ {
+ local_check(a == b);
+ }
+ void local_check(bool b)
+ {
+ passed &= b;
+ }
+ void test() {
+ const pretype& const_pre_vector = pre_vector;
+ local_check_equal(real_vector.size(), pre_vector.size());
+ local_check_equal(real_vector.empty(), pre_vector.empty());
+ for (Size s = 0; s < real_vector.size(); s++) {
+ local_check(real_vector[s] == pre_vector[s]);
+ local_check(&(pre_vector[s]) == &(pre_vector.begin()[s]));
+ local_check(&(pre_vector[s]) == &*(pre_vector.begin() + s));
+ local_check(&(pre_vector[s]) == &*((pre_vector.end() + s) - real_vector.size()));
+ }
+ // local_check(realtype(pre_vector) == real_vector);
+ local_check(pretype(real_vector.begin(), real_vector.end()) == pre_vector);
+ local_check(pretype(pre_vector.begin(), pre_vector.end()) == pre_vector);
+ size_t pos = 0;
+ for (const T& v : pre_vector) {
+ local_check(v == real_vector[pos++]);
+ }
+ for (const T& v : reverse_iterate(pre_vector)) {
+ local_check(v == real_vector[--pos]);
+ }
+ for (const T& v : const_pre_vector) {
+ local_check(v == real_vector[pos++]);
+ }
+ for (const T& v : reverse_iterate(const_pre_vector)) {
+ local_check(v == real_vector[--pos]);
+ }
+ CDataStream ss1(SER_DISK, 0);
+ CDataStream ss2(SER_DISK, 0);
+ ss1 << real_vector;
+ ss2 << pre_vector;
+ local_check_equal(ss1.size(), ss2.size());
+ for (Size s = 0; s < ss1.size(); s++) {
+ local_check_equal(ss1[s], ss2[s]);
+ }
+ }
+
+public:
+ void resize(Size s) {
+ real_vector.resize(s);
+ local_check_equal(real_vector.size(), s);
+ pre_vector.resize(s);
+ local_check_equal(pre_vector.size(), s);
+ test();
+ }
+
+ void reserve(Size s) {
+ real_vector.reserve(s);
+ local_check(real_vector.capacity() >= s);
+ pre_vector.reserve(s);
+ local_check(pre_vector.capacity() >= s);
+ test();
+ }
+
+ void insert(Size position, const T& value) {
+ real_vector.insert(real_vector.begin() + position, value);
+ pre_vector.insert(pre_vector.begin() + position, value);
+ test();
+ }
+
+ void insert(Size position, Size count, const T& value) {
+ real_vector.insert(real_vector.begin() + position, count, value);
+ pre_vector.insert(pre_vector.begin() + position, count, value);
+ test();
+ }
+
+ template<typename I>
+ void insert_range(Size position, I first, I last) {
+ real_vector.insert(real_vector.begin() + position, first, last);
+ pre_vector.insert(pre_vector.begin() + position, first, last);
+ test();
+ }
+
+ void erase(Size position) {
+ real_vector.erase(real_vector.begin() + position);
+ pre_vector.erase(pre_vector.begin() + position);
+ test();
+ }
+
+ void erase(Size first, Size last) {
+ real_vector.erase(real_vector.begin() + first, real_vector.begin() + last);
+ pre_vector.erase(pre_vector.begin() + first, pre_vector.begin() + last);
+ test();
+ }
+
+ void update(Size pos, const T& value) {
+ real_vector[pos] = value;
+ pre_vector[pos] = value;
+ test();
+ }
+
+ void push_back(const T& value) {
+ real_vector.push_back(value);
+ pre_vector.push_back(value);
+ test();
+ }
+
+ void pop_back() {
+ real_vector.pop_back();
+ pre_vector.pop_back();
+ test();
+ }
+
+ void clear() {
+ real_vector.clear();
+ pre_vector.clear();
+ }
+
+ void assign(Size n, const T& value) {
+ real_vector.assign(n, value);
+ pre_vector.assign(n, value);
+ }
+
+ Size size() const {
+ return real_vector.size();
+ }
+
+ Size capacity() const {
+ return pre_vector.capacity();
+ }
+
+ void shrink_to_fit() {
+ pre_vector.shrink_to_fit();
+ test();
+ }
+
+ void swap() {
+ real_vector.swap(real_vector_alt);
+ pre_vector.swap(pre_vector_alt);
+ test();
+ }
+
+ void move() {
+ real_vector = std::move(real_vector_alt);
+ real_vector_alt.clear();
+ pre_vector = std::move(pre_vector_alt);
+ pre_vector_alt.clear();
+ }
+
+ void copy() {
+ real_vector = real_vector_alt;
+ pre_vector = pre_vector_alt;
+ }
+
+ ~prevector_tester() {
+ BOOST_CHECK_MESSAGE(passed, "insecure_rand: " + rand_seed.ToString());
+ }
+
+ prevector_tester() {
+ SeedInsecureRand();
+ rand_seed = insecure_rand_seed;
+ rand_cache = insecure_rand_ctx;
+ }
+};
+
+BOOST_AUTO_TEST_CASE(PrevectorTestInt)
+{
+ for (int j = 0; j < 64; j++) {
+ prevector_tester<8, int> test;
+ for (int i = 0; i < 2048; i++) {
+ if (InsecureRandBits(2) == 0) {
+ test.insert(InsecureRandRange(test.size() + 1), InsecureRand32());
+ }
+ if (test.size() > 0 && InsecureRandBits(2) == 1) {
+ test.erase(InsecureRandRange(test.size()));
+ }
+ if (InsecureRandBits(3) == 2) {
+ int new_size = std::max(0, std::min(30, (int)test.size() + (int)InsecureRandRange(5) - 2));
+ test.resize(new_size);
+ }
+ if (InsecureRandBits(3) == 3) {
+ test.insert(InsecureRandRange(test.size() + 1), 1 + InsecureRandBool(), InsecureRand32());
+ }
+ if (InsecureRandBits(3) == 4) {
+ int del = std::min<int>(test.size(), 1 + (InsecureRandBool()));
+ int beg = InsecureRandRange(test.size() + 1 - del);
+ test.erase(beg, beg + del);
+ }
+ if (InsecureRandBits(4) == 5) {
+ test.push_back(InsecureRand32());
+ }
+ if (test.size() > 0 && InsecureRandBits(4) == 6) {
+ test.pop_back();
+ }
+ if (InsecureRandBits(5) == 7) {
+ int values[4];
+ int num = 1 + (InsecureRandBits(2));
+ for (int k = 0; k < num; k++) {
+ values[k] = InsecureRand32();
+ }
+ test.insert_range(InsecureRandRange(test.size() + 1), values, values + num);
+ }
+ if (InsecureRandBits(5) == 8) {
+ int del = std::min<int>(test.size(), 1 + (InsecureRandBits(2)));
+ int beg = InsecureRandRange(test.size() + 1 - del);
+ test.erase(beg, beg + del);
+ }
+ if (InsecureRandBits(5) == 9) {
+ test.reserve(InsecureRandBits(5));
+ }
+ if (InsecureRandBits(6) == 10) {
+ test.shrink_to_fit();
+ }
+ if (test.size() > 0) {
+ test.update(InsecureRandRange(test.size()), InsecureRand32());
+ }
+ if (InsecureRandBits(10) == 11) {
+ test.clear();
+ }
+ if (InsecureRandBits(9) == 12) {
+ test.assign(InsecureRandBits(5), InsecureRand32());
+ }
+ if (InsecureRandBits(3) == 3) {
+ test.swap();
+ }
+ if (InsecureRandBits(4) == 8) {
+ test.copy();
+ }
+ if (InsecureRandBits(5) == 18) {
+ test.move();
+ }
+ }
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/raii_event_tests.cpp b/src/test/raii_event_tests.cpp
new file mode 100644
index 0000000000..bdb411d53f
--- /dev/null
+++ b/src/test/raii_event_tests.cpp
@@ -0,0 +1,94 @@
+// Copyright (c) 2016-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <event2/event.h>
+
+#ifdef EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED
+// It would probably be ideal to define dummy test(s) that report skipped, but boost::test doesn't seem to make that practical (at least not in versions available with common distros)
+
+#include <map>
+#include <stdlib.h>
+
+#include <support/events.h>
+
+#include <test/test_bitcoin.h>
+
+#include <vector>
+
+#include <boost/test/unit_test.hpp>
+
+static std::map<void*, short> tags;
+static std::map<void*, uint16_t> orders;
+static uint16_t tagSequence = 0;
+
+static void* tag_malloc(size_t sz) {
+ void* mem = malloc(sz);
+ if (!mem) return mem;
+ tags[mem]++;
+ orders[mem] = tagSequence++;
+ return mem;
+}
+
+static void tag_free(void* mem) {
+ tags[mem]--;
+ orders[mem] = tagSequence++;
+ free(mem);
+}
+
+BOOST_FIXTURE_TEST_SUITE(raii_event_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(raii_event_creation)
+{
+ event_set_mem_functions(tag_malloc, realloc, tag_free);
+
+ void* base_ptr = nullptr;
+ {
+ auto base = obtain_event_base();
+ base_ptr = (void*)base.get();
+ BOOST_CHECK(tags[base_ptr] == 1);
+ }
+ BOOST_CHECK(tags[base_ptr] == 0);
+
+ void* event_ptr = nullptr;
+ {
+ auto base = obtain_event_base();
+ auto event = obtain_event(base.get(), -1, 0, nullptr, nullptr);
+
+ base_ptr = (void*)base.get();
+ event_ptr = (void*)event.get();
+
+ BOOST_CHECK(tags[base_ptr] == 1);
+ BOOST_CHECK(tags[event_ptr] == 1);
+ }
+ BOOST_CHECK(tags[base_ptr] == 0);
+ BOOST_CHECK(tags[event_ptr] == 0);
+
+ event_set_mem_functions(malloc, realloc, free);
+}
+
+BOOST_AUTO_TEST_CASE(raii_event_order)
+{
+ event_set_mem_functions(tag_malloc, realloc, tag_free);
+
+ void* base_ptr = nullptr;
+ void* event_ptr = nullptr;
+ {
+ auto base = obtain_event_base();
+ auto event = obtain_event(base.get(), -1, 0, nullptr, nullptr);
+
+ base_ptr = (void*)base.get();
+ event_ptr = (void*)event.get();
+
+ // base should have allocated before event
+ BOOST_CHECK(orders[base_ptr] < orders[event_ptr]);
+ }
+ // base should be freed after event
+ BOOST_CHECK(orders[base_ptr] > orders[event_ptr]);
+
+ event_set_mem_functions(malloc, realloc, free);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+#endif // EVENT_SET_MEM_FUNCTIONS_IMPLEMENTED
diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp
new file mode 100644
index 0000000000..679e857ce6
--- /dev/null
+++ b/src/test/random_tests.cpp
@@ -0,0 +1,82 @@
+// Copyright (c) 2017-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <random.h>
+
+#include <test/test_bitcoin.h>
+
+#include <boost/test/unit_test.hpp>
+
+#include <random>
+#include <algorithm>
+
+BOOST_FIXTURE_TEST_SUITE(random_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(osrandom_tests)
+{
+ BOOST_CHECK(Random_SanityCheck());
+}
+
+BOOST_AUTO_TEST_CASE(fastrandom_tests)
+{
+ // Check that deterministic FastRandomContexts are deterministic
+ FastRandomContext ctx1(true);
+ FastRandomContext ctx2(true);
+
+ BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32());
+ BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32());
+ BOOST_CHECK_EQUAL(ctx1.rand64(), ctx2.rand64());
+ BOOST_CHECK_EQUAL(ctx1.randbits(3), ctx2.randbits(3));
+ BOOST_CHECK(ctx1.randbytes(17) == ctx2.randbytes(17));
+ BOOST_CHECK(ctx1.rand256() == ctx2.rand256());
+ BOOST_CHECK_EQUAL(ctx1.randbits(7), ctx2.randbits(7));
+ BOOST_CHECK(ctx1.randbytes(128) == ctx2.randbytes(128));
+ BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32());
+ BOOST_CHECK_EQUAL(ctx1.randbits(3), ctx2.randbits(3));
+ BOOST_CHECK(ctx1.rand256() == ctx2.rand256());
+ BOOST_CHECK(ctx1.randbytes(50) == ctx2.randbytes(50));
+
+ // Check that a nondeterministic ones are not
+ FastRandomContext ctx3;
+ FastRandomContext ctx4;
+ BOOST_CHECK(ctx3.rand64() != ctx4.rand64()); // extremely unlikely to be equal
+ BOOST_CHECK(ctx3.rand256() != ctx4.rand256());
+ BOOST_CHECK(ctx3.randbytes(7) != ctx4.randbytes(7));
+}
+
+BOOST_AUTO_TEST_CASE(fastrandom_randbits)
+{
+ FastRandomContext ctx1;
+ FastRandomContext ctx2;
+ for (int bits = 0; bits < 63; ++bits) {
+ for (int j = 0; j < 1000; ++j) {
+ uint64_t rangebits = ctx1.randbits(bits);
+ BOOST_CHECK_EQUAL(rangebits >> bits, 0U);
+ uint64_t range = ((uint64_t)1) << bits | rangebits;
+ uint64_t rand = ctx2.randrange(range);
+ BOOST_CHECK(rand < range);
+ }
+ }
+}
+
+/** Does-it-compile test for compatibility with standard C++11 RNG interface. */
+BOOST_AUTO_TEST_CASE(stdrandom_test)
+{
+ FastRandomContext ctx;
+ std::uniform_int_distribution<int> distribution(3, 9);
+ for (int i = 0; i < 100; ++i) {
+ int x = distribution(ctx);
+ BOOST_CHECK(x >= 3);
+ BOOST_CHECK(x <= 9);
+
+ std::vector<int> test{1,2,3,4,5,6,7,8,9,10};
+ std::shuffle(test.begin(), test.end(), ctx);
+ for (int j = 1; j <= 10; ++j) {
+ BOOST_CHECK(std::find(test.begin(), test.end(), j) != test.end());
+ }
+ }
+
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/reverselock_tests.cpp b/src/test/reverselock_tests.cpp
new file mode 100644
index 0000000000..91c76fda88
--- /dev/null
+++ b/src/test/reverselock_tests.cpp
@@ -0,0 +1,60 @@
+// Copyright (c) 2015-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <reverselock.h>
+#include <test/test_bitcoin.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(reverselock_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(reverselock_basics)
+{
+ boost::mutex mutex;
+ boost::unique_lock<boost::mutex> lock(mutex);
+
+ BOOST_CHECK(lock.owns_lock());
+ {
+ reverse_lock<boost::unique_lock<boost::mutex> > rlock(lock);
+ BOOST_CHECK(!lock.owns_lock());
+ }
+ BOOST_CHECK(lock.owns_lock());
+}
+
+BOOST_AUTO_TEST_CASE(reverselock_errors)
+{
+ boost::mutex mutex;
+ boost::unique_lock<boost::mutex> lock(mutex);
+
+ // Make sure trying to reverse lock an unlocked lock fails
+ lock.unlock();
+
+ BOOST_CHECK(!lock.owns_lock());
+
+ bool failed = false;
+ try {
+ reverse_lock<boost::unique_lock<boost::mutex> > rlock(lock);
+ } catch(...) {
+ failed = true;
+ }
+
+ BOOST_CHECK(failed);
+ BOOST_CHECK(!lock.owns_lock());
+
+ // Locking the original lock after it has been taken by a reverse lock
+ // makes no sense. Ensure that the original lock no longer owns the lock
+ // after giving it to a reverse one.
+
+ lock.lock();
+ BOOST_CHECK(lock.owns_lock());
+ {
+ reverse_lock<boost::unique_lock<boost::mutex> > rlock(lock);
+ BOOST_CHECK(!lock.owns_lock());
+ }
+
+ BOOST_CHECK(failed);
+ BOOST_CHECK(lock.owns_lock());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
new file mode 100644
index 0000000000..d0f6fba78d
--- /dev/null
+++ b/src/test/rpc_tests.cpp
@@ -0,0 +1,339 @@
+// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <rpc/server.h>
+#include <rpc/client.h>
+
+#include <core_io.h>
+#include <key_io.h>
+#include <netbase.h>
+
+#include <test/test_bitcoin.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/test/unit_test.hpp>
+
+#include <univalue.h>
+
+UniValue CallRPC(std::string args)
+{
+ std::vector<std::string> vArgs;
+ boost::split(vArgs, args, boost::is_any_of(" \t"));
+ std::string strMethod = vArgs[0];
+ vArgs.erase(vArgs.begin());
+ JSONRPCRequest request;
+ request.strMethod = strMethod;
+ request.params = RPCConvertValues(strMethod, vArgs);
+ request.fHelp = false;
+ BOOST_CHECK(tableRPC[strMethod]);
+ rpcfn_type method = tableRPC[strMethod]->actor;
+ try {
+ UniValue result = (*method)(request);
+ return result;
+ }
+ catch (const UniValue& objError) {
+ throw std::runtime_error(find_value(objError, "message").get_str());
+ }
+}
+
+
+BOOST_FIXTURE_TEST_SUITE(rpc_tests, TestingSetup)
+
+BOOST_AUTO_TEST_CASE(rpc_rawparams)
+{
+ // Test raw transaction API argument handling
+ UniValue r;
+
+ BOOST_CHECK_THROW(CallRPC("getrawtransaction"), std::runtime_error);
+ BOOST_CHECK_THROW(CallRPC("getrawtransaction not_hex"), std::runtime_error);
+ BOOST_CHECK_THROW(CallRPC("getrawtransaction a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed not_int"), std::runtime_error);
+
+ BOOST_CHECK_THROW(CallRPC("createrawtransaction"), std::runtime_error);
+ BOOST_CHECK_THROW(CallRPC("createrawtransaction null null"), std::runtime_error);
+ BOOST_CHECK_THROW(CallRPC("createrawtransaction not_array"), std::runtime_error);
+ BOOST_CHECK_THROW(CallRPC("createrawtransaction {} {}"), std::runtime_error);
+ BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [] {}"));
+ BOOST_CHECK_THROW(CallRPC("createrawtransaction [] {} extra"), std::runtime_error);
+
+ BOOST_CHECK_THROW(CallRPC("decoderawtransaction"), std::runtime_error);
+ BOOST_CHECK_THROW(CallRPC("decoderawtransaction null"), std::runtime_error);
+ BOOST_CHECK_THROW(CallRPC("decoderawtransaction DEADBEEF"), std::runtime_error);
+ std::string rawtx = "0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000";
+ BOOST_CHECK_NO_THROW(r = CallRPC(std::string("decoderawtransaction ")+rawtx));
+ BOOST_CHECK_EQUAL(find_value(r.get_obj(), "size").get_int(), 193);
+ BOOST_CHECK_EQUAL(find_value(r.get_obj(), "version").get_int(), 1);
+ BOOST_CHECK_EQUAL(find_value(r.get_obj(), "locktime").get_int(), 0);
+ BOOST_CHECK_THROW(CallRPC(std::string("decoderawtransaction ")+rawtx+" extra"), std::runtime_error);
+ BOOST_CHECK_NO_THROW(r = CallRPC(std::string("decoderawtransaction ")+rawtx+" false"));
+ BOOST_CHECK_THROW(r = CallRPC(std::string("decoderawtransaction ")+rawtx+" false extra"), std::runtime_error);
+
+ // Only check failure cases for sendrawtransaction, there's no network to send to...
+ BOOST_CHECK_THROW(CallRPC("sendrawtransaction"), std::runtime_error);
+ BOOST_CHECK_THROW(CallRPC("sendrawtransaction null"), std::runtime_error);
+ BOOST_CHECK_THROW(CallRPC("sendrawtransaction DEADBEEF"), std::runtime_error);
+ BOOST_CHECK_THROW(CallRPC(std::string("sendrawtransaction ")+rawtx+" extra"), std::runtime_error);
+}
+
+BOOST_AUTO_TEST_CASE(rpc_togglenetwork)
+{
+ UniValue r;
+
+ r = CallRPC("getnetworkinfo");
+ bool netState = find_value(r.get_obj(), "networkactive").get_bool();
+ BOOST_CHECK_EQUAL(netState, true);
+
+ BOOST_CHECK_NO_THROW(CallRPC("setnetworkactive false"));
+ r = CallRPC("getnetworkinfo");
+ int numConnection = find_value(r.get_obj(), "connections").get_int();
+ BOOST_CHECK_EQUAL(numConnection, 0);
+
+ netState = find_value(r.get_obj(), "networkactive").get_bool();
+ BOOST_CHECK_EQUAL(netState, false);
+
+ BOOST_CHECK_NO_THROW(CallRPC("setnetworkactive true"));
+ r = CallRPC("getnetworkinfo");
+ netState = find_value(r.get_obj(), "networkactive").get_bool();
+ BOOST_CHECK_EQUAL(netState, true);
+}
+
+BOOST_AUTO_TEST_CASE(rpc_rawsign)
+{
+ UniValue r;
+ // input is a 1-of-2 multisig (so is output):
+ std::string prevout =
+ "[{\"txid\":\"b4cc287e58f87cdae59417329f710f3ecd75a4ee1d2872b7248f50977c8493f3\","
+ "\"vout\":1,\"scriptPubKey\":\"a914b10c9df5f7edf436c697f02f1efdba4cf399615187\","
+ "\"redeemScript\":\"512103debedc17b3df2badbcdd86d5feb4562b86fe182e5998abd8bcd4f122c6155b1b21027e940bb73ab8732bfdf7f9216ecefca5b94d6df834e77e108f68e66f126044c052ae\"}]";
+ r = CallRPC(std::string("createrawtransaction ")+prevout+" "+
+ "{\"3HqAe9LtNBjnsfM4CyYaWTnvCaUYT7v4oZ\":11}");
+ std::string notsigned = r.get_str();
+ std::string privkey1 = "\"KzsXybp9jX64P5ekX1KUxRQ79Jht9uzW7LorgwE65i5rWACL6LQe\"";
+ std::string privkey2 = "\"Kyhdf5LuKTRx4ge69ybABsiUAWjVRK4XGxAKk2FQLp2HjGMy87Z4\"";
+ r = CallRPC(std::string("signrawtransactionwithkey ")+notsigned+" [] "+prevout);
+ BOOST_CHECK(find_value(r.get_obj(), "complete").get_bool() == false);
+ r = CallRPC(std::string("signrawtransactionwithkey ")+notsigned+" ["+privkey1+","+privkey2+"] "+prevout);
+ BOOST_CHECK(find_value(r.get_obj(), "complete").get_bool() == true);
+}
+
+BOOST_AUTO_TEST_CASE(rpc_createraw_op_return)
+{
+ BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"68656c6c6f776f726c64\"}"));
+
+ // Allow more than one data transaction output
+ BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"68656c6c6f776f726c64\",\"data\":\"68656c6c6f776f726c64\"}"));
+
+ // Key not "data" (bad address)
+ BOOST_CHECK_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"somedata\":\"68656c6c6f776f726c64\"}"), std::runtime_error);
+
+ // Bad hex encoding of data output
+ BOOST_CHECK_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"12345\"}"), std::runtime_error);
+ BOOST_CHECK_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"12345g\"}"), std::runtime_error);
+
+ // Data 81 bytes long
+ BOOST_CHECK_NO_THROW(CallRPC("createrawtransaction [{\"txid\":\"a3b807410df0b60fcb9736768df5823938b2f838694939ba45f3c0a1bff150ed\",\"vout\":0}] {\"data\":\"010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081\"}"));
+}
+
+BOOST_AUTO_TEST_CASE(rpc_format_monetary_values)
+{
+ BOOST_CHECK(ValueFromAmount(0LL).write() == "0.00000000");
+ BOOST_CHECK(ValueFromAmount(1LL).write() == "0.00000001");
+ BOOST_CHECK(ValueFromAmount(17622195LL).write() == "0.17622195");
+ BOOST_CHECK(ValueFromAmount(50000000LL).write() == "0.50000000");
+ BOOST_CHECK(ValueFromAmount(89898989LL).write() == "0.89898989");
+ BOOST_CHECK(ValueFromAmount(100000000LL).write() == "1.00000000");
+ BOOST_CHECK(ValueFromAmount(2099999999999990LL).write() == "20999999.99999990");
+ BOOST_CHECK(ValueFromAmount(2099999999999999LL).write() == "20999999.99999999");
+
+ BOOST_CHECK_EQUAL(ValueFromAmount(0).write(), "0.00000000");
+ BOOST_CHECK_EQUAL(ValueFromAmount((COIN/10000)*123456789).write(), "12345.67890000");
+ BOOST_CHECK_EQUAL(ValueFromAmount(-COIN).write(), "-1.00000000");
+ BOOST_CHECK_EQUAL(ValueFromAmount(-COIN/10).write(), "-0.10000000");
+
+ BOOST_CHECK_EQUAL(ValueFromAmount(COIN*100000000).write(), "100000000.00000000");
+ BOOST_CHECK_EQUAL(ValueFromAmount(COIN*10000000).write(), "10000000.00000000");
+ BOOST_CHECK_EQUAL(ValueFromAmount(COIN*1000000).write(), "1000000.00000000");
+ BOOST_CHECK_EQUAL(ValueFromAmount(COIN*100000).write(), "100000.00000000");
+ BOOST_CHECK_EQUAL(ValueFromAmount(COIN*10000).write(), "10000.00000000");
+ BOOST_CHECK_EQUAL(ValueFromAmount(COIN*1000).write(), "1000.00000000");
+ BOOST_CHECK_EQUAL(ValueFromAmount(COIN*100).write(), "100.00000000");
+ BOOST_CHECK_EQUAL(ValueFromAmount(COIN*10).write(), "10.00000000");
+ BOOST_CHECK_EQUAL(ValueFromAmount(COIN).write(), "1.00000000");
+ BOOST_CHECK_EQUAL(ValueFromAmount(COIN/10).write(), "0.10000000");
+ BOOST_CHECK_EQUAL(ValueFromAmount(COIN/100).write(), "0.01000000");
+ BOOST_CHECK_EQUAL(ValueFromAmount(COIN/1000).write(), "0.00100000");
+ BOOST_CHECK_EQUAL(ValueFromAmount(COIN/10000).write(), "0.00010000");
+ BOOST_CHECK_EQUAL(ValueFromAmount(COIN/100000).write(), "0.00001000");
+ BOOST_CHECK_EQUAL(ValueFromAmount(COIN/1000000).write(), "0.00000100");
+ BOOST_CHECK_EQUAL(ValueFromAmount(COIN/10000000).write(), "0.00000010");
+ BOOST_CHECK_EQUAL(ValueFromAmount(COIN/100000000).write(), "0.00000001");
+}
+
+static UniValue ValueFromString(const std::string &str)
+{
+ UniValue value;
+ BOOST_CHECK(value.setNumStr(str));
+ return value;
+}
+
+BOOST_AUTO_TEST_CASE(rpc_parse_monetary_values)
+{
+ BOOST_CHECK_THROW(AmountFromValue(ValueFromString("-0.00000001")), UniValue);
+ BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0")), 0LL);
+ BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.00000000")), 0LL);
+ BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.00000001")), 1LL);
+ BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.17622195")), 17622195LL);
+ BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.5")), 50000000LL);
+ BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.50000000")), 50000000LL);
+ BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.89898989")), 89898989LL);
+ BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("1.00000000")), 100000000LL);
+ BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("20999999.9999999")), 2099999999999990LL);
+ BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("20999999.99999999")), 2099999999999999LL);
+
+ BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("1e-8")), COIN/100000000);
+ BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.1e-7")), COIN/100000000);
+ BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.01e-6")), COIN/100000000);
+ BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.0000000000000000000000000000000000000000000000000000000000000000000000000001e+68")), COIN/100000000);
+ BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("10000000000000000000000000000000000000000000000000000000000000000e-64")), COIN);
+ BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000e64")), COIN);
+
+ BOOST_CHECK_THROW(AmountFromValue(ValueFromString("1e-9")), UniValue); //should fail
+ BOOST_CHECK_THROW(AmountFromValue(ValueFromString("0.000000019")), UniValue); //should fail
+ BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.00000001000000")), 1LL); //should pass, cut trailing 0
+ BOOST_CHECK_THROW(AmountFromValue(ValueFromString("19e-9")), UniValue); //should fail
+ BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("0.19e-6")), 19); //should pass, leading 0 is present
+
+ BOOST_CHECK_THROW(AmountFromValue(ValueFromString("92233720368.54775808")), UniValue); //overflow error
+ BOOST_CHECK_THROW(AmountFromValue(ValueFromString("1e+11")), UniValue); //overflow error
+ BOOST_CHECK_THROW(AmountFromValue(ValueFromString("1e11")), UniValue); //overflow error signless
+ BOOST_CHECK_THROW(AmountFromValue(ValueFromString("93e+9")), UniValue); //overflow error
+}
+
+BOOST_AUTO_TEST_CASE(json_parse_errors)
+{
+ // Valid
+ BOOST_CHECK_EQUAL(ParseNonRFCJSONValue("1.0").get_real(), 1.0);
+ // Valid, with leading or trailing whitespace
+ BOOST_CHECK_EQUAL(ParseNonRFCJSONValue(" 1.0").get_real(), 1.0);
+ BOOST_CHECK_EQUAL(ParseNonRFCJSONValue("1.0 ").get_real(), 1.0);
+
+ BOOST_CHECK_THROW(AmountFromValue(ParseNonRFCJSONValue(".19e-6")), std::runtime_error); //should fail, missing leading 0, therefore invalid JSON
+ BOOST_CHECK_EQUAL(AmountFromValue(ParseNonRFCJSONValue("0.00000000000000000000000000000000000001e+30 ")), 1);
+ // Invalid, initial garbage
+ BOOST_CHECK_THROW(ParseNonRFCJSONValue("[1.0"), std::runtime_error);
+ BOOST_CHECK_THROW(ParseNonRFCJSONValue("a1.0"), std::runtime_error);
+ // Invalid, trailing garbage
+ BOOST_CHECK_THROW(ParseNonRFCJSONValue("1.0sds"), std::runtime_error);
+ BOOST_CHECK_THROW(ParseNonRFCJSONValue("1.0]"), std::runtime_error);
+ // BTC addresses should fail parsing
+ BOOST_CHECK_THROW(ParseNonRFCJSONValue("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"), std::runtime_error);
+ BOOST_CHECK_THROW(ParseNonRFCJSONValue("3J98t1WpEZ73CNmQviecrnyiWrnqRhWNL"), std::runtime_error);
+}
+
+BOOST_AUTO_TEST_CASE(rpc_ban)
+{
+ BOOST_CHECK_NO_THROW(CallRPC(std::string("clearbanned")));
+
+ UniValue r;
+ BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban 127.0.0.0 add")));
+ BOOST_CHECK_THROW(r = CallRPC(std::string("setban 127.0.0.0:8334")), std::runtime_error); //portnumber for setban not allowed
+ BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
+ UniValue ar = r.get_array();
+ UniValue o1 = ar[0].get_obj();
+ UniValue adr = find_value(o1, "address");
+ BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/32");
+ BOOST_CHECK_NO_THROW(CallRPC(std::string("setban 127.0.0.0 remove")));
+ BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
+ ar = r.get_array();
+ BOOST_CHECK_EQUAL(ar.size(), 0U);
+
+ BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban 127.0.0.0/24 add 9907731200 true")));
+ BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
+ ar = r.get_array();
+ o1 = ar[0].get_obj();
+ adr = find_value(o1, "address");
+ UniValue banned_until = find_value(o1, "banned_until");
+ BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/24");
+ BOOST_CHECK_EQUAL(banned_until.get_int64(), 9907731200); // absolute time check
+
+ BOOST_CHECK_NO_THROW(CallRPC(std::string("clearbanned")));
+
+ BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban 127.0.0.0/24 add 200")));
+ BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
+ ar = r.get_array();
+ o1 = ar[0].get_obj();
+ adr = find_value(o1, "address");
+ banned_until = find_value(o1, "banned_until");
+ BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/24");
+ int64_t now = GetTime();
+ BOOST_CHECK(banned_until.get_int64() > now);
+ BOOST_CHECK(banned_until.get_int64()-now <= 200);
+
+ // must throw an exception because 127.0.0.1 is in already banned subnet range
+ BOOST_CHECK_THROW(r = CallRPC(std::string("setban 127.0.0.1 add")), std::runtime_error);
+
+ BOOST_CHECK_NO_THROW(CallRPC(std::string("setban 127.0.0.0/24 remove")));
+ BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
+ ar = r.get_array();
+ BOOST_CHECK_EQUAL(ar.size(), 0U);
+
+ BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban 127.0.0.0/255.255.0.0 add")));
+ BOOST_CHECK_THROW(r = CallRPC(std::string("setban 127.0.1.1 add")), std::runtime_error);
+
+ BOOST_CHECK_NO_THROW(CallRPC(std::string("clearbanned")));
+ BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
+ ar = r.get_array();
+ BOOST_CHECK_EQUAL(ar.size(), 0U);
+
+
+ BOOST_CHECK_THROW(r = CallRPC(std::string("setban test add")), std::runtime_error); //invalid IP
+
+ //IPv6 tests
+ BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban FE80:0000:0000:0000:0202:B3FF:FE1E:8329 add")));
+ BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
+ ar = r.get_array();
+ o1 = ar[0].get_obj();
+ adr = find_value(o1, "address");
+ BOOST_CHECK_EQUAL(adr.get_str(), "fe80::202:b3ff:fe1e:8329/128");
+
+ BOOST_CHECK_NO_THROW(CallRPC(std::string("clearbanned")));
+ BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban 2001:db8::/ffff:fffc:0:0:0:0:0:0 add")));
+ BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
+ ar = r.get_array();
+ o1 = ar[0].get_obj();
+ adr = find_value(o1, "address");
+ BOOST_CHECK_EQUAL(adr.get_str(), "2001:db8::/30");
+
+ BOOST_CHECK_NO_THROW(CallRPC(std::string("clearbanned")));
+ BOOST_CHECK_NO_THROW(r = CallRPC(std::string("setban 2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/128 add")));
+ BOOST_CHECK_NO_THROW(r = CallRPC(std::string("listbanned")));
+ ar = r.get_array();
+ o1 = ar[0].get_obj();
+ adr = find_value(o1, "address");
+ BOOST_CHECK_EQUAL(adr.get_str(), "2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/128");
+}
+
+BOOST_AUTO_TEST_CASE(rpc_convert_values_generatetoaddress)
+{
+ UniValue result;
+
+ BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", {"101", "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a"}));
+ BOOST_CHECK_EQUAL(result[0].get_int(), 101);
+ BOOST_CHECK_EQUAL(result[1].get_str(), "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a");
+
+ BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", {"101", "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU"}));
+ BOOST_CHECK_EQUAL(result[0].get_int(), 101);
+ BOOST_CHECK_EQUAL(result[1].get_str(), "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU");
+
+ BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", {"1", "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a", "9"}));
+ BOOST_CHECK_EQUAL(result[0].get_int(), 1);
+ BOOST_CHECK_EQUAL(result[1].get_str(), "mkESjLZW66TmHhiFX8MCaBjrhZ543PPh9a");
+ BOOST_CHECK_EQUAL(result[2].get_int(), 9);
+
+ BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", {"1", "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU", "9"}));
+ BOOST_CHECK_EQUAL(result[0].get_int(), 1);
+ BOOST_CHECK_EQUAL(result[1].get_str(), "mhMbmE2tE9xzJYCV9aNC8jKWN31vtGrguU");
+ BOOST_CHECK_EQUAL(result[2].get_int(), 9);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/sanity_tests.cpp b/src/test/sanity_tests.cpp
new file mode 100644
index 0000000000..8085a21928
--- /dev/null
+++ b/src/test/sanity_tests.cpp
@@ -0,0 +1,20 @@
+// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <compat/sanity.h>
+#include <key.h>
+#include <test/test_bitcoin.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(sanity_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(basic_sanity)
+{
+ BOOST_CHECK_MESSAGE(glibc_sanity_test() == true, "libc sanity test");
+ BOOST_CHECK_MESSAGE(glibcxx_sanity_test() == true, "stdlib sanity test");
+ BOOST_CHECK_MESSAGE(ECC_InitSanityCheck() == true, "openssl ECC test");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/scheduler_tests.cpp b/src/test/scheduler_tests.cpp
new file mode 100644
index 0000000000..001d8eb64b
--- /dev/null
+++ b/src/test/scheduler_tests.cpp
@@ -0,0 +1,157 @@
+// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <random.h>
+#include <scheduler.h>
+
+#include <test/test_bitcoin.h>
+
+#include <boost/bind.hpp>
+#include <boost/thread.hpp>
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_SUITE(scheduler_tests)
+
+static void microTask(CScheduler& s, boost::mutex& mutex, int& counter, int delta, boost::chrono::system_clock::time_point rescheduleTime)
+{
+ {
+ boost::unique_lock<boost::mutex> lock(mutex);
+ counter += delta;
+ }
+ boost::chrono::system_clock::time_point noTime = boost::chrono::system_clock::time_point::min();
+ if (rescheduleTime != noTime) {
+ CScheduler::Function f = boost::bind(&microTask, boost::ref(s), boost::ref(mutex), boost::ref(counter), -delta + 1, noTime);
+ s.schedule(f, rescheduleTime);
+ }
+}
+
+static void MicroSleep(uint64_t n)
+{
+#if defined(HAVE_WORKING_BOOST_SLEEP_FOR)
+ boost::this_thread::sleep_for(boost::chrono::microseconds(n));
+#elif defined(HAVE_WORKING_BOOST_SLEEP)
+ boost::this_thread::sleep(boost::posix_time::microseconds(n));
+#else
+ //should never get here
+ #error missing boost sleep implementation
+#endif
+}
+
+BOOST_AUTO_TEST_CASE(manythreads)
+{
+ // Stress test: hundreds of microsecond-scheduled tasks,
+ // serviced by 10 threads.
+ //
+ // So... ten shared counters, which if all the tasks execute
+ // properly will sum to the number of tasks done.
+ // Each task adds or subtracts a random amount from one of the
+ // counters, and then schedules another task 0-1000
+ // microseconds in the future to subtract or add from
+ // the counter -random_amount+1, so in the end the shared
+ // counters should sum to the number of initial tasks performed.
+ CScheduler microTasks;
+
+ boost::mutex counterMutex[10];
+ int counter[10] = { 0 };
+ FastRandomContext rng(42);
+ auto zeroToNine = [](FastRandomContext& rc) -> int { return rc.randrange(10); }; // [0, 9]
+ auto randomMsec = [](FastRandomContext& rc) -> int { return -11 + (int)rc.randrange(1012); }; // [-11, 1000]
+ auto randomDelta = [](FastRandomContext& rc) -> int { return -1000 + (int)rc.randrange(2001); }; // [-1000, 1000]
+
+ boost::chrono::system_clock::time_point start = boost::chrono::system_clock::now();
+ boost::chrono::system_clock::time_point now = start;
+ boost::chrono::system_clock::time_point first, last;
+ size_t nTasks = microTasks.getQueueInfo(first, last);
+ BOOST_CHECK(nTasks == 0);
+
+ for (int i = 0; i < 100; ++i) {
+ boost::chrono::system_clock::time_point t = now + boost::chrono::microseconds(randomMsec(rng));
+ boost::chrono::system_clock::time_point tReschedule = now + boost::chrono::microseconds(500 + randomMsec(rng));
+ int whichCounter = zeroToNine(rng);
+ CScheduler::Function f = boost::bind(&microTask, boost::ref(microTasks),
+ boost::ref(counterMutex[whichCounter]), boost::ref(counter[whichCounter]),
+ randomDelta(rng), tReschedule);
+ microTasks.schedule(f, t);
+ }
+ nTasks = microTasks.getQueueInfo(first, last);
+ BOOST_CHECK(nTasks == 100);
+ BOOST_CHECK(first < last);
+ BOOST_CHECK(last > now);
+
+ // As soon as these are created they will start running and servicing the queue
+ boost::thread_group microThreads;
+ for (int i = 0; i < 5; i++)
+ microThreads.create_thread(boost::bind(&CScheduler::serviceQueue, &microTasks));
+
+ MicroSleep(600);
+ now = boost::chrono::system_clock::now();
+
+ // More threads and more tasks:
+ for (int i = 0; i < 5; i++)
+ microThreads.create_thread(boost::bind(&CScheduler::serviceQueue, &microTasks));
+ for (int i = 0; i < 100; i++) {
+ boost::chrono::system_clock::time_point t = now + boost::chrono::microseconds(randomMsec(rng));
+ boost::chrono::system_clock::time_point tReschedule = now + boost::chrono::microseconds(500 + randomMsec(rng));
+ int whichCounter = zeroToNine(rng);
+ CScheduler::Function f = boost::bind(&microTask, boost::ref(microTasks),
+ boost::ref(counterMutex[whichCounter]), boost::ref(counter[whichCounter]),
+ randomDelta(rng), tReschedule);
+ microTasks.schedule(f, t);
+ }
+
+ // Drain the task queue then exit threads
+ microTasks.stop(true);
+ microThreads.join_all(); // ... wait until all the threads are done
+
+ int counterSum = 0;
+ for (int i = 0; i < 10; i++) {
+ BOOST_CHECK(counter[i] != 0);
+ counterSum += counter[i];
+ }
+ BOOST_CHECK_EQUAL(counterSum, 200);
+}
+
+BOOST_AUTO_TEST_CASE(singlethreadedscheduler_ordered)
+{
+ CScheduler scheduler;
+
+ // each queue should be well ordered with respect to itself but not other queues
+ SingleThreadedSchedulerClient queue1(&scheduler);
+ SingleThreadedSchedulerClient queue2(&scheduler);
+
+ // create more threads than queues
+ // if the queues only permit execution of one task at once then
+ // the extra threads should effectively be doing nothing
+ // if they don't we'll get out of order behaviour
+ boost::thread_group threads;
+ for (int i = 0; i < 5; ++i) {
+ threads.create_thread(boost::bind(&CScheduler::serviceQueue, &scheduler));
+ }
+
+ // these are not atomic, if SinglethreadedSchedulerClient prevents
+ // parallel execution at the queue level no synchronization should be required here
+ int counter1 = 0;
+ int counter2 = 0;
+
+ // just simply count up on each queue - if execution is properly ordered then
+ // the callbacks should run in exactly the order in which they were enqueued
+ for (int i = 0; i < 100; ++i) {
+ queue1.AddToProcessQueue([i, &counter1]() {
+ BOOST_CHECK_EQUAL(i, counter1++);
+ });
+
+ queue2.AddToProcessQueue([i, &counter2]() {
+ BOOST_CHECK_EQUAL(i, counter2++);
+ });
+ }
+
+ // finish up
+ scheduler.stop(true);
+ threads.join_all();
+
+ BOOST_CHECK_EQUAL(counter1, 100);
+ BOOST_CHECK_EQUAL(counter2, 100);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/script_p2sh_tests.cpp b/src/test/script_p2sh_tests.cpp
new file mode 100644
index 0000000000..5b10935302
--- /dev/null
+++ b/src/test/script_p2sh_tests.cpp
@@ -0,0 +1,369 @@
+// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <consensus/tx_verify.h>
+#include <core_io.h>
+#include <key.h>
+#include <keystore.h>
+#include <validation.h>
+#include <policy/policy.h>
+#include <script/script.h>
+#include <script/script_error.h>
+#include <script/sign.h>
+#include <script/ismine.h>
+#include <test/test_bitcoin.h>
+
+#include <vector>
+
+#include <boost/test/unit_test.hpp>
+
+// Helpers:
+static std::vector<unsigned char>
+Serialize(const CScript& s)
+{
+ std::vector<unsigned char> sSerialized(s.begin(), s.end());
+ return sSerialized;
+}
+
+static bool
+Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict, ScriptError& err)
+{
+ // Create dummy to/from transactions:
+ CMutableTransaction txFrom;
+ txFrom.vout.resize(1);
+ txFrom.vout[0].scriptPubKey = scriptPubKey;
+
+ CMutableTransaction txTo;
+ txTo.vin.resize(1);
+ txTo.vout.resize(1);
+ txTo.vin[0].prevout.n = 0;
+ txTo.vin[0].prevout.hash = txFrom.GetHash();
+ txTo.vin[0].scriptSig = scriptSig;
+ txTo.vout[0].nValue = 1;
+
+ return VerifyScript(scriptSig, scriptPubKey, nullptr, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, MutableTransactionSignatureChecker(&txTo, 0, txFrom.vout[0].nValue), &err);
+}
+
+
+BOOST_FIXTURE_TEST_SUITE(script_p2sh_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(sign)
+{
+ LOCK(cs_main);
+ // Pay-to-script-hash looks like this:
+ // scriptSig: <sig> <sig...> <serialized_script>
+ // scriptPubKey: HASH160 <hash> EQUAL
+
+ // Test SignSignature() (and therefore the version of Solver() that signs transactions)
+ CBasicKeyStore keystore;
+ CKey key[4];
+ for (int i = 0; i < 4; i++)
+ {
+ key[i].MakeNewKey(true);
+ keystore.AddKey(key[i]);
+ }
+
+ // 8 Scripts: checking all combinations of
+ // different keys, straight/P2SH, pubkey/pubkeyhash
+ CScript standardScripts[4];
+ standardScripts[0] << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG;
+ standardScripts[1] = GetScriptForDestination(key[1].GetPubKey().GetID());
+ standardScripts[2] << ToByteVector(key[1].GetPubKey()) << OP_CHECKSIG;
+ standardScripts[3] = GetScriptForDestination(key[2].GetPubKey().GetID());
+ CScript evalScripts[4];
+ for (int i = 0; i < 4; i++)
+ {
+ keystore.AddCScript(standardScripts[i]);
+ evalScripts[i] = GetScriptForDestination(CScriptID(standardScripts[i]));
+ }
+
+ CMutableTransaction txFrom; // Funding transaction:
+ std::string reason;
+ txFrom.vout.resize(8);
+ for (int i = 0; i < 4; i++)
+ {
+ txFrom.vout[i].scriptPubKey = evalScripts[i];
+ txFrom.vout[i].nValue = COIN;
+ txFrom.vout[i+4].scriptPubKey = standardScripts[i];
+ txFrom.vout[i+4].nValue = COIN;
+ }
+ BOOST_CHECK(IsStandardTx(txFrom, reason));
+
+ CMutableTransaction txTo[8]; // Spending transactions
+ for (int i = 0; i < 8; i++)
+ {
+ txTo[i].vin.resize(1);
+ txTo[i].vout.resize(1);
+ txTo[i].vin[0].prevout.n = i;
+ txTo[i].vin[0].prevout.hash = txFrom.GetHash();
+ txTo[i].vout[0].nValue = 1;
+ BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
+ }
+ for (int i = 0; i < 8; i++)
+ {
+ BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i));
+ }
+ // All of the above should be OK, and the txTos have valid signatures
+ // Check to make sure signature verification fails if we use the wrong ScriptSig:
+ for (int i = 0; i < 8; i++) {
+ PrecomputedTransactionData txdata(txTo[i]);
+ for (int j = 0; j < 8; j++)
+ {
+ CScript sigSave = txTo[i].vin[0].scriptSig;
+ txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig;
+ bool sigOK = CScriptCheck(txFrom.vout[txTo[i].vin[0].prevout.n], txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false, &txdata)();
+ if (i == j)
+ BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j));
+ else
+ BOOST_CHECK_MESSAGE(!sigOK, strprintf("VerifySignature %d %d", i, j));
+ txTo[i].vin[0].scriptSig = sigSave;
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(norecurse)
+{
+ ScriptError err;
+ // Make sure only the outer pay-to-script-hash does the
+ // extra-validation thing:
+ CScript invalidAsScript;
+ invalidAsScript << OP_INVALIDOPCODE << OP_INVALIDOPCODE;
+
+ CScript p2sh = GetScriptForDestination(CScriptID(invalidAsScript));
+
+ CScript scriptSig;
+ scriptSig << Serialize(invalidAsScript);
+
+ // Should not verify, because it will try to execute OP_INVALIDOPCODE
+ BOOST_CHECK(!Verify(scriptSig, p2sh, true, err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_BAD_OPCODE, ScriptErrorString(err));
+
+ // Try to recur, and verification should succeed because
+ // the inner HASH160 <> EQUAL should only check the hash:
+ CScript p2sh2 = GetScriptForDestination(CScriptID(p2sh));
+ CScript scriptSig2;
+ scriptSig2 << Serialize(invalidAsScript) << Serialize(p2sh);
+
+ BOOST_CHECK(Verify(scriptSig2, p2sh2, true, err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
+}
+
+BOOST_AUTO_TEST_CASE(set)
+{
+ LOCK(cs_main);
+ // Test the CScript::Set* methods
+ CBasicKeyStore keystore;
+ CKey key[4];
+ std::vector<CPubKey> keys;
+ for (int i = 0; i < 4; i++)
+ {
+ key[i].MakeNewKey(true);
+ keystore.AddKey(key[i]);
+ keys.push_back(key[i].GetPubKey());
+ }
+
+ CScript inner[4];
+ inner[0] = GetScriptForDestination(key[0].GetPubKey().GetID());
+ inner[1] = GetScriptForMultisig(2, std::vector<CPubKey>(keys.begin(), keys.begin()+2));
+ inner[2] = GetScriptForMultisig(1, std::vector<CPubKey>(keys.begin(), keys.begin()+2));
+ inner[3] = GetScriptForMultisig(2, std::vector<CPubKey>(keys.begin(), keys.begin()+3));
+
+ CScript outer[4];
+ for (int i = 0; i < 4; i++)
+ {
+ outer[i] = GetScriptForDestination(CScriptID(inner[i]));
+ keystore.AddCScript(inner[i]);
+ }
+
+ CMutableTransaction txFrom; // Funding transaction:
+ std::string reason;
+ txFrom.vout.resize(4);
+ for (int i = 0; i < 4; i++)
+ {
+ txFrom.vout[i].scriptPubKey = outer[i];
+ txFrom.vout[i].nValue = CENT;
+ }
+ BOOST_CHECK(IsStandardTx(txFrom, reason));
+
+ CMutableTransaction txTo[4]; // Spending transactions
+ for (int i = 0; i < 4; i++)
+ {
+ txTo[i].vin.resize(1);
+ txTo[i].vout.resize(1);
+ txTo[i].vin[0].prevout.n = i;
+ txTo[i].vin[0].prevout.hash = txFrom.GetHash();
+ txTo[i].vout[0].nValue = 1*CENT;
+ txTo[i].vout[0].scriptPubKey = inner[i];
+ BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
+ }
+ for (int i = 0; i < 4; i++)
+ {
+ BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i));
+ BOOST_CHECK_MESSAGE(IsStandardTx(txTo[i], reason), strprintf("txTo[%d].IsStandard", i));
+ }
+}
+
+BOOST_AUTO_TEST_CASE(is)
+{
+ // Test CScript::IsPayToScriptHash()
+ uint160 dummy;
+ CScript p2sh;
+ p2sh << OP_HASH160 << ToByteVector(dummy) << OP_EQUAL;
+ BOOST_CHECK(p2sh.IsPayToScriptHash());
+
+ // Not considered pay-to-script-hash if using one of the OP_PUSHDATA opcodes:
+ static const unsigned char direct[] = { OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL };
+ BOOST_CHECK(CScript(direct, direct+sizeof(direct)).IsPayToScriptHash());
+ static const unsigned char pushdata1[] = { OP_HASH160, OP_PUSHDATA1, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL };
+ BOOST_CHECK(!CScript(pushdata1, pushdata1+sizeof(pushdata1)).IsPayToScriptHash());
+ static const unsigned char pushdata2[] = { OP_HASH160, OP_PUSHDATA2, 20,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL };
+ BOOST_CHECK(!CScript(pushdata2, pushdata2+sizeof(pushdata2)).IsPayToScriptHash());
+ static const unsigned char pushdata4[] = { OP_HASH160, OP_PUSHDATA4, 20,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL };
+ BOOST_CHECK(!CScript(pushdata4, pushdata4+sizeof(pushdata4)).IsPayToScriptHash());
+
+ CScript not_p2sh;
+ BOOST_CHECK(!not_p2sh.IsPayToScriptHash());
+
+ not_p2sh.clear(); not_p2sh << OP_HASH160 << ToByteVector(dummy) << ToByteVector(dummy) << OP_EQUAL;
+ BOOST_CHECK(!not_p2sh.IsPayToScriptHash());
+
+ not_p2sh.clear(); not_p2sh << OP_NOP << ToByteVector(dummy) << OP_EQUAL;
+ BOOST_CHECK(!not_p2sh.IsPayToScriptHash());
+
+ not_p2sh.clear(); not_p2sh << OP_HASH160 << ToByteVector(dummy) << OP_CHECKSIG;
+ BOOST_CHECK(!not_p2sh.IsPayToScriptHash());
+}
+
+BOOST_AUTO_TEST_CASE(switchover)
+{
+ // Test switch over code
+ CScript notValid;
+ ScriptError err;
+ notValid << OP_11 << OP_12 << OP_EQUALVERIFY;
+ CScript scriptSig;
+ scriptSig << Serialize(notValid);
+
+ CScript fund = GetScriptForDestination(CScriptID(notValid));
+
+
+ // Validation should succeed under old rules (hash is correct):
+ BOOST_CHECK(Verify(scriptSig, fund, false, err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
+ // Fail under new:
+ BOOST_CHECK(!Verify(scriptSig, fund, true, err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EQUALVERIFY, ScriptErrorString(err));
+}
+
+BOOST_AUTO_TEST_CASE(AreInputsStandard)
+{
+ LOCK(cs_main);
+ CCoinsView coinsDummy;
+ CCoinsViewCache coins(&coinsDummy);
+ CBasicKeyStore keystore;
+ CKey key[6];
+ std::vector<CPubKey> keys;
+ for (int i = 0; i < 6; i++)
+ {
+ key[i].MakeNewKey(true);
+ keystore.AddKey(key[i]);
+ }
+ for (int i = 0; i < 3; i++)
+ keys.push_back(key[i].GetPubKey());
+
+ CMutableTransaction txFrom;
+ txFrom.vout.resize(7);
+
+ // First three are standard:
+ CScript pay1 = GetScriptForDestination(key[0].GetPubKey().GetID());
+ keystore.AddCScript(pay1);
+ CScript pay1of3 = GetScriptForMultisig(1, keys);
+
+ txFrom.vout[0].scriptPubKey = GetScriptForDestination(CScriptID(pay1)); // P2SH (OP_CHECKSIG)
+ txFrom.vout[0].nValue = 1000;
+ txFrom.vout[1].scriptPubKey = pay1; // ordinary OP_CHECKSIG
+ txFrom.vout[1].nValue = 2000;
+ txFrom.vout[2].scriptPubKey = pay1of3; // ordinary OP_CHECKMULTISIG
+ txFrom.vout[2].nValue = 3000;
+
+ // vout[3] is complicated 1-of-3 AND 2-of-3
+ // ... that is OK if wrapped in P2SH:
+ CScript oneAndTwo;
+ oneAndTwo << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey());
+ oneAndTwo << OP_3 << OP_CHECKMULTISIGVERIFY;
+ oneAndTwo << OP_2 << ToByteVector(key[3].GetPubKey()) << ToByteVector(key[4].GetPubKey()) << ToByteVector(key[5].GetPubKey());
+ oneAndTwo << OP_3 << OP_CHECKMULTISIG;
+ keystore.AddCScript(oneAndTwo);
+ txFrom.vout[3].scriptPubKey = GetScriptForDestination(CScriptID(oneAndTwo));
+ txFrom.vout[3].nValue = 4000;
+
+ // vout[4] is max sigops:
+ CScript fifteenSigops; fifteenSigops << OP_1;
+ for (unsigned i = 0; i < MAX_P2SH_SIGOPS; i++)
+ fifteenSigops << ToByteVector(key[i%3].GetPubKey());
+ fifteenSigops << OP_15 << OP_CHECKMULTISIG;
+ keystore.AddCScript(fifteenSigops);
+ txFrom.vout[4].scriptPubKey = GetScriptForDestination(CScriptID(fifteenSigops));
+ txFrom.vout[4].nValue = 5000;
+
+ // vout[5/6] are non-standard because they exceed MAX_P2SH_SIGOPS
+ CScript sixteenSigops; sixteenSigops << OP_16 << OP_CHECKMULTISIG;
+ keystore.AddCScript(sixteenSigops);
+ txFrom.vout[5].scriptPubKey = GetScriptForDestination(CScriptID(sixteenSigops));
+ txFrom.vout[5].nValue = 5000;
+ CScript twentySigops; twentySigops << OP_CHECKMULTISIG;
+ keystore.AddCScript(twentySigops);
+ txFrom.vout[6].scriptPubKey = GetScriptForDestination(CScriptID(twentySigops));
+ txFrom.vout[6].nValue = 6000;
+
+ AddCoins(coins, txFrom, 0);
+
+ CMutableTransaction txTo;
+ txTo.vout.resize(1);
+ txTo.vout[0].scriptPubKey = GetScriptForDestination(key[1].GetPubKey().GetID());
+
+ txTo.vin.resize(5);
+ for (int i = 0; i < 5; i++)
+ {
+ txTo.vin[i].prevout.n = i;
+ txTo.vin[i].prevout.hash = txFrom.GetHash();
+ }
+ BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL));
+ BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 1, SIGHASH_ALL));
+ BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 2, SIGHASH_ALL));
+ // SignSignature doesn't know how to sign these. We're
+ // not testing validating signatures, so just create
+ // dummy signatures that DO include the correct P2SH scripts:
+ txTo.vin[3].scriptSig << OP_11 << OP_11 << std::vector<unsigned char>(oneAndTwo.begin(), oneAndTwo.end());
+ txTo.vin[4].scriptSig << std::vector<unsigned char>(fifteenSigops.begin(), fifteenSigops.end());
+
+ BOOST_CHECK(::AreInputsStandard(txTo, coins));
+ // 22 P2SH sigops for all inputs (1 for vin[0], 6 for vin[3], 15 for vin[4]
+ BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txTo, coins), 22U);
+
+ CMutableTransaction txToNonStd1;
+ txToNonStd1.vout.resize(1);
+ txToNonStd1.vout[0].scriptPubKey = GetScriptForDestination(key[1].GetPubKey().GetID());
+ txToNonStd1.vout[0].nValue = 1000;
+ txToNonStd1.vin.resize(1);
+ txToNonStd1.vin[0].prevout.n = 5;
+ txToNonStd1.vin[0].prevout.hash = txFrom.GetHash();
+ txToNonStd1.vin[0].scriptSig << std::vector<unsigned char>(sixteenSigops.begin(), sixteenSigops.end());
+
+ BOOST_CHECK(!::AreInputsStandard(txToNonStd1, coins));
+ BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txToNonStd1, coins), 16U);
+
+ CMutableTransaction txToNonStd2;
+ txToNonStd2.vout.resize(1);
+ txToNonStd2.vout[0].scriptPubKey = GetScriptForDestination(key[1].GetPubKey().GetID());
+ txToNonStd2.vout[0].nValue = 1000;
+ txToNonStd2.vin.resize(1);
+ txToNonStd2.vin[0].prevout.n = 6;
+ txToNonStd2.vin[0].prevout.hash = txFrom.GetHash();
+ txToNonStd2.vin[0].scriptSig << std::vector<unsigned char>(twentySigops.begin(), twentySigops.end());
+
+ BOOST_CHECK(!::AreInputsStandard(txToNonStd2, coins));
+ BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txToNonStd2, coins), 20U);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/script_standard_tests.cpp b/src/test/script_standard_tests.cpp
new file mode 100644
index 0000000000..bf57272ab2
--- /dev/null
+++ b/src/test/script_standard_tests.cpp
@@ -0,0 +1,746 @@
+// Copyright (c) 2017-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <key.h>
+#include <keystore.h>
+#include <script/ismine.h>
+#include <script/script.h>
+#include <script/script_error.h>
+#include <script/standard.h>
+#include <test/test_bitcoin.h>
+
+#include <boost/test/unit_test.hpp>
+
+
+BOOST_FIXTURE_TEST_SUITE(script_standard_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(script_standard_Solver_success)
+{
+ CKey keys[3];
+ CPubKey pubkeys[3];
+ for (int i = 0; i < 3; i++) {
+ keys[i].MakeNewKey(true);
+ pubkeys[i] = keys[i].GetPubKey();
+ }
+
+ CScript s;
+ txnouttype whichType;
+ std::vector<std::vector<unsigned char> > solutions;
+
+ // TX_PUBKEY
+ s.clear();
+ s << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
+ BOOST_CHECK(Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(whichType, TX_PUBKEY);
+ BOOST_CHECK_EQUAL(solutions.size(), 1U);
+ BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0]));
+
+ // TX_PUBKEYHASH
+ s.clear();
+ s << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
+ BOOST_CHECK(Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(whichType, TX_PUBKEYHASH);
+ BOOST_CHECK_EQUAL(solutions.size(), 1U);
+ BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID()));
+
+ // TX_SCRIPTHASH
+ CScript redeemScript(s); // initialize with leftover P2PKH script
+ s.clear();
+ s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
+ BOOST_CHECK(Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(whichType, TX_SCRIPTHASH);
+ BOOST_CHECK_EQUAL(solutions.size(), 1U);
+ BOOST_CHECK(solutions[0] == ToByteVector(CScriptID(redeemScript)));
+
+ // TX_MULTISIG
+ s.clear();
+ s << OP_1 <<
+ ToByteVector(pubkeys[0]) <<
+ ToByteVector(pubkeys[1]) <<
+ OP_2 << OP_CHECKMULTISIG;
+ BOOST_CHECK(Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(whichType, TX_MULTISIG);
+ BOOST_CHECK_EQUAL(solutions.size(), 4U);
+ BOOST_CHECK(solutions[0] == std::vector<unsigned char>({1}));
+ BOOST_CHECK(solutions[1] == ToByteVector(pubkeys[0]));
+ BOOST_CHECK(solutions[2] == ToByteVector(pubkeys[1]));
+ BOOST_CHECK(solutions[3] == std::vector<unsigned char>({2}));
+
+ s.clear();
+ s << OP_2 <<
+ ToByteVector(pubkeys[0]) <<
+ ToByteVector(pubkeys[1]) <<
+ ToByteVector(pubkeys[2]) <<
+ OP_3 << OP_CHECKMULTISIG;
+ BOOST_CHECK(Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(whichType, TX_MULTISIG);
+ BOOST_CHECK_EQUAL(solutions.size(), 5U);
+ BOOST_CHECK(solutions[0] == std::vector<unsigned char>({2}));
+ BOOST_CHECK(solutions[1] == ToByteVector(pubkeys[0]));
+ BOOST_CHECK(solutions[2] == ToByteVector(pubkeys[1]));
+ BOOST_CHECK(solutions[3] == ToByteVector(pubkeys[2]));
+ BOOST_CHECK(solutions[4] == std::vector<unsigned char>({3}));
+
+ // TX_NULL_DATA
+ s.clear();
+ s << OP_RETURN <<
+ std::vector<unsigned char>({0}) <<
+ std::vector<unsigned char>({75}) <<
+ std::vector<unsigned char>({255});
+ BOOST_CHECK(Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(whichType, TX_NULL_DATA);
+ BOOST_CHECK_EQUAL(solutions.size(), 0U);
+
+ // TX_WITNESS_V0_KEYHASH
+ s.clear();
+ s << OP_0 << ToByteVector(pubkeys[0].GetID());
+ BOOST_CHECK(Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(whichType, TX_WITNESS_V0_KEYHASH);
+ BOOST_CHECK_EQUAL(solutions.size(), 1U);
+ BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID()));
+
+ // TX_WITNESS_V0_SCRIPTHASH
+ uint256 scriptHash;
+ CSHA256().Write(&redeemScript[0], redeemScript.size())
+ .Finalize(scriptHash.begin());
+
+ s.clear();
+ s << OP_0 << ToByteVector(scriptHash);
+ BOOST_CHECK(Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(whichType, TX_WITNESS_V0_SCRIPTHASH);
+ BOOST_CHECK_EQUAL(solutions.size(), 1U);
+ BOOST_CHECK(solutions[0] == ToByteVector(scriptHash));
+
+ // TX_NONSTANDARD
+ s.clear();
+ s << OP_9 << OP_ADD << OP_11 << OP_EQUAL;
+ BOOST_CHECK(!Solver(s, whichType, solutions));
+ BOOST_CHECK_EQUAL(whichType, TX_NONSTANDARD);
+}
+
+BOOST_AUTO_TEST_CASE(script_standard_Solver_failure)
+{
+ CKey key;
+ CPubKey pubkey;
+ key.MakeNewKey(true);
+ pubkey = key.GetPubKey();
+
+ CScript s;
+ txnouttype whichType;
+ std::vector<std::vector<unsigned char> > solutions;
+
+ // TX_PUBKEY with incorrectly sized pubkey
+ s.clear();
+ s << std::vector<unsigned char>(30, 0x01) << OP_CHECKSIG;
+ BOOST_CHECK(!Solver(s, whichType, solutions));
+
+ // TX_PUBKEYHASH with incorrectly sized key hash
+ s.clear();
+ s << OP_DUP << OP_HASH160 << ToByteVector(pubkey) << OP_EQUALVERIFY << OP_CHECKSIG;
+ BOOST_CHECK(!Solver(s, whichType, solutions));
+
+ // TX_SCRIPTHASH with incorrectly sized script hash
+ s.clear();
+ s << OP_HASH160 << std::vector<unsigned char>(21, 0x01) << OP_EQUAL;
+ BOOST_CHECK(!Solver(s, whichType, solutions));
+
+ // TX_MULTISIG 0/2
+ s.clear();
+ s << OP_0 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
+ BOOST_CHECK(!Solver(s, whichType, solutions));
+
+ // TX_MULTISIG 2/1
+ s.clear();
+ s << OP_2 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
+ BOOST_CHECK(!Solver(s, whichType, solutions));
+
+ // TX_MULTISIG n = 2 with 1 pubkey
+ s.clear();
+ s << OP_1 << ToByteVector(pubkey) << OP_2 << OP_CHECKMULTISIG;
+ BOOST_CHECK(!Solver(s, whichType, solutions));
+
+ // TX_MULTISIG n = 1 with 0 pubkeys
+ s.clear();
+ s << OP_1 << OP_1 << OP_CHECKMULTISIG;
+ BOOST_CHECK(!Solver(s, whichType, solutions));
+
+ // TX_NULL_DATA with other opcodes
+ s.clear();
+ s << OP_RETURN << std::vector<unsigned char>({75}) << OP_ADD;
+ BOOST_CHECK(!Solver(s, whichType, solutions));
+
+ // TX_WITNESS with incorrect program size
+ s.clear();
+ s << OP_0 << std::vector<unsigned char>(19, 0x01);
+ BOOST_CHECK(!Solver(s, whichType, solutions));
+}
+
+BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination)
+{
+ CKey key;
+ CPubKey pubkey;
+ key.MakeNewKey(true);
+ pubkey = key.GetPubKey();
+
+ CScript s;
+ CTxDestination address;
+
+ // TX_PUBKEY
+ s.clear();
+ s << ToByteVector(pubkey) << OP_CHECKSIG;
+ BOOST_CHECK(ExtractDestination(s, address));
+ BOOST_CHECK(boost::get<CKeyID>(&address) &&
+ *boost::get<CKeyID>(&address) == pubkey.GetID());
+
+ // TX_PUBKEYHASH
+ s.clear();
+ s << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
+ BOOST_CHECK(ExtractDestination(s, address));
+ BOOST_CHECK(boost::get<CKeyID>(&address) &&
+ *boost::get<CKeyID>(&address) == pubkey.GetID());
+
+ // TX_SCRIPTHASH
+ CScript redeemScript(s); // initialize with leftover P2PKH script
+ s.clear();
+ s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
+ BOOST_CHECK(ExtractDestination(s, address));
+ BOOST_CHECK(boost::get<CScriptID>(&address) &&
+ *boost::get<CScriptID>(&address) == CScriptID(redeemScript));
+
+ // TX_MULTISIG
+ s.clear();
+ s << OP_1 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
+ BOOST_CHECK(!ExtractDestination(s, address));
+
+ // TX_NULL_DATA
+ s.clear();
+ s << OP_RETURN << std::vector<unsigned char>({75});
+ BOOST_CHECK(!ExtractDestination(s, address));
+
+ // TX_WITNESS_V0_KEYHASH
+ s.clear();
+ s << OP_0 << ToByteVector(pubkey.GetID());
+ BOOST_CHECK(ExtractDestination(s, address));
+ WitnessV0KeyHash keyhash;
+ CHash160().Write(pubkey.begin(), pubkey.size()).Finalize(keyhash.begin());
+ BOOST_CHECK(boost::get<WitnessV0KeyHash>(&address) && *boost::get<WitnessV0KeyHash>(&address) == keyhash);
+
+ // TX_WITNESS_V0_SCRIPTHASH
+ s.clear();
+ WitnessV0ScriptHash scripthash;
+ CSHA256().Write(redeemScript.data(), redeemScript.size()).Finalize(scripthash.begin());
+ s << OP_0 << ToByteVector(scripthash);
+ BOOST_CHECK(ExtractDestination(s, address));
+ BOOST_CHECK(boost::get<WitnessV0ScriptHash>(&address) && *boost::get<WitnessV0ScriptHash>(&address) == scripthash);
+
+ // TX_WITNESS with unknown version
+ s.clear();
+ s << OP_1 << ToByteVector(pubkey);
+ BOOST_CHECK(ExtractDestination(s, address));
+ WitnessUnknown unk;
+ unk.length = 33;
+ unk.version = 1;
+ std::copy(pubkey.begin(), pubkey.end(), unk.program);
+ BOOST_CHECK(boost::get<WitnessUnknown>(&address) && *boost::get<WitnessUnknown>(&address) == unk);
+}
+
+BOOST_AUTO_TEST_CASE(script_standard_ExtractDestinations)
+{
+ CKey keys[3];
+ CPubKey pubkeys[3];
+ for (int i = 0; i < 3; i++) {
+ keys[i].MakeNewKey(true);
+ pubkeys[i] = keys[i].GetPubKey();
+ }
+
+ CScript s;
+ txnouttype whichType;
+ std::vector<CTxDestination> addresses;
+ int nRequired;
+
+ // TX_PUBKEY
+ s.clear();
+ s << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
+ BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired));
+ BOOST_CHECK_EQUAL(whichType, TX_PUBKEY);
+ BOOST_CHECK_EQUAL(addresses.size(), 1U);
+ BOOST_CHECK_EQUAL(nRequired, 1);
+ BOOST_CHECK(boost::get<CKeyID>(&addresses[0]) &&
+ *boost::get<CKeyID>(&addresses[0]) == pubkeys[0].GetID());
+
+ // TX_PUBKEYHASH
+ s.clear();
+ s << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
+ BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired));
+ BOOST_CHECK_EQUAL(whichType, TX_PUBKEYHASH);
+ BOOST_CHECK_EQUAL(addresses.size(), 1U);
+ BOOST_CHECK_EQUAL(nRequired, 1);
+ BOOST_CHECK(boost::get<CKeyID>(&addresses[0]) &&
+ *boost::get<CKeyID>(&addresses[0]) == pubkeys[0].GetID());
+
+ // TX_SCRIPTHASH
+ CScript redeemScript(s); // initialize with leftover P2PKH script
+ s.clear();
+ s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
+ BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired));
+ BOOST_CHECK_EQUAL(whichType, TX_SCRIPTHASH);
+ BOOST_CHECK_EQUAL(addresses.size(), 1U);
+ BOOST_CHECK_EQUAL(nRequired, 1);
+ BOOST_CHECK(boost::get<CScriptID>(&addresses[0]) &&
+ *boost::get<CScriptID>(&addresses[0]) == CScriptID(redeemScript));
+
+ // TX_MULTISIG
+ s.clear();
+ s << OP_2 <<
+ ToByteVector(pubkeys[0]) <<
+ ToByteVector(pubkeys[1]) <<
+ OP_2 << OP_CHECKMULTISIG;
+ BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired));
+ BOOST_CHECK_EQUAL(whichType, TX_MULTISIG);
+ BOOST_CHECK_EQUAL(addresses.size(), 2U);
+ BOOST_CHECK_EQUAL(nRequired, 2);
+ BOOST_CHECK(boost::get<CKeyID>(&addresses[0]) &&
+ *boost::get<CKeyID>(&addresses[0]) == pubkeys[0].GetID());
+ BOOST_CHECK(boost::get<CKeyID>(&addresses[1]) &&
+ *boost::get<CKeyID>(&addresses[1]) == pubkeys[1].GetID());
+
+ // TX_NULL_DATA
+ s.clear();
+ s << OP_RETURN << std::vector<unsigned char>({75});
+ BOOST_CHECK(!ExtractDestinations(s, whichType, addresses, nRequired));
+}
+
+BOOST_AUTO_TEST_CASE(script_standard_GetScriptFor_)
+{
+ CKey keys[3];
+ CPubKey pubkeys[3];
+ for (int i = 0; i < 3; i++) {
+ keys[i].MakeNewKey(true);
+ pubkeys[i] = keys[i].GetPubKey();
+ }
+
+ CScript expected, result;
+
+ // CKeyID
+ expected.clear();
+ expected << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
+ result = GetScriptForDestination(pubkeys[0].GetID());
+ BOOST_CHECK(result == expected);
+
+ // CScriptID
+ CScript redeemScript(result);
+ expected.clear();
+ expected << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
+ result = GetScriptForDestination(CScriptID(redeemScript));
+ BOOST_CHECK(result == expected);
+
+ // CNoDestination
+ expected.clear();
+ result = GetScriptForDestination(CNoDestination());
+ BOOST_CHECK(result == expected);
+
+ // GetScriptForRawPubKey
+ expected.clear();
+ expected << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
+ result = GetScriptForRawPubKey(pubkeys[0]);
+ BOOST_CHECK(result == expected);
+
+ // GetScriptForMultisig
+ expected.clear();
+ expected << OP_2 <<
+ ToByteVector(pubkeys[0]) <<
+ ToByteVector(pubkeys[1]) <<
+ ToByteVector(pubkeys[2]) <<
+ OP_3 << OP_CHECKMULTISIG;
+ result = GetScriptForMultisig(2, std::vector<CPubKey>(pubkeys, pubkeys + 3));
+ BOOST_CHECK(result == expected);
+
+ // GetScriptForWitness
+ CScript witnessScript;
+
+ witnessScript << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
+ expected.clear();
+ expected << OP_0 << ToByteVector(pubkeys[0].GetID());
+ result = GetScriptForWitness(witnessScript);
+ BOOST_CHECK(result == expected);
+
+ witnessScript.clear();
+ witnessScript << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
+ result = GetScriptForWitness(witnessScript);
+ BOOST_CHECK(result == expected);
+
+ witnessScript.clear();
+ witnessScript << OP_1 << ToByteVector(pubkeys[0]) << OP_1 << OP_CHECKMULTISIG;
+
+ uint256 scriptHash;
+ CSHA256().Write(&witnessScript[0], witnessScript.size())
+ .Finalize(scriptHash.begin());
+
+ expected.clear();
+ expected << OP_0 << ToByteVector(scriptHash);
+ result = GetScriptForWitness(witnessScript);
+ BOOST_CHECK(result == expected);
+}
+
+BOOST_AUTO_TEST_CASE(script_standard_IsMine)
+{
+ CKey keys[2];
+ CPubKey pubkeys[2];
+ for (int i = 0; i < 2; i++) {
+ keys[i].MakeNewKey(true);
+ pubkeys[i] = keys[i].GetPubKey();
+ }
+
+ CKey uncompressedKey;
+ uncompressedKey.MakeNewKey(false);
+ CPubKey uncompressedPubkey = uncompressedKey.GetPubKey();
+
+ CScript scriptPubKey;
+ isminetype result;
+
+ // P2PK compressed
+ {
+ CBasicKeyStore keystore;
+ scriptPubKey = GetScriptForRawPubKey(pubkeys[0]);
+
+ // Keystore does not have key
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+
+ // Keystore has key
+ keystore.AddKey(keys[0]);
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ }
+
+ // P2PK uncompressed
+ {
+ CBasicKeyStore keystore;
+ scriptPubKey = GetScriptForRawPubKey(uncompressedPubkey);
+
+ // Keystore does not have key
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+
+ // Keystore has key
+ keystore.AddKey(uncompressedKey);
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ }
+
+ // P2PKH compressed
+ {
+ CBasicKeyStore keystore;
+ scriptPubKey = GetScriptForDestination(pubkeys[0].GetID());
+
+ // Keystore does not have key
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+
+ // Keystore has key
+ keystore.AddKey(keys[0]);
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ }
+
+ // P2PKH uncompressed
+ {
+ CBasicKeyStore keystore;
+ scriptPubKey = GetScriptForDestination(uncompressedPubkey.GetID());
+
+ // Keystore does not have key
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+
+ // Keystore has key
+ keystore.AddKey(uncompressedKey);
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ }
+
+ // P2SH
+ {
+ CBasicKeyStore keystore;
+
+ CScript redeemScript = GetScriptForDestination(pubkeys[0].GetID());
+ scriptPubKey = GetScriptForDestination(CScriptID(redeemScript));
+
+ // Keystore does not have redeemScript or key
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+
+ // Keystore has redeemScript but no key
+ keystore.AddCScript(redeemScript);
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+
+ // Keystore has redeemScript and key
+ keystore.AddKey(keys[0]);
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ }
+
+ // (P2PKH inside) P2SH inside P2SH (invalid)
+ {
+ CBasicKeyStore keystore;
+
+ CScript redeemscript_inner = GetScriptForDestination(pubkeys[0].GetID());
+ CScript redeemscript = GetScriptForDestination(CScriptID(redeemscript_inner));
+ scriptPubKey = GetScriptForDestination(CScriptID(redeemscript));
+
+ keystore.AddCScript(redeemscript);
+ keystore.AddCScript(redeemscript_inner);
+ keystore.AddCScript(scriptPubKey);
+ keystore.AddKey(keys[0]);
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ }
+
+ // (P2PKH inside) P2SH inside P2WSH (invalid)
+ {
+ CBasicKeyStore keystore;
+
+ CScript redeemscript = GetScriptForDestination(pubkeys[0].GetID());
+ CScript witnessscript = GetScriptForDestination(CScriptID(redeemscript));
+ scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
+
+ keystore.AddCScript(witnessscript);
+ keystore.AddCScript(redeemscript);
+ keystore.AddCScript(scriptPubKey);
+ keystore.AddKey(keys[0]);
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ }
+
+ // P2WPKH inside P2WSH (invalid)
+ {
+ CBasicKeyStore keystore;
+
+ CScript witnessscript = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0].GetID()));
+ scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
+
+ keystore.AddCScript(witnessscript);
+ keystore.AddCScript(scriptPubKey);
+ keystore.AddKey(keys[0]);
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ }
+
+ // (P2PKH inside) P2WSH inside P2WSH (invalid)
+ {
+ CBasicKeyStore keystore;
+
+ CScript witnessscript_inner = GetScriptForDestination(pubkeys[0].GetID());
+ CScript witnessscript = GetScriptForDestination(WitnessV0ScriptHash(witnessscript_inner));
+ scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
+
+ keystore.AddCScript(witnessscript_inner);
+ keystore.AddCScript(witnessscript);
+ keystore.AddCScript(scriptPubKey);
+ keystore.AddKey(keys[0]);
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ }
+
+ // P2WPKH compressed
+ {
+ CBasicKeyStore keystore;
+ keystore.AddKey(keys[0]);
+
+ scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0].GetID()));
+
+ // Keystore implicitly has key and P2SH redeemScript
+ keystore.AddCScript(scriptPubKey);
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ }
+
+ // P2WPKH uncompressed
+ {
+ CBasicKeyStore keystore;
+ keystore.AddKey(uncompressedKey);
+
+ scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(uncompressedPubkey.GetID()));
+
+ // Keystore has key, but no P2SH redeemScript
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+
+ // Keystore has key and P2SH redeemScript
+ keystore.AddCScript(scriptPubKey);
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ }
+
+ // scriptPubKey multisig
+ {
+ CBasicKeyStore keystore;
+
+ scriptPubKey = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
+
+ // Keystore does not have any keys
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+
+ // Keystore has 1/2 keys
+ keystore.AddKey(uncompressedKey);
+
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+
+ // Keystore has 2/2 keys
+ keystore.AddKey(keys[1]);
+
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+
+ // Keystore has 2/2 keys and the script
+ keystore.AddCScript(scriptPubKey);
+
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ }
+
+ // P2SH multisig
+ {
+ CBasicKeyStore keystore;
+ keystore.AddKey(uncompressedKey);
+ keystore.AddKey(keys[1]);
+
+ CScript redeemScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
+ scriptPubKey = GetScriptForDestination(CScriptID(redeemScript));
+
+ // Keystore has no redeemScript
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+
+ // Keystore has redeemScript
+ keystore.AddCScript(redeemScript);
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ }
+
+ // P2WSH multisig with compressed keys
+ {
+ CBasicKeyStore keystore;
+ keystore.AddKey(keys[0]);
+ keystore.AddKey(keys[1]);
+
+ CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
+ scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
+
+ // Keystore has keys, but no witnessScript or P2SH redeemScript
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+
+ // Keystore has keys and witnessScript, but no P2SH redeemScript
+ keystore.AddCScript(witnessScript);
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+
+ // Keystore has keys, witnessScript, P2SH redeemScript
+ keystore.AddCScript(scriptPubKey);
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ }
+
+ // P2WSH multisig with uncompressed key
+ {
+ CBasicKeyStore keystore;
+ keystore.AddKey(uncompressedKey);
+ keystore.AddKey(keys[1]);
+
+ CScript witnessScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
+ scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
+
+ // Keystore has keys, but no witnessScript or P2SH redeemScript
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+
+ // Keystore has keys and witnessScript, but no P2SH redeemScript
+ keystore.AddCScript(witnessScript);
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+
+ // Keystore has keys, witnessScript, P2SH redeemScript
+ keystore.AddCScript(scriptPubKey);
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ }
+
+ // P2WSH multisig wrapped in P2SH
+ {
+ CBasicKeyStore keystore;
+
+ CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
+ CScript redeemScript = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
+ scriptPubKey = GetScriptForDestination(CScriptID(redeemScript));
+
+ // Keystore has no witnessScript, P2SH redeemScript, or keys
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+
+ // Keystore has witnessScript and P2SH redeemScript, but no keys
+ keystore.AddCScript(redeemScript);
+ keystore.AddCScript(witnessScript);
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+
+ // Keystore has keys, witnessScript, P2SH redeemScript
+ keystore.AddKey(keys[0]);
+ keystore.AddKey(keys[1]);
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_SPENDABLE);
+ }
+
+ // OP_RETURN
+ {
+ CBasicKeyStore keystore;
+ keystore.AddKey(keys[0]);
+
+ scriptPubKey.clear();
+ scriptPubKey << OP_RETURN << ToByteVector(pubkeys[0]);
+
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ }
+
+ // witness unspendable
+ {
+ CBasicKeyStore keystore;
+ keystore.AddKey(keys[0]);
+
+ scriptPubKey.clear();
+ scriptPubKey << OP_0 << ToByteVector(ParseHex("aabb"));
+
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ }
+
+ // witness unknown
+ {
+ CBasicKeyStore keystore;
+ keystore.AddKey(keys[0]);
+
+ scriptPubKey.clear();
+ scriptPubKey << OP_16 << ToByteVector(ParseHex("aabb"));
+
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ }
+
+ // Nonstandard
+ {
+ CBasicKeyStore keystore;
+ keystore.AddKey(keys[0]);
+
+ scriptPubKey.clear();
+ scriptPubKey << OP_9 << OP_ADD << OP_11 << OP_EQUAL;
+
+ result = IsMine(keystore, scriptPubKey);
+ BOOST_CHECK_EQUAL(result, ISMINE_NO);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
new file mode 100644
index 0000000000..e56080b278
--- /dev/null
+++ b/src/test/script_tests.cpp
@@ -0,0 +1,1640 @@
+// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <test/data/script_tests.json.h>
+
+#include <core_io.h>
+#include <key.h>
+#include <keystore.h>
+#include <script/script.h>
+#include <script/script_error.h>
+#include <script/sign.h>
+#include <util.h>
+#include <utilstrencodings.h>
+#include <test/test_bitcoin.h>
+#include <rpc/server.h>
+
+#if defined(HAVE_CONSENSUS_LIB)
+#include <script/bitcoinconsensus.h>
+#endif
+
+#include <fstream>
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+#include <boost/test/unit_test.hpp>
+
+#include <univalue.h>
+
+// Uncomment if you want to output updated JSON tests.
+// #define UPDATE_JSON_TESTS
+
+static const unsigned int gFlags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
+
+unsigned int ParseScriptFlags(std::string strFlags);
+std::string FormatScriptFlags(unsigned int flags);
+
+UniValue
+read_json(const std::string& jsondata)
+{
+ UniValue v;
+
+ if (!v.read(jsondata) || !v.isArray())
+ {
+ BOOST_ERROR("Parse error.");
+ return UniValue(UniValue::VARR);
+ }
+ return v.get_array();
+}
+
+struct ScriptErrorDesc
+{
+ ScriptError_t err;
+ const char *name;
+};
+
+static ScriptErrorDesc script_errors[]={
+ {SCRIPT_ERR_OK, "OK"},
+ {SCRIPT_ERR_UNKNOWN_ERROR, "UNKNOWN_ERROR"},
+ {SCRIPT_ERR_EVAL_FALSE, "EVAL_FALSE"},
+ {SCRIPT_ERR_OP_RETURN, "OP_RETURN"},
+ {SCRIPT_ERR_SCRIPT_SIZE, "SCRIPT_SIZE"},
+ {SCRIPT_ERR_PUSH_SIZE, "PUSH_SIZE"},
+ {SCRIPT_ERR_OP_COUNT, "OP_COUNT"},
+ {SCRIPT_ERR_STACK_SIZE, "STACK_SIZE"},
+ {SCRIPT_ERR_SIG_COUNT, "SIG_COUNT"},
+ {SCRIPT_ERR_PUBKEY_COUNT, "PUBKEY_COUNT"},
+ {SCRIPT_ERR_VERIFY, "VERIFY"},
+ {SCRIPT_ERR_EQUALVERIFY, "EQUALVERIFY"},
+ {SCRIPT_ERR_CHECKMULTISIGVERIFY, "CHECKMULTISIGVERIFY"},
+ {SCRIPT_ERR_CHECKSIGVERIFY, "CHECKSIGVERIFY"},
+ {SCRIPT_ERR_NUMEQUALVERIFY, "NUMEQUALVERIFY"},
+ {SCRIPT_ERR_BAD_OPCODE, "BAD_OPCODE"},
+ {SCRIPT_ERR_DISABLED_OPCODE, "DISABLED_OPCODE"},
+ {SCRIPT_ERR_INVALID_STACK_OPERATION, "INVALID_STACK_OPERATION"},
+ {SCRIPT_ERR_INVALID_ALTSTACK_OPERATION, "INVALID_ALTSTACK_OPERATION"},
+ {SCRIPT_ERR_UNBALANCED_CONDITIONAL, "UNBALANCED_CONDITIONAL"},
+ {SCRIPT_ERR_NEGATIVE_LOCKTIME, "NEGATIVE_LOCKTIME"},
+ {SCRIPT_ERR_UNSATISFIED_LOCKTIME, "UNSATISFIED_LOCKTIME"},
+ {SCRIPT_ERR_SIG_HASHTYPE, "SIG_HASHTYPE"},
+ {SCRIPT_ERR_SIG_DER, "SIG_DER"},
+ {SCRIPT_ERR_MINIMALDATA, "MINIMALDATA"},
+ {SCRIPT_ERR_SIG_PUSHONLY, "SIG_PUSHONLY"},
+ {SCRIPT_ERR_SIG_HIGH_S, "SIG_HIGH_S"},
+ {SCRIPT_ERR_SIG_NULLDUMMY, "SIG_NULLDUMMY"},
+ {SCRIPT_ERR_PUBKEYTYPE, "PUBKEYTYPE"},
+ {SCRIPT_ERR_CLEANSTACK, "CLEANSTACK"},
+ {SCRIPT_ERR_MINIMALIF, "MINIMALIF"},
+ {SCRIPT_ERR_SIG_NULLFAIL, "NULLFAIL"},
+ {SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS, "DISCOURAGE_UPGRADABLE_NOPS"},
+ {SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM, "DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"},
+ {SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH, "WITNESS_PROGRAM_WRONG_LENGTH"},
+ {SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY, "WITNESS_PROGRAM_WITNESS_EMPTY"},
+ {SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH, "WITNESS_PROGRAM_MISMATCH"},
+ {SCRIPT_ERR_WITNESS_MALLEATED, "WITNESS_MALLEATED"},
+ {SCRIPT_ERR_WITNESS_MALLEATED_P2SH, "WITNESS_MALLEATED_P2SH"},
+ {SCRIPT_ERR_WITNESS_UNEXPECTED, "WITNESS_UNEXPECTED"},
+ {SCRIPT_ERR_WITNESS_PUBKEYTYPE, "WITNESS_PUBKEYTYPE"},
+ {SCRIPT_ERR_OP_CODESEPARATOR, "OP_CODESEPARATOR"},
+ {SCRIPT_ERR_SIG_FINDANDDELETE, "SIG_FINDANDDELETE"},
+};
+
+static const char *FormatScriptError(ScriptError_t err)
+{
+ for (unsigned int i=0; i<ARRAYLEN(script_errors); ++i)
+ if (script_errors[i].err == err)
+ return script_errors[i].name;
+ BOOST_ERROR("Unknown scripterror enumeration value, update script_errors in script_tests.cpp.");
+ return "";
+}
+
+static ScriptError_t ParseScriptError(const std::string &name)
+{
+ for (unsigned int i=0; i<ARRAYLEN(script_errors); ++i)
+ if (script_errors[i].name == name)
+ return script_errors[i].err;
+ BOOST_ERROR("Unknown scripterror \"" << name << "\" in test description");
+ return SCRIPT_ERR_UNKNOWN_ERROR;
+}
+
+BOOST_FIXTURE_TEST_SUITE(script_tests, BasicTestingSetup)
+
+CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey, int nValue = 0)
+{
+ CMutableTransaction txCredit;
+ txCredit.nVersion = 1;
+ txCredit.nLockTime = 0;
+ txCredit.vin.resize(1);
+ txCredit.vout.resize(1);
+ txCredit.vin[0].prevout.SetNull();
+ txCredit.vin[0].scriptSig = CScript() << CScriptNum(0) << CScriptNum(0);
+ txCredit.vin[0].nSequence = CTxIn::SEQUENCE_FINAL;
+ txCredit.vout[0].scriptPubKey = scriptPubKey;
+ txCredit.vout[0].nValue = nValue;
+
+ return txCredit;
+}
+
+CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CScriptWitness& scriptWitness, const CTransaction& txCredit)
+{
+ CMutableTransaction txSpend;
+ txSpend.nVersion = 1;
+ txSpend.nLockTime = 0;
+ txSpend.vin.resize(1);
+ txSpend.vout.resize(1);
+ txSpend.vin[0].scriptWitness = scriptWitness;
+ txSpend.vin[0].prevout.hash = txCredit.GetHash();
+ txSpend.vin[0].prevout.n = 0;
+ txSpend.vin[0].scriptSig = scriptSig;
+ txSpend.vin[0].nSequence = CTxIn::SEQUENCE_FINAL;
+ txSpend.vout[0].scriptPubKey = CScript();
+ txSpend.vout[0].nValue = txCredit.vout[0].nValue;
+
+ return txSpend;
+}
+
+void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, const CScriptWitness& scriptWitness, int flags, const std::string& message, int scriptError, CAmount nValue = 0)
+{
+ bool expect = (scriptError == SCRIPT_ERR_OK);
+ if (flags & SCRIPT_VERIFY_CLEANSTACK) {
+ flags |= SCRIPT_VERIFY_P2SH;
+ flags |= SCRIPT_VERIFY_WITNESS;
+ }
+ ScriptError err;
+ const CTransaction txCredit{BuildCreditingTransaction(scriptPubKey, nValue)};
+ CMutableTransaction tx = BuildSpendingTransaction(scriptSig, scriptWitness, txCredit);
+ CMutableTransaction tx2 = tx;
+ BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, &scriptWitness, flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue), &err) == expect, message);
+ BOOST_CHECK_MESSAGE(err == scriptError, std::string(FormatScriptError(err)) + " where " + std::string(FormatScriptError((ScriptError_t)scriptError)) + " expected: " + message);
+
+ // Verify that removing flags from a passing test or adding flags to a failing test does not change the result.
+ for (int i = 0; i < 16; ++i) {
+ int extra_flags = InsecureRandBits(16);
+ int combined_flags = expect ? (flags & ~extra_flags) : (flags | extra_flags);
+ // Weed out some invalid flag combinations.
+ if (combined_flags & SCRIPT_VERIFY_CLEANSTACK && ~combined_flags & (SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS)) continue;
+ if (combined_flags & SCRIPT_VERIFY_WITNESS && ~combined_flags & SCRIPT_VERIFY_P2SH) continue;
+ BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, &scriptWitness, combined_flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue), &err) == expect, message + strprintf(" (with flags %x)", combined_flags));
+ }
+
+#if defined(HAVE_CONSENSUS_LIB)
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << tx2;
+ int libconsensus_flags = flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_ALL;
+ if (libconsensus_flags == flags) {
+ if (flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS) {
+ BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(scriptPubKey.data(), scriptPubKey.size(), txCredit.vout[0].nValue, (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, nullptr) == expect, message);
+ } else {
+ BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script_with_amount(scriptPubKey.data(), scriptPubKey.size(), 0, (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, nullptr) == expect, message);
+ BOOST_CHECK_MESSAGE(bitcoinconsensus_verify_script(scriptPubKey.data(), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), 0, libconsensus_flags, nullptr) == expect,message);
+ }
+ }
+#endif
+}
+
+void static NegateSignatureS(std::vector<unsigned char>& vchSig) {
+ // Parse the signature.
+ std::vector<unsigned char> r, s;
+ r = std::vector<unsigned char>(vchSig.begin() + 4, vchSig.begin() + 4 + vchSig[3]);
+ s = std::vector<unsigned char>(vchSig.begin() + 6 + vchSig[3], vchSig.begin() + 6 + vchSig[3] + vchSig[5 + vchSig[3]]);
+
+ // Really ugly to implement mod-n negation here, but it would be feature creep to expose such functionality from libsecp256k1.
+ static const unsigned char order[33] = {
+ 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
+ 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
+ 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41
+ };
+ while (s.size() < 33) {
+ s.insert(s.begin(), 0x00);
+ }
+ int carry = 0;
+ for (int p = 32; p >= 1; p--) {
+ int n = (int)order[p] - s[p] - carry;
+ s[p] = (n + 256) & 0xFF;
+ carry = (n < 0);
+ }
+ assert(carry == 0);
+ if (s.size() > 1 && s[0] == 0 && s[1] < 0x80) {
+ s.erase(s.begin());
+ }
+
+ // Reconstruct the signature.
+ vchSig.clear();
+ vchSig.push_back(0x30);
+ vchSig.push_back(4 + r.size() + s.size());
+ vchSig.push_back(0x02);
+ vchSig.push_back(r.size());
+ vchSig.insert(vchSig.end(), r.begin(), r.end());
+ vchSig.push_back(0x02);
+ vchSig.push_back(s.size());
+ vchSig.insert(vchSig.end(), s.begin(), s.end());
+}
+
+namespace
+{
+const unsigned char vchKey0[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
+const unsigned char vchKey1[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0};
+const unsigned char vchKey2[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0};
+
+struct KeyData
+{
+ CKey key0, key0C, key1, key1C, key2, key2C;
+ CPubKey pubkey0, pubkey0C, pubkey0H;
+ CPubKey pubkey1, pubkey1C;
+ CPubKey pubkey2, pubkey2C;
+
+ KeyData()
+ {
+
+ key0.Set(vchKey0, vchKey0 + 32, false);
+ key0C.Set(vchKey0, vchKey0 + 32, true);
+ pubkey0 = key0.GetPubKey();
+ pubkey0H = key0.GetPubKey();
+ pubkey0C = key0C.GetPubKey();
+ *const_cast<unsigned char*>(&pubkey0H[0]) = 0x06 | (pubkey0H[64] & 1);
+
+ key1.Set(vchKey1, vchKey1 + 32, false);
+ key1C.Set(vchKey1, vchKey1 + 32, true);
+ pubkey1 = key1.GetPubKey();
+ pubkey1C = key1C.GetPubKey();
+
+ key2.Set(vchKey2, vchKey2 + 32, false);
+ key2C.Set(vchKey2, vchKey2 + 32, true);
+ pubkey2 = key2.GetPubKey();
+ pubkey2C = key2C.GetPubKey();
+ }
+};
+
+enum class WitnessMode {
+ NONE,
+ PKH,
+ SH
+};
+
+class TestBuilder
+{
+private:
+ //! Actually executed script
+ CScript script;
+ //! The P2SH redeemscript
+ CScript redeemscript;
+ //! The Witness embedded script
+ CScript witscript;
+ CScriptWitness scriptWitness;
+ CTransactionRef creditTx;
+ CMutableTransaction spendTx;
+ bool havePush;
+ std::vector<unsigned char> push;
+ std::string comment;
+ int flags;
+ int scriptError;
+ CAmount nValue;
+
+ void DoPush()
+ {
+ if (havePush) {
+ spendTx.vin[0].scriptSig << push;
+ havePush = false;
+ }
+ }
+
+ void DoPush(const std::vector<unsigned char>& data)
+ {
+ DoPush();
+ push = data;
+ havePush = true;
+ }
+
+public:
+ TestBuilder(const CScript& script_, const std::string& comment_, int flags_, bool P2SH = false, WitnessMode wm = WitnessMode::NONE, int witnessversion = 0, CAmount nValue_ = 0) : script(script_), havePush(false), comment(comment_), flags(flags_), scriptError(SCRIPT_ERR_OK), nValue(nValue_)
+ {
+ CScript scriptPubKey = script;
+ if (wm == WitnessMode::PKH) {
+ uint160 hash;
+ CHash160().Write(&script[1], script.size() - 1).Finalize(hash.begin());
+ script = CScript() << OP_DUP << OP_HASH160 << ToByteVector(hash) << OP_EQUALVERIFY << OP_CHECKSIG;
+ scriptPubKey = CScript() << witnessversion << ToByteVector(hash);
+ } else if (wm == WitnessMode::SH) {
+ witscript = scriptPubKey;
+ uint256 hash;
+ CSHA256().Write(&witscript[0], witscript.size()).Finalize(hash.begin());
+ scriptPubKey = CScript() << witnessversion << ToByteVector(hash);
+ }
+ if (P2SH) {
+ redeemscript = scriptPubKey;
+ scriptPubKey = CScript() << OP_HASH160 << ToByteVector(CScriptID(redeemscript)) << OP_EQUAL;
+ }
+ creditTx = MakeTransactionRef(BuildCreditingTransaction(scriptPubKey, nValue));
+ spendTx = BuildSpendingTransaction(CScript(), CScriptWitness(), *creditTx);
+ }
+
+ TestBuilder& ScriptError(ScriptError_t err)
+ {
+ scriptError = err;
+ return *this;
+ }
+
+ TestBuilder& Add(const CScript& _script)
+ {
+ DoPush();
+ spendTx.vin[0].scriptSig += _script;
+ return *this;
+ }
+
+ TestBuilder& Num(int num)
+ {
+ DoPush();
+ spendTx.vin[0].scriptSig << num;
+ return *this;
+ }
+
+ TestBuilder& Push(const std::string& hex)
+ {
+ DoPush(ParseHex(hex));
+ return *this;
+ }
+
+ TestBuilder& Push(const CScript& _script) {
+ DoPush(std::vector<unsigned char>(_script.begin(), _script.end()));
+ return *this;
+ }
+
+ TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32, SigVersion sigversion = SigVersion::BASE, CAmount amount = 0)
+ {
+ uint256 hash = SignatureHash(script, spendTx, 0, nHashType, amount, sigversion);
+ std::vector<unsigned char> vchSig, r, s;
+ uint32_t iter = 0;
+ do {
+ key.Sign(hash, vchSig, iter++);
+ if ((lenS == 33) != (vchSig[5 + vchSig[3]] == 33)) {
+ NegateSignatureS(vchSig);
+ }
+ r = std::vector<unsigned char>(vchSig.begin() + 4, vchSig.begin() + 4 + vchSig[3]);
+ s = std::vector<unsigned char>(vchSig.begin() + 6 + vchSig[3], vchSig.begin() + 6 + vchSig[3] + vchSig[5 + vchSig[3]]);
+ } while (lenR != r.size() || lenS != s.size());
+ vchSig.push_back(static_cast<unsigned char>(nHashType));
+ DoPush(vchSig);
+ return *this;
+ }
+
+ TestBuilder& PushWitSig(const CKey& key, CAmount amount = -1, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32, SigVersion sigversion = SigVersion::WITNESS_V0)
+ {
+ if (amount == -1)
+ amount = nValue;
+ return PushSig(key, nHashType, lenR, lenS, sigversion, amount).AsWit();
+ }
+
+ TestBuilder& Push(const CPubKey& pubkey)
+ {
+ DoPush(std::vector<unsigned char>(pubkey.begin(), pubkey.end()));
+ return *this;
+ }
+
+ TestBuilder& PushRedeem()
+ {
+ DoPush(std::vector<unsigned char>(redeemscript.begin(), redeemscript.end()));
+ return *this;
+ }
+
+ TestBuilder& PushWitRedeem()
+ {
+ DoPush(std::vector<unsigned char>(witscript.begin(), witscript.end()));
+ return AsWit();
+ }
+
+ TestBuilder& EditPush(unsigned int pos, const std::string& hexin, const std::string& hexout)
+ {
+ assert(havePush);
+ std::vector<unsigned char> datain = ParseHex(hexin);
+ std::vector<unsigned char> dataout = ParseHex(hexout);
+ assert(pos + datain.size() <= push.size());
+ BOOST_CHECK_MESSAGE(std::vector<unsigned char>(push.begin() + pos, push.begin() + pos + datain.size()) == datain, comment);
+ push.erase(push.begin() + pos, push.begin() + pos + datain.size());
+ push.insert(push.begin() + pos, dataout.begin(), dataout.end());
+ return *this;
+ }
+
+ TestBuilder& DamagePush(unsigned int pos)
+ {
+ assert(havePush);
+ assert(pos < push.size());
+ push[pos] ^= 1;
+ return *this;
+ }
+
+ TestBuilder& Test()
+ {
+ TestBuilder copy = *this; // Make a copy so we can rollback the push.
+ DoPush();
+ DoTest(creditTx->vout[0].scriptPubKey, spendTx.vin[0].scriptSig, scriptWitness, flags, comment, scriptError, nValue);
+ *this = copy;
+ return *this;
+ }
+
+ TestBuilder& AsWit()
+ {
+ assert(havePush);
+ scriptWitness.stack.push_back(push);
+ havePush = false;
+ return *this;
+ }
+
+ UniValue GetJSON()
+ {
+ DoPush();
+ UniValue array(UniValue::VARR);
+ if (!scriptWitness.stack.empty()) {
+ UniValue wit(UniValue::VARR);
+ for (unsigned i = 0; i < scriptWitness.stack.size(); i++) {
+ wit.push_back(HexStr(scriptWitness.stack[i]));
+ }
+ wit.push_back(ValueFromAmount(nValue));
+ array.push_back(wit);
+ }
+ array.push_back(FormatScript(spendTx.vin[0].scriptSig));
+ array.push_back(FormatScript(creditTx->vout[0].scriptPubKey));
+ array.push_back(FormatScriptFlags(flags));
+ array.push_back(FormatScriptError((ScriptError_t)scriptError));
+ array.push_back(comment);
+ return array;
+ }
+
+ std::string GetComment() const
+ {
+ return comment;
+ }
+};
+
+std::string JSONPrettyPrint(const UniValue& univalue)
+{
+ std::string ret = univalue.write(4);
+ // Workaround for libunivalue pretty printer, which puts a space between commas and newlines
+ size_t pos = 0;
+ while ((pos = ret.find(" \n", pos)) != std::string::npos) {
+ ret.replace(pos, 2, "\n");
+ pos++;
+ }
+ return ret;
+}
+} // namespace
+
+BOOST_AUTO_TEST_CASE(script_build)
+{
+ const KeyData keys;
+
+ std::vector<TestBuilder> tests;
+
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "P2PK", 0
+ ).PushSig(keys.key0));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "P2PK, bad sig", 0
+ ).PushSig(keys.key0).DamagePush(10).ScriptError(SCRIPT_ERR_EVAL_FALSE));
+
+ tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey1C.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG,
+ "P2PKH", 0
+ ).PushSig(keys.key1).Push(keys.pubkey1C));
+ tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey2C.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG,
+ "P2PKH, bad pubkey", 0
+ ).PushSig(keys.key2).Push(keys.pubkey2C).DamagePush(5).ScriptError(SCRIPT_ERR_EQUALVERIFY));
+
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
+ "P2PK anyonecanpay", 0
+ ).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_ANYONECANPAY));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
+ "P2PK anyonecanpay marked with normal hashtype", 0
+ ).PushSig(keys.key1, SIGHASH_ALL | SIGHASH_ANYONECANPAY).EditPush(70, "81", "01").ScriptError(SCRIPT_ERR_EVAL_FALSE));
+
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG,
+ "P2SH(P2PK)", SCRIPT_VERIFY_P2SH, true
+ ).PushSig(keys.key0).PushRedeem());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG,
+ "P2SH(P2PK), bad redeemscript", SCRIPT_VERIFY_P2SH, true
+ ).PushSig(keys.key0).PushRedeem().DamagePush(10).ScriptError(SCRIPT_ERR_EVAL_FALSE));
+
+ tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey0.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG,
+ "P2SH(P2PKH)", SCRIPT_VERIFY_P2SH, true
+ ).PushSig(keys.key0).Push(keys.pubkey0).PushRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey1.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG,
+ "P2SH(P2PKH), bad sig but no VERIFY_P2SH", 0, true
+ ).PushSig(keys.key0).DamagePush(10).PushRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey1.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG,
+ "P2SH(P2PKH), bad sig", SCRIPT_VERIFY_P2SH, true
+ ).PushSig(keys.key0).DamagePush(10).PushRedeem().ScriptError(SCRIPT_ERR_EQUALVERIFY));
+
+ tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG,
+ "3-of-3", 0
+ ).Num(0).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2));
+ tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG,
+ "3-of-3, 2 sigs", 0
+ ).Num(0).PushSig(keys.key0).PushSig(keys.key1).Num(0).ScriptError(SCRIPT_ERR_EVAL_FALSE));
+
+ tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG,
+ "P2SH(2-of-3)", SCRIPT_VERIFY_P2SH, true
+ ).Num(0).PushSig(keys.key1).PushSig(keys.key2).PushRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG,
+ "P2SH(2-of-3), 1 sig", SCRIPT_VERIFY_P2SH, true
+ ).Num(0).PushSig(keys.key1).Num(0).PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
+
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
+ "P2PK with too much R padding but no DERSIG", 0
+ ).PushSig(keys.key1, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000"));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
+ "P2PK with too much R padding", SCRIPT_VERIFY_DERSIG
+ ).PushSig(keys.key1, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").ScriptError(SCRIPT_ERR_SIG_DER));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
+ "P2PK with too much S padding but no DERSIG", 0
+ ).PushSig(keys.key1, SIGHASH_ALL).EditPush(1, "44", "45").EditPush(37, "20", "2100"));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
+ "P2PK with too much S padding", SCRIPT_VERIFY_DERSIG
+ ).PushSig(keys.key1, SIGHASH_ALL).EditPush(1, "44", "45").EditPush(37, "20", "2100").ScriptError(SCRIPT_ERR_SIG_DER));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
+ "P2PK with too little R padding but no DERSIG", 0
+ ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
+ "P2PK with too little R padding", SCRIPT_VERIFY_DERSIG
+ ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_SIG_DER));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG << OP_NOT,
+ "P2PK NOT with bad sig with too much R padding but no DERSIG", 0
+ ).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").DamagePush(10));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG << OP_NOT,
+ "P2PK NOT with bad sig with too much R padding", SCRIPT_VERIFY_DERSIG
+ ).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").DamagePush(10).ScriptError(SCRIPT_ERR_SIG_DER));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG << OP_NOT,
+ "P2PK NOT with too much R padding but no DERSIG", 0
+ ).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG << OP_NOT,
+ "P2PK NOT with too much R padding", SCRIPT_VERIFY_DERSIG
+ ).PushSig(keys.key2, SIGHASH_ALL, 31, 32).EditPush(1, "43021F", "44022000").ScriptError(SCRIPT_ERR_SIG_DER));
+
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
+ "BIP66 example 1, without DERSIG", 0
+ ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
+ "BIP66 example 1, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_SIG_DER));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT,
+ "BIP66 example 2, without DERSIG", 0
+ ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT,
+ "BIP66 example 2, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_SIG_DER));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
+ "BIP66 example 3, without DERSIG", 0
+ ).Num(0).ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
+ "BIP66 example 3, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(0).ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT,
+ "BIP66 example 4, without DERSIG", 0
+ ).Num(0));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT,
+ "BIP66 example 4, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(0));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
+ "BIP66 example 5, without DERSIG", 0
+ ).Num(1).ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG,
+ "BIP66 example 5, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(1).ScriptError(SCRIPT_ERR_SIG_DER));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT,
+ "BIP66 example 6, without DERSIG", 0
+ ).Num(1));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1C) << OP_CHECKSIG << OP_NOT,
+ "BIP66 example 6, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(1).ScriptError(SCRIPT_ERR_SIG_DER));
+ tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG,
+ "BIP66 example 7, without DERSIG", 0
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2));
+ tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG,
+ "BIP66 example 7, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2).ScriptError(SCRIPT_ERR_SIG_DER));
+ tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT,
+ "BIP66 example 8, without DERSIG", 0
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2).ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT,
+ "BIP66 example 8, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").PushSig(keys.key2).ScriptError(SCRIPT_ERR_SIG_DER));
+ tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG,
+ "BIP66 example 9, without DERSIG", 0
+ ).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG,
+ "BIP66 example 9, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_SIG_DER));
+ tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT,
+ "BIP66 example 10, without DERSIG", 0
+ ).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220"));
+ tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT,
+ "BIP66 example 10, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(0).Num(0).PushSig(keys.key2, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").ScriptError(SCRIPT_ERR_SIG_DER));
+ tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG,
+ "BIP66 example 11, without DERSIG", 0
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0).ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG,
+ "BIP66 example 11, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0).ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT,
+ "BIP66 example 12, without DERSIG", 0
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0));
+ tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_2 << OP_CHECKMULTISIG << OP_NOT,
+ "BIP66 example 12, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL, 33, 32).EditPush(1, "45022100", "440220").Num(0));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
+ "P2PK with multi-byte hashtype, without DERSIG", 0
+ ).PushSig(keys.key2, SIGHASH_ALL).EditPush(70, "01", "0101"));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
+ "P2PK with multi-byte hashtype, with DERSIG", SCRIPT_VERIFY_DERSIG
+ ).PushSig(keys.key2, SIGHASH_ALL).EditPush(70, "01", "0101").ScriptError(SCRIPT_ERR_SIG_DER));
+
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
+ "P2PK with high S but no LOW_S", 0
+ ).PushSig(keys.key2, SIGHASH_ALL, 32, 33));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
+ "P2PK with high S", SCRIPT_VERIFY_LOW_S
+ ).PushSig(keys.key2, SIGHASH_ALL, 32, 33).ScriptError(SCRIPT_ERR_SIG_HIGH_S));
+
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG,
+ "P2PK with hybrid pubkey but no STRICTENC", 0
+ ).PushSig(keys.key0, SIGHASH_ALL));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG,
+ "P2PK with hybrid pubkey", SCRIPT_VERIFY_STRICTENC
+ ).PushSig(keys.key0, SIGHASH_ALL).ScriptError(SCRIPT_ERR_PUBKEYTYPE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT,
+ "P2PK NOT with hybrid pubkey but no STRICTENC", 0
+ ).PushSig(keys.key0, SIGHASH_ALL).ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT,
+ "P2PK NOT with hybrid pubkey", SCRIPT_VERIFY_STRICTENC
+ ).PushSig(keys.key0, SIGHASH_ALL).ScriptError(SCRIPT_ERR_PUBKEYTYPE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT,
+ "P2PK NOT with invalid hybrid pubkey but no STRICTENC", 0
+ ).PushSig(keys.key0, SIGHASH_ALL).DamagePush(10));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0H) << OP_CHECKSIG << OP_NOT,
+ "P2PK NOT with invalid hybrid pubkey", SCRIPT_VERIFY_STRICTENC
+ ).PushSig(keys.key0, SIGHASH_ALL).DamagePush(10).ScriptError(SCRIPT_ERR_PUBKEYTYPE));
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey0H) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG,
+ "1-of-2 with the second 1 hybrid pubkey and no STRICTENC", 0
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL));
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey0H) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG,
+ "1-of-2 with the second 1 hybrid pubkey", SCRIPT_VERIFY_STRICTENC
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL));
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0H) << OP_2 << OP_CHECKMULTISIG,
+ "1-of-2 with the first 1 hybrid pubkey", SCRIPT_VERIFY_STRICTENC
+ ).Num(0).PushSig(keys.key1, SIGHASH_ALL).ScriptError(SCRIPT_ERR_PUBKEYTYPE));
+
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
+ "P2PK with undefined hashtype but no STRICTENC", 0
+ ).PushSig(keys.key1, 5));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
+ "P2PK with undefined hashtype", SCRIPT_VERIFY_STRICTENC
+ ).PushSig(keys.key1, 5).ScriptError(SCRIPT_ERR_SIG_HASHTYPE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG << OP_NOT,
+ "P2PK NOT with invalid sig and undefined hashtype but no STRICTENC", 0
+ ).PushSig(keys.key1, 5).DamagePush(10));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG << OP_NOT,
+ "P2PK NOT with invalid sig and undefined hashtype", SCRIPT_VERIFY_STRICTENC
+ ).PushSig(keys.key1, 5).DamagePush(10).ScriptError(SCRIPT_ERR_SIG_HASHTYPE));
+
+ tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG,
+ "3-of-3 with nonzero dummy but no NULLDUMMY", 0
+ ).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2));
+ tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG,
+ "3-of-3 with nonzero dummy", SCRIPT_VERIFY_NULLDUMMY
+ ).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2).ScriptError(SCRIPT_ERR_SIG_NULLDUMMY));
+ tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG << OP_NOT,
+ "3-of-3 NOT with invalid sig and nonzero dummy but no NULLDUMMY", 0
+ ).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2).DamagePush(10));
+ tests.push_back(TestBuilder(CScript() << OP_3 << ToByteVector(keys.pubkey0C) << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey2C) << OP_3 << OP_CHECKMULTISIG << OP_NOT,
+ "3-of-3 NOT with invalid sig with nonzero dummy", SCRIPT_VERIFY_NULLDUMMY
+ ).Num(1).PushSig(keys.key0).PushSig(keys.key1).PushSig(keys.key2).DamagePush(10).ScriptError(SCRIPT_ERR_SIG_NULLDUMMY));
+
+ tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG,
+ "2-of-2 with two identical keys and sigs pushed using OP_DUP but no SIGPUSHONLY", 0
+ ).Num(0).PushSig(keys.key1).Add(CScript() << OP_DUP));
+ tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG,
+ "2-of-2 with two identical keys and sigs pushed using OP_DUP", SCRIPT_VERIFY_SIGPUSHONLY
+ ).Num(0).PushSig(keys.key1).Add(CScript() << OP_DUP).ScriptError(SCRIPT_ERR_SIG_PUSHONLY));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
+ "P2SH(P2PK) with non-push scriptSig but no P2SH or SIGPUSHONLY", 0, true
+ ).PushSig(keys.key2).Add(CScript() << OP_NOP8).PushRedeem());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
+ "P2PK with non-push scriptSig but with P2SH validation", 0
+ ).PushSig(keys.key2).Add(CScript() << OP_NOP8));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
+ "P2SH(P2PK) with non-push scriptSig but no SIGPUSHONLY", SCRIPT_VERIFY_P2SH, true
+ ).PushSig(keys.key2).Add(CScript() << OP_NOP8).PushRedeem().ScriptError(SCRIPT_ERR_SIG_PUSHONLY));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey2C) << OP_CHECKSIG,
+ "P2SH(P2PK) with non-push scriptSig but not P2SH", SCRIPT_VERIFY_SIGPUSHONLY, true
+ ).PushSig(keys.key2).Add(CScript() << OP_NOP8).PushRedeem().ScriptError(SCRIPT_ERR_SIG_PUSHONLY));
+ tests.push_back(TestBuilder(CScript() << OP_2 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey1C) << OP_2 << OP_CHECKMULTISIG,
+ "2-of-2 with two identical keys and sigs pushed", SCRIPT_VERIFY_SIGPUSHONLY
+ ).Num(0).PushSig(keys.key1).PushSig(keys.key1));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "P2PK with unnecessary input but no CLEANSTACK", SCRIPT_VERIFY_P2SH
+ ).Num(11).PushSig(keys.key0));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "P2PK with unnecessary input", SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH
+ ).Num(11).PushSig(keys.key0).ScriptError(SCRIPT_ERR_CLEANSTACK));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "P2SH with unnecessary input but no CLEANSTACK", SCRIPT_VERIFY_P2SH, true
+ ).Num(11).PushSig(keys.key0).PushRedeem());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "P2SH with unnecessary input", SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH, true
+ ).Num(11).PushSig(keys.key0).PushRedeem().ScriptError(SCRIPT_ERR_CLEANSTACK));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "P2SH with CLEANSTACK", SCRIPT_VERIFY_CLEANSTACK | SCRIPT_VERIFY_P2SH, true
+ ).PushSig(keys.key0).PushRedeem());
+
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "Basic P2WSH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::SH,
+ 0, 1).PushWitSig(keys.key0).PushWitRedeem());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
+ "Basic P2WPKH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::PKH,
+ 0, 1).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "Basic P2SH(P2WSH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WitnessMode::SH,
+ 0, 1).PushWitSig(keys.key0).PushWitRedeem().PushRedeem());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
+ "Basic P2SH(P2WPKH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WitnessMode::PKH,
+ 0, 1).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().PushRedeem());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
+ "Basic P2WSH with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::SH
+ ).PushWitSig(keys.key0).PushWitRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1),
+ "Basic P2WPKH with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::PKH
+ ).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit().ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
+ "Basic P2SH(P2WSH) with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WitnessMode::SH
+ ).PushWitSig(keys.key0).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1),
+ "Basic P2SH(P2WPKH) with the wrong key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WitnessMode::PKH
+ ).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit().PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
+ "Basic P2WSH with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, false, WitnessMode::SH
+ ).PushWitSig(keys.key0).PushWitRedeem());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1),
+ "Basic P2WPKH with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, false, WitnessMode::PKH
+ ).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1) << OP_CHECKSIG,
+ "Basic P2SH(P2WSH) with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, true, WitnessMode::SH
+ ).PushWitSig(keys.key0).PushWitRedeem().PushRedeem());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1),
+ "Basic P2SH(P2WPKH) with the wrong key but no WITNESS", SCRIPT_VERIFY_P2SH, true, WitnessMode::PKH
+ ).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit().PushRedeem());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "Basic P2WSH with wrong value", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::SH,
+ 0, 0).PushWitSig(keys.key0, 1).PushWitRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
+ "Basic P2WPKH with wrong value", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::PKH,
+ 0, 0).PushWitSig(keys.key0, 1).Push(keys.pubkey0).AsWit().ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "Basic P2SH(P2WSH) with wrong value", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WitnessMode::SH,
+ 0, 0).PushWitSig(keys.key0, 1).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
+ "Basic P2SH(P2WPKH) with wrong value", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WitnessMode::PKH,
+ 0, 0).PushWitSig(keys.key0, 1).Push(keys.pubkey0).AsWit().PushRedeem().ScriptError(SCRIPT_ERR_EVAL_FALSE));
+
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
+ "P2WPKH with future witness version", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH |
+ SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM, false, WitnessMode::PKH, 1
+ ).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().ScriptError(SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM));
+ {
+ CScript witscript = CScript() << ToByteVector(keys.pubkey0);
+ uint256 hash;
+ CSHA256().Write(&witscript[0], witscript.size()).Finalize(hash.begin());
+ std::vector<unsigned char> hashBytes = ToByteVector(hash);
+ hashBytes.pop_back();
+ tests.push_back(TestBuilder(CScript() << OP_0 << hashBytes,
+ "P2WPKH with wrong witness program length", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false
+ ).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().ScriptError(SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH));
+ }
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "P2WSH with empty witness", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::SH
+ ).ScriptError(SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY));
+ {
+ CScript witscript = CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG;
+ tests.push_back(TestBuilder(witscript,
+ "P2WSH with witness program mismatch", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::SH
+ ).PushWitSig(keys.key0).Push(witscript).DamagePush(0).AsWit().ScriptError(SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH));
+ }
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
+ "P2WPKH with witness program mismatch", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::PKH
+ ).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().Push("0").AsWit().ScriptError(SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
+ "P2WPKH with non-empty scriptSig", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::PKH
+ ).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().Num(11).ScriptError(SCRIPT_ERR_WITNESS_MALLEATED));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey1),
+ "P2SH(P2WPKH) with superfluous push in scriptSig", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WitnessMode::PKH
+ ).PushWitSig(keys.key0).Push(keys.pubkey1).AsWit().Num(11).PushRedeem().ScriptError(SCRIPT_ERR_WITNESS_MALLEATED_P2SH));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "P2PK with witness", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH
+ ).PushSig(keys.key0).Push("0").AsWit().ScriptError(SCRIPT_ERR_WITNESS_UNEXPECTED));
+
+ // Compressed keys should pass SCRIPT_VERIFY_WITNESS_PUBKEYTYPE
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG,
+ "Basic P2WSH with compressed key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WitnessMode::SH,
+ 0, 1).PushWitSig(keys.key0C).PushWitRedeem());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C),
+ "Basic P2WPKH with compressed key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WitnessMode::PKH,
+ 0, 1).PushWitSig(keys.key0C).Push(keys.pubkey0C).AsWit());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG,
+ "Basic P2SH(P2WSH) with compressed key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WitnessMode::SH,
+ 0, 1).PushWitSig(keys.key0C).PushWitRedeem().PushRedeem());
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C),
+ "Basic P2SH(P2WPKH) with compressed key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WitnessMode::PKH,
+ 0, 1).PushWitSig(keys.key0C).Push(keys.pubkey0C).AsWit().PushRedeem());
+
+ // Testing uncompressed key in witness with SCRIPT_VERIFY_WITNESS_PUBKEYTYPE
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "Basic P2WSH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WitnessMode::SH,
+ 0, 1).PushWitSig(keys.key0).PushWitRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
+ "Basic P2WPKH", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WitnessMode::PKH,
+ 0, 1).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG,
+ "Basic P2SH(P2WSH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WitnessMode::SH,
+ 0, 1).PushWitSig(keys.key0).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
+ tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0),
+ "Basic P2SH(P2WPKH)", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WitnessMode::PKH,
+ 0, 1).PushWitSig(keys.key0).Push(keys.pubkey0).AsWit().PushRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
+
+ // P2WSH 1-of-2 multisig with compressed keys
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
+ "P2WSH CHECKMULTISIG with compressed keys", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WitnessMode::SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0C).PushWitRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
+ "P2SH(P2WSH) CHECKMULTISIG with compressed keys", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WitnessMode::SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0C).PushWitRedeem().PushRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
+ "P2WSH CHECKMULTISIG with compressed keys", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WitnessMode::SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1C).PushWitRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
+ "P2SH(P2WSH) CHECKMULTISIG with compressed keys", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WitnessMode::SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1C).PushWitRedeem().PushRedeem());
+
+ // P2WSH 1-of-2 multisig with first key uncompressed
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG,
+ "P2WSH CHECKMULTISIG with first key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0).PushWitRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG,
+ "P2SH(P2WSH) CHECKMULTISIG first key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WitnessMode::SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0).PushWitRedeem().PushRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG,
+ "P2WSH CHECKMULTISIG with first key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WitnessMode::SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0).PushWitRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG,
+ "P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WitnessMode::SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG,
+ "P2WSH CHECKMULTISIG with first key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1C).PushWitRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG,
+ "P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WitnessMode::SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1C).PushWitRedeem().PushRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG,
+ "P2WSH CHECKMULTISIG with first key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WitnessMode::SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1C).PushWitRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1C) << ToByteVector(keys.pubkey0) << OP_2 << OP_CHECKMULTISIG,
+ "P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WitnessMode::SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1C).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
+ // P2WSH 1-of-2 multisig with second key uncompressed
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
+ "P2WSH CHECKMULTISIG with second key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0C).PushWitRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
+ "P2SH(P2WSH) CHECKMULTISIG second key uncompressed and signing with the first key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WitnessMode::SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0C).PushWitRedeem().PushRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
+ "P2WSH CHECKMULTISIG with second key uncompressed and signing with the first key should pass as the uncompressed key is not used", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WitnessMode::SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0C).PushWitRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
+ "P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the first key should pass as the uncompressed key is not used", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WitnessMode::SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key0C).PushWitRedeem().PushRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
+ "P2WSH CHECKMULTISIG with second key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false, WitnessMode::SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1).PushWitRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
+ "P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true, WitnessMode::SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1).PushWitRedeem().PushRedeem());
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
+ "P2WSH CHECKMULTISIG with second key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, false, WitnessMode::SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1).PushWitRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
+ tests.push_back(TestBuilder(CScript() << OP_1 << ToByteVector(keys.pubkey1) << ToByteVector(keys.pubkey0C) << OP_2 << OP_CHECKMULTISIG,
+ "P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the second key", SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, true, WitnessMode::SH,
+ 0, 1).Push(CScript()).AsWit().PushWitSig(keys.key1).PushWitRedeem().PushRedeem().ScriptError(SCRIPT_ERR_WITNESS_PUBKEYTYPE));
+
+ std::set<std::string> tests_set;
+
+ {
+ UniValue json_tests = read_json(std::string(json_tests::script_tests, json_tests::script_tests + sizeof(json_tests::script_tests)));
+
+ for (unsigned int idx = 0; idx < json_tests.size(); idx++) {
+ const UniValue& tv = json_tests[idx];
+ tests_set.insert(JSONPrettyPrint(tv.get_array()));
+ }
+ }
+
+ std::string strGen;
+
+ for (TestBuilder& test : tests) {
+ test.Test();
+ std::string str = JSONPrettyPrint(test.GetJSON());
+#ifndef UPDATE_JSON_TESTS
+ if (tests_set.count(str) == 0) {
+ BOOST_CHECK_MESSAGE(false, "Missing auto script_valid test: " + test.GetComment());
+ }
+#endif
+ strGen += str + ",\n";
+ }
+
+#ifdef UPDATE_JSON_TESTS
+ FILE* file = fopen("script_tests.json.gen", "w");
+ fputs(strGen.c_str(), file);
+ fclose(file);
+#endif
+}
+
+BOOST_AUTO_TEST_CASE(script_json_test)
+{
+ // Read tests from test/data/script_tests.json
+ // Format is an array of arrays
+ // Inner arrays are [ ["wit"..., nValue]?, "scriptSig", "scriptPubKey", "flags", "expected_scripterror" ]
+ // ... where scriptSig and scriptPubKey are stringified
+ // scripts.
+ // If a witness is given, then the last value in the array should be the
+ // amount (nValue) to use in the crediting tx
+ UniValue tests = read_json(std::string(json_tests::script_tests, json_tests::script_tests + sizeof(json_tests::script_tests)));
+
+ for (unsigned int idx = 0; idx < tests.size(); idx++) {
+ UniValue test = tests[idx];
+ std::string strTest = test.write();
+ CScriptWitness witness;
+ CAmount nValue = 0;
+ unsigned int pos = 0;
+ if (test.size() > 0 && test[pos].isArray()) {
+ unsigned int i=0;
+ for (i = 0; i < test[pos].size()-1; i++) {
+ witness.stack.push_back(ParseHex(test[pos][i].get_str()));
+ }
+ nValue = AmountFromValue(test[pos][i]);
+ pos++;
+ }
+ if (test.size() < 4 + pos) // Allow size > 3; extra stuff ignored (useful for comments)
+ {
+ if (test.size() != 1) {
+ BOOST_ERROR("Bad test: " << strTest);
+ }
+ continue;
+ }
+ std::string scriptSigString = test[pos++].get_str();
+ CScript scriptSig = ParseScript(scriptSigString);
+ std::string scriptPubKeyString = test[pos++].get_str();
+ CScript scriptPubKey = ParseScript(scriptPubKeyString);
+ unsigned int scriptflags = ParseScriptFlags(test[pos++].get_str());
+ int scriptError = ParseScriptError(test[pos++].get_str());
+
+ DoTest(scriptPubKey, scriptSig, witness, scriptflags, strTest, scriptError, nValue);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(script_PushData)
+{
+ // Check that PUSHDATA1, PUSHDATA2, and PUSHDATA4 create the same value on
+ // the stack as the 1-75 opcodes do.
+ static const unsigned char direct[] = { 1, 0x5a };
+ static const unsigned char pushdata1[] = { OP_PUSHDATA1, 1, 0x5a };
+ static const unsigned char pushdata2[] = { OP_PUSHDATA2, 1, 0, 0x5a };
+ static const unsigned char pushdata4[] = { OP_PUSHDATA4, 1, 0, 0, 0, 0x5a };
+
+ ScriptError err;
+ std::vector<std::vector<unsigned char> > directStack;
+ BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
+
+ std::vector<std::vector<unsigned char> > pushdata1Stack;
+ BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
+ BOOST_CHECK(pushdata1Stack == directStack);
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
+
+ std::vector<std::vector<unsigned char> > pushdata2Stack;
+ BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
+ BOOST_CHECK(pushdata2Stack == directStack);
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
+
+ std::vector<std::vector<unsigned char> > pushdata4Stack;
+ BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SigVersion::BASE, &err));
+ BOOST_CHECK(pushdata4Stack == directStack);
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
+}
+
+static CScript
+sign_multisig(const CScript& scriptPubKey, const std::vector<CKey>& keys, const CTransaction& transaction)
+{
+ uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL, 0, SigVersion::BASE);
+
+ CScript result;
+ //
+ // NOTE: CHECKMULTISIG has an unfortunate bug; it requires
+ // one extra item on the stack, before the signatures.
+ // Putting OP_0 on the stack is the workaround;
+ // fixing the bug would mean splitting the block chain (old
+ // clients would not accept new CHECKMULTISIG transactions,
+ // and vice-versa)
+ //
+ result << OP_0;
+ for (const CKey &key : keys)
+ {
+ std::vector<unsigned char> vchSig;
+ BOOST_CHECK(key.Sign(hash, vchSig));
+ vchSig.push_back((unsigned char)SIGHASH_ALL);
+ result << vchSig;
+ }
+ return result;
+}
+static CScript
+sign_multisig(const CScript& scriptPubKey, const CKey& key, const CTransaction& transaction)
+{
+ std::vector<CKey> keys;
+ keys.push_back(key);
+ return sign_multisig(scriptPubKey, keys, transaction);
+}
+
+BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12)
+{
+ ScriptError err;
+ CKey key1, key2, key3;
+ key1.MakeNewKey(true);
+ key2.MakeNewKey(false);
+ key3.MakeNewKey(true);
+
+ CScript scriptPubKey12;
+ scriptPubKey12 << OP_1 << ToByteVector(key1.GetPubKey()) << ToByteVector(key2.GetPubKey()) << OP_2 << OP_CHECKMULTISIG;
+
+ const CTransaction txFrom12{BuildCreditingTransaction(scriptPubKey12)};
+ CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), CScriptWitness(), txFrom12);
+
+ CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12);
+ BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
+ txTo12.vout[0].nValue = 2;
+ BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
+
+ CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12);
+ BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
+
+ CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12);
+ BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
+}
+
+BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
+{
+ ScriptError err;
+ CKey key1, key2, key3, key4;
+ key1.MakeNewKey(true);
+ key2.MakeNewKey(false);
+ key3.MakeNewKey(true);
+ key4.MakeNewKey(false);
+
+ CScript scriptPubKey23;
+ scriptPubKey23 << OP_2 << ToByteVector(key1.GetPubKey()) << ToByteVector(key2.GetPubKey()) << ToByteVector(key3.GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
+
+ const CTransaction txFrom23{BuildCreditingTransaction(scriptPubKey23)};
+ CMutableTransaction txTo23 = BuildSpendingTransaction(CScript(), CScriptWitness(), txFrom23);
+
+ std::vector<CKey> keys;
+ keys.push_back(key1); keys.push_back(key2);
+ CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
+ BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
+
+ keys.clear();
+ keys.push_back(key1); keys.push_back(key3);
+ CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
+ BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
+
+ keys.clear();
+ keys.push_back(key2); keys.push_back(key3);
+ CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
+ BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
+
+ keys.clear();
+ keys.push_back(key2); keys.push_back(key2); // Can't re-use sig
+ CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
+ BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
+
+ keys.clear();
+ keys.push_back(key2); keys.push_back(key1); // sigs must be in correct order
+ CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
+ BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
+
+ keys.clear();
+ keys.push_back(key3); keys.push_back(key2); // sigs must be in correct order
+ CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
+ BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
+
+ keys.clear();
+ keys.push_back(key4); keys.push_back(key2); // sigs must match pubkeys
+ CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23);
+ BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
+
+ keys.clear();
+ keys.push_back(key1); keys.push_back(key4); // sigs must match pubkeys
+ CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23);
+ BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
+
+ keys.clear(); // Must have signatures
+ CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23);
+ BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, nullptr, gFlags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
+}
+
+/* Wrapper around ProduceSignature to combine two scriptsigs */
+SignatureData CombineSignatures(const CTxOut& txout, const CMutableTransaction& tx, const SignatureData& scriptSig1, const SignatureData& scriptSig2)
+{
+ SignatureData data;
+ data.MergeSignatureData(scriptSig1);
+ data.MergeSignatureData(scriptSig2);
+ ProduceSignature(DUMMY_SIGNING_PROVIDER, MutableTransactionSignatureCreator(&tx, 0, txout.nValue), txout.scriptPubKey, data);
+ return data;
+}
+
+BOOST_AUTO_TEST_CASE(script_combineSigs)
+{
+ // Test the ProduceSignature's ability to combine signatures function
+ CBasicKeyStore keystore;
+ std::vector<CKey> keys;
+ std::vector<CPubKey> pubkeys;
+ for (int i = 0; i < 3; i++)
+ {
+ CKey key;
+ key.MakeNewKey(i%2 == 1);
+ keys.push_back(key);
+ pubkeys.push_back(key.GetPubKey());
+ keystore.AddKey(key);
+ }
+
+ CMutableTransaction txFrom = BuildCreditingTransaction(GetScriptForDestination(keys[0].GetPubKey().GetID()));
+ CMutableTransaction txTo = BuildSpendingTransaction(CScript(), CScriptWitness(), txFrom);
+ CScript& scriptPubKey = txFrom.vout[0].scriptPubKey;
+ SignatureData scriptSig;
+
+ SignatureData empty;
+ SignatureData combined = CombineSignatures(txFrom.vout[0], txTo, empty, empty);
+ BOOST_CHECK(combined.scriptSig.empty());
+
+ // Single signature case:
+ SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); // changes scriptSig
+ scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]);
+ combined = CombineSignatures(txFrom.vout[0], txTo, scriptSig, empty);
+ BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig);
+ combined = CombineSignatures(txFrom.vout[0], txTo, empty, scriptSig);
+ BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig);
+ SignatureData scriptSigCopy = scriptSig;
+ // Signing again will give a different, valid signature:
+ SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL);
+ scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]);
+ combined = CombineSignatures(txFrom.vout[0], txTo, scriptSigCopy, scriptSig);
+ BOOST_CHECK(combined.scriptSig == scriptSigCopy.scriptSig || combined.scriptSig == scriptSig.scriptSig);
+
+ // P2SH, single-signature case:
+ CScript pkSingle; pkSingle << ToByteVector(keys[0].GetPubKey()) << OP_CHECKSIG;
+ keystore.AddCScript(pkSingle);
+ scriptPubKey = GetScriptForDestination(CScriptID(pkSingle));
+ SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL);
+ scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]);
+ combined = CombineSignatures(txFrom.vout[0], txTo, scriptSig, empty);
+ BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig);
+ combined = CombineSignatures(txFrom.vout[0], txTo, empty, scriptSig);
+ BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig);
+ scriptSigCopy = scriptSig;
+ SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL);
+ scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]);
+ combined = CombineSignatures(txFrom.vout[0], txTo, scriptSigCopy, scriptSig);
+ BOOST_CHECK(combined.scriptSig == scriptSigCopy.scriptSig || combined.scriptSig == scriptSig.scriptSig);
+
+ // Hardest case: Multisig 2-of-3
+ scriptPubKey = GetScriptForMultisig(2, pubkeys);
+ keystore.AddCScript(scriptPubKey);
+ SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL);
+ scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]);
+ combined = CombineSignatures(txFrom.vout[0], txTo, scriptSig, empty);
+ BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig);
+ combined = CombineSignatures(txFrom.vout[0], txTo, empty, scriptSig);
+ BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig);
+
+ // A couple of partially-signed versions:
+ std::vector<unsigned char> sig1;
+ uint256 hash1 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_ALL, 0, SigVersion::BASE);
+ BOOST_CHECK(keys[0].Sign(hash1, sig1));
+ sig1.push_back(SIGHASH_ALL);
+ std::vector<unsigned char> sig2;
+ uint256 hash2 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_NONE, 0, SigVersion::BASE);
+ BOOST_CHECK(keys[1].Sign(hash2, sig2));
+ sig2.push_back(SIGHASH_NONE);
+ std::vector<unsigned char> sig3;
+ uint256 hash3 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_SINGLE, 0, SigVersion::BASE);
+ 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;
+ SignatureData partial1_sigs;
+ partial1_sigs.signatures.emplace(keys[0].GetPubKey().GetID(), SigPair(keys[0].GetPubKey(), sig1));
+ SignatureData partial2_sigs;
+ partial2_sigs.signatures.emplace(keys[1].GetPubKey().GetID(), SigPair(keys[1].GetPubKey(), sig2));
+ SignatureData partial3_sigs;
+ partial3_sigs.signatures.emplace(keys[2].GetPubKey().GetID(), SigPair(keys[2].GetPubKey(), sig3));
+
+ combined = CombineSignatures(txFrom.vout[0], txTo, partial1_sigs, partial1_sigs);
+ BOOST_CHECK(combined.scriptSig == partial1a);
+ combined = CombineSignatures(txFrom.vout[0], txTo, partial1_sigs, partial2_sigs);
+ BOOST_CHECK(combined.scriptSig == complete12);
+ combined = CombineSignatures(txFrom.vout[0], txTo, partial2_sigs, partial1_sigs);
+ BOOST_CHECK(combined.scriptSig == complete12);
+ combined = CombineSignatures(txFrom.vout[0], txTo, partial1_sigs, partial2_sigs);
+ BOOST_CHECK(combined.scriptSig == complete12);
+ combined = CombineSignatures(txFrom.vout[0], txTo, partial3_sigs, partial1_sigs);
+ BOOST_CHECK(combined.scriptSig == complete13);
+ combined = CombineSignatures(txFrom.vout[0], txTo, partial2_sigs, partial3_sigs);
+ BOOST_CHECK(combined.scriptSig == complete23);
+ combined = CombineSignatures(txFrom.vout[0], txTo, partial3_sigs, partial2_sigs);
+ BOOST_CHECK(combined.scriptSig == complete23);
+ combined = CombineSignatures(txFrom.vout[0], txTo, partial3_sigs, partial3_sigs);
+ BOOST_CHECK(combined.scriptSig == partial3c);
+}
+
+BOOST_AUTO_TEST_CASE(script_standard_push)
+{
+ ScriptError err;
+ for (int i=0; i<67000; i++) {
+ CScript script;
+ script << i;
+ BOOST_CHECK_MESSAGE(script.IsPushOnly(), "Number " << i << " is not pure push.");
+ BOOST_CHECK_MESSAGE(VerifyScript(script, CScript() << OP_1, nullptr, SCRIPT_VERIFY_MINIMALDATA, BaseSignatureChecker(), &err), "Number " << i << " push is not minimal data.");
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
+ }
+
+ for (unsigned int i=0; i<=MAX_SCRIPT_ELEMENT_SIZE; i++) {
+ std::vector<unsigned char> data(i, '\111');
+ CScript script;
+ script << data;
+ BOOST_CHECK_MESSAGE(script.IsPushOnly(), "Length " << i << " is not pure push.");
+ BOOST_CHECK_MESSAGE(VerifyScript(script, CScript() << OP_1, nullptr, SCRIPT_VERIFY_MINIMALDATA, BaseSignatureChecker(), &err), "Length " << i << " push is not minimal data.");
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
+ }
+}
+
+BOOST_AUTO_TEST_CASE(script_IsPushOnly_on_invalid_scripts)
+{
+ // IsPushOnly returns false when given a script containing only pushes that
+ // are invalid due to truncation. IsPushOnly() is consensus critical
+ // because P2SH evaluation uses it, although this specific behavior should
+ // not be consensus critical as the P2SH evaluation would fail first due to
+ // the invalid push. Still, it doesn't hurt to test it explicitly.
+ static const unsigned char direct[] = { 1 };
+ BOOST_CHECK(!CScript(direct, direct+sizeof(direct)).IsPushOnly());
+}
+
+BOOST_AUTO_TEST_CASE(script_GetScriptAsm)
+{
+ BOOST_CHECK_EQUAL("OP_CHECKLOCKTIMEVERIFY", ScriptToAsmStr(CScript() << OP_NOP2, true));
+ BOOST_CHECK_EQUAL("OP_CHECKLOCKTIMEVERIFY", ScriptToAsmStr(CScript() << OP_CHECKLOCKTIMEVERIFY, true));
+ BOOST_CHECK_EQUAL("OP_CHECKLOCKTIMEVERIFY", ScriptToAsmStr(CScript() << OP_NOP2));
+ BOOST_CHECK_EQUAL("OP_CHECKLOCKTIMEVERIFY", ScriptToAsmStr(CScript() << OP_CHECKLOCKTIMEVERIFY));
+
+ std::string derSig("304502207fa7a6d1e0ee81132a269ad84e68d695483745cde8b541e3bf630749894e342a022100c1f7ab20e13e22fb95281a870f3dcf38d782e53023ee313d741ad0cfbc0c5090");
+ std::string pubKey("03b0da749730dc9b4b1f4a14d6902877a92541f5368778853d9c4a0cb7802dcfb2");
+ std::vector<unsigned char> vchPubKey = ToByteVector(ParseHex(pubKey));
+
+ BOOST_CHECK_EQUAL(derSig + "00 " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "00")) << vchPubKey, true));
+ BOOST_CHECK_EQUAL(derSig + "80 " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "80")) << vchPubKey, true));
+ BOOST_CHECK_EQUAL(derSig + "[ALL] " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "01")) << vchPubKey, true));
+ BOOST_CHECK_EQUAL(derSig + "[NONE] " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "02")) << vchPubKey, true));
+ BOOST_CHECK_EQUAL(derSig + "[SINGLE] " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "03")) << vchPubKey, true));
+ BOOST_CHECK_EQUAL(derSig + "[ALL|ANYONECANPAY] " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "81")) << vchPubKey, true));
+ BOOST_CHECK_EQUAL(derSig + "[NONE|ANYONECANPAY] " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "82")) << vchPubKey, true));
+ BOOST_CHECK_EQUAL(derSig + "[SINGLE|ANYONECANPAY] " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "83")) << vchPubKey, true));
+
+ BOOST_CHECK_EQUAL(derSig + "00 " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "00")) << vchPubKey));
+ BOOST_CHECK_EQUAL(derSig + "80 " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "80")) << vchPubKey));
+ BOOST_CHECK_EQUAL(derSig + "01 " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "01")) << vchPubKey));
+ BOOST_CHECK_EQUAL(derSig + "02 " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "02")) << vchPubKey));
+ BOOST_CHECK_EQUAL(derSig + "03 " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "03")) << vchPubKey));
+ BOOST_CHECK_EQUAL(derSig + "81 " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "81")) << vchPubKey));
+ BOOST_CHECK_EQUAL(derSig + "82 " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "82")) << vchPubKey));
+ BOOST_CHECK_EQUAL(derSig + "83 " + pubKey, ScriptToAsmStr(CScript() << ToByteVector(ParseHex(derSig + "83")) << vchPubKey));
+}
+
+static CScript
+ScriptFromHex(const char* hex)
+{
+ std::vector<unsigned char> data = ParseHex(hex);
+ return CScript(data.begin(), data.end());
+}
+
+
+BOOST_AUTO_TEST_CASE(script_FindAndDelete)
+{
+ // Exercise the FindAndDelete functionality
+ CScript s;
+ CScript d;
+ CScript expect;
+
+ s = CScript() << OP_1 << OP_2;
+ d = CScript(); // delete nothing should be a no-op
+ expect = s;
+ BOOST_CHECK_EQUAL(FindAndDelete(s, d), 0);
+ BOOST_CHECK(s == expect);
+
+ s = CScript() << OP_1 << OP_2 << OP_3;
+ d = CScript() << OP_2;
+ expect = CScript() << OP_1 << OP_3;
+ BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1);
+ BOOST_CHECK(s == expect);
+
+ s = CScript() << OP_3 << OP_1 << OP_3 << OP_3 << OP_4 << OP_3;
+ d = CScript() << OP_3;
+ expect = CScript() << OP_1 << OP_4;
+ BOOST_CHECK_EQUAL(FindAndDelete(s, d), 4);
+ BOOST_CHECK(s == expect);
+
+ s = ScriptFromHex("0302ff03"); // PUSH 0x02ff03 onto stack
+ d = ScriptFromHex("0302ff03");
+ expect = CScript();
+ BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1);
+ BOOST_CHECK(s == expect);
+
+ s = ScriptFromHex("0302ff030302ff03"); // PUSH 0x2ff03 PUSH 0x2ff03
+ d = ScriptFromHex("0302ff03");
+ expect = CScript();
+ BOOST_CHECK_EQUAL(FindAndDelete(s, d), 2);
+ BOOST_CHECK(s == expect);
+
+ s = ScriptFromHex("0302ff030302ff03");
+ d = ScriptFromHex("02");
+ expect = s; // FindAndDelete matches entire opcodes
+ BOOST_CHECK_EQUAL(FindAndDelete(s, d), 0);
+ BOOST_CHECK(s == expect);
+
+ s = ScriptFromHex("0302ff030302ff03");
+ d = ScriptFromHex("ff");
+ expect = s;
+ BOOST_CHECK_EQUAL(FindAndDelete(s, d), 0);
+ BOOST_CHECK(s == expect);
+
+ // This is an odd edge case: strip of the push-three-bytes
+ // prefix, leaving 02ff03 which is push-two-bytes:
+ s = ScriptFromHex("0302ff030302ff03");
+ d = ScriptFromHex("03");
+ expect = CScript() << ParseHex("ff03") << ParseHex("ff03");
+ BOOST_CHECK_EQUAL(FindAndDelete(s, d), 2);
+ BOOST_CHECK(s == expect);
+
+ // Byte sequence that spans multiple opcodes:
+ s = ScriptFromHex("02feed5169"); // PUSH(0xfeed) OP_1 OP_VERIFY
+ d = ScriptFromHex("feed51");
+ expect = s;
+ BOOST_CHECK_EQUAL(FindAndDelete(s, d), 0); // doesn't match 'inside' opcodes
+ BOOST_CHECK(s == expect);
+
+ s = ScriptFromHex("02feed5169"); // PUSH(0xfeed) OP_1 OP_VERIFY
+ d = ScriptFromHex("02feed51");
+ expect = ScriptFromHex("69");
+ BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1);
+ BOOST_CHECK(s == expect);
+
+ s = ScriptFromHex("516902feed5169");
+ d = ScriptFromHex("feed51");
+ expect = s;
+ BOOST_CHECK_EQUAL(FindAndDelete(s, d), 0);
+ BOOST_CHECK(s == expect);
+
+ s = ScriptFromHex("516902feed5169");
+ d = ScriptFromHex("02feed51");
+ expect = ScriptFromHex("516969");
+ BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1);
+ BOOST_CHECK(s == expect);
+
+ s = CScript() << OP_0 << OP_0 << OP_1 << OP_1;
+ d = CScript() << OP_0 << OP_1;
+ expect = CScript() << OP_0 << OP_1; // FindAndDelete is single-pass
+ BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1);
+ BOOST_CHECK(s == expect);
+
+ s = CScript() << OP_0 << OP_0 << OP_1 << OP_0 << OP_1 << OP_1;
+ d = CScript() << OP_0 << OP_1;
+ expect = CScript() << OP_0 << OP_1; // FindAndDelete is single-pass
+ BOOST_CHECK_EQUAL(FindAndDelete(s, d), 2);
+ BOOST_CHECK(s == expect);
+
+ // Another weird edge case:
+ // End with invalid push (not enough data)...
+ s = ScriptFromHex("0003feed");
+ d = ScriptFromHex("03feed"); // ... can remove the invalid push
+ expect = ScriptFromHex("00");
+ BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1);
+ BOOST_CHECK(s == expect);
+
+ s = ScriptFromHex("0003feed");
+ d = ScriptFromHex("00");
+ expect = ScriptFromHex("03feed");
+ BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1);
+ BOOST_CHECK(s == expect);
+}
+
+BOOST_AUTO_TEST_CASE(script_HasValidOps)
+{
+ // Exercise the HasValidOps functionality
+ CScript script;
+ script = ScriptFromHex("76a9141234567890abcdefa1a2a3a4a5a6a7a8a9a0aaab88ac"); // Normal script
+ BOOST_CHECK(script.HasValidOps());
+ script = ScriptFromHex("76a914ff34567890abcdefa1a2a3a4a5a6a7a8a9a0aaab88ac");
+ BOOST_CHECK(script.HasValidOps());
+ script = ScriptFromHex("ff88ac"); // Script with OP_INVALIDOPCODE explicit
+ BOOST_CHECK(!script.HasValidOps());
+ script = ScriptFromHex("88acc0"); // Script with undefined opcode
+ BOOST_CHECK(!script.HasValidOps());
+}
+
+BOOST_AUTO_TEST_CASE(script_can_append_self)
+{
+ CScript s, d;
+
+ s = ScriptFromHex("00");
+ s += s;
+ d = ScriptFromHex("0000");
+ BOOST_CHECK(s == d);
+
+ // check doubling a script that's large enough to require reallocation
+ static const char hex[] = "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f";
+ s = CScript() << ParseHex(hex) << OP_CHECKSIG;
+ d = CScript() << ParseHex(hex) << OP_CHECKSIG << ParseHex(hex) << OP_CHECKSIG;
+ s += s;
+ BOOST_CHECK(s == d);
+}
+
+
+#if defined(HAVE_CONSENSUS_LIB)
+
+/* Test simple (successful) usage of bitcoinconsensus_verify_script */
+BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_returns_true)
+{
+ unsigned int libconsensus_flags = 0;
+ int nIn = 0;
+
+ CScript scriptPubKey;
+ CScript scriptSig;
+ CScriptWitness wit;
+
+ scriptPubKey << OP_1;
+ CTransaction creditTx = BuildCreditingTransaction(scriptPubKey, 1);
+ CTransaction spendTx = BuildSpendingTransaction(scriptSig, wit, creditTx);
+
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << spendTx;
+
+ bitcoinconsensus_error err;
+ int result = bitcoinconsensus_verify_script(scriptPubKey.data(), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), nIn, libconsensus_flags, &err);
+ BOOST_CHECK_EQUAL(result, 1);
+ BOOST_CHECK_EQUAL(err, bitcoinconsensus_ERR_OK);
+}
+
+/* Test bitcoinconsensus_verify_script returns invalid tx index err*/
+BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_tx_index_err)
+{
+ unsigned int libconsensus_flags = 0;
+ int nIn = 3;
+
+ CScript scriptPubKey;
+ CScript scriptSig;
+ CScriptWitness wit;
+
+ scriptPubKey << OP_EQUAL;
+ CTransaction creditTx = BuildCreditingTransaction(scriptPubKey, 1);
+ CTransaction spendTx = BuildSpendingTransaction(scriptSig, wit, creditTx);
+
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << spendTx;
+
+ bitcoinconsensus_error err;
+ int result = bitcoinconsensus_verify_script(scriptPubKey.data(), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), nIn, libconsensus_flags, &err);
+ BOOST_CHECK_EQUAL(result, 0);
+ BOOST_CHECK_EQUAL(err, bitcoinconsensus_ERR_TX_INDEX);
+}
+
+/* Test bitcoinconsensus_verify_script returns tx size mismatch err*/
+BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_tx_size)
+{
+ unsigned int libconsensus_flags = 0;
+ int nIn = 0;
+
+ CScript scriptPubKey;
+ CScript scriptSig;
+ CScriptWitness wit;
+
+ scriptPubKey << OP_EQUAL;
+ CTransaction creditTx = BuildCreditingTransaction(scriptPubKey, 1);
+ CTransaction spendTx = BuildSpendingTransaction(scriptSig, wit, creditTx);
+
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << spendTx;
+
+ bitcoinconsensus_error err;
+ int result = bitcoinconsensus_verify_script(scriptPubKey.data(), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size() * 2, nIn, libconsensus_flags, &err);
+ BOOST_CHECK_EQUAL(result, 0);
+ BOOST_CHECK_EQUAL(err, bitcoinconsensus_ERR_TX_SIZE_MISMATCH);
+}
+
+/* Test bitcoinconsensus_verify_script returns invalid tx serialization error */
+BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_tx_serialization)
+{
+ unsigned int libconsensus_flags = 0;
+ int nIn = 0;
+
+ CScript scriptPubKey;
+ CScript scriptSig;
+ CScriptWitness wit;
+
+ scriptPubKey << OP_EQUAL;
+ CTransaction creditTx = BuildCreditingTransaction(scriptPubKey, 1);
+ CTransaction spendTx = BuildSpendingTransaction(scriptSig, wit, creditTx);
+
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << 0xffffffff;
+
+ bitcoinconsensus_error err;
+ int result = bitcoinconsensus_verify_script(scriptPubKey.data(), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), nIn, libconsensus_flags, &err);
+ BOOST_CHECK_EQUAL(result, 0);
+ BOOST_CHECK_EQUAL(err, bitcoinconsensus_ERR_TX_DESERIALIZE);
+}
+
+/* Test bitcoinconsensus_verify_script returns amount required error */
+BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_amount_required_err)
+{
+ unsigned int libconsensus_flags = bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS;
+ int nIn = 0;
+
+ CScript scriptPubKey;
+ CScript scriptSig;
+ CScriptWitness wit;
+
+ scriptPubKey << OP_EQUAL;
+ CTransaction creditTx = BuildCreditingTransaction(scriptPubKey, 1);
+ CTransaction spendTx = BuildSpendingTransaction(scriptSig, wit, creditTx);
+
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << spendTx;
+
+ bitcoinconsensus_error err;
+ int result = bitcoinconsensus_verify_script(scriptPubKey.data(), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), nIn, libconsensus_flags, &err);
+ BOOST_CHECK_EQUAL(result, 0);
+ BOOST_CHECK_EQUAL(err, bitcoinconsensus_ERR_AMOUNT_REQUIRED);
+}
+
+/* Test bitcoinconsensus_verify_script returns invalid flags err */
+BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_invalid_flags)
+{
+ unsigned int libconsensus_flags = 1 << 3;
+ int nIn = 0;
+
+ CScript scriptPubKey;
+ CScript scriptSig;
+ CScriptWitness wit;
+
+ scriptPubKey << OP_EQUAL;
+ CTransaction creditTx = BuildCreditingTransaction(scriptPubKey, 1);
+ CTransaction spendTx = BuildSpendingTransaction(scriptSig, wit, creditTx);
+
+ CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
+ stream << spendTx;
+
+ bitcoinconsensus_error err;
+ int result = bitcoinconsensus_verify_script(scriptPubKey.data(), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), nIn, libconsensus_flags, &err);
+ BOOST_CHECK_EQUAL(result, 0);
+ BOOST_CHECK_EQUAL(err, bitcoinconsensus_ERR_INVALID_FLAGS);
+}
+
+#endif
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/scriptnum10.h b/src/test/scriptnum10.h
new file mode 100644
index 0000000000..e763b64275
--- /dev/null
+++ b/src/test/scriptnum10.h
@@ -0,0 +1,183 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_TEST_SCRIPTNUM10_H
+#define BITCOIN_TEST_SCRIPTNUM10_H
+
+#include <algorithm>
+#include <limits>
+#include <stdexcept>
+#include <stdint.h>
+#include <string>
+#include <vector>
+#include <assert.h>
+
+class scriptnum10_error : public std::runtime_error
+{
+public:
+ explicit scriptnum10_error(const std::string& str) : std::runtime_error(str) {}
+};
+
+class CScriptNum10
+{
+/**
+ * The ScriptNum implementation from Bitcoin Core 0.10.0, for cross-comparison.
+ */
+public:
+
+ explicit CScriptNum10(const int64_t& n)
+ {
+ m_value = n;
+ }
+
+ static const size_t nDefaultMaxNumSize = 4;
+
+ explicit CScriptNum10(const std::vector<unsigned char>& vch, bool fRequireMinimal,
+ const size_t nMaxNumSize = nDefaultMaxNumSize)
+ {
+ if (vch.size() > nMaxNumSize) {
+ throw scriptnum10_error("script number overflow");
+ }
+ if (fRequireMinimal && vch.size() > 0) {
+ // Check that the number is encoded with the minimum possible
+ // number of bytes.
+ //
+ // If the most-significant-byte - excluding the sign bit - is zero
+ // then we're not minimal. Note how this test also rejects the
+ // negative-zero encoding, 0x80.
+ if ((vch.back() & 0x7f) == 0) {
+ // One exception: if there's more than one byte and the most
+ // significant bit of the second-most-significant-byte is set
+ // it would conflict with the sign bit. An example of this case
+ // is +-255, which encode to 0xff00 and 0xff80 respectively.
+ // (big-endian).
+ if (vch.size() <= 1 || (vch[vch.size() - 2] & 0x80) == 0) {
+ throw scriptnum10_error("non-minimally encoded script number");
+ }
+ }
+ }
+ m_value = set_vch(vch);
+ }
+
+ inline bool operator==(const int64_t& rhs) const { return m_value == rhs; }
+ inline bool operator!=(const int64_t& rhs) const { return m_value != rhs; }
+ inline bool operator<=(const int64_t& rhs) const { return m_value <= rhs; }
+ inline bool operator< (const int64_t& rhs) const { return m_value < rhs; }
+ inline bool operator>=(const int64_t& rhs) const { return m_value >= rhs; }
+ inline bool operator> (const int64_t& rhs) const { return m_value > rhs; }
+
+ inline bool operator==(const CScriptNum10& rhs) const { return operator==(rhs.m_value); }
+ inline bool operator!=(const CScriptNum10& rhs) const { return operator!=(rhs.m_value); }
+ inline bool operator<=(const CScriptNum10& rhs) const { return operator<=(rhs.m_value); }
+ inline bool operator< (const CScriptNum10& rhs) const { return operator< (rhs.m_value); }
+ inline bool operator>=(const CScriptNum10& rhs) const { return operator>=(rhs.m_value); }
+ inline bool operator> (const CScriptNum10& rhs) const { return operator> (rhs.m_value); }
+
+ inline CScriptNum10 operator+( const int64_t& rhs) const { return CScriptNum10(m_value + rhs);}
+ inline CScriptNum10 operator-( const int64_t& rhs) const { return CScriptNum10(m_value - rhs);}
+ inline CScriptNum10 operator+( const CScriptNum10& rhs) const { return operator+(rhs.m_value); }
+ inline CScriptNum10 operator-( const CScriptNum10& rhs) const { return operator-(rhs.m_value); }
+
+ inline CScriptNum10& operator+=( const CScriptNum10& rhs) { return operator+=(rhs.m_value); }
+ inline CScriptNum10& operator-=( const CScriptNum10& rhs) { return operator-=(rhs.m_value); }
+
+ inline CScriptNum10 operator-() const
+ {
+ assert(m_value != std::numeric_limits<int64_t>::min());
+ return CScriptNum10(-m_value);
+ }
+
+ inline CScriptNum10& operator=( const int64_t& rhs)
+ {
+ m_value = rhs;
+ return *this;
+ }
+
+ inline CScriptNum10& operator+=( const int64_t& rhs)
+ {
+ assert(rhs == 0 || (rhs > 0 && m_value <= std::numeric_limits<int64_t>::max() - rhs) ||
+ (rhs < 0 && m_value >= std::numeric_limits<int64_t>::min() - rhs));
+ m_value += rhs;
+ return *this;
+ }
+
+ inline CScriptNum10& operator-=( const int64_t& rhs)
+ {
+ assert(rhs == 0 || (rhs > 0 && m_value >= std::numeric_limits<int64_t>::min() + rhs) ||
+ (rhs < 0 && m_value <= std::numeric_limits<int64_t>::max() + rhs));
+ m_value -= rhs;
+ return *this;
+ }
+
+ int getint() const
+ {
+ if (m_value > std::numeric_limits<int>::max())
+ return std::numeric_limits<int>::max();
+ else if (m_value < std::numeric_limits<int>::min())
+ return std::numeric_limits<int>::min();
+ return m_value;
+ }
+
+ std::vector<unsigned char> getvch() const
+ {
+ return serialize(m_value);
+ }
+
+ static std::vector<unsigned char> serialize(const int64_t& value)
+ {
+ if(value == 0)
+ return std::vector<unsigned char>();
+
+ std::vector<unsigned char> result;
+ const bool neg = value < 0;
+ uint64_t absvalue = neg ? -value : value;
+
+ while(absvalue)
+ {
+ result.push_back(absvalue & 0xff);
+ absvalue >>= 8;
+ }
+
+// - If the most significant byte is >= 0x80 and the value is positive, push a
+// new zero-byte to make the significant byte < 0x80 again.
+
+// - If the most significant byte is >= 0x80 and the value is negative, push a
+// new 0x80 byte that will be popped off when converting to an integral.
+
+// - If the most significant byte is < 0x80 and the value is negative, add
+// 0x80 to it, since it will be subtracted and interpreted as a negative when
+// converting to an integral.
+
+ if (result.back() & 0x80)
+ result.push_back(neg ? 0x80 : 0);
+ else if (neg)
+ result.back() |= 0x80;
+
+ return result;
+ }
+
+private:
+ static int64_t set_vch(const std::vector<unsigned char>& vch)
+ {
+ if (vch.empty())
+ return 0;
+
+ int64_t result = 0;
+ for (size_t i = 0; i != vch.size(); ++i)
+ result |= static_cast<int64_t>(vch[i]) << 8*i;
+
+ // If the input vector's most significant byte is 0x80, remove it from
+ // the result's msb and return a negative.
+ if (vch.back() & 0x80)
+ return -((int64_t)(result & ~(0x80ULL << (8 * (vch.size() - 1)))));
+
+ return result;
+ }
+
+ int64_t m_value;
+};
+
+
+#endif // BITCOIN_TEST_BIGNUM_H
diff --git a/src/test/scriptnum_tests.cpp b/src/test/scriptnum_tests.cpp
new file mode 100644
index 0000000000..f9b407ce3e
--- /dev/null
+++ b/src/test/scriptnum_tests.cpp
@@ -0,0 +1,200 @@
+// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <test/scriptnum10.h>
+#include <script/script.h>
+#include <test/test_bitcoin.h>
+
+#include <boost/test/unit_test.hpp>
+#include <limits.h>
+#include <stdint.h>
+
+BOOST_FIXTURE_TEST_SUITE(scriptnum_tests, BasicTestingSetup)
+
+/** A selection of numbers that do not trigger int64_t overflow
+ * when added/subtracted. */
+static const int64_t values[] = { 0, 1, -2, 127, 128, -255, 256, (1LL << 15) - 1, -(1LL << 16), (1LL << 24) - 1, (1LL << 31), 1 - (1LL << 32), 1LL << 40 };
+
+static const int64_t offsets[] = { 1, 0x79, 0x80, 0x81, 0xFF, 0x7FFF, 0x8000, 0xFFFF, 0x10000};
+
+static bool verify(const CScriptNum10& bignum, const CScriptNum& scriptnum)
+{
+ return bignum.getvch() == scriptnum.getvch() && bignum.getint() == scriptnum.getint();
+}
+
+static void CheckCreateVch(const int64_t& num)
+{
+ CScriptNum10 bignum(num);
+ CScriptNum scriptnum(num);
+ BOOST_CHECK(verify(bignum, scriptnum));
+
+ CScriptNum10 bignum2(bignum.getvch(), false);
+ CScriptNum scriptnum2(scriptnum.getvch(), false);
+ BOOST_CHECK(verify(bignum2, scriptnum2));
+
+ CScriptNum10 bignum3(scriptnum2.getvch(), false);
+ CScriptNum scriptnum3(bignum2.getvch(), false);
+ BOOST_CHECK(verify(bignum3, scriptnum3));
+}
+
+static void CheckCreateInt(const int64_t& num)
+{
+ CScriptNum10 bignum(num);
+ CScriptNum scriptnum(num);
+ BOOST_CHECK(verify(bignum, scriptnum));
+ BOOST_CHECK(verify(CScriptNum10(bignum.getint()), CScriptNum(scriptnum.getint())));
+ BOOST_CHECK(verify(CScriptNum10(scriptnum.getint()), CScriptNum(bignum.getint())));
+ BOOST_CHECK(verify(CScriptNum10(CScriptNum10(scriptnum.getint()).getint()), CScriptNum(CScriptNum(bignum.getint()).getint())));
+}
+
+
+static void CheckAdd(const int64_t& num1, const int64_t& num2)
+{
+ const CScriptNum10 bignum1(num1);
+ const CScriptNum10 bignum2(num2);
+ const CScriptNum scriptnum1(num1);
+ const CScriptNum scriptnum2(num2);
+ CScriptNum10 bignum3(num1);
+ CScriptNum10 bignum4(num1);
+ CScriptNum scriptnum3(num1);
+ CScriptNum scriptnum4(num1);
+
+ // int64_t overflow is undefined.
+ bool invalid = (((num2 > 0) && (num1 > (std::numeric_limits<int64_t>::max() - num2))) ||
+ ((num2 < 0) && (num1 < (std::numeric_limits<int64_t>::min() - num2))));
+ if (!invalid)
+ {
+ BOOST_CHECK(verify(bignum1 + bignum2, scriptnum1 + scriptnum2));
+ BOOST_CHECK(verify(bignum1 + bignum2, scriptnum1 + num2));
+ BOOST_CHECK(verify(bignum1 + bignum2, scriptnum2 + num1));
+ }
+}
+
+static void CheckNegate(const int64_t& num)
+{
+ const CScriptNum10 bignum(num);
+ const CScriptNum scriptnum(num);
+
+ // -INT64_MIN is undefined
+ if (num != std::numeric_limits<int64_t>::min())
+ BOOST_CHECK(verify(-bignum, -scriptnum));
+}
+
+static void CheckSubtract(const int64_t& num1, const int64_t& num2)
+{
+ const CScriptNum10 bignum1(num1);
+ const CScriptNum10 bignum2(num2);
+ const CScriptNum scriptnum1(num1);
+ const CScriptNum scriptnum2(num2);
+
+ // int64_t overflow is undefined.
+ bool invalid = ((num2 > 0 && num1 < std::numeric_limits<int64_t>::min() + num2) ||
+ (num2 < 0 && num1 > std::numeric_limits<int64_t>::max() + num2));
+ if (!invalid)
+ {
+ BOOST_CHECK(verify(bignum1 - bignum2, scriptnum1 - scriptnum2));
+ BOOST_CHECK(verify(bignum1 - bignum2, scriptnum1 - num2));
+ }
+
+ invalid = ((num1 > 0 && num2 < std::numeric_limits<int64_t>::min() + num1) ||
+ (num1 < 0 && num2 > std::numeric_limits<int64_t>::max() + num1));
+ if (!invalid)
+ {
+ BOOST_CHECK(verify(bignum2 - bignum1, scriptnum2 - scriptnum1));
+ BOOST_CHECK(verify(bignum2 - bignum1, scriptnum2 - num1));
+ }
+}
+
+static void CheckCompare(const int64_t& num1, const int64_t& num2)
+{
+ const CScriptNum10 bignum1(num1);
+ const CScriptNum10 bignum2(num2);
+ const CScriptNum scriptnum1(num1);
+ const CScriptNum scriptnum2(num2);
+
+ BOOST_CHECK((bignum1 == bignum1) == (scriptnum1 == scriptnum1));
+ BOOST_CHECK((bignum1 != bignum1) == (scriptnum1 != scriptnum1));
+ BOOST_CHECK((bignum1 < bignum1) == (scriptnum1 < scriptnum1));
+ BOOST_CHECK((bignum1 > bignum1) == (scriptnum1 > scriptnum1));
+ BOOST_CHECK((bignum1 >= bignum1) == (scriptnum1 >= scriptnum1));
+ BOOST_CHECK((bignum1 <= bignum1) == (scriptnum1 <= scriptnum1));
+
+ BOOST_CHECK((bignum1 == bignum1) == (scriptnum1 == num1));
+ BOOST_CHECK((bignum1 != bignum1) == (scriptnum1 != num1));
+ BOOST_CHECK((bignum1 < bignum1) == (scriptnum1 < num1));
+ BOOST_CHECK((bignum1 > bignum1) == (scriptnum1 > num1));
+ BOOST_CHECK((bignum1 >= bignum1) == (scriptnum1 >= num1));
+ BOOST_CHECK((bignum1 <= bignum1) == (scriptnum1 <= num1));
+
+ BOOST_CHECK((bignum1 == bignum2) == (scriptnum1 == scriptnum2));
+ BOOST_CHECK((bignum1 != bignum2) == (scriptnum1 != scriptnum2));
+ BOOST_CHECK((bignum1 < bignum2) == (scriptnum1 < scriptnum2));
+ BOOST_CHECK((bignum1 > bignum2) == (scriptnum1 > scriptnum2));
+ BOOST_CHECK((bignum1 >= bignum2) == (scriptnum1 >= scriptnum2));
+ BOOST_CHECK((bignum1 <= bignum2) == (scriptnum1 <= scriptnum2));
+
+ BOOST_CHECK((bignum1 == bignum2) == (scriptnum1 == num2));
+ BOOST_CHECK((bignum1 != bignum2) == (scriptnum1 != num2));
+ BOOST_CHECK((bignum1 < bignum2) == (scriptnum1 < num2));
+ BOOST_CHECK((bignum1 > bignum2) == (scriptnum1 > num2));
+ BOOST_CHECK((bignum1 >= bignum2) == (scriptnum1 >= num2));
+ BOOST_CHECK((bignum1 <= bignum2) == (scriptnum1 <= num2));
+}
+
+static void RunCreate(const int64_t& num)
+{
+ CheckCreateInt(num);
+ CScriptNum scriptnum(num);
+ if (scriptnum.getvch().size() <= CScriptNum::nDefaultMaxNumSize)
+ CheckCreateVch(num);
+ else
+ {
+ BOOST_CHECK_THROW (CheckCreateVch(num), scriptnum10_error);
+ }
+}
+
+static void RunOperators(const int64_t& num1, const int64_t& num2)
+{
+ CheckAdd(num1, num2);
+ CheckSubtract(num1, num2);
+ CheckNegate(num1);
+ CheckCompare(num1, num2);
+}
+
+BOOST_AUTO_TEST_CASE(creation)
+{
+ for(size_t i = 0; i < sizeof(values) / sizeof(values[0]); ++i)
+ {
+ for(size_t j = 0; j < sizeof(offsets) / sizeof(offsets[0]); ++j)
+ {
+ RunCreate(values[i]);
+ RunCreate(values[i] + offsets[j]);
+ RunCreate(values[i] - offsets[j]);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(operators)
+{
+ for(size_t i = 0; i < sizeof(values) / sizeof(values[0]); ++i)
+ {
+ for(size_t j = 0; j < sizeof(offsets) / sizeof(offsets[0]); ++j)
+ {
+ RunOperators(values[i], values[i]);
+ RunOperators(values[i], -values[i]);
+ RunOperators(values[i], values[j]);
+ RunOperators(values[i], -values[j]);
+ RunOperators(values[i] + values[j], values[j]);
+ RunOperators(values[i] + values[j], -values[j]);
+ RunOperators(values[i] - values[j], values[j]);
+ RunOperators(values[i] - values[j], -values[j]);
+ RunOperators(values[i] + values[j], values[i] + values[j]);
+ RunOperators(values[i] + values[j], values[i] - values[j]);
+ RunOperators(values[i] - values[j], values[i] + values[j]);
+ RunOperators(values[i] - values[j], values[i] - values[j]);
+ }
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp
new file mode 100644
index 0000000000..3a06145861
--- /dev/null
+++ b/src/test/serialize_tests.cpp
@@ -0,0 +1,373 @@
+// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <serialize.h>
+#include <streams.h>
+#include <hash.h>
+#include <test/test_bitcoin.h>
+
+#include <stdint.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(serialize_tests, BasicTestingSetup)
+
+class CSerializeMethodsTestSingle
+{
+protected:
+ int intval;
+ bool boolval;
+ std::string stringval;
+ char charstrval[16];
+ CTransactionRef txval;
+public:
+ CSerializeMethodsTestSingle() = default;
+ CSerializeMethodsTestSingle(int intvalin, bool boolvalin, std::string stringvalin, const char* charstrvalin, const CTransactionRef& txvalin) : intval(intvalin), boolval(boolvalin), stringval(std::move(stringvalin)), txval(txvalin)
+ {
+ memcpy(charstrval, charstrvalin, sizeof(charstrval));
+ }
+
+ ADD_SERIALIZE_METHODS;
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream& s, Operation ser_action) {
+ READWRITE(intval);
+ READWRITE(boolval);
+ READWRITE(stringval);
+ READWRITE(charstrval);
+ READWRITE(txval);
+ }
+
+ bool operator==(const CSerializeMethodsTestSingle& rhs)
+ {
+ return intval == rhs.intval && \
+ boolval == rhs.boolval && \
+ stringval == rhs.stringval && \
+ strcmp(charstrval, rhs.charstrval) == 0 && \
+ *txval == *rhs.txval;
+ }
+};
+
+class CSerializeMethodsTestMany : public CSerializeMethodsTestSingle
+{
+public:
+ using CSerializeMethodsTestSingle::CSerializeMethodsTestSingle;
+ ADD_SERIALIZE_METHODS;
+
+ template <typename Stream, typename Operation>
+ inline void SerializationOp(Stream& s, Operation ser_action) {
+ READWRITE(intval, boolval, stringval, charstrval, txval);
+ }
+};
+
+BOOST_AUTO_TEST_CASE(sizes)
+{
+ BOOST_CHECK_EQUAL(sizeof(char), GetSerializeSize(char(0), 0));
+ BOOST_CHECK_EQUAL(sizeof(int8_t), GetSerializeSize(int8_t(0), 0));
+ BOOST_CHECK_EQUAL(sizeof(uint8_t), GetSerializeSize(uint8_t(0), 0));
+ BOOST_CHECK_EQUAL(sizeof(int16_t), GetSerializeSize(int16_t(0), 0));
+ BOOST_CHECK_EQUAL(sizeof(uint16_t), GetSerializeSize(uint16_t(0), 0));
+ BOOST_CHECK_EQUAL(sizeof(int32_t), GetSerializeSize(int32_t(0), 0));
+ BOOST_CHECK_EQUAL(sizeof(uint32_t), GetSerializeSize(uint32_t(0), 0));
+ BOOST_CHECK_EQUAL(sizeof(int64_t), GetSerializeSize(int64_t(0), 0));
+ BOOST_CHECK_EQUAL(sizeof(uint64_t), GetSerializeSize(uint64_t(0), 0));
+ BOOST_CHECK_EQUAL(sizeof(float), GetSerializeSize(float(0), 0));
+ BOOST_CHECK_EQUAL(sizeof(double), GetSerializeSize(double(0), 0));
+ // Bool is serialized as char
+ BOOST_CHECK_EQUAL(sizeof(char), GetSerializeSize(bool(0), 0));
+
+ // Sanity-check GetSerializeSize and c++ type matching
+ BOOST_CHECK_EQUAL(GetSerializeSize(char(0), 0), 1U);
+ BOOST_CHECK_EQUAL(GetSerializeSize(int8_t(0), 0), 1U);
+ BOOST_CHECK_EQUAL(GetSerializeSize(uint8_t(0), 0), 1U);
+ BOOST_CHECK_EQUAL(GetSerializeSize(int16_t(0), 0), 2U);
+ BOOST_CHECK_EQUAL(GetSerializeSize(uint16_t(0), 0), 2U);
+ BOOST_CHECK_EQUAL(GetSerializeSize(int32_t(0), 0), 4U);
+ BOOST_CHECK_EQUAL(GetSerializeSize(uint32_t(0), 0), 4U);
+ BOOST_CHECK_EQUAL(GetSerializeSize(int64_t(0), 0), 8U);
+ BOOST_CHECK_EQUAL(GetSerializeSize(uint64_t(0), 0), 8U);
+ BOOST_CHECK_EQUAL(GetSerializeSize(float(0), 0), 4U);
+ BOOST_CHECK_EQUAL(GetSerializeSize(double(0), 0), 8U);
+ BOOST_CHECK_EQUAL(GetSerializeSize(bool(0), 0), 1U);
+}
+
+BOOST_AUTO_TEST_CASE(floats_conversion)
+{
+ // Choose values that map unambiguously to binary floating point to avoid
+ // rounding issues at the compiler side.
+ BOOST_CHECK_EQUAL(ser_uint32_to_float(0x00000000), 0.0F);
+ BOOST_CHECK_EQUAL(ser_uint32_to_float(0x3f000000), 0.5F);
+ BOOST_CHECK_EQUAL(ser_uint32_to_float(0x3f800000), 1.0F);
+ BOOST_CHECK_EQUAL(ser_uint32_to_float(0x40000000), 2.0F);
+ BOOST_CHECK_EQUAL(ser_uint32_to_float(0x40800000), 4.0F);
+ BOOST_CHECK_EQUAL(ser_uint32_to_float(0x44444444), 785.066650390625F);
+
+ BOOST_CHECK_EQUAL(ser_float_to_uint32(0.0F), 0x00000000U);
+ BOOST_CHECK_EQUAL(ser_float_to_uint32(0.5F), 0x3f000000U);
+ BOOST_CHECK_EQUAL(ser_float_to_uint32(1.0F), 0x3f800000U);
+ BOOST_CHECK_EQUAL(ser_float_to_uint32(2.0F), 0x40000000U);
+ BOOST_CHECK_EQUAL(ser_float_to_uint32(4.0F), 0x40800000U);
+ BOOST_CHECK_EQUAL(ser_float_to_uint32(785.066650390625F), 0x44444444U);
+}
+
+BOOST_AUTO_TEST_CASE(doubles_conversion)
+{
+ // Choose values that map unambiguously to binary floating point to avoid
+ // rounding issues at the compiler side.
+ BOOST_CHECK_EQUAL(ser_uint64_to_double(0x0000000000000000ULL), 0.0);
+ BOOST_CHECK_EQUAL(ser_uint64_to_double(0x3fe0000000000000ULL), 0.5);
+ BOOST_CHECK_EQUAL(ser_uint64_to_double(0x3ff0000000000000ULL), 1.0);
+ BOOST_CHECK_EQUAL(ser_uint64_to_double(0x4000000000000000ULL), 2.0);
+ BOOST_CHECK_EQUAL(ser_uint64_to_double(0x4010000000000000ULL), 4.0);
+ BOOST_CHECK_EQUAL(ser_uint64_to_double(0x4088888880000000ULL), 785.066650390625);
+
+ BOOST_CHECK_EQUAL(ser_double_to_uint64(0.0), 0x0000000000000000ULL);
+ BOOST_CHECK_EQUAL(ser_double_to_uint64(0.5), 0x3fe0000000000000ULL);
+ BOOST_CHECK_EQUAL(ser_double_to_uint64(1.0), 0x3ff0000000000000ULL);
+ BOOST_CHECK_EQUAL(ser_double_to_uint64(2.0), 0x4000000000000000ULL);
+ BOOST_CHECK_EQUAL(ser_double_to_uint64(4.0), 0x4010000000000000ULL);
+ BOOST_CHECK_EQUAL(ser_double_to_uint64(785.066650390625), 0x4088888880000000ULL);
+}
+/*
+Python code to generate the below hashes:
+
+ def reversed_hex(x):
+ return binascii.hexlify(''.join(reversed(x)))
+ def dsha256(x):
+ return hashlib.sha256(hashlib.sha256(x).digest()).digest()
+
+ reversed_hex(dsha256(''.join(struct.pack('<f', x) for x in range(0,1000)))) == '8e8b4cf3e4df8b332057e3e23af42ebc663b61e0495d5e7e32d85099d7f3fe0c'
+ reversed_hex(dsha256(''.join(struct.pack('<d', x) for x in range(0,1000)))) == '43d0c82591953c4eafe114590d392676a01585d25b25d433557f0d7878b23f96'
+*/
+BOOST_AUTO_TEST_CASE(floats)
+{
+ CDataStream ss(SER_DISK, 0);
+ // encode
+ for (int i = 0; i < 1000; i++) {
+ ss << float(i);
+ }
+ BOOST_CHECK(Hash(ss.begin(), ss.end()) == uint256S("8e8b4cf3e4df8b332057e3e23af42ebc663b61e0495d5e7e32d85099d7f3fe0c"));
+
+ // decode
+ for (int i = 0; i < 1000; i++) {
+ float j;
+ ss >> j;
+ BOOST_CHECK_MESSAGE(i == j, "decoded:" << j << " expected:" << i);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(doubles)
+{
+ CDataStream ss(SER_DISK, 0);
+ // encode
+ for (int i = 0; i < 1000; i++) {
+ ss << double(i);
+ }
+ BOOST_CHECK(Hash(ss.begin(), ss.end()) == uint256S("43d0c82591953c4eafe114590d392676a01585d25b25d433557f0d7878b23f96"));
+
+ // decode
+ for (int i = 0; i < 1000; i++) {
+ double j;
+ ss >> j;
+ BOOST_CHECK_MESSAGE(i == j, "decoded:" << j << " expected:" << i);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(varints)
+{
+ // encode
+
+ CDataStream ss(SER_DISK, 0);
+ CDataStream::size_type size = 0;
+ for (int i = 0; i < 100000; i++) {
+ ss << VARINT(i, VarIntMode::NONNEGATIVE_SIGNED);
+ size += ::GetSerializeSize(VARINT(i, VarIntMode::NONNEGATIVE_SIGNED), 0, 0);
+ BOOST_CHECK(size == ss.size());
+ }
+
+ for (uint64_t i = 0; i < 100000000000ULL; i += 999999937) {
+ ss << VARINT(i);
+ size += ::GetSerializeSize(VARINT(i), 0, 0);
+ BOOST_CHECK(size == ss.size());
+ }
+
+ // decode
+ for (int i = 0; i < 100000; i++) {
+ int j = -1;
+ ss >> VARINT(j, VarIntMode::NONNEGATIVE_SIGNED);
+ BOOST_CHECK_MESSAGE(i == j, "decoded:" << j << " expected:" << i);
+ }
+
+ for (uint64_t i = 0; i < 100000000000ULL; i += 999999937) {
+ uint64_t j = -1;
+ ss >> VARINT(j);
+ BOOST_CHECK_MESSAGE(i == j, "decoded:" << j << " expected:" << i);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(varints_bitpatterns)
+{
+ CDataStream ss(SER_DISK, 0);
+ ss << VARINT(0, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "00"); ss.clear();
+ ss << VARINT(0x7f, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "7f"); ss.clear();
+ ss << VARINT((int8_t)0x7f, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "7f"); ss.clear();
+ ss << VARINT(0x80, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "8000"); ss.clear();
+ ss << VARINT((uint8_t)0x80); BOOST_CHECK_EQUAL(HexStr(ss), "8000"); ss.clear();
+ ss << VARINT(0x1234, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "a334"); ss.clear();
+ ss << VARINT((int16_t)0x1234, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "a334"); ss.clear();
+ ss << VARINT(0xffff, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "82fe7f"); ss.clear();
+ ss << VARINT((uint16_t)0xffff); BOOST_CHECK_EQUAL(HexStr(ss), "82fe7f"); ss.clear();
+ ss << VARINT(0x123456, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "c7e756"); ss.clear();
+ ss << VARINT((int32_t)0x123456, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "c7e756"); ss.clear();
+ ss << VARINT(0x80123456U); BOOST_CHECK_EQUAL(HexStr(ss), "86ffc7e756"); ss.clear();
+ ss << VARINT((uint32_t)0x80123456U); BOOST_CHECK_EQUAL(HexStr(ss), "86ffc7e756"); ss.clear();
+ ss << VARINT(0xffffffff); BOOST_CHECK_EQUAL(HexStr(ss), "8efefefe7f"); ss.clear();
+ ss << VARINT(0x7fffffffffffffffLL, VarIntMode::NONNEGATIVE_SIGNED); BOOST_CHECK_EQUAL(HexStr(ss), "fefefefefefefefe7f"); ss.clear();
+ ss << VARINT(0xffffffffffffffffULL); BOOST_CHECK_EQUAL(HexStr(ss), "80fefefefefefefefe7f"); ss.clear();
+}
+
+BOOST_AUTO_TEST_CASE(compactsize)
+{
+ CDataStream ss(SER_DISK, 0);
+ std::vector<char>::size_type i, j;
+
+ for (i = 1; i <= MAX_SIZE; i *= 2)
+ {
+ WriteCompactSize(ss, i-1);
+ WriteCompactSize(ss, i);
+ }
+ for (i = 1; i <= MAX_SIZE; i *= 2)
+ {
+ j = ReadCompactSize(ss);
+ BOOST_CHECK_MESSAGE((i-1) == j, "decoded:" << j << " expected:" << (i-1));
+ j = ReadCompactSize(ss);
+ BOOST_CHECK_MESSAGE(i == j, "decoded:" << j << " expected:" << i);
+ }
+}
+
+static bool isCanonicalException(const std::ios_base::failure& ex)
+{
+ std::ios_base::failure expectedException("non-canonical ReadCompactSize()");
+
+ // The string returned by what() can be different for different platforms.
+ // Instead of directly comparing the ex.what() with an expected string,
+ // create an instance of exception to see if ex.what() matches
+ // the expected explanatory string returned by the exception instance.
+ return strcmp(expectedException.what(), ex.what()) == 0;
+}
+
+
+BOOST_AUTO_TEST_CASE(noncanonical)
+{
+ // Write some non-canonical CompactSize encodings, and
+ // make sure an exception is thrown when read back.
+ CDataStream ss(SER_DISK, 0);
+ std::vector<char>::size_type n;
+
+ // zero encoded with three bytes:
+ ss.write("\xfd\x00\x00", 3);
+ BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
+
+ // 0xfc encoded with three bytes:
+ ss.write("\xfd\xfc\x00", 3);
+ BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
+
+ // 0xfd encoded with three bytes is OK:
+ ss.write("\xfd\xfd\x00", 3);
+ n = ReadCompactSize(ss);
+ BOOST_CHECK(n == 0xfd);
+
+ // zero encoded with five bytes:
+ ss.write("\xfe\x00\x00\x00\x00", 5);
+ BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
+
+ // 0xffff encoded with five bytes:
+ ss.write("\xfe\xff\xff\x00\x00", 5);
+ BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
+
+ // zero encoded with nine bytes:
+ ss.write("\xff\x00\x00\x00\x00\x00\x00\x00\x00", 9);
+ BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
+
+ // 0x01ffffff encoded with nine bytes:
+ ss.write("\xff\xff\xff\xff\x01\x00\x00\x00\x00", 9);
+ BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
+}
+
+BOOST_AUTO_TEST_CASE(insert_delete)
+{
+ // Test inserting/deleting bytes.
+ CDataStream ss(SER_DISK, 0);
+ BOOST_CHECK_EQUAL(ss.size(), 0U);
+
+ ss.write("\x00\x01\x02\xff", 4);
+ BOOST_CHECK_EQUAL(ss.size(), 4U);
+
+ char c = (char)11;
+
+ // Inserting at beginning/end/middle:
+ ss.insert(ss.begin(), c);
+ BOOST_CHECK_EQUAL(ss.size(), 5U);
+ BOOST_CHECK_EQUAL(ss[0], c);
+ BOOST_CHECK_EQUAL(ss[1], 0);
+
+ ss.insert(ss.end(), c);
+ BOOST_CHECK_EQUAL(ss.size(), 6U);
+ BOOST_CHECK_EQUAL(ss[4], (char)0xff);
+ BOOST_CHECK_EQUAL(ss[5], c);
+
+ ss.insert(ss.begin()+2, c);
+ BOOST_CHECK_EQUAL(ss.size(), 7U);
+ BOOST_CHECK_EQUAL(ss[2], c);
+
+ // Delete at beginning/end/middle
+ ss.erase(ss.begin());
+ BOOST_CHECK_EQUAL(ss.size(), 6U);
+ BOOST_CHECK_EQUAL(ss[0], 0);
+
+ ss.erase(ss.begin()+ss.size()-1);
+ BOOST_CHECK_EQUAL(ss.size(), 5U);
+ BOOST_CHECK_EQUAL(ss[4], (char)0xff);
+
+ ss.erase(ss.begin()+1);
+ BOOST_CHECK_EQUAL(ss.size(), 4U);
+ BOOST_CHECK_EQUAL(ss[0], 0);
+ BOOST_CHECK_EQUAL(ss[1], 1);
+ BOOST_CHECK_EQUAL(ss[2], 2);
+ BOOST_CHECK_EQUAL(ss[3], (char)0xff);
+
+ // Make sure GetAndClear does the right thing:
+ CSerializeData d;
+ ss.GetAndClear(d);
+ BOOST_CHECK_EQUAL(ss.size(), 0U);
+}
+
+BOOST_AUTO_TEST_CASE(class_methods)
+{
+ int intval(100);
+ bool boolval(true);
+ std::string stringval("testing");
+ const char charstrval[16] = "testing charstr";
+ CMutableTransaction txval;
+ CTransactionRef tx_ref{MakeTransactionRef(txval)};
+ CSerializeMethodsTestSingle methodtest1(intval, boolval, stringval, charstrval, tx_ref);
+ CSerializeMethodsTestMany methodtest2(intval, boolval, stringval, charstrval, tx_ref);
+ CSerializeMethodsTestSingle methodtest3;
+ CSerializeMethodsTestMany methodtest4;
+ CDataStream ss(SER_DISK, PROTOCOL_VERSION);
+ BOOST_CHECK(methodtest1 == methodtest2);
+ ss << methodtest1;
+ ss >> methodtest4;
+ ss << methodtest2;
+ ss >> methodtest3;
+ BOOST_CHECK(methodtest1 == methodtest2);
+ BOOST_CHECK(methodtest2 == methodtest3);
+ BOOST_CHECK(methodtest3 == methodtest4);
+
+ CDataStream ss2(SER_DISK, PROTOCOL_VERSION, intval, boolval, stringval, charstrval, txval);
+ ss2 >> methodtest3;
+ BOOST_CHECK(methodtest3 == methodtest4);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp
new file mode 100644
index 0000000000..e6905457bb
--- /dev/null
+++ b/src/test/sighash_tests.cpp
@@ -0,0 +1,211 @@
+// Copyright (c) 2013-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <consensus/tx_verify.h>
+#include <consensus/validation.h>
+#include <test/data/sighash.json.h>
+#include <hash.h>
+#include <script/interpreter.h>
+#include <script/script.h>
+#include <serialize.h>
+#include <streams.h>
+#include <test/test_bitcoin.h>
+#include <util.h>
+#include <utilstrencodings.h>
+#include <version.h>
+
+#include <iostream>
+
+#include <boost/test/unit_test.hpp>
+
+#include <univalue.h>
+
+extern UniValue read_json(const std::string& jsondata);
+
+// Old script.cpp SignatureHash function
+uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
+{
+ static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
+ if (nIn >= txTo.vin.size())
+ {
+ return one;
+ }
+ CMutableTransaction txTmp(txTo);
+
+ // In case concatenating two scripts ends up with two codeseparators,
+ // or an extra one at the end, this prevents all those possible incompatibilities.
+ FindAndDelete(scriptCode, CScript(OP_CODESEPARATOR));
+
+ // Blank out other inputs' signatures
+ for (unsigned int i = 0; i < txTmp.vin.size(); i++)
+ txTmp.vin[i].scriptSig = CScript();
+ txTmp.vin[nIn].scriptSig = scriptCode;
+
+ // Blank out some of the outputs
+ if ((nHashType & 0x1f) == SIGHASH_NONE)
+ {
+ // Wildcard payee
+ txTmp.vout.clear();
+
+ // Let the others update at will
+ for (unsigned int i = 0; i < txTmp.vin.size(); i++)
+ if (i != nIn)
+ txTmp.vin[i].nSequence = 0;
+ }
+ else if ((nHashType & 0x1f) == SIGHASH_SINGLE)
+ {
+ // Only lock-in the txout payee at same index as txin
+ unsigned int nOut = nIn;
+ if (nOut >= txTmp.vout.size())
+ {
+ return one;
+ }
+ txTmp.vout.resize(nOut+1);
+ for (unsigned int i = 0; i < nOut; i++)
+ txTmp.vout[i].SetNull();
+
+ // Let the others update at will
+ for (unsigned int i = 0; i < txTmp.vin.size(); i++)
+ if (i != nIn)
+ txTmp.vin[i].nSequence = 0;
+ }
+
+ // Blank out other inputs completely, not recommended for open transactions
+ if (nHashType & SIGHASH_ANYONECANPAY)
+ {
+ txTmp.vin[0] = txTmp.vin[nIn];
+ txTmp.vin.resize(1);
+ }
+
+ // Serialize and hash
+ CHashWriter ss(SER_GETHASH, SERIALIZE_TRANSACTION_NO_WITNESS);
+ ss << txTmp << nHashType;
+ return ss.GetHash();
+}
+
+void static RandomScript(CScript &script) {
+ static const opcodetype oplist[] = {OP_FALSE, OP_1, OP_2, OP_3, OP_CHECKSIG, OP_IF, OP_VERIF, OP_RETURN, OP_CODESEPARATOR};
+ script = CScript();
+ int ops = (InsecureRandRange(10));
+ for (int i=0; i<ops; i++)
+ script << oplist[InsecureRandRange(sizeof(oplist)/sizeof(oplist[0]))];
+}
+
+void static RandomTransaction(CMutableTransaction &tx, bool fSingle) {
+ tx.nVersion = InsecureRand32();
+ tx.vin.clear();
+ tx.vout.clear();
+ tx.nLockTime = (InsecureRandBool()) ? InsecureRand32() : 0;
+ int ins = (InsecureRandBits(2)) + 1;
+ int outs = fSingle ? ins : (InsecureRandBits(2)) + 1;
+ for (int in = 0; in < ins; in++) {
+ tx.vin.push_back(CTxIn());
+ CTxIn &txin = tx.vin.back();
+ txin.prevout.hash = InsecureRand256();
+ txin.prevout.n = InsecureRandBits(2);
+ RandomScript(txin.scriptSig);
+ txin.nSequence = (InsecureRandBool()) ? InsecureRand32() : (unsigned int)-1;
+ }
+ for (int out = 0; out < outs; out++) {
+ tx.vout.push_back(CTxOut());
+ CTxOut &txout = tx.vout.back();
+ txout.nValue = InsecureRandRange(100000000);
+ RandomScript(txout.scriptPubKey);
+ }
+}
+
+BOOST_FIXTURE_TEST_SUITE(sighash_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(sighash_test)
+{
+ SeedInsecureRand(false);
+
+ #if defined(PRINT_SIGHASH_JSON)
+ std::cout << "[\n";
+ std::cout << "\t[\"raw_transaction, script, input_index, hashType, signature_hash (result)\"],\n";
+ int nRandomTests = 500;
+ #else
+ int nRandomTests = 50000;
+ #endif
+ for (int i=0; i<nRandomTests; i++) {
+ int nHashType = InsecureRand32();
+ CMutableTransaction txTo;
+ RandomTransaction(txTo, (nHashType & 0x1f) == SIGHASH_SINGLE);
+ CScript scriptCode;
+ RandomScript(scriptCode);
+ int nIn = InsecureRandRange(txTo.vin.size());
+
+ uint256 sh, sho;
+ sho = SignatureHashOld(scriptCode, txTo, nIn, nHashType);
+ sh = SignatureHash(scriptCode, txTo, nIn, nHashType, 0, SigVersion::BASE);
+ #if defined(PRINT_SIGHASH_JSON)
+ CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
+ ss << txTo;
+
+ std::cout << "\t[\"" ;
+ std::cout << HexStr(ss.begin(), ss.end()) << "\", \"";
+ std::cout << HexStr(scriptCode) << "\", ";
+ std::cout << nIn << ", ";
+ std::cout << nHashType << ", \"";
+ std::cout << sho.GetHex() << "\"]";
+ if (i+1 != nRandomTests) {
+ std::cout << ",";
+ }
+ std::cout << "\n";
+ #endif
+ BOOST_CHECK(sh == sho);
+ }
+ #if defined(PRINT_SIGHASH_JSON)
+ std::cout << "]\n";
+ #endif
+}
+
+// Goal: check that SignatureHash generates correct hash
+BOOST_AUTO_TEST_CASE(sighash_from_data)
+{
+ UniValue tests = read_json(std::string(json_tests::sighash, json_tests::sighash + sizeof(json_tests::sighash)));
+
+ for (unsigned int idx = 0; idx < tests.size(); idx++) {
+ UniValue test = tests[idx];
+ std::string strTest = test.write();
+ if (test.size() < 1) // Allow for extra stuff (useful for comments)
+ {
+ BOOST_ERROR("Bad test: " << strTest);
+ continue;
+ }
+ if (test.size() == 1) continue; // comment
+
+ std::string raw_tx, raw_script, sigHashHex;
+ int nIn, nHashType;
+ uint256 sh;
+ CTransactionRef tx;
+ CScript scriptCode = CScript();
+
+ try {
+ // deserialize test data
+ raw_tx = test[0].get_str();
+ raw_script = test[1].get_str();
+ nIn = test[2].get_int();
+ nHashType = test[3].get_int();
+ sigHashHex = test[4].get_str();
+
+ CDataStream stream(ParseHex(raw_tx), SER_NETWORK, PROTOCOL_VERSION);
+ stream >> tx;
+
+ CValidationState state;
+ BOOST_CHECK_MESSAGE(CheckTransaction(*tx, state), strTest);
+ BOOST_CHECK(state.IsValid());
+
+ std::vector<unsigned char> raw = ParseHex(raw_script);
+ scriptCode.insert(scriptCode.end(), raw.begin(), raw.end());
+ } catch (...) {
+ BOOST_ERROR("Bad test, couldn't deserialize data: " << strTest);
+ continue;
+ }
+
+ sh = SignatureHash(scriptCode, *tx, nIn, nHashType, 0, SigVersion::BASE);
+ BOOST_CHECK_MESSAGE(sh.GetHex() == sigHashHex, strTest);
+ }
+}
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp
new file mode 100644
index 0000000000..5462fea777
--- /dev/null
+++ b/src/test/sigopcount_tests.cpp
@@ -0,0 +1,232 @@
+// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <consensus/tx_verify.h>
+#include <consensus/validation.h>
+#include <pubkey.h>
+#include <key.h>
+#include <script/script.h>
+#include <script/standard.h>
+#include <uint256.h>
+#include <test/test_bitcoin.h>
+
+#include <vector>
+
+#include <boost/test/unit_test.hpp>
+
+// Helpers:
+static std::vector<unsigned char>
+Serialize(const CScript& s)
+{
+ std::vector<unsigned char> sSerialized(s.begin(), s.end());
+ return sSerialized;
+}
+
+BOOST_FIXTURE_TEST_SUITE(sigopcount_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(GetSigOpCount)
+{
+ // Test CScript::GetSigOpCount()
+ CScript s1;
+ BOOST_CHECK_EQUAL(s1.GetSigOpCount(false), 0U);
+ BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 0U);
+
+ uint160 dummy;
+ s1 << OP_1 << ToByteVector(dummy) << ToByteVector(dummy) << OP_2 << OP_CHECKMULTISIG;
+ BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 2U);
+ s1 << OP_IF << OP_CHECKSIG << OP_ENDIF;
+ BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 3U);
+ BOOST_CHECK_EQUAL(s1.GetSigOpCount(false), 21U);
+
+ CScript p2sh = GetScriptForDestination(CScriptID(s1));
+ CScript scriptSig;
+ scriptSig << OP_0 << Serialize(s1);
+ BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(scriptSig), 3U);
+
+ std::vector<CPubKey> keys;
+ for (int i = 0; i < 3; i++)
+ {
+ CKey k;
+ k.MakeNewKey(true);
+ keys.push_back(k.GetPubKey());
+ }
+ CScript s2 = GetScriptForMultisig(1, keys);
+ BOOST_CHECK_EQUAL(s2.GetSigOpCount(true), 3U);
+ BOOST_CHECK_EQUAL(s2.GetSigOpCount(false), 20U);
+
+ p2sh = GetScriptForDestination(CScriptID(s2));
+ BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(true), 0U);
+ BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(false), 0U);
+ CScript scriptSig2;
+ scriptSig2 << OP_1 << ToByteVector(dummy) << ToByteVector(dummy) << Serialize(s2);
+ BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(scriptSig2), 3U);
+}
+
+/**
+ * Verifies script execution of the zeroth scriptPubKey of tx output and
+ * zeroth scriptSig and witness of tx input.
+ */
+static ScriptError VerifyWithFlag(const CTransaction& output, const CMutableTransaction& input, int flags)
+{
+ ScriptError error;
+ CTransaction inputi(input);
+ bool ret = VerifyScript(inputi.vin[0].scriptSig, output.vout[0].scriptPubKey, &inputi.vin[0].scriptWitness, flags, TransactionSignatureChecker(&inputi, 0, output.vout[0].nValue), &error);
+ BOOST_CHECK((ret == true) == (error == SCRIPT_ERR_OK));
+
+ return error;
+}
+
+/**
+ * Builds a creationTx from scriptPubKey and a spendingTx from scriptSig
+ * and witness such that spendingTx spends output zero of creationTx.
+ * Also inserts creationTx's output into the coins view.
+ */
+static void BuildTxs(CMutableTransaction& spendingTx, CCoinsViewCache& coins, CMutableTransaction& creationTx, const CScript& scriptPubKey, const CScript& scriptSig, const CScriptWitness& witness)
+{
+ creationTx.nVersion = 1;
+ creationTx.vin.resize(1);
+ creationTx.vin[0].prevout.SetNull();
+ creationTx.vin[0].scriptSig = CScript();
+ creationTx.vout.resize(1);
+ creationTx.vout[0].nValue = 1;
+ creationTx.vout[0].scriptPubKey = scriptPubKey;
+
+ spendingTx.nVersion = 1;
+ spendingTx.vin.resize(1);
+ spendingTx.vin[0].prevout.hash = creationTx.GetHash();
+ spendingTx.vin[0].prevout.n = 0;
+ spendingTx.vin[0].scriptSig = scriptSig;
+ spendingTx.vin[0].scriptWitness = witness;
+ spendingTx.vout.resize(1);
+ spendingTx.vout[0].nValue = 1;
+ spendingTx.vout[0].scriptPubKey = CScript();
+
+ AddCoins(coins, creationTx, 0);
+}
+
+BOOST_AUTO_TEST_CASE(GetTxSigOpCost)
+{
+ // Transaction creates outputs
+ CMutableTransaction creationTx;
+ // Transaction that spends outputs and whose
+ // sig op cost is going to be tested
+ CMutableTransaction spendingTx;
+
+ // Create utxo set
+ CCoinsView coinsDummy;
+ CCoinsViewCache coins(&coinsDummy);
+ // Create key
+ CKey key;
+ key.MakeNewKey(true);
+ CPubKey pubkey = key.GetPubKey();
+ // Default flags
+ int flags = SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH;
+
+ // Multisig script (legacy counting)
+ {
+ CScript scriptPubKey = CScript() << 1 << ToByteVector(pubkey) << ToByteVector(pubkey) << 2 << OP_CHECKMULTISIGVERIFY;
+ // Do not use a valid signature to avoid using wallet operations.
+ CScript scriptSig = CScript() << OP_0 << OP_0;
+
+ BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, CScriptWitness());
+ // Legacy counting only includes signature operations in scriptSigs and scriptPubKeys
+ // of a transaction and does not take the actual executed sig operations into account.
+ // spendingTx in itself does not contain a signature operation.
+ assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 0);
+ // creationTx contains two signature operations in its scriptPubKey, but legacy counting
+ // is not accurate.
+ assert(GetTransactionSigOpCost(CTransaction(creationTx), coins, flags) == MAX_PUBKEYS_PER_MULTISIG * WITNESS_SCALE_FACTOR);
+ // Sanity check: script verification fails because of an invalid signature.
+ assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY);
+ }
+
+ // Multisig nested in P2SH
+ {
+ CScript redeemScript = CScript() << 1 << ToByteVector(pubkey) << ToByteVector(pubkey) << 2 << OP_CHECKMULTISIGVERIFY;
+ CScript scriptPubKey = GetScriptForDestination(CScriptID(redeemScript));
+ CScript scriptSig = CScript() << OP_0 << OP_0 << ToByteVector(redeemScript);
+
+ BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, CScriptWitness());
+ assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 2 * WITNESS_SCALE_FACTOR);
+ assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY);
+ }
+
+ // P2WPKH witness program
+ {
+ CScript p2pk = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
+ CScript scriptPubKey = GetScriptForWitness(p2pk);
+ CScript scriptSig = CScript();
+ CScriptWitness scriptWitness;
+ scriptWitness.stack.push_back(std::vector<unsigned char>(0));
+ scriptWitness.stack.push_back(std::vector<unsigned char>(0));
+
+
+ BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness);
+ assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 1);
+ // No signature operations if we don't verify the witness.
+ assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags & ~SCRIPT_VERIFY_WITNESS) == 0);
+ assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_EQUALVERIFY);
+
+ // The sig op cost for witness version != 0 is zero.
+ assert(scriptPubKey[0] == 0x00);
+ scriptPubKey[0] = 0x51;
+ BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness);
+ assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 0);
+ scriptPubKey[0] = 0x00;
+ BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness);
+
+ // The witness of a coinbase transaction is not taken into account.
+ spendingTx.vin[0].prevout.SetNull();
+ assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 0);
+ }
+
+ // P2WPKH nested in P2SH
+ {
+ CScript p2pk = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
+ CScript scriptSig = GetScriptForWitness(p2pk);
+ CScript scriptPubKey = GetScriptForDestination(CScriptID(scriptSig));
+ scriptSig = CScript() << ToByteVector(scriptSig);
+ CScriptWitness scriptWitness;
+ scriptWitness.stack.push_back(std::vector<unsigned char>(0));
+ scriptWitness.stack.push_back(std::vector<unsigned char>(0));
+
+ BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness);
+ assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 1);
+ assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_EQUALVERIFY);
+ }
+
+ // P2WSH witness program
+ {
+ CScript witnessScript = CScript() << 1 << ToByteVector(pubkey) << ToByteVector(pubkey) << 2 << OP_CHECKMULTISIGVERIFY;
+ CScript scriptPubKey = GetScriptForWitness(witnessScript);
+ CScript scriptSig = CScript();
+ CScriptWitness scriptWitness;
+ scriptWitness.stack.push_back(std::vector<unsigned char>(0));
+ scriptWitness.stack.push_back(std::vector<unsigned char>(0));
+ scriptWitness.stack.push_back(std::vector<unsigned char>(witnessScript.begin(), witnessScript.end()));
+
+ BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness);
+ assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 2);
+ assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags & ~SCRIPT_VERIFY_WITNESS) == 0);
+ assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY);
+ }
+
+ // P2WSH nested in P2SH
+ {
+ CScript witnessScript = CScript() << 1 << ToByteVector(pubkey) << ToByteVector(pubkey) << 2 << OP_CHECKMULTISIGVERIFY;
+ CScript redeemScript = GetScriptForWitness(witnessScript);
+ CScript scriptPubKey = GetScriptForDestination(CScriptID(redeemScript));
+ CScript scriptSig = CScript() << ToByteVector(redeemScript);
+ CScriptWitness scriptWitness;
+ scriptWitness.stack.push_back(std::vector<unsigned char>(0));
+ scriptWitness.stack.push_back(std::vector<unsigned char>(0));
+ scriptWitness.stack.push_back(std::vector<unsigned char>(witnessScript.begin(), witnessScript.end()));
+
+ BuildTxs(spendingTx, coins, creationTx, scriptPubKey, scriptSig, scriptWitness);
+ assert(GetTransactionSigOpCost(CTransaction(spendingTx), coins, flags) == 2);
+ assert(VerifyWithFlag(creationTx, spendingTx, flags) == SCRIPT_ERR_CHECKMULTISIGVERIFY);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp
new file mode 100644
index 0000000000..bcd2a9c7b6
--- /dev/null
+++ b/src/test/skiplist_tests.cpp
@@ -0,0 +1,180 @@
+// Copyright (c) 2014-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <chain.h>
+#include <util.h>
+#include <test/test_bitcoin.h>
+
+#include <vector>
+
+#include <boost/test/unit_test.hpp>
+
+#define SKIPLIST_LENGTH 300000
+
+BOOST_FIXTURE_TEST_SUITE(skiplist_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(skiplist_test)
+{
+ std::vector<CBlockIndex> vIndex(SKIPLIST_LENGTH);
+
+ for (int i=0; i<SKIPLIST_LENGTH; i++) {
+ vIndex[i].nHeight = i;
+ vIndex[i].pprev = (i == 0) ? nullptr : &vIndex[i - 1];
+ vIndex[i].BuildSkip();
+ }
+
+ for (int i=0; i<SKIPLIST_LENGTH; i++) {
+ if (i > 0) {
+ BOOST_CHECK(vIndex[i].pskip == &vIndex[vIndex[i].pskip->nHeight]);
+ BOOST_CHECK(vIndex[i].pskip->nHeight < i);
+ } else {
+ BOOST_CHECK(vIndex[i].pskip == nullptr);
+ }
+ }
+
+ for (int i=0; i < 1000; i++) {
+ int from = InsecureRandRange(SKIPLIST_LENGTH - 1);
+ int to = InsecureRandRange(from + 1);
+
+ BOOST_CHECK(vIndex[SKIPLIST_LENGTH - 1].GetAncestor(from) == &vIndex[from]);
+ BOOST_CHECK(vIndex[from].GetAncestor(to) == &vIndex[to]);
+ BOOST_CHECK(vIndex[from].GetAncestor(0) == vIndex.data());
+ }
+}
+
+BOOST_AUTO_TEST_CASE(getlocator_test)
+{
+ // Build a main chain 100000 blocks long.
+ std::vector<uint256> vHashMain(100000);
+ std::vector<CBlockIndex> vBlocksMain(100000);
+ for (unsigned int i=0; i<vBlocksMain.size(); i++) {
+ vHashMain[i] = ArithToUint256(i); // Set the hash equal to the height, so we can quickly check the distances.
+ vBlocksMain[i].nHeight = i;
+ vBlocksMain[i].pprev = i ? &vBlocksMain[i - 1] : nullptr;
+ vBlocksMain[i].phashBlock = &vHashMain[i];
+ vBlocksMain[i].BuildSkip();
+ BOOST_CHECK_EQUAL((int)UintToArith256(vBlocksMain[i].GetBlockHash()).GetLow64(), vBlocksMain[i].nHeight);
+ BOOST_CHECK(vBlocksMain[i].pprev == nullptr || vBlocksMain[i].nHeight == vBlocksMain[i].pprev->nHeight + 1);
+ }
+
+ // Build a branch that splits off at block 49999, 50000 blocks long.
+ std::vector<uint256> vHashSide(50000);
+ std::vector<CBlockIndex> vBlocksSide(50000);
+ for (unsigned int i=0; i<vBlocksSide.size(); i++) {
+ vHashSide[i] = ArithToUint256(i + 50000 + (arith_uint256(1) << 128)); // Add 1<<128 to the hashes, so GetLow64() still returns the height.
+ vBlocksSide[i].nHeight = i + 50000;
+ vBlocksSide[i].pprev = i ? &vBlocksSide[i - 1] : (vBlocksMain.data()+49999);
+ vBlocksSide[i].phashBlock = &vHashSide[i];
+ vBlocksSide[i].BuildSkip();
+ BOOST_CHECK_EQUAL((int)UintToArith256(vBlocksSide[i].GetBlockHash()).GetLow64(), vBlocksSide[i].nHeight);
+ BOOST_CHECK(vBlocksSide[i].pprev == nullptr || vBlocksSide[i].nHeight == vBlocksSide[i].pprev->nHeight + 1);
+ }
+
+ // Build a CChain for the main branch.
+ CChain chain;
+ chain.SetTip(&vBlocksMain.back());
+
+ // Test 100 random starting points for locators.
+ for (int n=0; n<100; n++) {
+ int r = InsecureRandRange(150000);
+ CBlockIndex* tip = (r < 100000) ? &vBlocksMain[r] : &vBlocksSide[r - 100000];
+ CBlockLocator locator = chain.GetLocator(tip);
+
+ // The first result must be the block itself, the last one must be genesis.
+ BOOST_CHECK(locator.vHave.front() == tip->GetBlockHash());
+ BOOST_CHECK(locator.vHave.back() == vBlocksMain[0].GetBlockHash());
+
+ // Entries 1 through 11 (inclusive) go back one step each.
+ for (unsigned int i = 1; i < 12 && i < locator.vHave.size() - 1; i++) {
+ BOOST_CHECK_EQUAL(UintToArith256(locator.vHave[i]).GetLow64(), tip->nHeight - i);
+ }
+
+ // The further ones (excluding the last one) go back with exponential steps.
+ unsigned int dist = 2;
+ for (unsigned int i = 12; i < locator.vHave.size() - 1; i++) {
+ BOOST_CHECK_EQUAL(UintToArith256(locator.vHave[i - 1]).GetLow64() - UintToArith256(locator.vHave[i]).GetLow64(), dist);
+ dist *= 2;
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(findearliestatleast_test)
+{
+ std::vector<uint256> vHashMain(100000);
+ std::vector<CBlockIndex> vBlocksMain(100000);
+ for (unsigned int i=0; i<vBlocksMain.size(); i++) {
+ vHashMain[i] = ArithToUint256(i); // Set the hash equal to the height
+ vBlocksMain[i].nHeight = i;
+ vBlocksMain[i].pprev = i ? &vBlocksMain[i - 1] : nullptr;
+ vBlocksMain[i].phashBlock = &vHashMain[i];
+ vBlocksMain[i].BuildSkip();
+ if (i < 10) {
+ vBlocksMain[i].nTime = i;
+ vBlocksMain[i].nTimeMax = i;
+ } else {
+ // randomly choose something in the range [MTP, MTP*2]
+ int64_t medianTimePast = vBlocksMain[i].GetMedianTimePast();
+ int r = InsecureRandRange(medianTimePast);
+ vBlocksMain[i].nTime = r + medianTimePast;
+ vBlocksMain[i].nTimeMax = std::max(vBlocksMain[i].nTime, vBlocksMain[i-1].nTimeMax);
+ }
+ }
+ // Check that we set nTimeMax up correctly.
+ unsigned int curTimeMax = 0;
+ for (unsigned int i=0; i<vBlocksMain.size(); ++i) {
+ curTimeMax = std::max(curTimeMax, vBlocksMain[i].nTime);
+ BOOST_CHECK(curTimeMax == vBlocksMain[i].nTimeMax);
+ }
+
+ // Build a CChain for the main branch.
+ CChain chain;
+ chain.SetTip(&vBlocksMain.back());
+
+ // Verify that FindEarliestAtLeast is correct.
+ for (unsigned int i=0; i<10000; ++i) {
+ // Pick a random element in vBlocksMain.
+ int r = InsecureRandRange(vBlocksMain.size());
+ int64_t test_time = vBlocksMain[r].nTime;
+ CBlockIndex *ret = chain.FindEarliestAtLeast(test_time);
+ BOOST_CHECK(ret->nTimeMax >= test_time);
+ BOOST_CHECK((ret->pprev==nullptr) || ret->pprev->nTimeMax < test_time);
+ BOOST_CHECK(vBlocksMain[r].GetAncestor(ret->nHeight) == ret);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(findearliestatleast_edge_test)
+{
+ std::list<CBlockIndex> blocks;
+ for (unsigned int timeMax : {100, 100, 100, 200, 200, 200, 300, 300, 300}) {
+ CBlockIndex* prev = blocks.empty() ? nullptr : &blocks.back();
+ blocks.emplace_back();
+ blocks.back().nHeight = prev ? prev->nHeight + 1 : 0;
+ blocks.back().pprev = prev;
+ blocks.back().BuildSkip();
+ blocks.back().nTimeMax = timeMax;
+ }
+
+ CChain chain;
+ chain.SetTip(&blocks.back());
+
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(50)->nHeight, 0);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(100)->nHeight, 0);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(150)->nHeight, 3);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(200)->nHeight, 3);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(250)->nHeight, 6);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(300)->nHeight, 6);
+ BOOST_CHECK(!chain.FindEarliestAtLeast(350));
+
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0)->nHeight, 0);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(-1)->nHeight, 0);
+
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(std::numeric_limits<int64_t>::min())->nHeight, 0);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(std::numeric_limits<unsigned int>::min())->nHeight, 0);
+ BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(-int64_t(std::numeric_limits<unsigned int>::max()) - 1)->nHeight, 0);
+ BOOST_CHECK(!chain.FindEarliestAtLeast(std::numeric_limits<int64_t>::max()));
+ BOOST_CHECK(!chain.FindEarliestAtLeast(std::numeric_limits<unsigned int>::max()));
+ BOOST_CHECK(!chain.FindEarliestAtLeast(int64_t(std::numeric_limits<unsigned int>::max()) + 1));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp
new file mode 100644
index 0000000000..6a0aa864d9
--- /dev/null
+++ b/src/test/streams_tests.cpp
@@ -0,0 +1,126 @@
+// Copyright (c) 2012-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <streams.h>
+#include <support/allocators/zeroafterfree.h>
+#include <test/test_bitcoin.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(streams_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(streams_vector_writer)
+{
+ unsigned char a(1);
+ unsigned char b(2);
+ unsigned char bytes[] = { 3, 4, 5, 6 };
+ std::vector<unsigned char> vch;
+
+ // Each test runs twice. Serializing a second time at the same starting
+ // point should yield the same results, even if the first test grew the
+ // vector.
+
+ CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 0, a, b);
+ BOOST_CHECK((vch == std::vector<unsigned char>{{1, 2}}));
+ CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 0, a, b);
+ BOOST_CHECK((vch == std::vector<unsigned char>{{1, 2}}));
+ vch.clear();
+
+ CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 2, a, b);
+ BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 1, 2}}));
+ CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 2, a, b);
+ BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 1, 2}}));
+ vch.clear();
+
+ vch.resize(5, 0);
+ CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 2, a, b);
+ BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 1, 2, 0}}));
+ CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 2, a, b);
+ BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 1, 2, 0}}));
+ vch.clear();
+
+ vch.resize(4, 0);
+ CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 3, a, b);
+ BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 0, 1, 2}}));
+ CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 3, a, b);
+ BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 0, 1, 2}}));
+ vch.clear();
+
+ vch.resize(4, 0);
+ CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 4, a, b);
+ BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 0, 0, 1, 2}}));
+ CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 4, a, b);
+ BOOST_CHECK((vch == std::vector<unsigned char>{{0, 0, 0, 0, 1, 2}}));
+ vch.clear();
+
+ CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 0, bytes);
+ BOOST_CHECK((vch == std::vector<unsigned char>{{3, 4, 5, 6}}));
+ CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 0, bytes);
+ BOOST_CHECK((vch == std::vector<unsigned char>{{3, 4, 5, 6}}));
+ vch.clear();
+
+ vch.resize(4, 8);
+ CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 2, a, bytes, b);
+ BOOST_CHECK((vch == std::vector<unsigned char>{{8, 8, 1, 3, 4, 5, 6, 2}}));
+ CVectorWriter(SER_NETWORK, INIT_PROTO_VERSION, vch, 2, a, bytes, b);
+ BOOST_CHECK((vch == std::vector<unsigned char>{{8, 8, 1, 3, 4, 5, 6, 2}}));
+ vch.clear();
+}
+
+BOOST_AUTO_TEST_CASE(streams_serializedata_xor)
+{
+ std::vector<char> in;
+ std::vector<char> expected_xor;
+ std::vector<unsigned char> key;
+ CDataStream ds(in, 0, 0);
+
+ // Degenerate case
+
+ key.push_back('\x00');
+ key.push_back('\x00');
+ ds.Xor(key);
+ BOOST_CHECK_EQUAL(
+ std::string(expected_xor.begin(), expected_xor.end()),
+ std::string(ds.begin(), ds.end()));
+
+ in.push_back('\x0f');
+ in.push_back('\xf0');
+ expected_xor.push_back('\xf0');
+ expected_xor.push_back('\x0f');
+
+ // Single character key
+
+ ds.clear();
+ ds.insert(ds.begin(), in.begin(), in.end());
+ key.clear();
+
+ key.push_back('\xff');
+ ds.Xor(key);
+ BOOST_CHECK_EQUAL(
+ std::string(expected_xor.begin(), expected_xor.end()),
+ std::string(ds.begin(), ds.end()));
+
+ // Multi character key
+
+ in.clear();
+ expected_xor.clear();
+ in.push_back('\xf0');
+ in.push_back('\x0f');
+ expected_xor.push_back('\x0f');
+ expected_xor.push_back('\x00');
+
+ ds.clear();
+ ds.insert(ds.begin(), in.begin(), in.end());
+
+ key.clear();
+ key.push_back('\xff');
+ key.push_back('\x0f');
+
+ ds.Xor(key);
+ BOOST_CHECK_EQUAL(
+ std::string(expected_xor.begin(), expected_xor.end()),
+ std::string(ds.begin(), ds.end()));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
new file mode 100644
index 0000000000..9c3285fb0c
--- /dev/null
+++ b/src/test/test_bitcoin.cpp
@@ -0,0 +1,199 @@
+// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <test/test_bitcoin.h>
+
+#include <chainparams.h>
+#include <consensus/consensus.h>
+#include <consensus/validation.h>
+#include <crypto/sha256.h>
+#include <validation.h>
+#include <miner.h>
+#include <net_processing.h>
+#include <pow.h>
+#include <ui_interface.h>
+#include <streams.h>
+#include <rpc/server.h>
+#include <rpc/register.h>
+#include <script/sigcache.h>
+
+void CConnmanTest::AddNode(CNode& node)
+{
+ LOCK(g_connman->cs_vNodes);
+ g_connman->vNodes.push_back(&node);
+}
+
+void CConnmanTest::ClearNodes()
+{
+ LOCK(g_connman->cs_vNodes);
+ for (CNode* node : g_connman->vNodes) {
+ delete node;
+ }
+ g_connman->vNodes.clear();
+}
+
+uint256 insecure_rand_seed = GetRandHash();
+FastRandomContext insecure_rand_ctx(insecure_rand_seed);
+
+extern bool fPrintToConsole;
+extern void noui_connect();
+
+std::ostream& operator<<(std::ostream& os, const uint256& num)
+{
+ os << num.ToString();
+ return os;
+}
+
+BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
+ : m_path_root(fs::temp_directory_path() / "test_bitcoin" / strprintf("%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(1 << 30))))
+{
+ SHA256AutoDetect();
+ RandomInit();
+ ECC_Start();
+ SetupEnvironment();
+ SetupNetworking();
+ InitSignatureCache();
+ InitScriptExecutionCache();
+ fCheckBlockIndex = true;
+ SelectParams(chainName);
+ noui_connect();
+}
+
+BasicTestingSetup::~BasicTestingSetup()
+{
+ fs::remove_all(m_path_root);
+ ECC_Stop();
+}
+
+fs::path BasicTestingSetup::SetDataDir(const std::string& name)
+{
+ fs::path ret = m_path_root / name;
+ fs::create_directories(ret);
+ gArgs.ForceSetArg("-datadir", ret.string());
+ return ret;
+}
+
+TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(chainName)
+{
+ SetDataDir("tempdir");
+ const CChainParams& chainparams = Params();
+ // Ideally we'd move all the RPC tests to the functional testing framework
+ // instead of unit tests, but for now we need these here.
+
+ RegisterAllCoreRPCCommands(tableRPC);
+ ClearDatadirCache();
+
+ // We have to run a scheduler thread to prevent ActivateBestChain
+ // from blocking due to queue overrun.
+ threadGroup.create_thread(boost::bind(&CScheduler::serviceQueue, &scheduler));
+ GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
+
+ mempool.setSanityCheck(1.0);
+ pblocktree.reset(new CBlockTreeDB(1 << 20, true));
+ pcoinsdbview.reset(new CCoinsViewDB(1 << 23, true));
+ pcoinsTip.reset(new CCoinsViewCache(pcoinsdbview.get()));
+ if (!LoadGenesisBlock(chainparams)) {
+ throw std::runtime_error("LoadGenesisBlock failed.");
+ }
+ {
+ CValidationState state;
+ if (!ActivateBestChain(state, chainparams)) {
+ throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", FormatStateMessage(state)));
+ }
+ }
+ nScriptCheckThreads = 3;
+ for (int i=0; i < nScriptCheckThreads-1; i++)
+ threadGroup.create_thread(&ThreadScriptCheck);
+ g_connman = std::unique_ptr<CConnman>(new CConnman(0x1337, 0x1337)); // Deterministic randomness for tests.
+ connman = g_connman.get();
+ peerLogic.reset(new PeerLogicValidation(connman, scheduler, /*enable_bip61=*/true));
+}
+
+TestingSetup::~TestingSetup()
+{
+ threadGroup.interrupt_all();
+ threadGroup.join_all();
+ GetMainSignals().FlushBackgroundCallbacks();
+ GetMainSignals().UnregisterBackgroundSignalScheduler();
+ g_connman.reset();
+ peerLogic.reset();
+ UnloadBlockIndex();
+ pcoinsTip.reset();
+ pcoinsdbview.reset();
+ pblocktree.reset();
+}
+
+TestChain100Setup::TestChain100Setup() : TestingSetup(CBaseChainParams::REGTEST)
+{
+ // CreateAndProcessBlock() does not support building SegWit blocks, so don't activate in these tests.
+ // TODO: fix the code to support SegWit blocks.
+ UpdateVersionBitsParameters(Consensus::DEPLOYMENT_SEGWIT, 0, Consensus::BIP9Deployment::NO_TIMEOUT);
+ // Generate a 100-block chain:
+ coinbaseKey.MakeNewKey(true);
+ CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
+ for (int i = 0; i < COINBASE_MATURITY; i++)
+ {
+ std::vector<CMutableTransaction> noTxns;
+ CBlock b = CreateAndProcessBlock(noTxns, scriptPubKey);
+ m_coinbase_txns.push_back(b.vtx[0]);
+ }
+}
+
+//
+// Create a new block with just given transactions, coinbase paying to
+// scriptPubKey, and try to add it to the current chain.
+//
+CBlock
+TestChain100Setup::CreateAndProcessBlock(const std::vector<CMutableTransaction>& txns, const CScript& scriptPubKey)
+{
+ const CChainParams& chainparams = Params();
+ std::unique_ptr<CBlockTemplate> pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey);
+ CBlock& block = pblocktemplate->block;
+
+ // Replace mempool-selected txns with just coinbase plus passed-in txns:
+ block.vtx.resize(1);
+ for (const CMutableTransaction& tx : txns)
+ block.vtx.push_back(MakeTransactionRef(tx));
+ // IncrementExtraNonce creates a valid coinbase and merkleRoot
+ {
+ LOCK(cs_main);
+ unsigned int extraNonce = 0;
+ IncrementExtraNonce(&block, chainActive.Tip(), extraNonce);
+ }
+
+ while (!CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus())) ++block.nNonce;
+
+ std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(block);
+ ProcessNewBlock(chainparams, shared_pblock, true, nullptr);
+
+ CBlock result = block;
+ return result;
+}
+
+TestChain100Setup::~TestChain100Setup()
+{
+}
+
+
+CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CMutableTransaction &tx) {
+ return FromTx(MakeTransactionRef(tx));
+}
+
+CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CTransactionRef& tx)
+{
+ return CTxMemPoolEntry(tx, nFee, nTime, nHeight,
+ spendsCoinbase, sigOpCost, lp);
+}
+
+/**
+ * @returns a real block (0000000000013b8ab2cd513b0261a14096412195a72a0c4827d229dcc7e0f7af)
+ * with 9 txs.
+ */
+CBlock getBlock13b8a()
+{
+ CBlock block;
+ CDataStream stream(ParseHex("0100000090f0a9f110702f808219ebea1173056042a714bad51b916cb6800000000000005275289558f51c9966699404ae2294730c3c9f9bda53523ce50e9b95e558da2fdb261b4d4c86041b1ab1bf930901000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07044c86041b0146ffffffff0100f2052a01000000434104e18f7afbe4721580e81e8414fc8c24d7cfacf254bb5c7b949450c3e997c2dc1242487a8169507b631eb3771f2b425483fb13102c4eb5d858eef260fe70fbfae0ac00000000010000000196608ccbafa16abada902780da4dc35dafd7af05fa0da08cf833575f8cf9e836000000004a493046022100dab24889213caf43ae6adc41cf1c9396c08240c199f5225acf45416330fd7dbd022100fe37900e0644bf574493a07fc5edba06dbc07c311b947520c2d514bc5725dcb401ffffffff0100f2052a010000001976a914f15d1921f52e4007b146dfa60f369ed2fc393ce288ac000000000100000001fb766c1288458c2bafcfec81e48b24d98ec706de6b8af7c4e3c29419bfacb56d000000008c493046022100f268ba165ce0ad2e6d93f089cfcd3785de5c963bb5ea6b8c1b23f1ce3e517b9f022100da7c0f21adc6c401887f2bfd1922f11d76159cbc597fbd756a23dcbb00f4d7290141042b4e8625a96127826915a5b109852636ad0da753c9e1d5606a50480cd0c40f1f8b8d898235e571fe9357d9ec842bc4bba1827daaf4de06d71844d0057707966affffffff0280969800000000001976a9146963907531db72d0ed1a0cfb471ccb63923446f388ac80d6e34c000000001976a914f0688ba1c0d1ce182c7af6741e02658c7d4dfcd388ac000000000100000002c40297f730dd7b5a99567eb8d27b78758f607507c52292d02d4031895b52f2ff010000008b483045022100f7edfd4b0aac404e5bab4fd3889e0c6c41aa8d0e6fa122316f68eddd0a65013902205b09cc8b2d56e1cd1f7f2fafd60a129ed94504c4ac7bdc67b56fe67512658b3e014104732012cb962afa90d31b25d8fb0e32c94e513ab7a17805c14ca4c3423e18b4fb5d0e676841733cb83abaf975845c9f6f2a8097b7d04f4908b18368d6fc2d68ecffffffffca5065ff9617cbcba45eb23726df6498a9b9cafed4f54cbab9d227b0035ddefb000000008a473044022068010362a13c7f9919fa832b2dee4e788f61f6f5d344a7c2a0da6ae740605658022006d1af525b9a14a35c003b78b72bd59738cd676f845d1ff3fc25049e01003614014104732012cb962afa90d31b25d8fb0e32c94e513ab7a17805c14ca4c3423e18b4fb5d0e676841733cb83abaf975845c9f6f2a8097b7d04f4908b18368d6fc2d68ecffffffff01001ec4110200000043410469ab4181eceb28985b9b4e895c13fa5e68d85761b7eee311db5addef76fa8621865134a221bd01f28ec9999ee3e021e60766e9d1f3458c115fb28650605f11c9ac000000000100000001cdaf2f758e91c514655e2dc50633d1e4c84989f8aa90a0dbc883f0d23ed5c2fa010000008b48304502207ab51be6f12a1962ba0aaaf24a20e0b69b27a94fac5adf45aa7d2d18ffd9236102210086ae728b370e5329eead9accd880d0cb070aea0c96255fae6c4f1ddcce1fd56e014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff02404b4c00000000001976a9142b6ba7c9d796b75eef7942fc9288edd37c32f5c388ac002d3101000000001976a9141befba0cdc1ad56529371864d9f6cb042faa06b588ac000000000100000001b4a47603e71b61bc3326efd90111bf02d2f549b067f4c4a8fa183b57a0f800cb010000008a4730440220177c37f9a505c3f1a1f0ce2da777c339bd8339ffa02c7cb41f0a5804f473c9230220585b25a2ee80eb59292e52b987dad92acb0c64eced92ed9ee105ad153cdb12d001410443bd44f683467e549dae7d20d1d79cbdb6df985c6e9c029c8d0c6cb46cc1a4d3cf7923c5021b27f7a0b562ada113bc85d5fda5a1b41e87fe6e8802817cf69996ffffffff0280651406000000001976a9145505614859643ab7b547cd7f1f5e7e2a12322d3788ac00aa0271000000001976a914ea4720a7a52fc166c55ff2298e07baf70ae67e1b88ac00000000010000000586c62cd602d219bb60edb14a3e204de0705176f9022fe49a538054fb14abb49e010000008c493046022100f2bc2aba2534becbdf062eb993853a42bbbc282083d0daf9b4b585bd401aa8c9022100b1d7fd7ee0b95600db8535bbf331b19eed8d961f7a8e54159c53675d5f69df8c014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff03ad0e58ccdac3df9dc28a218bcf6f1997b0a93306faaa4b3a28ae83447b2179010000008b483045022100be12b2937179da88599e27bb31c3525097a07cdb52422d165b3ca2f2020ffcf702200971b51f853a53d644ebae9ec8f3512e442b1bcb6c315a5b491d119d10624c83014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff2acfcab629bbc8685792603762c921580030ba144af553d271716a95089e107b010000008b483045022100fa579a840ac258871365dd48cd7552f96c8eea69bd00d84f05b283a0dab311e102207e3c0ee9234814cfbb1b659b83671618f45abc1326b9edcc77d552a4f2a805c0014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffffdcdc6023bbc9944a658ddc588e61eacb737ddf0a3cd24f113b5a8634c517fcd2000000008b4830450221008d6df731df5d32267954bd7d2dda2302b74c6c2a6aa5c0ca64ecbabc1af03c75022010e55c571d65da7701ae2da1956c442df81bbf076cdbac25133f99d98a9ed34c014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffffe15557cd5ce258f479dfd6dc6514edf6d7ed5b21fcfa4a038fd69f06b83ac76e010000008b483045022023b3e0ab071eb11de2eb1cc3a67261b866f86bf6867d4558165f7c8c8aca2d86022100dc6e1f53a91de3efe8f63512850811f26284b62f850c70ca73ed5de8771fb451014104462e76fd4067b3a0aa42070082dcb0bf2f388b6495cf33d789904f07d0f55c40fbd4b82963c69b3dc31895d0c772c812b1d5fbcade15312ef1c0e8ebbb12dcd4ffffffff01404b4c00000000001976a9142b6ba7c9d796b75eef7942fc9288edd37c32f5c388ac00000000010000000166d7577163c932b4f9690ca6a80b6e4eb001f0a2fa9023df5595602aae96ed8d000000008a4730440220262b42546302dfb654a229cefc86432b89628ff259dc87edd1154535b16a67e102207b4634c020a97c3e7bbd0d4d19da6aa2269ad9dded4026e896b213d73ca4b63f014104979b82d02226b3a4597523845754d44f13639e3bf2df5e82c6aab2bdc79687368b01b1ab8b19875ae3c90d661a3d0a33161dab29934edeb36aa01976be3baf8affffffff02404b4c00000000001976a9144854e695a02af0aeacb823ccbc272134561e0a1688ac40420f00000000001976a914abee93376d6b37b5c2940655a6fcaf1c8e74237988ac0000000001000000014e3f8ef2e91349a9059cb4f01e54ab2597c1387161d3da89919f7ea6acdbb371010000008c49304602210081f3183471a5ca22307c0800226f3ef9c353069e0773ac76bb580654d56aa523022100d4c56465bdc069060846f4fbf2f6b20520b2a80b08b168b31e66ddb9c694e240014104976c79848e18251612f8940875b2b08d06e6dc73b9840e8860c066b7e87432c477e9a59a453e71e6d76d5fe34058b800a098fc1740ce3012e8fc8a00c96af966ffffffff02c0e1e400000000001976a9144134e75a6fcb6042034aab5e18570cf1f844f54788ac404b4c00000000001976a9142b6ba7c9d796b75eef7942fc9288edd37c32f5c388ac00000000"), SER_NETWORK, PROTOCOL_VERSION);
+ stream >> block;
+ return block;
+}
diff --git a/src/test/test_bitcoin.h b/src/test/test_bitcoin.h
new file mode 100644
index 0000000000..b87d9bea5d
--- /dev/null
+++ b/src/test/test_bitcoin.h
@@ -0,0 +1,130 @@
+// Copyright (c) 2015-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_TEST_TEST_BITCOIN_H
+#define BITCOIN_TEST_TEST_BITCOIN_H
+
+#include <chainparamsbase.h>
+#include <fs.h>
+#include <key.h>
+#include <pubkey.h>
+#include <random.h>
+#include <scheduler.h>
+#include <txdb.h>
+#include <txmempool.h>
+
+#include <memory>
+
+#include <boost/thread.hpp>
+
+extern uint256 insecure_rand_seed;
+extern FastRandomContext insecure_rand_ctx;
+
+static inline void SeedInsecureRand(bool fDeterministic = false)
+{
+ if (fDeterministic) {
+ insecure_rand_seed = uint256();
+ } else {
+ insecure_rand_seed = GetRandHash();
+ }
+ insecure_rand_ctx = FastRandomContext(insecure_rand_seed);
+}
+
+static inline uint32_t InsecureRand32() { return insecure_rand_ctx.rand32(); }
+static inline uint256 InsecureRand256() { return insecure_rand_ctx.rand256(); }
+static inline uint64_t InsecureRandBits(int bits) { return insecure_rand_ctx.randbits(bits); }
+static inline uint64_t InsecureRandRange(uint64_t range) { return insecure_rand_ctx.randrange(range); }
+static inline bool InsecureRandBool() { return insecure_rand_ctx.randbool(); }
+
+/** Basic testing setup.
+ * This just configures logging and chain parameters.
+ */
+struct BasicTestingSetup {
+ ECCVerifyHandle globalVerifyHandle;
+
+ explicit BasicTestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
+ ~BasicTestingSetup();
+
+ fs::path SetDataDir(const std::string& name);
+
+private:
+ const fs::path m_path_root;
+};
+
+/** Testing setup that configures a complete environment.
+ * Included are data directory, coins database, script check threads setup.
+ */
+class CConnman;
+class CNode;
+struct CConnmanTest {
+ static void AddNode(CNode& node);
+ static void ClearNodes();
+};
+
+class PeerLogicValidation;
+struct TestingSetup: public BasicTestingSetup {
+ boost::thread_group threadGroup;
+ CConnman* connman;
+ CScheduler scheduler;
+ std::unique_ptr<PeerLogicValidation> peerLogic;
+
+ explicit TestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
+ ~TestingSetup();
+};
+
+class CBlock;
+struct CMutableTransaction;
+class CScript;
+
+//
+// Testing fixture that pre-creates a
+// 100-block REGTEST-mode block chain
+//
+struct TestChain100Setup : public TestingSetup {
+ TestChain100Setup();
+
+ // Create a new block with just given transactions, coinbase paying to
+ // scriptPubKey, and try to add it to the current chain.
+ CBlock CreateAndProcessBlock(const std::vector<CMutableTransaction>& txns,
+ const CScript& scriptPubKey);
+
+ ~TestChain100Setup();
+
+ std::vector<CTransactionRef> m_coinbase_txns; // For convenience, coinbase transactions
+ CKey coinbaseKey; // private/public key needed to spend coinbase transactions
+};
+
+class CTxMemPoolEntry;
+
+struct TestMemPoolEntryHelper
+{
+ // Default values
+ CAmount nFee;
+ int64_t nTime;
+ unsigned int nHeight;
+ bool spendsCoinbase;
+ unsigned int sigOpCost;
+ LockPoints lp;
+
+ TestMemPoolEntryHelper() :
+ nFee(0), nTime(0), nHeight(1),
+ spendsCoinbase(false), sigOpCost(4) { }
+
+ CTxMemPoolEntry FromTx(const CMutableTransaction& tx);
+ CTxMemPoolEntry FromTx(const CTransactionRef& tx);
+
+ // Change the default value
+ TestMemPoolEntryHelper &Fee(CAmount _fee) { nFee = _fee; return *this; }
+ TestMemPoolEntryHelper &Time(int64_t _time) { nTime = _time; return *this; }
+ TestMemPoolEntryHelper &Height(unsigned int _height) { nHeight = _height; return *this; }
+ TestMemPoolEntryHelper &SpendsCoinbase(bool _flag) { spendsCoinbase = _flag; return *this; }
+ TestMemPoolEntryHelper &SigOpsCost(unsigned int _sigopsCost) { sigOpCost = _sigopsCost; return *this; }
+};
+
+CBlock getBlock13b8a();
+
+// define an implicit conversion here so that uint256 may be used directly in BOOST_CHECK_*
+std::ostream& operator<<(std::ostream& os, const uint256& num);
+
+#endif
diff --git a/src/test/test_bitcoin_fuzzy.cpp b/src/test/test_bitcoin_fuzzy.cpp
new file mode 100644
index 0000000000..4d835db7be
--- /dev/null
+++ b/src/test/test_bitcoin_fuzzy.cpp
@@ -0,0 +1,329 @@
+// Copyright (c) 2009-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#if defined(HAVE_CONFIG_H)
+#include <config/bitcoin-config.h>
+#endif
+
+#include <consensus/merkle.h>
+#include <primitives/block.h>
+#include <script/script.h>
+#include <addrman.h>
+#include <chain.h>
+#include <coins.h>
+#include <compressor.h>
+#include <net.h>
+#include <protocol.h>
+#include <streams.h>
+#include <undo.h>
+#include <version.h>
+#include <pubkey.h>
+#include <blockencodings.h>
+
+#include <stdint.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <memory>
+#include <vector>
+
+enum TEST_ID {
+ CBLOCK_DESERIALIZE=0,
+ CTRANSACTION_DESERIALIZE,
+ CBLOCKLOCATOR_DESERIALIZE,
+ CBLOCKMERKLEROOT,
+ CADDRMAN_DESERIALIZE,
+ CBLOCKHEADER_DESERIALIZE,
+ CBANENTRY_DESERIALIZE,
+ CTXUNDO_DESERIALIZE,
+ CBLOCKUNDO_DESERIALIZE,
+ CCOINS_DESERIALIZE,
+ CNETADDR_DESERIALIZE,
+ CSERVICE_DESERIALIZE,
+ CMESSAGEHEADER_DESERIALIZE,
+ CADDRESS_DESERIALIZE,
+ CINV_DESERIALIZE,
+ CBLOOMFILTER_DESERIALIZE,
+ CDISKBLOCKINDEX_DESERIALIZE,
+ CTXOUTCOMPRESSOR_DESERIALIZE,
+ BLOCKTRANSACTIONS_DESERIALIZE,
+ BLOCKTRANSACTIONSREQUEST_DESERIALIZE,
+ TEST_ID_END
+};
+
+static bool read_stdin(std::vector<uint8_t> &data) {
+ uint8_t buffer[1024];
+ ssize_t length=0;
+ while((length = read(STDIN_FILENO, buffer, 1024)) > 0) {
+ data.insert(data.end(), buffer, buffer+length);
+
+ if (data.size() > (1<<20)) return false;
+ }
+ return length==0;
+}
+
+static int test_one_input(std::vector<uint8_t> buffer) {
+ if (buffer.size() < sizeof(uint32_t)) return 0;
+
+ uint32_t test_id = 0xffffffff;
+ memcpy(&test_id, buffer.data(), sizeof(uint32_t));
+ buffer.erase(buffer.begin(), buffer.begin() + sizeof(uint32_t));
+
+ if (test_id >= TEST_ID_END) return 0;
+
+ CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION);
+ try {
+ int nVersion;
+ ds >> nVersion;
+ ds.SetVersion(nVersion);
+ } catch (const std::ios_base::failure& e) {
+ return 0;
+ }
+
+ switch(test_id) {
+ case CBLOCK_DESERIALIZE:
+ {
+ try
+ {
+ CBlock block;
+ ds >> block;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CTRANSACTION_DESERIALIZE:
+ {
+ try
+ {
+ CTransaction tx(deserialize, ds);
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CBLOCKLOCATOR_DESERIALIZE:
+ {
+ try
+ {
+ CBlockLocator bl;
+ ds >> bl;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CBLOCKMERKLEROOT:
+ {
+ try
+ {
+ CBlock block;
+ ds >> block;
+ bool mutated;
+ BlockMerkleRoot(block, &mutated);
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CADDRMAN_DESERIALIZE:
+ {
+ try
+ {
+ CAddrMan am;
+ ds >> am;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CBLOCKHEADER_DESERIALIZE:
+ {
+ try
+ {
+ CBlockHeader bh;
+ ds >> bh;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CBANENTRY_DESERIALIZE:
+ {
+ try
+ {
+ CBanEntry be;
+ ds >> be;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CTXUNDO_DESERIALIZE:
+ {
+ try
+ {
+ CTxUndo tu;
+ ds >> tu;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CBLOCKUNDO_DESERIALIZE:
+ {
+ try
+ {
+ CBlockUndo bu;
+ ds >> bu;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CCOINS_DESERIALIZE:
+ {
+ try
+ {
+ Coin coin;
+ ds >> coin;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CNETADDR_DESERIALIZE:
+ {
+ try
+ {
+ CNetAddr na;
+ ds >> na;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CSERVICE_DESERIALIZE:
+ {
+ try
+ {
+ CService s;
+ ds >> s;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CMESSAGEHEADER_DESERIALIZE:
+ {
+ CMessageHeader::MessageStartChars pchMessageStart = {0x00, 0x00, 0x00, 0x00};
+ try
+ {
+ CMessageHeader mh(pchMessageStart);
+ ds >> mh;
+ if (!mh.IsValid(pchMessageStart)) {return 0;}
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CADDRESS_DESERIALIZE:
+ {
+ try
+ {
+ CAddress a;
+ ds >> a;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CINV_DESERIALIZE:
+ {
+ try
+ {
+ CInv i;
+ ds >> i;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CBLOOMFILTER_DESERIALIZE:
+ {
+ try
+ {
+ CBloomFilter bf;
+ ds >> bf;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CDISKBLOCKINDEX_DESERIALIZE:
+ {
+ try
+ {
+ CDiskBlockIndex dbi;
+ ds >> dbi;
+ } catch (const std::ios_base::failure& e) {return 0;}
+ break;
+ }
+ case CTXOUTCOMPRESSOR_DESERIALIZE:
+ {
+ CTxOut to;
+ CTxOutCompressor toc(to);
+ try
+ {
+ ds >> toc;
+ } catch (const std::ios_base::failure& e) {return 0;}
+
+ break;
+ }
+ case BLOCKTRANSACTIONS_DESERIALIZE:
+ {
+ try
+ {
+ BlockTransactions bt;
+ ds >> bt;
+ } catch (const std::ios_base::failure& e) {return 0;}
+
+ break;
+ }
+ case BLOCKTRANSACTIONSREQUEST_DESERIALIZE:
+ {
+ try
+ {
+ BlockTransactionsRequest btr;
+ ds >> btr;
+ } catch (const std::ios_base::failure& e) {return 0;}
+
+ break;
+ }
+ default:
+ return 0;
+ }
+ return 0;
+}
+
+static std::unique_ptr<ECCVerifyHandle> globalVerifyHandle;
+void initialize() {
+ globalVerifyHandle = std::unique_ptr<ECCVerifyHandle>(new ECCVerifyHandle());
+}
+
+// This function is used by libFuzzer
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ test_one_input(std::vector<uint8_t>(data, data + size));
+ return 0;
+}
+
+// This function is used by libFuzzer
+extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
+ initialize();
+ return 0;
+}
+
+// Disabled under WIN32 due to clash with Cygwin's WinMain.
+#ifndef WIN32
+// Declare main(...) "weak" to allow for libFuzzer linking. libFuzzer provides
+// the main(...) function.
+__attribute__((weak))
+#endif
+int main(int argc, char **argv)
+{
+ initialize();
+#ifdef __AFL_INIT
+ // Enable AFL deferred forkserver mode. Requires compilation using
+ // afl-clang-fast++. See fuzzing.md for details.
+ __AFL_INIT();
+#endif
+
+#ifdef __AFL_LOOP
+ // Enable AFL persistent mode. Requires compilation using afl-clang-fast++.
+ // See fuzzing.md for details.
+ int ret = 0;
+ while (__AFL_LOOP(1000)) {
+ std::vector<uint8_t> buffer;
+ if (!read_stdin(buffer)) {
+ continue;
+ }
+ ret = test_one_input(buffer);
+ }
+ return ret;
+#else
+ std::vector<uint8_t> buffer;
+ if (!read_stdin(buffer)) {
+ return 0;
+ }
+ return test_one_input(buffer);
+#endif
+}
diff --git a/src/test/test_bitcoin_main.cpp b/src/test/test_bitcoin_main.cpp
new file mode 100644
index 0000000000..6c066d3fea
--- /dev/null
+++ b/src/test/test_bitcoin_main.cpp
@@ -0,0 +1,28 @@
+// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#define BOOST_TEST_MODULE Bitcoin Test Suite
+
+#include <net.h>
+
+#include <memory>
+
+#include <boost/test/unit_test.hpp>
+
+std::unique_ptr<CConnman> g_connman;
+
+[[noreturn]] void Shutdown(void* parg)
+{
+ std::exit(EXIT_SUCCESS);
+}
+
+[[noreturn]] void StartShutdown()
+{
+ std::exit(EXIT_SUCCESS);
+}
+
+bool ShutdownRequested()
+{
+ return false;
+}
diff --git a/src/test/timedata_tests.cpp b/src/test/timedata_tests.cpp
new file mode 100644
index 0000000000..474a67497f
--- /dev/null
+++ b/src/test/timedata_tests.cpp
@@ -0,0 +1,37 @@
+// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+//
+#include <timedata.h>
+#include <test/test_bitcoin.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(timedata_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(util_MedianFilter)
+{
+ CMedianFilter<int> filter(5, 15);
+
+ BOOST_CHECK_EQUAL(filter.median(), 15);
+
+ filter.input(20); // [15 20]
+ BOOST_CHECK_EQUAL(filter.median(), 17);
+
+ filter.input(30); // [15 20 30]
+ BOOST_CHECK_EQUAL(filter.median(), 20);
+
+ filter.input(3); // [3 15 20 30]
+ BOOST_CHECK_EQUAL(filter.median(), 17);
+
+ filter.input(7); // [3 7 15 20 30]
+ BOOST_CHECK_EQUAL(filter.median(), 15);
+
+ filter.input(18); // [3 7 18 20 30]
+ BOOST_CHECK_EQUAL(filter.median(), 18);
+
+ filter.input(0); // [0 3 7 18 30]
+ BOOST_CHECK_EQUAL(filter.median(), 7);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/torcontrol_tests.cpp b/src/test/torcontrol_tests.cpp
new file mode 100644
index 0000000000..c7ceb2f1e9
--- /dev/null
+++ b/src/test/torcontrol_tests.cpp
@@ -0,0 +1,207 @@
+// Copyright (c) 2017 The Zcash developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+//
+#include <test/test_bitcoin.h>
+#include <torcontrol.h>
+
+#include <boost/test/unit_test.hpp>
+
+#include <map>
+#include <string>
+#include <utility>
+
+
+std::pair<std::string, std::string> SplitTorReplyLine(const std::string& s);
+std::map<std::string, std::string> ParseTorReplyMapping(const std::string& s);
+
+
+BOOST_FIXTURE_TEST_SUITE(torcontrol_tests, BasicTestingSetup)
+
+static void CheckSplitTorReplyLine(std::string input, std::string command, std::string args)
+{
+ BOOST_TEST_MESSAGE(std::string("CheckSplitTorReplyLine(") + input + ")");
+ auto ret = SplitTorReplyLine(input);
+ BOOST_CHECK_EQUAL(ret.first, command);
+ BOOST_CHECK_EQUAL(ret.second, args);
+}
+
+BOOST_AUTO_TEST_CASE(util_SplitTorReplyLine)
+{
+ // Data we should receive during normal usage
+ CheckSplitTorReplyLine(
+ "PROTOCOLINFO PIVERSION",
+ "PROTOCOLINFO", "PIVERSION");
+ CheckSplitTorReplyLine(
+ "AUTH METHODS=COOKIE,SAFECOOKIE COOKIEFILE=\"/home/x/.tor/control_auth_cookie\"",
+ "AUTH", "METHODS=COOKIE,SAFECOOKIE COOKIEFILE=\"/home/x/.tor/control_auth_cookie\"");
+ CheckSplitTorReplyLine(
+ "AUTH METHODS=NULL",
+ "AUTH", "METHODS=NULL");
+ CheckSplitTorReplyLine(
+ "AUTH METHODS=HASHEDPASSWORD",
+ "AUTH", "METHODS=HASHEDPASSWORD");
+ CheckSplitTorReplyLine(
+ "VERSION Tor=\"0.2.9.8 (git-a0df013ea241b026)\"",
+ "VERSION", "Tor=\"0.2.9.8 (git-a0df013ea241b026)\"");
+ CheckSplitTorReplyLine(
+ "AUTHCHALLENGE SERVERHASH=aaaa SERVERNONCE=bbbb",
+ "AUTHCHALLENGE", "SERVERHASH=aaaa SERVERNONCE=bbbb");
+
+ // Other valid inputs
+ CheckSplitTorReplyLine("COMMAND", "COMMAND", "");
+ CheckSplitTorReplyLine("COMMAND SOME ARGS", "COMMAND", "SOME ARGS");
+
+ // These inputs are valid because PROTOCOLINFO accepts an OtherLine that is
+ // just an OptArguments, which enables multiple spaces to be present
+ // between the command and arguments.
+ CheckSplitTorReplyLine("COMMAND ARGS", "COMMAND", " ARGS");
+ CheckSplitTorReplyLine("COMMAND EVEN+more ARGS", "COMMAND", " EVEN+more ARGS");
+}
+
+static void CheckParseTorReplyMapping(std::string input, std::map<std::string,std::string> expected)
+{
+ BOOST_TEST_MESSAGE(std::string("CheckParseTorReplyMapping(") + input + ")");
+ auto ret = ParseTorReplyMapping(input);
+ BOOST_CHECK_EQUAL(ret.size(), expected.size());
+ auto r_it = ret.begin();
+ auto e_it = expected.begin();
+ while (r_it != ret.end() && e_it != expected.end()) {
+ BOOST_CHECK_EQUAL(r_it->first, e_it->first);
+ BOOST_CHECK_EQUAL(r_it->second, e_it->second);
+ r_it++;
+ e_it++;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(util_ParseTorReplyMapping)
+{
+ // Data we should receive during normal usage
+ CheckParseTorReplyMapping(
+ "METHODS=COOKIE,SAFECOOKIE COOKIEFILE=\"/home/x/.tor/control_auth_cookie\"", {
+ {"METHODS", "COOKIE,SAFECOOKIE"},
+ {"COOKIEFILE", "/home/x/.tor/control_auth_cookie"},
+ });
+ CheckParseTorReplyMapping(
+ "METHODS=NULL", {
+ {"METHODS", "NULL"},
+ });
+ CheckParseTorReplyMapping(
+ "METHODS=HASHEDPASSWORD", {
+ {"METHODS", "HASHEDPASSWORD"},
+ });
+ CheckParseTorReplyMapping(
+ "Tor=\"0.2.9.8 (git-a0df013ea241b026)\"", {
+ {"Tor", "0.2.9.8 (git-a0df013ea241b026)"},
+ });
+ CheckParseTorReplyMapping(
+ "SERVERHASH=aaaa SERVERNONCE=bbbb", {
+ {"SERVERHASH", "aaaa"},
+ {"SERVERNONCE", "bbbb"},
+ });
+ CheckParseTorReplyMapping(
+ "ServiceID=exampleonion1234", {
+ {"ServiceID", "exampleonion1234"},
+ });
+ CheckParseTorReplyMapping(
+ "PrivateKey=RSA1024:BLOB", {
+ {"PrivateKey", "RSA1024:BLOB"},
+ });
+ CheckParseTorReplyMapping(
+ "ClientAuth=bob:BLOB", {
+ {"ClientAuth", "bob:BLOB"},
+ });
+
+ // Other valid inputs
+ CheckParseTorReplyMapping(
+ "Foo=Bar=Baz Spam=Eggs", {
+ {"Foo", "Bar=Baz"},
+ {"Spam", "Eggs"},
+ });
+ CheckParseTorReplyMapping(
+ "Foo=\"Bar=Baz\"", {
+ {"Foo", "Bar=Baz"},
+ });
+ CheckParseTorReplyMapping(
+ "Foo=\"Bar Baz\"", {
+ {"Foo", "Bar Baz"},
+ });
+
+ // Escapes
+ CheckParseTorReplyMapping(
+ "Foo=\"Bar\\ Baz\"", {
+ {"Foo", "Bar Baz"},
+ });
+ CheckParseTorReplyMapping(
+ "Foo=\"Bar\\Baz\"", {
+ {"Foo", "BarBaz"},
+ });
+ CheckParseTorReplyMapping(
+ "Foo=\"Bar\\@Baz\"", {
+ {"Foo", "Bar@Baz"},
+ });
+ CheckParseTorReplyMapping(
+ "Foo=\"Bar\\\"Baz\" Spam=\"\\\"Eggs\\\"\"", {
+ {"Foo", "Bar\"Baz"},
+ {"Spam", "\"Eggs\""},
+ });
+ CheckParseTorReplyMapping(
+ "Foo=\"Bar\\\\Baz\"", {
+ {"Foo", "Bar\\Baz"},
+ });
+
+ // C escapes
+ CheckParseTorReplyMapping(
+ "Foo=\"Bar\\nBaz\\t\" Spam=\"\\rEggs\" Octals=\"\\1a\\11\\17\\18\\81\\377\\378\\400\\2222\" Final=Check", {
+ {"Foo", "Bar\nBaz\t"},
+ {"Spam", "\rEggs"},
+ {"Octals", "\1a\11\17\1" "881\377\37" "8\40" "0\222" "2"},
+ {"Final", "Check"},
+ });
+ CheckParseTorReplyMapping(
+ "Valid=Mapping Escaped=\"Escape\\\\\"", {
+ {"Valid", "Mapping"},
+ {"Escaped", "Escape\\"},
+ });
+ CheckParseTorReplyMapping(
+ "Valid=Mapping Bare=\"Escape\\\"", {});
+ CheckParseTorReplyMapping(
+ "OneOctal=\"OneEnd\\1\" TwoOctal=\"TwoEnd\\11\"", {
+ {"OneOctal", "OneEnd\1"},
+ {"TwoOctal", "TwoEnd\11"},
+ });
+
+ // Special handling for null case
+ // (needed because string comparison reads the null as end-of-string)
+ BOOST_TEST_MESSAGE(std::string("CheckParseTorReplyMapping(Null=\"\\0\")"));
+ auto ret = ParseTorReplyMapping("Null=\"\\0\"");
+ BOOST_CHECK_EQUAL(ret.size(), 1U);
+ auto r_it = ret.begin();
+ BOOST_CHECK_EQUAL(r_it->first, "Null");
+ BOOST_CHECK_EQUAL(r_it->second.size(), 1U);
+ BOOST_CHECK_EQUAL(r_it->second[0], '\0');
+
+ // A more complex valid grammar. PROTOCOLINFO accepts a VersionLine that
+ // takes a key=value pair followed by an OptArguments, making this valid.
+ // Because an OptArguments contains no semantic data, there is no point in
+ // parsing it.
+ CheckParseTorReplyMapping(
+ "SOME=args,here MORE optional=arguments here", {
+ {"SOME", "args,here"},
+ });
+
+ // Inputs that are effectively invalid under the target grammar.
+ // PROTOCOLINFO accepts an OtherLine that is just an OptArguments, which
+ // would make these inputs valid. However,
+ // - This parser is never used in that situation, because the
+ // SplitTorReplyLine parser enables OtherLine to be skipped.
+ // - Even if these were valid, an OptArguments contains no semantic data,
+ // so there is no point in parsing it.
+ CheckParseTorReplyMapping("ARGS", {});
+ CheckParseTorReplyMapping("MORE ARGS", {});
+ CheckParseTorReplyMapping("MORE ARGS", {});
+ CheckParseTorReplyMapping("EVEN more=ARGS", {});
+ CheckParseTorReplyMapping("EVEN+more ARGS", {});
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
new file mode 100644
index 0000000000..33f0a83b7e
--- /dev/null
+++ b/src/test/transaction_tests.cpp
@@ -0,0 +1,771 @@
+// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <test/data/tx_invalid.json.h>
+#include <test/data/tx_valid.json.h>
+#include <test/test_bitcoin.h>
+
+#include <clientversion.h>
+#include <checkqueue.h>
+#include <consensus/tx_verify.h>
+#include <consensus/validation.h>
+#include <core_io.h>
+#include <key.h>
+#include <keystore.h>
+#include <validation.h>
+#include <policy/policy.h>
+#include <script/script.h>
+#include <script/sign.h>
+#include <script/script_error.h>
+#include <script/standard.h>
+#include <utilstrencodings.h>
+
+#include <map>
+#include <string>
+
+#include <boost/algorithm/string/classification.hpp>
+#include <boost/algorithm/string/split.hpp>
+#include <boost/test/unit_test.hpp>
+
+#include <univalue.h>
+
+typedef std::vector<unsigned char> valtype;
+
+// In script_tests.cpp
+extern UniValue read_json(const std::string& jsondata);
+
+static std::map<std::string, unsigned int> mapFlagNames = {
+ {std::string("NONE"), (unsigned int)SCRIPT_VERIFY_NONE},
+ {std::string("P2SH"), (unsigned int)SCRIPT_VERIFY_P2SH},
+ {std::string("STRICTENC"), (unsigned int)SCRIPT_VERIFY_STRICTENC},
+ {std::string("DERSIG"), (unsigned int)SCRIPT_VERIFY_DERSIG},
+ {std::string("LOW_S"), (unsigned int)SCRIPT_VERIFY_LOW_S},
+ {std::string("SIGPUSHONLY"), (unsigned int)SCRIPT_VERIFY_SIGPUSHONLY},
+ {std::string("MINIMALDATA"), (unsigned int)SCRIPT_VERIFY_MINIMALDATA},
+ {std::string("NULLDUMMY"), (unsigned int)SCRIPT_VERIFY_NULLDUMMY},
+ {std::string("DISCOURAGE_UPGRADABLE_NOPS"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS},
+ {std::string("CLEANSTACK"), (unsigned int)SCRIPT_VERIFY_CLEANSTACK},
+ {std::string("MINIMALIF"), (unsigned int)SCRIPT_VERIFY_MINIMALIF},
+ {std::string("NULLFAIL"), (unsigned int)SCRIPT_VERIFY_NULLFAIL},
+ {std::string("CHECKLOCKTIMEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY},
+ {std::string("CHECKSEQUENCEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKSEQUENCEVERIFY},
+ {std::string("WITNESS"), (unsigned int)SCRIPT_VERIFY_WITNESS},
+ {std::string("DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM},
+ {std::string("WITNESS_PUBKEYTYPE"), (unsigned int)SCRIPT_VERIFY_WITNESS_PUBKEYTYPE},
+ {std::string("CONST_SCRIPTCODE"), (unsigned int)SCRIPT_VERIFY_CONST_SCRIPTCODE},
+};
+
+unsigned int ParseScriptFlags(std::string strFlags)
+{
+ if (strFlags.empty()) {
+ return 0;
+ }
+ unsigned int flags = 0;
+ std::vector<std::string> words;
+ boost::algorithm::split(words, strFlags, boost::algorithm::is_any_of(","));
+
+ for (std::string word : words)
+ {
+ if (!mapFlagNames.count(word))
+ BOOST_ERROR("Bad test: unknown verification flag '" << word << "'");
+ flags |= mapFlagNames[word];
+ }
+
+ return flags;
+}
+
+std::string FormatScriptFlags(unsigned int flags)
+{
+ if (flags == 0) {
+ return "";
+ }
+ std::string ret;
+ std::map<std::string, unsigned int>::const_iterator it = mapFlagNames.begin();
+ while (it != mapFlagNames.end()) {
+ if (flags & it->second) {
+ ret += it->first + ",";
+ }
+ it++;
+ }
+ return ret.substr(0, ret.size() - 1);
+}
+
+BOOST_FIXTURE_TEST_SUITE(transaction_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(tx_valid)
+{
+ // Read tests from test/data/tx_valid.json
+ // Format is an array of arrays
+ // Inner arrays are either [ "comment" ]
+ // or [[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], serializedTransaction, verifyFlags
+ // ... where all scripts are stringified scripts.
+ //
+ // verifyFlags is a comma separated list of script verification flags to apply, or "NONE"
+ UniValue tests = read_json(std::string(json_tests::tx_valid, json_tests::tx_valid + sizeof(json_tests::tx_valid)));
+
+ ScriptError err;
+ for (unsigned int idx = 0; idx < tests.size(); idx++) {
+ UniValue test = tests[idx];
+ std::string strTest = test.write();
+ if (test[0].isArray())
+ {
+ if (test.size() != 3 || !test[1].isStr() || !test[2].isStr())
+ {
+ BOOST_ERROR("Bad test: " << strTest);
+ continue;
+ }
+
+ std::map<COutPoint, CScript> mapprevOutScriptPubKeys;
+ std::map<COutPoint, int64_t> mapprevOutValues;
+ UniValue inputs = test[0].get_array();
+ bool fValid = true;
+ for (unsigned int inpIdx = 0; inpIdx < inputs.size(); inpIdx++) {
+ const UniValue& input = inputs[inpIdx];
+ if (!input.isArray())
+ {
+ fValid = false;
+ break;
+ }
+ UniValue vinput = input.get_array();
+ if (vinput.size() < 3 || vinput.size() > 4)
+ {
+ fValid = false;
+ break;
+ }
+ COutPoint outpoint(uint256S(vinput[0].get_str()), vinput[1].get_int());
+ mapprevOutScriptPubKeys[outpoint] = ParseScript(vinput[2].get_str());
+ if (vinput.size() >= 4)
+ {
+ mapprevOutValues[outpoint] = vinput[3].get_int64();
+ }
+ }
+ if (!fValid)
+ {
+ BOOST_ERROR("Bad test: " << strTest);
+ continue;
+ }
+
+ std::string transaction = test[1].get_str();
+ CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION);
+ CTransaction tx(deserialize, stream);
+
+ CValidationState state;
+ BOOST_CHECK_MESSAGE(CheckTransaction(tx, state), strTest);
+ BOOST_CHECK(state.IsValid());
+
+ PrecomputedTransactionData txdata(tx);
+ for (unsigned int i = 0; i < tx.vin.size(); i++)
+ {
+ if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout))
+ {
+ BOOST_ERROR("Bad test: " << strTest);
+ break;
+ }
+
+ CAmount amount = 0;
+ if (mapprevOutValues.count(tx.vin[i].prevout)) {
+ amount = mapprevOutValues[tx.vin[i].prevout];
+ }
+ unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
+ const CScriptWitness *witness = &tx.vin[i].scriptWitness;
+ BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout],
+ witness, verify_flags, TransactionSignatureChecker(&tx, i, amount, txdata), &err),
+ strTest);
+ BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
+ }
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(tx_invalid)
+{
+ // Read tests from test/data/tx_invalid.json
+ // Format is an array of arrays
+ // Inner arrays are either [ "comment" ]
+ // or [[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], serializedTransaction, verifyFlags
+ // ... where all scripts are stringified scripts.
+ //
+ // verifyFlags is a comma separated list of script verification flags to apply, or "NONE"
+ UniValue tests = read_json(std::string(json_tests::tx_invalid, json_tests::tx_invalid + sizeof(json_tests::tx_invalid)));
+
+ // Initialize to SCRIPT_ERR_OK. The tests expect err to be changed to a
+ // value other than SCRIPT_ERR_OK.
+ ScriptError err = SCRIPT_ERR_OK;
+ for (unsigned int idx = 0; idx < tests.size(); idx++) {
+ UniValue test = tests[idx];
+ std::string strTest = test.write();
+ if (test[0].isArray())
+ {
+ if (test.size() != 3 || !test[1].isStr() || !test[2].isStr())
+ {
+ BOOST_ERROR("Bad test: " << strTest);
+ continue;
+ }
+
+ std::map<COutPoint, CScript> mapprevOutScriptPubKeys;
+ std::map<COutPoint, int64_t> mapprevOutValues;
+ UniValue inputs = test[0].get_array();
+ bool fValid = true;
+ for (unsigned int inpIdx = 0; inpIdx < inputs.size(); inpIdx++) {
+ const UniValue& input = inputs[inpIdx];
+ if (!input.isArray())
+ {
+ fValid = false;
+ break;
+ }
+ UniValue vinput = input.get_array();
+ if (vinput.size() < 3 || vinput.size() > 4)
+ {
+ fValid = false;
+ break;
+ }
+ COutPoint outpoint(uint256S(vinput[0].get_str()), vinput[1].get_int());
+ mapprevOutScriptPubKeys[outpoint] = ParseScript(vinput[2].get_str());
+ if (vinput.size() >= 4)
+ {
+ mapprevOutValues[outpoint] = vinput[3].get_int64();
+ }
+ }
+ if (!fValid)
+ {
+ BOOST_ERROR("Bad test: " << strTest);
+ continue;
+ }
+
+ std::string transaction = test[1].get_str();
+ CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION );
+ CTransaction tx(deserialize, stream);
+
+ CValidationState state;
+ fValid = CheckTransaction(tx, state) && state.IsValid();
+
+ PrecomputedTransactionData txdata(tx);
+ for (unsigned int i = 0; i < tx.vin.size() && fValid; i++)
+ {
+ if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout))
+ {
+ BOOST_ERROR("Bad test: " << strTest);
+ break;
+ }
+
+ unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
+ CAmount amount = 0;
+ if (mapprevOutValues.count(tx.vin[i].prevout)) {
+ amount = mapprevOutValues[tx.vin[i].prevout];
+ }
+ const CScriptWitness *witness = &tx.vin[i].scriptWitness;
+ fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout],
+ witness, verify_flags, TransactionSignatureChecker(&tx, i, amount, txdata), &err);
+ }
+ BOOST_CHECK_MESSAGE(!fValid, strTest);
+ BOOST_CHECK_MESSAGE(err != SCRIPT_ERR_OK, ScriptErrorString(err));
+ }
+ }
+}
+
+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};
+ std::vector<unsigned char> vch(ch, ch + sizeof(ch) -1);
+ CDataStream stream(vch, SER_DISK, CLIENT_VERSION);
+ CMutableTransaction tx;
+ stream >> tx;
+ CValidationState state;
+ BOOST_CHECK_MESSAGE(CheckTransaction(tx, state) && state.IsValid(), "Simple deserialized transaction should be valid.");
+
+ // Check that duplicate txins fail
+ tx.vin.push_back(tx.vin[0]);
+ BOOST_CHECK_MESSAGE(!CheckTransaction(tx, state) || !state.IsValid(), "Transaction with duplicate txins should be invalid.");
+}
+
+//
+// Helper: create two dummy transactions, each with
+// two outputs. The first has 11 and 50 CENT outputs
+// paid to a TX_PUBKEY, the second 21 and 22 CENT outputs
+// paid to a TX_PUBKEYHASH.
+//
+static std::vector<CMutableTransaction>
+SetupDummyInputs(CBasicKeyStore& keystoreRet, CCoinsViewCache& coinsRet)
+{
+ std::vector<CMutableTransaction> dummyTransactions;
+ dummyTransactions.resize(2);
+
+ // Add some keys to the keystore:
+ CKey key[4];
+ for (int i = 0; i < 4; i++)
+ {
+ key[i].MakeNewKey(i % 2);
+ keystoreRet.AddKey(key[i]);
+ }
+
+ // Create some dummy input transactions
+ dummyTransactions[0].vout.resize(2);
+ dummyTransactions[0].vout[0].nValue = 11*CENT;
+ dummyTransactions[0].vout[0].scriptPubKey << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG;
+ dummyTransactions[0].vout[1].nValue = 50*CENT;
+ dummyTransactions[0].vout[1].scriptPubKey << ToByteVector(key[1].GetPubKey()) << OP_CHECKSIG;
+ AddCoins(coinsRet, dummyTransactions[0], 0);
+
+ dummyTransactions[1].vout.resize(2);
+ dummyTransactions[1].vout[0].nValue = 21*CENT;
+ dummyTransactions[1].vout[0].scriptPubKey = GetScriptForDestination(key[2].GetPubKey().GetID());
+ dummyTransactions[1].vout[1].nValue = 22*CENT;
+ dummyTransactions[1].vout[1].scriptPubKey = GetScriptForDestination(key[3].GetPubKey().GetID());
+ AddCoins(coinsRet, dummyTransactions[1], 0);
+
+ return dummyTransactions;
+}
+
+BOOST_AUTO_TEST_CASE(test_Get)
+{
+ CBasicKeyStore keystore;
+ CCoinsView coinsDummy;
+ CCoinsViewCache coins(&coinsDummy);
+ std::vector<CMutableTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
+
+ CMutableTransaction t1;
+ t1.vin.resize(3);
+ t1.vin[0].prevout.hash = dummyTransactions[0].GetHash();
+ t1.vin[0].prevout.n = 1;
+ t1.vin[0].scriptSig << std::vector<unsigned char>(65, 0);
+ t1.vin[1].prevout.hash = dummyTransactions[1].GetHash();
+ t1.vin[1].prevout.n = 0;
+ t1.vin[1].scriptSig << std::vector<unsigned char>(65, 0) << std::vector<unsigned char>(33, 4);
+ t1.vin[2].prevout.hash = dummyTransactions[1].GetHash();
+ t1.vin[2].prevout.n = 1;
+ t1.vin[2].scriptSig << std::vector<unsigned char>(65, 0) << std::vector<unsigned char>(33, 4);
+ t1.vout.resize(2);
+ t1.vout[0].nValue = 90*CENT;
+ t1.vout[0].scriptPubKey << OP_1;
+
+ BOOST_CHECK(AreInputsStandard(t1, coins));
+ BOOST_CHECK_EQUAL(coins.GetValueIn(t1), (50+21+22)*CENT);
+}
+
+static void CreateCreditAndSpend(const CKeyStore& keystore, const CScript& outscript, CTransactionRef& output, CMutableTransaction& input, bool success = true)
+{
+ CMutableTransaction outputm;
+ outputm.nVersion = 1;
+ outputm.vin.resize(1);
+ outputm.vin[0].prevout.SetNull();
+ outputm.vin[0].scriptSig = CScript();
+ outputm.vout.resize(1);
+ outputm.vout[0].nValue = 1;
+ outputm.vout[0].scriptPubKey = outscript;
+ CDataStream ssout(SER_NETWORK, PROTOCOL_VERSION);
+ ssout << outputm;
+ ssout >> output;
+ assert(output->vin.size() == 1);
+ assert(output->vin[0] == outputm.vin[0]);
+ assert(output->vout.size() == 1);
+ assert(output->vout[0] == outputm.vout[0]);
+
+ CMutableTransaction inputm;
+ inputm.nVersion = 1;
+ inputm.vin.resize(1);
+ inputm.vin[0].prevout.hash = output->GetHash();
+ inputm.vin[0].prevout.n = 0;
+ inputm.vout.resize(1);
+ inputm.vout[0].nValue = 1;
+ inputm.vout[0].scriptPubKey = CScript();
+ bool ret = SignSignature(keystore, *output, inputm, 0, SIGHASH_ALL);
+ assert(ret == success);
+ CDataStream ssin(SER_NETWORK, PROTOCOL_VERSION);
+ ssin << inputm;
+ ssin >> input;
+ assert(input.vin.size() == 1);
+ assert(input.vin[0] == inputm.vin[0]);
+ assert(input.vout.size() == 1);
+ assert(input.vout[0] == inputm.vout[0]);
+ assert(input.vin[0].scriptWitness.stack == inputm.vin[0].scriptWitness.stack);
+}
+
+static void CheckWithFlag(const CTransactionRef& output, const CMutableTransaction& input, int flags, bool success)
+{
+ ScriptError error;
+ CTransaction inputi(input);
+ bool ret = VerifyScript(inputi.vin[0].scriptSig, output->vout[0].scriptPubKey, &inputi.vin[0].scriptWitness, flags, TransactionSignatureChecker(&inputi, 0, output->vout[0].nValue), &error);
+ assert(ret == success);
+}
+
+static CScript PushAll(const std::vector<valtype>& values)
+{
+ CScript result;
+ for (const valtype& v : values) {
+ if (v.size() == 0) {
+ result << OP_0;
+ } else if (v.size() == 1 && v[0] >= 1 && v[0] <= 16) {
+ result << CScript::EncodeOP_N(v[0]);
+ } else {
+ result << v;
+ }
+ }
+ return result;
+}
+
+static void ReplaceRedeemScript(CScript& script, const CScript& redeemScript)
+{
+ std::vector<valtype> stack;
+ EvalScript(stack, script, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), SigVersion::BASE);
+ assert(stack.size() > 0);
+ stack.back() = std::vector<unsigned char>(redeemScript.begin(), redeemScript.end());
+ script = PushAll(stack);
+}
+
+BOOST_AUTO_TEST_CASE(test_big_witness_transaction) {
+ CMutableTransaction mtx;
+ mtx.nVersion = 1;
+
+ CKey key;
+ key.MakeNewKey(true); // Need to use compressed keys in segwit or the signing will fail
+ CBasicKeyStore keystore;
+ keystore.AddKeyPubKey(key, key.GetPubKey());
+ CKeyID hash = key.GetPubKey().GetID();
+ CScript scriptPubKey = CScript() << OP_0 << std::vector<unsigned char>(hash.begin(), hash.end());
+
+ std::vector<int> sigHashes;
+ sigHashes.push_back(SIGHASH_NONE | SIGHASH_ANYONECANPAY);
+ sigHashes.push_back(SIGHASH_SINGLE | SIGHASH_ANYONECANPAY);
+ sigHashes.push_back(SIGHASH_ALL | SIGHASH_ANYONECANPAY);
+ sigHashes.push_back(SIGHASH_NONE);
+ sigHashes.push_back(SIGHASH_SINGLE);
+ sigHashes.push_back(SIGHASH_ALL);
+
+ // create a big transaction of 4500 inputs signed by the same key
+ for(uint32_t ij = 0; ij < 4500; ij++) {
+ uint32_t i = mtx.vin.size();
+ uint256 prevId;
+ prevId.SetHex("0000000000000000000000000000000000000000000000000000000000000100");
+ COutPoint outpoint(prevId, i);
+
+ mtx.vin.resize(mtx.vin.size() + 1);
+ mtx.vin[i].prevout = outpoint;
+ mtx.vin[i].scriptSig = CScript();
+
+ mtx.vout.resize(mtx.vout.size() + 1);
+ mtx.vout[i].nValue = 1000;
+ mtx.vout[i].scriptPubKey = CScript() << OP_1;
+ }
+
+ // sign all inputs
+ for(uint32_t i = 0; i < mtx.vin.size(); i++) {
+ bool hashSigned = SignSignature(keystore, scriptPubKey, mtx, i, 1000, sigHashes.at(i % sigHashes.size()));
+ assert(hashSigned);
+ }
+
+ CDataStream ssout(SER_NETWORK, PROTOCOL_VERSION);
+ auto vstream = WithOrVersion(&ssout, 0);
+ vstream << mtx;
+ CTransaction tx(deserialize, vstream);
+
+ // check all inputs concurrently, with the cache
+ PrecomputedTransactionData txdata(tx);
+ boost::thread_group threadGroup;
+ CCheckQueue<CScriptCheck> scriptcheckqueue(128);
+ CCheckQueueControl<CScriptCheck> control(&scriptcheckqueue);
+
+ for (int i=0; i<20; i++)
+ threadGroup.create_thread(boost::bind(&CCheckQueue<CScriptCheck>::Thread, boost::ref(scriptcheckqueue)));
+
+ std::vector<Coin> coins;
+ for(uint32_t i = 0; i < mtx.vin.size(); i++) {
+ Coin coin;
+ coin.nHeight = 1;
+ coin.fCoinBase = false;
+ coin.out.nValue = 1000;
+ coin.out.scriptPubKey = scriptPubKey;
+ coins.emplace_back(std::move(coin));
+ }
+
+ for(uint32_t i = 0; i < mtx.vin.size(); i++) {
+ std::vector<CScriptCheck> vChecks;
+ CScriptCheck check(coins[tx.vin[i].prevout.n].out, tx, i, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false, &txdata);
+ vChecks.push_back(CScriptCheck());
+ check.swap(vChecks.back());
+ control.Add(vChecks);
+ }
+
+ bool controlCheck = control.Wait();
+ assert(controlCheck);
+
+ threadGroup.interrupt_all();
+ threadGroup.join_all();
+}
+
+SignatureData CombineSignatures(const CMutableTransaction& input1, const CMutableTransaction& input2, const CTransactionRef tx)
+{
+ SignatureData sigdata;
+ sigdata = DataFromTransaction(input1, 0, tx->vout[0]);
+ sigdata.MergeSignatureData(DataFromTransaction(input2, 0, tx->vout[0]));
+ ProduceSignature(DUMMY_SIGNING_PROVIDER, MutableTransactionSignatureCreator(&input1, 0, tx->vout[0].nValue), tx->vout[0].scriptPubKey, sigdata);
+ return sigdata;
+}
+
+BOOST_AUTO_TEST_CASE(test_witness)
+{
+ CBasicKeyStore keystore, keystore2;
+ CKey key1, key2, key3, key1L, key2L;
+ CPubKey pubkey1, pubkey2, pubkey3, pubkey1L, pubkey2L;
+ key1.MakeNewKey(true);
+ key2.MakeNewKey(true);
+ key3.MakeNewKey(true);
+ key1L.MakeNewKey(false);
+ key2L.MakeNewKey(false);
+ pubkey1 = key1.GetPubKey();
+ pubkey2 = key2.GetPubKey();
+ pubkey3 = key3.GetPubKey();
+ pubkey1L = key1L.GetPubKey();
+ pubkey2L = key2L.GetPubKey();
+ keystore.AddKeyPubKey(key1, pubkey1);
+ keystore.AddKeyPubKey(key2, pubkey2);
+ keystore.AddKeyPubKey(key1L, pubkey1L);
+ keystore.AddKeyPubKey(key2L, pubkey2L);
+ CScript scriptPubkey1, scriptPubkey2, scriptPubkey1L, scriptPubkey2L, scriptMulti;
+ scriptPubkey1 << ToByteVector(pubkey1) << OP_CHECKSIG;
+ scriptPubkey2 << ToByteVector(pubkey2) << OP_CHECKSIG;
+ scriptPubkey1L << ToByteVector(pubkey1L) << OP_CHECKSIG;
+ scriptPubkey2L << ToByteVector(pubkey2L) << OP_CHECKSIG;
+ std::vector<CPubKey> oneandthree;
+ oneandthree.push_back(pubkey1);
+ oneandthree.push_back(pubkey3);
+ scriptMulti = GetScriptForMultisig(2, oneandthree);
+ keystore.AddCScript(scriptPubkey1);
+ keystore.AddCScript(scriptPubkey2);
+ keystore.AddCScript(scriptPubkey1L);
+ keystore.AddCScript(scriptPubkey2L);
+ keystore.AddCScript(scriptMulti);
+ keystore.AddCScript(GetScriptForWitness(scriptPubkey1));
+ keystore.AddCScript(GetScriptForWitness(scriptPubkey2));
+ keystore.AddCScript(GetScriptForWitness(scriptPubkey1L));
+ keystore.AddCScript(GetScriptForWitness(scriptPubkey2L));
+ keystore.AddCScript(GetScriptForWitness(scriptMulti));
+ keystore2.AddCScript(scriptMulti);
+ keystore2.AddCScript(GetScriptForWitness(scriptMulti));
+ keystore2.AddKeyPubKey(key3, pubkey3);
+
+ CTransactionRef output1, output2;
+ CMutableTransaction input1, input2;
+
+ // Normal pay-to-compressed-pubkey.
+ CreateCreditAndSpend(keystore, scriptPubkey1, output1, input1);
+ CreateCreditAndSpend(keystore, scriptPubkey2, output2, input2);
+ CheckWithFlag(output1, input1, 0, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
+ CheckWithFlag(output1, input2, 0, false);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, false);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
+ CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
+
+ // P2SH pay-to-compressed-pubkey.
+ CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptPubkey1)), output1, input1);
+ CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptPubkey2)), output2, input2);
+ ReplaceRedeemScript(input2.vin[0].scriptSig, scriptPubkey1);
+ CheckWithFlag(output1, input1, 0, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
+ CheckWithFlag(output1, input2, 0, true);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, false);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
+ CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
+
+ // Witness pay-to-compressed-pubkey (v0).
+ CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey1), output1, input1);
+ CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey2), output2, input2);
+ CheckWithFlag(output1, input1, 0, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
+ CheckWithFlag(output1, input2, 0, true);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
+ CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
+
+ // P2SH witness pay-to-compressed-pubkey (v0).
+ CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey1))), output1, input1);
+ CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey2))), output2, input2);
+ ReplaceRedeemScript(input2.vin[0].scriptSig, GetScriptForWitness(scriptPubkey1));
+ CheckWithFlag(output1, input1, 0, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
+ CheckWithFlag(output1, input2, 0, true);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
+ CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
+
+ // Normal pay-to-uncompressed-pubkey.
+ CreateCreditAndSpend(keystore, scriptPubkey1L, output1, input1);
+ CreateCreditAndSpend(keystore, scriptPubkey2L, output2, input2);
+ CheckWithFlag(output1, input1, 0, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
+ CheckWithFlag(output1, input2, 0, false);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, false);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
+ CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
+
+ // P2SH pay-to-uncompressed-pubkey.
+ CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptPubkey1L)), output1, input1);
+ CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptPubkey2L)), output2, input2);
+ ReplaceRedeemScript(input2.vin[0].scriptSig, scriptPubkey1L);
+ CheckWithFlag(output1, input1, 0, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
+ CheckWithFlag(output1, input2, 0, true);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_P2SH, false);
+ CheckWithFlag(output1, input2, SCRIPT_VERIFY_WITNESS | SCRIPT_VERIFY_P2SH, false);
+ CheckWithFlag(output1, input2, STANDARD_SCRIPT_VERIFY_FLAGS, false);
+
+ // Signing disabled for witness pay-to-uncompressed-pubkey (v1).
+ CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey1L), output1, input1, false);
+ CreateCreditAndSpend(keystore, GetScriptForWitness(scriptPubkey2L), output2, input2, false);
+
+ // Signing disabled for P2SH witness pay-to-uncompressed-pubkey (v1).
+ CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey1L))), output1, input1, false);
+ CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptPubkey2L))), output2, input2, false);
+
+ // Normal 2-of-2 multisig
+ CreateCreditAndSpend(keystore, scriptMulti, output1, input1, false);
+ CheckWithFlag(output1, input1, 0, false);
+ CreateCreditAndSpend(keystore2, scriptMulti, output2, input2, false);
+ CheckWithFlag(output2, input2, 0, false);
+ BOOST_CHECK(*output1 == *output2);
+ UpdateInput(input1.vin[0], CombineSignatures(input1, input2, output1));
+ CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
+
+ // P2SH 2-of-2 multisig
+ CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(scriptMulti)), output1, input1, false);
+ CheckWithFlag(output1, input1, 0, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, false);
+ CreateCreditAndSpend(keystore2, GetScriptForDestination(CScriptID(scriptMulti)), output2, input2, false);
+ CheckWithFlag(output2, input2, 0, true);
+ CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH, false);
+ BOOST_CHECK(*output1 == *output2);
+ UpdateInput(input1.vin[0], CombineSignatures(input1, input2, output1));
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
+
+ // Witness 2-of-2 multisig
+ CreateCreditAndSpend(keystore, GetScriptForWitness(scriptMulti), output1, input1, false);
+ CheckWithFlag(output1, input1, 0, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false);
+ CreateCreditAndSpend(keystore2, GetScriptForWitness(scriptMulti), output2, input2, false);
+ CheckWithFlag(output2, input2, 0, true);
+ CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false);
+ BOOST_CHECK(*output1 == *output2);
+ UpdateInput(input1.vin[0], CombineSignatures(input1, input2, output1));
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true);
+ CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
+
+ // P2SH witness 2-of-2 multisig
+ CreateCreditAndSpend(keystore, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptMulti))), output1, input1, false);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false);
+ CreateCreditAndSpend(keystore2, GetScriptForDestination(CScriptID(GetScriptForWitness(scriptMulti))), output2, input2, false);
+ CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH, true);
+ CheckWithFlag(output2, input2, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false);
+ BOOST_CHECK(*output1 == *output2);
+ UpdateInput(input1.vin[0], CombineSignatures(input1, input2, output1));
+ CheckWithFlag(output1, input1, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true);
+ CheckWithFlag(output1, input1, STANDARD_SCRIPT_VERIFY_FLAGS, true);
+}
+
+BOOST_AUTO_TEST_CASE(test_IsStandard)
+{
+ LOCK(cs_main);
+ CBasicKeyStore keystore;
+ CCoinsView coinsDummy;
+ CCoinsViewCache coins(&coinsDummy);
+ std::vector<CMutableTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
+
+ CMutableTransaction t;
+ t.vin.resize(1);
+ t.vin[0].prevout.hash = dummyTransactions[0].GetHash();
+ t.vin[0].prevout.n = 1;
+ t.vin[0].scriptSig << std::vector<unsigned char>(65, 0);
+ t.vout.resize(1);
+ t.vout[0].nValue = 90*CENT;
+ CKey key;
+ key.MakeNewKey(true);
+ t.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());
+
+ std::string reason;
+ BOOST_CHECK(IsStandardTx(t, reason));
+
+ // Check dust with default relay fee:
+ CAmount nDustThreshold = 182 * dustRelayFee.GetFeePerK()/1000;
+ BOOST_CHECK_EQUAL(nDustThreshold, 546);
+ // dust:
+ t.vout[0].nValue = nDustThreshold - 1;
+ BOOST_CHECK(!IsStandardTx(t, reason));
+ // not dust:
+ t.vout[0].nValue = nDustThreshold;
+ BOOST_CHECK(IsStandardTx(t, reason));
+
+ // Check dust with odd relay fee to verify rounding:
+ // nDustThreshold = 182 * 3702 / 1000
+ dustRelayFee = CFeeRate(3702);
+ // dust:
+ t.vout[0].nValue = 673 - 1;
+ BOOST_CHECK(!IsStandardTx(t, reason));
+ // not dust:
+ t.vout[0].nValue = 673;
+ BOOST_CHECK(IsStandardTx(t, reason));
+ dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE);
+
+ t.vout[0].scriptPubKey = CScript() << OP_1;
+ BOOST_CHECK(!IsStandardTx(t, reason));
+
+ // MAX_OP_RETURN_RELAY-byte TX_NULL_DATA (standard)
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
+ BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY, t.vout[0].scriptPubKey.size());
+ BOOST_CHECK(IsStandardTx(t, reason));
+
+ // MAX_OP_RETURN_RELAY+1-byte TX_NULL_DATA (non-standard)
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3800");
+ BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY + 1, t.vout[0].scriptPubKey.size());
+ BOOST_CHECK(!IsStandardTx(t, reason));
+
+ // Data payload can be encoded in any way...
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("");
+ BOOST_CHECK(IsStandardTx(t, reason));
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("00") << ParseHex("01");
+ BOOST_CHECK(IsStandardTx(t, reason));
+ // OP_RESERVED *is* considered to be a PUSHDATA type opcode by IsPushOnly()!
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN << OP_RESERVED << -1 << 0 << ParseHex("01") << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9 << 10 << 11 << 12 << 13 << 14 << 15 << 16;
+ BOOST_CHECK(IsStandardTx(t, reason));
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN << 0 << ParseHex("01") << 2 << ParseHex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
+ BOOST_CHECK(IsStandardTx(t, reason));
+
+ // ...so long as it only contains PUSHDATA's
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN << OP_RETURN;
+ BOOST_CHECK(!IsStandardTx(t, reason));
+
+ // TX_NULL_DATA w/o PUSHDATA
+ t.vout.resize(1);
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN;
+ BOOST_CHECK(IsStandardTx(t, reason));
+
+ // Only one TX_NULL_DATA permitted in all cases
+ t.vout.resize(2);
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
+ t.vout[1].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
+ BOOST_CHECK(!IsStandardTx(t, reason));
+
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38");
+ t.vout[1].scriptPubKey = CScript() << OP_RETURN;
+ BOOST_CHECK(!IsStandardTx(t, reason));
+
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN;
+ t.vout[1].scriptPubKey = CScript() << OP_RETURN;
+ BOOST_CHECK(!IsStandardTx(t, reason));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/txindex_tests.cpp b/src/test/txindex_tests.cpp
new file mode 100644
index 0000000000..be7ee2428b
--- /dev/null
+++ b/src/test/txindex_tests.cpp
@@ -0,0 +1,66 @@
+// Copyright (c) 2017-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <index/txindex.h>
+#include <script/standard.h>
+#include <test/test_bitcoin.h>
+#include <util.h>
+#include <utiltime.h>
+#include <validation.h>
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_SUITE(txindex_tests)
+
+BOOST_FIXTURE_TEST_CASE(txindex_initial_sync, TestChain100Setup)
+{
+ TxIndex txindex(1 << 20, true);
+
+ CTransactionRef tx_disk;
+ uint256 block_hash;
+
+ // Transaction should not be found in the index before it is started.
+ for (const auto& txn : m_coinbase_txns) {
+ BOOST_CHECK(!txindex.FindTx(txn->GetHash(), block_hash, tx_disk));
+ }
+
+ // BlockUntilSyncedToCurrentChain should return false before txindex is started.
+ BOOST_CHECK(!txindex.BlockUntilSyncedToCurrentChain());
+
+ txindex.Start();
+
+ // Allow tx index to catch up with the block index.
+ constexpr int64_t timeout_ms = 10 * 1000;
+ int64_t time_start = GetTimeMillis();
+ while (!txindex.BlockUntilSyncedToCurrentChain()) {
+ BOOST_REQUIRE(time_start + timeout_ms > GetTimeMillis());
+ MilliSleep(100);
+ }
+
+ // Check that txindex has all txs that were in the chain before it started.
+ for (const auto& txn : m_coinbase_txns) {
+ if (!txindex.FindTx(txn->GetHash(), block_hash, tx_disk)) {
+ BOOST_ERROR("FindTx failed");
+ } else if (tx_disk->GetHash() != txn->GetHash()) {
+ BOOST_ERROR("Read incorrect tx");
+ }
+ }
+
+ // Check that new transactions in new blocks make it into the index.
+ for (int i = 0; i < 10; i++) {
+ CScript coinbase_script_pub_key = GetScriptForDestination(coinbaseKey.GetPubKey().GetID());
+ std::vector<CMutableTransaction> no_txns;
+ const CBlock& block = CreateAndProcessBlock(no_txns, coinbase_script_pub_key);
+ const CTransaction& txn = *block.vtx[0];
+
+ BOOST_CHECK(txindex.BlockUntilSyncedToCurrentChain());
+ if (!txindex.FindTx(txn.GetHash(), block_hash, tx_disk)) {
+ BOOST_ERROR("FindTx failed");
+ } else if (tx_disk->GetHash() != txn.GetHash()) {
+ BOOST_ERROR("Read incorrect tx");
+ }
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/txvalidation_tests.cpp b/src/test/txvalidation_tests.cpp
new file mode 100644
index 0000000000..2d1eb7b772
--- /dev/null
+++ b/src/test/txvalidation_tests.cpp
@@ -0,0 +1,61 @@
+// Copyright (c) 2017 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <validation.h>
+#include <txmempool.h>
+#include <amount.h>
+#include <consensus/validation.h>
+#include <primitives/transaction.h>
+#include <script/script.h>
+#include <test/test_bitcoin.h>
+
+#include <boost/test/unit_test.hpp>
+
+
+BOOST_AUTO_TEST_SUITE(txvalidation_tests)
+
+/**
+ * Ensure that the mempool won't accept coinbase transactions.
+ */
+BOOST_FIXTURE_TEST_CASE(tx_mempool_reject_coinbase, TestChain100Setup)
+{
+ CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
+ CMutableTransaction coinbaseTx;
+
+ coinbaseTx.nVersion = 1;
+ coinbaseTx.vin.resize(1);
+ coinbaseTx.vout.resize(1);
+ coinbaseTx.vin[0].scriptSig = CScript() << OP_11 << OP_EQUAL;
+ coinbaseTx.vout[0].nValue = 1 * CENT;
+ coinbaseTx.vout[0].scriptPubKey = scriptPubKey;
+
+ assert(CTransaction(coinbaseTx).IsCoinBase());
+
+ CValidationState state;
+
+ LOCK(cs_main);
+
+ unsigned int initialPoolSize = mempool.size();
+
+ BOOST_CHECK_EQUAL(
+ false,
+ AcceptToMemoryPool(mempool, state, MakeTransactionRef(coinbaseTx),
+ nullptr /* pfMissingInputs */,
+ nullptr /* plTxnReplaced */,
+ true /* bypass_limits */,
+ 0 /* nAbsurdFee */));
+
+ // Check that the transaction hasn't been added to mempool.
+ BOOST_CHECK_EQUAL(mempool.size(), initialPoolSize);
+
+ // Check that the validation state reflects the unsuccessful attempt.
+ BOOST_CHECK(state.IsInvalid());
+ BOOST_CHECK_EQUAL(state.GetRejectReason(), "coinbase");
+
+ int nDoS;
+ BOOST_CHECK_EQUAL(state.IsInvalid(nDoS), true);
+ BOOST_CHECK_EQUAL(nDoS, 100);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp
new file mode 100644
index 0000000000..2bf835a756
--- /dev/null
+++ b/src/test/txvalidationcache_tests.cpp
@@ -0,0 +1,371 @@
+// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <consensus/validation.h>
+#include <key.h>
+#include <validation.h>
+#include <miner.h>
+#include <pubkey.h>
+#include <txmempool.h>
+#include <random.h>
+#include <script/standard.h>
+#include <script/sign.h>
+#include <test/test_bitcoin.h>
+#include <utiltime.h>
+#include <core_io.h>
+#include <keystore.h>
+#include <policy/policy.h>
+
+#include <boost/test/unit_test.hpp>
+
+bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks);
+
+BOOST_AUTO_TEST_SUITE(tx_validationcache_tests)
+
+static bool
+ToMemPool(const CMutableTransaction& tx)
+{
+ LOCK(cs_main);
+
+ CValidationState state;
+ return AcceptToMemoryPool(mempool, state, MakeTransactionRef(tx), nullptr /* pfMissingInputs */,
+ nullptr /* plTxnReplaced */, true /* bypass_limits */, 0 /* nAbsurdFee */);
+}
+
+BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
+{
+ // Make sure skipping validation of transactions that were
+ // validated going into the memory pool does not allow
+ // double-spends in blocks to pass validation when they should not.
+
+ CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
+
+ // Create a double-spend of mature coinbase txn:
+ std::vector<CMutableTransaction> spends;
+ spends.resize(2);
+ for (int i = 0; i < 2; i++)
+ {
+ spends[i].nVersion = 1;
+ spends[i].vin.resize(1);
+ spends[i].vin[0].prevout.hash = m_coinbase_txns[0]->GetHash();
+ spends[i].vin[0].prevout.n = 0;
+ spends[i].vout.resize(1);
+ spends[i].vout[0].nValue = 11*CENT;
+ spends[i].vout[0].scriptPubKey = scriptPubKey;
+
+ // Sign:
+ std::vector<unsigned char> vchSig;
+ uint256 hash = SignatureHash(scriptPubKey, spends[i], 0, SIGHASH_ALL, 0, SigVersion::BASE);
+ BOOST_CHECK(coinbaseKey.Sign(hash, vchSig));
+ vchSig.push_back((unsigned char)SIGHASH_ALL);
+ spends[i].vin[0].scriptSig << vchSig;
+ }
+
+ CBlock block;
+
+ // Test 1: block with both of those transactions should be rejected.
+ block = CreateAndProcessBlock(spends, scriptPubKey);
+ BOOST_CHECK(chainActive.Tip()->GetBlockHash() != block.GetHash());
+
+ // Test 2: ... and should be rejected if spend1 is in the memory pool
+ BOOST_CHECK(ToMemPool(spends[0]));
+ block = CreateAndProcessBlock(spends, scriptPubKey);
+ BOOST_CHECK(chainActive.Tip()->GetBlockHash() != block.GetHash());
+ mempool.clear();
+
+ // Test 3: ... and should be rejected if spend2 is in the memory pool
+ BOOST_CHECK(ToMemPool(spends[1]));
+ block = CreateAndProcessBlock(spends, scriptPubKey);
+ BOOST_CHECK(chainActive.Tip()->GetBlockHash() != block.GetHash());
+ mempool.clear();
+
+ // Final sanity test: first spend in mempool, second in block, that's OK:
+ std::vector<CMutableTransaction> oneSpend;
+ oneSpend.push_back(spends[0]);
+ BOOST_CHECK(ToMemPool(spends[1]));
+ block = CreateAndProcessBlock(oneSpend, scriptPubKey);
+ BOOST_CHECK(chainActive.Tip()->GetBlockHash() == block.GetHash());
+ // spends[1] should have been removed from the mempool when the
+ // block with spends[0] is accepted:
+ BOOST_CHECK_EQUAL(mempool.size(), 0U);
+}
+
+// Run CheckInputs (using pcoinsTip) on the given transaction, for all script
+// flags. Test that CheckInputs passes for all flags that don't overlap with
+// the failing_flags argument, but otherwise fails.
+// CHECKLOCKTIMEVERIFY and CHECKSEQUENCEVERIFY (and future NOP codes that may
+// get reassigned) have an interaction with DISCOURAGE_UPGRADABLE_NOPS: if
+// the script flags used contain DISCOURAGE_UPGRADABLE_NOPS but don't contain
+// CHECKLOCKTIMEVERIFY (or CHECKSEQUENCEVERIFY), but the script does contain
+// OP_CHECKLOCKTIMEVERIFY (or OP_CHECKSEQUENCEVERIFY), then script execution
+// should fail.
+// Capture this interaction with the upgraded_nop argument: set it when evaluating
+// any script flag that is implemented as an upgraded NOP code.
+static void ValidateCheckInputsForAllFlags(const CTransaction &tx, uint32_t failing_flags, bool add_to_cache)
+{
+ PrecomputedTransactionData txdata(tx);
+ // If we add many more flags, this loop can get too expensive, but we can
+ // rewrite in the future to randomly pick a set of flags to evaluate.
+ for (uint32_t test_flags=0; test_flags < (1U << 16); test_flags += 1) {
+ CValidationState state;
+ // Filter out incompatible flag choices
+ if ((test_flags & SCRIPT_VERIFY_CLEANSTACK)) {
+ // CLEANSTACK requires P2SH and WITNESS, see VerifyScript() in
+ // script/interpreter.cpp
+ test_flags |= SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS;
+ }
+ if ((test_flags & SCRIPT_VERIFY_WITNESS)) {
+ // WITNESS requires P2SH
+ test_flags |= SCRIPT_VERIFY_P2SH;
+ }
+ bool ret = CheckInputs(tx, state, pcoinsTip.get(), true, test_flags, true, add_to_cache, txdata, nullptr);
+ // CheckInputs should succeed iff test_flags doesn't intersect with
+ // failing_flags
+ bool expected_return_value = !(test_flags & failing_flags);
+ BOOST_CHECK_EQUAL(ret, expected_return_value);
+
+ // Test the caching
+ if (ret && add_to_cache) {
+ // Check that we get a cache hit if the tx was valid
+ std::vector<CScriptCheck> scriptchecks;
+ BOOST_CHECK(CheckInputs(tx, state, pcoinsTip.get(), true, test_flags, true, add_to_cache, txdata, &scriptchecks));
+ BOOST_CHECK(scriptchecks.empty());
+ } else {
+ // Check that we get script executions to check, if the transaction
+ // was invalid, or we didn't add to cache.
+ std::vector<CScriptCheck> scriptchecks;
+ BOOST_CHECK(CheckInputs(tx, state, pcoinsTip.get(), true, test_flags, true, add_to_cache, txdata, &scriptchecks));
+ BOOST_CHECK_EQUAL(scriptchecks.size(), tx.vin.size());
+ }
+ }
+}
+
+BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
+{
+ // Test that passing CheckInputs with one set of script flags doesn't imply
+ // that we would pass again with a different set of flags.
+ {
+ LOCK(cs_main);
+ InitScriptExecutionCache();
+ }
+
+ CScript p2pk_scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
+ CScript p2sh_scriptPubKey = GetScriptForDestination(CScriptID(p2pk_scriptPubKey));
+ CScript p2pkh_scriptPubKey = GetScriptForDestination(coinbaseKey.GetPubKey().GetID());
+ CScript p2wpkh_scriptPubKey = GetScriptForWitness(p2pkh_scriptPubKey);
+
+ CBasicKeyStore keystore;
+ keystore.AddKey(coinbaseKey);
+ keystore.AddCScript(p2pk_scriptPubKey);
+
+ // flags to test: SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, SCRIPT_VERIFY_CHECKSEQUENCE_VERIFY, SCRIPT_VERIFY_NULLDUMMY, uncompressed pubkey thing
+
+ // Create 2 outputs that match the three scripts above, spending the first
+ // coinbase tx.
+ CMutableTransaction spend_tx;
+
+ spend_tx.nVersion = 1;
+ spend_tx.vin.resize(1);
+ spend_tx.vin[0].prevout.hash = m_coinbase_txns[0]->GetHash();
+ spend_tx.vin[0].prevout.n = 0;
+ spend_tx.vout.resize(4);
+ spend_tx.vout[0].nValue = 11*CENT;
+ spend_tx.vout[0].scriptPubKey = p2sh_scriptPubKey;
+ spend_tx.vout[1].nValue = 11*CENT;
+ spend_tx.vout[1].scriptPubKey = p2wpkh_scriptPubKey;
+ spend_tx.vout[2].nValue = 11*CENT;
+ spend_tx.vout[2].scriptPubKey = CScript() << OP_CHECKLOCKTIMEVERIFY << OP_DROP << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
+ spend_tx.vout[3].nValue = 11*CENT;
+ spend_tx.vout[3].scriptPubKey = CScript() << OP_CHECKSEQUENCEVERIFY << OP_DROP << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
+
+ // Sign, with a non-DER signature
+ {
+ std::vector<unsigned char> vchSig;
+ uint256 hash = SignatureHash(p2pk_scriptPubKey, spend_tx, 0, SIGHASH_ALL, 0, SigVersion::BASE);
+ BOOST_CHECK(coinbaseKey.Sign(hash, vchSig));
+ vchSig.push_back((unsigned char) 0); // padding byte makes this non-DER
+ vchSig.push_back((unsigned char)SIGHASH_ALL);
+ spend_tx.vin[0].scriptSig << vchSig;
+ }
+
+ // Test that invalidity under a set of flags doesn't preclude validity
+ // under other (eg consensus) flags.
+ // spend_tx is invalid according to DERSIG
+ {
+ LOCK(cs_main);
+
+ CValidationState state;
+ PrecomputedTransactionData ptd_spend_tx(spend_tx);
+
+ BOOST_CHECK(!CheckInputs(spend_tx, state, pcoinsTip.get(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, nullptr));
+
+ // If we call again asking for scriptchecks (as happens in
+ // ConnectBlock), we should add a script check object for this -- we're
+ // not caching invalidity (if that changes, delete this test case).
+ std::vector<CScriptCheck> scriptchecks;
+ BOOST_CHECK(CheckInputs(spend_tx, state, pcoinsTip.get(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, &scriptchecks));
+ BOOST_CHECK_EQUAL(scriptchecks.size(), 1U);
+
+ // Test that CheckInputs returns true iff DERSIG-enforcing flags are
+ // not present. Don't add these checks to the cache, so that we can
+ // test later that block validation works fine in the absence of cached
+ // successes.
+ ValidateCheckInputsForAllFlags(spend_tx, SCRIPT_VERIFY_DERSIG | SCRIPT_VERIFY_LOW_S | SCRIPT_VERIFY_STRICTENC, false);
+ }
+
+ // And if we produce a block with this tx, it should be valid (DERSIG not
+ // enabled yet), even though there's no cache entry.
+ CBlock block;
+
+ block = CreateAndProcessBlock({spend_tx}, p2pk_scriptPubKey);
+ BOOST_CHECK(chainActive.Tip()->GetBlockHash() == block.GetHash());
+ BOOST_CHECK(pcoinsTip->GetBestBlock() == block.GetHash());
+
+ LOCK(cs_main);
+
+ // Test P2SH: construct a transaction that is valid without P2SH, and
+ // then test validity with P2SH.
+ {
+ CMutableTransaction invalid_under_p2sh_tx;
+ invalid_under_p2sh_tx.nVersion = 1;
+ invalid_under_p2sh_tx.vin.resize(1);
+ invalid_under_p2sh_tx.vin[0].prevout.hash = spend_tx.GetHash();
+ invalid_under_p2sh_tx.vin[0].prevout.n = 0;
+ invalid_under_p2sh_tx.vout.resize(1);
+ invalid_under_p2sh_tx.vout[0].nValue = 11*CENT;
+ invalid_under_p2sh_tx.vout[0].scriptPubKey = p2pk_scriptPubKey;
+ std::vector<unsigned char> vchSig2(p2pk_scriptPubKey.begin(), p2pk_scriptPubKey.end());
+ invalid_under_p2sh_tx.vin[0].scriptSig << vchSig2;
+
+ ValidateCheckInputsForAllFlags(invalid_under_p2sh_tx, SCRIPT_VERIFY_P2SH, true);
+ }
+
+ // Test CHECKLOCKTIMEVERIFY
+ {
+ CMutableTransaction invalid_with_cltv_tx;
+ invalid_with_cltv_tx.nVersion = 1;
+ invalid_with_cltv_tx.nLockTime = 100;
+ invalid_with_cltv_tx.vin.resize(1);
+ invalid_with_cltv_tx.vin[0].prevout.hash = spend_tx.GetHash();
+ invalid_with_cltv_tx.vin[0].prevout.n = 2;
+ invalid_with_cltv_tx.vin[0].nSequence = 0;
+ invalid_with_cltv_tx.vout.resize(1);
+ invalid_with_cltv_tx.vout[0].nValue = 11*CENT;
+ invalid_with_cltv_tx.vout[0].scriptPubKey = p2pk_scriptPubKey;
+
+ // Sign
+ std::vector<unsigned char> vchSig;
+ uint256 hash = SignatureHash(spend_tx.vout[2].scriptPubKey, invalid_with_cltv_tx, 0, SIGHASH_ALL, 0, SigVersion::BASE);
+ BOOST_CHECK(coinbaseKey.Sign(hash, vchSig));
+ vchSig.push_back((unsigned char)SIGHASH_ALL);
+ invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 101;
+
+ ValidateCheckInputsForAllFlags(invalid_with_cltv_tx, SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true);
+
+ // Make it valid, and check again
+ invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 100;
+ CValidationState state;
+ PrecomputedTransactionData txdata(invalid_with_cltv_tx);
+ BOOST_CHECK(CheckInputs(invalid_with_cltv_tx, state, pcoinsTip.get(), true, SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true, true, txdata, nullptr));
+ }
+
+ // TEST CHECKSEQUENCEVERIFY
+ {
+ CMutableTransaction invalid_with_csv_tx;
+ invalid_with_csv_tx.nVersion = 2;
+ invalid_with_csv_tx.vin.resize(1);
+ invalid_with_csv_tx.vin[0].prevout.hash = spend_tx.GetHash();
+ invalid_with_csv_tx.vin[0].prevout.n = 3;
+ invalid_with_csv_tx.vin[0].nSequence = 100;
+ invalid_with_csv_tx.vout.resize(1);
+ invalid_with_csv_tx.vout[0].nValue = 11*CENT;
+ invalid_with_csv_tx.vout[0].scriptPubKey = p2pk_scriptPubKey;
+
+ // Sign
+ std::vector<unsigned char> vchSig;
+ uint256 hash = SignatureHash(spend_tx.vout[3].scriptPubKey, invalid_with_csv_tx, 0, SIGHASH_ALL, 0, SigVersion::BASE);
+ BOOST_CHECK(coinbaseKey.Sign(hash, vchSig));
+ vchSig.push_back((unsigned char)SIGHASH_ALL);
+ invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 101;
+
+ ValidateCheckInputsForAllFlags(invalid_with_csv_tx, SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true);
+
+ // Make it valid, and check again
+ invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 100;
+ CValidationState state;
+ PrecomputedTransactionData txdata(invalid_with_csv_tx);
+ BOOST_CHECK(CheckInputs(invalid_with_csv_tx, state, pcoinsTip.get(), true, SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true, true, txdata, nullptr));
+ }
+
+ // TODO: add tests for remaining script flags
+
+ // Test that passing CheckInputs with a valid witness doesn't imply success
+ // for the same tx with a different witness.
+ {
+ CMutableTransaction valid_with_witness_tx;
+ valid_with_witness_tx.nVersion = 1;
+ valid_with_witness_tx.vin.resize(1);
+ valid_with_witness_tx.vin[0].prevout.hash = spend_tx.GetHash();
+ valid_with_witness_tx.vin[0].prevout.n = 1;
+ valid_with_witness_tx.vout.resize(1);
+ valid_with_witness_tx.vout[0].nValue = 11*CENT;
+ valid_with_witness_tx.vout[0].scriptPubKey = p2pk_scriptPubKey;
+
+ // Sign
+ SignatureData sigdata;
+ ProduceSignature(keystore, MutableTransactionSignatureCreator(&valid_with_witness_tx, 0, 11*CENT, SIGHASH_ALL), spend_tx.vout[1].scriptPubKey, sigdata);
+ UpdateInput(valid_with_witness_tx.vin[0], sigdata);
+
+ // This should be valid under all script flags.
+ ValidateCheckInputsForAllFlags(valid_with_witness_tx, 0, true);
+
+ // Remove the witness, and check that it is now invalid.
+ valid_with_witness_tx.vin[0].scriptWitness.SetNull();
+ ValidateCheckInputsForAllFlags(valid_with_witness_tx, SCRIPT_VERIFY_WITNESS, true);
+ }
+
+ {
+ // Test a transaction with multiple inputs.
+ CMutableTransaction tx;
+
+ tx.nVersion = 1;
+ tx.vin.resize(2);
+ tx.vin[0].prevout.hash = spend_tx.GetHash();
+ tx.vin[0].prevout.n = 0;
+ tx.vin[1].prevout.hash = spend_tx.GetHash();
+ tx.vin[1].prevout.n = 1;
+ tx.vout.resize(1);
+ tx.vout[0].nValue = 22*CENT;
+ tx.vout[0].scriptPubKey = p2pk_scriptPubKey;
+
+ // Sign
+ for (int i=0; i<2; ++i) {
+ SignatureData sigdata;
+ ProduceSignature(keystore, MutableTransactionSignatureCreator(&tx, i, 11*CENT, SIGHASH_ALL), spend_tx.vout[i].scriptPubKey, sigdata);
+ UpdateInput(tx.vin[i], sigdata);
+ }
+
+ // This should be valid under all script flags
+ ValidateCheckInputsForAllFlags(tx, 0, true);
+
+ // Check that if the second input is invalid, but the first input is
+ // valid, the transaction is not cached.
+ // Invalidate vin[1]
+ tx.vin[1].scriptWitness.SetNull();
+
+ CValidationState state;
+ PrecomputedTransactionData txdata(tx);
+ // This transaction is now invalid under segwit, because of the second input.
+ BOOST_CHECK(!CheckInputs(tx, state, pcoinsTip.get(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, nullptr));
+
+ std::vector<CScriptCheck> scriptchecks;
+ // Make sure this transaction was not cached (ie because the first
+ // input was valid)
+ BOOST_CHECK(CheckInputs(tx, state, pcoinsTip.get(), true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, &scriptchecks));
+ // Should get 2 script checks back -- caching is on a whole-transaction basis.
+ BOOST_CHECK_EQUAL(scriptchecks.size(), 2U);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp
new file mode 100644
index 0000000000..f91b633b83
--- /dev/null
+++ b/src/test/uint256_tests.cpp
@@ -0,0 +1,282 @@
+// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <arith_uint256.h>
+#include <uint256.h>
+#include <version.h>
+#include <test/test_bitcoin.h>
+
+#include <boost/test/unit_test.hpp>
+#include <stdint.h>
+#include <sstream>
+#include <iomanip>
+#include <limits>
+#include <cmath>
+#include <string>
+#include <stdio.h>
+
+BOOST_FIXTURE_TEST_SUITE(uint256_tests, BasicTestingSetup)
+
+const unsigned char R1Array[] =
+ "\x9c\x52\x4a\xdb\xcf\x56\x11\x12\x2b\x29\x12\x5e\x5d\x35\xd2\xd2"
+ "\x22\x81\xaa\xb5\x33\xf0\x08\x32\xd5\x56\xb1\xf9\xea\xe5\x1d\x7d";
+const char R1ArrayHex[] = "7D1DE5EAF9B156D53208F033B5AA8122D2d2355d5e12292b121156cfdb4a529c";
+const uint256 R1L = uint256(std::vector<unsigned char>(R1Array,R1Array+32));
+const uint160 R1S = uint160(std::vector<unsigned char>(R1Array,R1Array+20));
+
+const unsigned char R2Array[] =
+ "\x70\x32\x1d\x7c\x47\xa5\x6b\x40\x26\x7e\x0a\xc3\xa6\x9c\xb6\xbf"
+ "\x13\x30\x47\xa3\x19\x2d\xda\x71\x49\x13\x72\xf0\xb4\xca\x81\xd7";
+const uint256 R2L = uint256(std::vector<unsigned char>(R2Array,R2Array+32));
+const uint160 R2S = uint160(std::vector<unsigned char>(R2Array,R2Array+20));
+
+const unsigned char ZeroArray[] =
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
+const uint256 ZeroL = uint256(std::vector<unsigned char>(ZeroArray,ZeroArray+32));
+const uint160 ZeroS = uint160(std::vector<unsigned char>(ZeroArray,ZeroArray+20));
+
+const unsigned char OneArray[] =
+ "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
+const uint256 OneL = uint256(std::vector<unsigned char>(OneArray,OneArray+32));
+const uint160 OneS = uint160(std::vector<unsigned char>(OneArray,OneArray+20));
+
+const unsigned char MaxArray[] =
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
+const uint256 MaxL = uint256(std::vector<unsigned char>(MaxArray,MaxArray+32));
+const uint160 MaxS = uint160(std::vector<unsigned char>(MaxArray,MaxArray+20));
+
+static std::string ArrayToString(const unsigned char A[], unsigned int width)
+{
+ std::stringstream Stream;
+ Stream << std::hex;
+ for (unsigned int i = 0; i < width; ++i)
+ {
+ Stream<<std::setw(2)<<std::setfill('0')<<(unsigned int)A[width-i-1];
+ }
+ return Stream.str();
+}
+
+inline uint160 uint160S(const char *str)
+{
+ uint160 rv;
+ rv.SetHex(str);
+ return rv;
+}
+inline uint160 uint160S(const std::string& str)
+{
+ uint160 rv;
+ rv.SetHex(str);
+ return rv;
+}
+
+BOOST_AUTO_TEST_CASE( basics ) // constructors, equality, inequality
+{
+ BOOST_CHECK(1 == 0+1);
+ // constructor uint256(vector<char>):
+ BOOST_CHECK(R1L.ToString() == ArrayToString(R1Array,32));
+ BOOST_CHECK(R1S.ToString() == ArrayToString(R1Array,20));
+ BOOST_CHECK(R2L.ToString() == ArrayToString(R2Array,32));
+ BOOST_CHECK(R2S.ToString() == ArrayToString(R2Array,20));
+ BOOST_CHECK(ZeroL.ToString() == ArrayToString(ZeroArray,32));
+ BOOST_CHECK(ZeroS.ToString() == ArrayToString(ZeroArray,20));
+ BOOST_CHECK(OneL.ToString() == ArrayToString(OneArray,32));
+ BOOST_CHECK(OneS.ToString() == ArrayToString(OneArray,20));
+ BOOST_CHECK(MaxL.ToString() == ArrayToString(MaxArray,32));
+ BOOST_CHECK(MaxS.ToString() == ArrayToString(MaxArray,20));
+ BOOST_CHECK(OneL.ToString() != ArrayToString(ZeroArray,32));
+ BOOST_CHECK(OneS.ToString() != ArrayToString(ZeroArray,20));
+
+ // == and !=
+ BOOST_CHECK(R1L != R2L && R1S != R2S);
+ BOOST_CHECK(ZeroL != OneL && ZeroS != OneS);
+ BOOST_CHECK(OneL != ZeroL && OneS != ZeroS);
+ BOOST_CHECK(MaxL != ZeroL && MaxS != ZeroS);
+
+ // String Constructor and Copy Constructor
+ BOOST_CHECK(uint256S("0x"+R1L.ToString()) == R1L);
+ BOOST_CHECK(uint256S("0x"+R2L.ToString()) == R2L);
+ BOOST_CHECK(uint256S("0x"+ZeroL.ToString()) == ZeroL);
+ BOOST_CHECK(uint256S("0x"+OneL.ToString()) == OneL);
+ BOOST_CHECK(uint256S("0x"+MaxL.ToString()) == MaxL);
+ BOOST_CHECK(uint256S(R1L.ToString()) == R1L);
+ BOOST_CHECK(uint256S(" 0x"+R1L.ToString()+" ") == R1L);
+ BOOST_CHECK(uint256S("") == ZeroL);
+ BOOST_CHECK(R1L == uint256S(R1ArrayHex));
+ BOOST_CHECK(uint256(R1L) == R1L);
+ BOOST_CHECK(uint256(ZeroL) == ZeroL);
+ BOOST_CHECK(uint256(OneL) == OneL);
+
+ BOOST_CHECK(uint160S("0x"+R1S.ToString()) == R1S);
+ BOOST_CHECK(uint160S("0x"+R2S.ToString()) == R2S);
+ BOOST_CHECK(uint160S("0x"+ZeroS.ToString()) == ZeroS);
+ BOOST_CHECK(uint160S("0x"+OneS.ToString()) == OneS);
+ BOOST_CHECK(uint160S("0x"+MaxS.ToString()) == MaxS);
+ BOOST_CHECK(uint160S(R1S.ToString()) == R1S);
+ BOOST_CHECK(uint160S(" 0x"+R1S.ToString()+" ") == R1S);
+ BOOST_CHECK(uint160S("") == ZeroS);
+ BOOST_CHECK(R1S == uint160S(R1ArrayHex));
+
+ BOOST_CHECK(uint160(R1S) == R1S);
+ BOOST_CHECK(uint160(ZeroS) == ZeroS);
+ BOOST_CHECK(uint160(OneS) == OneS);
+}
+
+BOOST_AUTO_TEST_CASE( comparison ) // <= >= < >
+{
+ uint256 LastL;
+ for (int i = 255; i >= 0; --i) {
+ uint256 TmpL;
+ *(TmpL.begin() + (i>>3)) |= 1<<(7-(i&7));
+ BOOST_CHECK( LastL < TmpL );
+ LastL = TmpL;
+ }
+
+ BOOST_CHECK( ZeroL < R1L );
+ BOOST_CHECK( R2L < R1L );
+ BOOST_CHECK( ZeroL < OneL );
+ BOOST_CHECK( OneL < MaxL );
+ BOOST_CHECK( R1L < MaxL );
+ BOOST_CHECK( R2L < MaxL );
+
+ uint160 LastS;
+ for (int i = 159; i >= 0; --i) {
+ uint160 TmpS;
+ *(TmpS.begin() + (i>>3)) |= 1<<(7-(i&7));
+ BOOST_CHECK( LastS < TmpS );
+ LastS = TmpS;
+ }
+ BOOST_CHECK( ZeroS < R1S );
+ BOOST_CHECK( R2S < R1S );
+ BOOST_CHECK( ZeroS < OneS );
+ BOOST_CHECK( OneS < MaxS );
+ BOOST_CHECK( R1S < MaxS );
+ BOOST_CHECK( R2S < MaxS );
+}
+
+BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 GetSerializeSize, Serialize, Unserialize
+{
+ BOOST_CHECK(R1L.GetHex() == R1L.ToString());
+ BOOST_CHECK(R2L.GetHex() == R2L.ToString());
+ BOOST_CHECK(OneL.GetHex() == OneL.ToString());
+ BOOST_CHECK(MaxL.GetHex() == MaxL.ToString());
+ uint256 TmpL(R1L);
+ BOOST_CHECK(TmpL == R1L);
+ TmpL.SetHex(R2L.ToString()); BOOST_CHECK(TmpL == R2L);
+ TmpL.SetHex(ZeroL.ToString()); BOOST_CHECK(TmpL == uint256());
+
+ TmpL.SetHex(R1L.ToString());
+ BOOST_CHECK(memcmp(R1L.begin(), R1Array, 32)==0);
+ BOOST_CHECK(memcmp(TmpL.begin(), R1Array, 32)==0);
+ BOOST_CHECK(memcmp(R2L.begin(), R2Array, 32)==0);
+ BOOST_CHECK(memcmp(ZeroL.begin(), ZeroArray, 32)==0);
+ BOOST_CHECK(memcmp(OneL.begin(), OneArray, 32)==0);
+ BOOST_CHECK(R1L.size() == sizeof(R1L));
+ BOOST_CHECK(sizeof(R1L) == 32);
+ BOOST_CHECK(R1L.size() == 32);
+ BOOST_CHECK(R2L.size() == 32);
+ BOOST_CHECK(ZeroL.size() == 32);
+ BOOST_CHECK(MaxL.size() == 32);
+ BOOST_CHECK(R1L.begin() + 32 == R1L.end());
+ BOOST_CHECK(R2L.begin() + 32 == R2L.end());
+ BOOST_CHECK(OneL.begin() + 32 == OneL.end());
+ BOOST_CHECK(MaxL.begin() + 32 == MaxL.end());
+ BOOST_CHECK(TmpL.begin() + 32 == TmpL.end());
+ BOOST_CHECK(GetSerializeSize(R1L, 0, PROTOCOL_VERSION) == 32);
+ BOOST_CHECK(GetSerializeSize(ZeroL, 0, PROTOCOL_VERSION) == 32);
+
+ CDataStream ss(0, PROTOCOL_VERSION);
+ ss << R1L;
+ BOOST_CHECK(ss.str() == std::string(R1Array,R1Array+32));
+ ss >> TmpL;
+ BOOST_CHECK(R1L == TmpL);
+ ss.clear();
+ ss << ZeroL;
+ BOOST_CHECK(ss.str() == std::string(ZeroArray,ZeroArray+32));
+ ss >> TmpL;
+ BOOST_CHECK(ZeroL == TmpL);
+ ss.clear();
+ ss << MaxL;
+ BOOST_CHECK(ss.str() == std::string(MaxArray,MaxArray+32));
+ ss >> TmpL;
+ BOOST_CHECK(MaxL == TmpL);
+ ss.clear();
+
+ BOOST_CHECK(R1S.GetHex() == R1S.ToString());
+ BOOST_CHECK(R2S.GetHex() == R2S.ToString());
+ BOOST_CHECK(OneS.GetHex() == OneS.ToString());
+ BOOST_CHECK(MaxS.GetHex() == MaxS.ToString());
+ uint160 TmpS(R1S);
+ BOOST_CHECK(TmpS == R1S);
+ TmpS.SetHex(R2S.ToString()); BOOST_CHECK(TmpS == R2S);
+ TmpS.SetHex(ZeroS.ToString()); BOOST_CHECK(TmpS == uint160());
+
+ TmpS.SetHex(R1S.ToString());
+ BOOST_CHECK(memcmp(R1S.begin(), R1Array, 20)==0);
+ BOOST_CHECK(memcmp(TmpS.begin(), R1Array, 20)==0);
+ BOOST_CHECK(memcmp(R2S.begin(), R2Array, 20)==0);
+ BOOST_CHECK(memcmp(ZeroS.begin(), ZeroArray, 20)==0);
+ BOOST_CHECK(memcmp(OneS.begin(), OneArray, 20)==0);
+ BOOST_CHECK(R1S.size() == sizeof(R1S));
+ BOOST_CHECK(sizeof(R1S) == 20);
+ BOOST_CHECK(R1S.size() == 20);
+ BOOST_CHECK(R2S.size() == 20);
+ BOOST_CHECK(ZeroS.size() == 20);
+ BOOST_CHECK(MaxS.size() == 20);
+ BOOST_CHECK(R1S.begin() + 20 == R1S.end());
+ BOOST_CHECK(R2S.begin() + 20 == R2S.end());
+ BOOST_CHECK(OneS.begin() + 20 == OneS.end());
+ BOOST_CHECK(MaxS.begin() + 20 == MaxS.end());
+ BOOST_CHECK(TmpS.begin() + 20 == TmpS.end());
+ BOOST_CHECK(GetSerializeSize(R1S, 0, PROTOCOL_VERSION) == 20);
+ BOOST_CHECK(GetSerializeSize(ZeroS, 0, PROTOCOL_VERSION) == 20);
+
+ ss << R1S;
+ BOOST_CHECK(ss.str() == std::string(R1Array,R1Array+20));
+ ss >> TmpS;
+ BOOST_CHECK(R1S == TmpS);
+ ss.clear();
+ ss << ZeroS;
+ BOOST_CHECK(ss.str() == std::string(ZeroArray,ZeroArray+20));
+ ss >> TmpS;
+ BOOST_CHECK(ZeroS == TmpS);
+ ss.clear();
+ ss << MaxS;
+ BOOST_CHECK(ss.str() == std::string(MaxArray,MaxArray+20));
+ ss >> TmpS;
+ BOOST_CHECK(MaxS == TmpS);
+ ss.clear();
+}
+
+BOOST_AUTO_TEST_CASE( conversion )
+{
+ BOOST_CHECK(ArithToUint256(UintToArith256(ZeroL)) == ZeroL);
+ BOOST_CHECK(ArithToUint256(UintToArith256(OneL)) == OneL);
+ BOOST_CHECK(ArithToUint256(UintToArith256(R1L)) == R1L);
+ BOOST_CHECK(ArithToUint256(UintToArith256(R2L)) == R2L);
+ BOOST_CHECK(UintToArith256(ZeroL) == 0);
+ BOOST_CHECK(UintToArith256(OneL) == 1);
+ BOOST_CHECK(ArithToUint256(0) == ZeroL);
+ BOOST_CHECK(ArithToUint256(1) == OneL);
+ BOOST_CHECK(arith_uint256(R1L.GetHex()) == UintToArith256(R1L));
+ BOOST_CHECK(arith_uint256(R2L.GetHex()) == UintToArith256(R2L));
+ BOOST_CHECK(R1L.GetHex() == UintToArith256(R1L).GetHex());
+ BOOST_CHECK(R2L.GetHex() == UintToArith256(R2L).GetHex());
+}
+
+BOOST_AUTO_TEST_CASE( operator_with_self )
+{
+ arith_uint256 v = UintToArith256(uint256S("02"));
+ v *= v;
+ BOOST_CHECK(v == UintToArith256(uint256S("04")));
+ v /= v;
+ BOOST_CHECK(v == UintToArith256(uint256S("01")));
+ v += v;
+ BOOST_CHECK(v == UintToArith256(uint256S("02")));
+ v -= v;
+ BOOST_CHECK(v == UintToArith256(uint256S("0")));
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
new file mode 100644
index 0000000000..b2960446eb
--- /dev/null
+++ b/src/test/util_tests.cpp
@@ -0,0 +1,1220 @@
+// Copyright (c) 2011-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <util.h>
+
+#include <clientversion.h>
+#include <primitives/transaction.h>
+#include <sync.h>
+#include <utilstrencodings.h>
+#include <utilmoneystr.h>
+#include <test/test_bitcoin.h>
+
+#include <stdint.h>
+#include <vector>
+#ifndef WIN32
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#endif
+
+#include <boost/test/unit_test.hpp>
+
+BOOST_FIXTURE_TEST_SUITE(util_tests, BasicTestingSetup)
+
+BOOST_AUTO_TEST_CASE(util_criticalsection)
+{
+ CCriticalSection cs;
+
+ do {
+ LOCK(cs);
+ break;
+
+ BOOST_ERROR("break was swallowed!");
+ } while(0);
+
+ do {
+ TRY_LOCK(cs, lockTest);
+ if (lockTest)
+ break;
+
+ BOOST_ERROR("break was swallowed!");
+ } while(0);
+}
+
+static const unsigned char ParseHex_expected[65] = {
+ 0x04, 0x67, 0x8a, 0xfd, 0xb0, 0xfe, 0x55, 0x48, 0x27, 0x19, 0x67, 0xf1, 0xa6, 0x71, 0x30, 0xb7,
+ 0x10, 0x5c, 0xd6, 0xa8, 0x28, 0xe0, 0x39, 0x09, 0xa6, 0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, 0xde,
+ 0xb6, 0x49, 0xf6, 0xbc, 0x3f, 0x4c, 0xef, 0x38, 0xc4, 0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, 0x12,
+ 0xde, 0x5c, 0x38, 0x4d, 0xf7, 0xba, 0x0b, 0x8d, 0x57, 0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, 0x1d,
+ 0x5f
+};
+BOOST_AUTO_TEST_CASE(util_ParseHex)
+{
+ std::vector<unsigned char> result;
+ std::vector<unsigned char> expected(ParseHex_expected, ParseHex_expected + sizeof(ParseHex_expected));
+ // Basic test vector
+ result = ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f");
+ BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
+
+ // Spaces between bytes must be supported
+ result = ParseHex("12 34 56 78");
+ BOOST_CHECK(result.size() == 4 && result[0] == 0x12 && result[1] == 0x34 && result[2] == 0x56 && result[3] == 0x78);
+
+ // Leading space must be supported (used in BerkeleyEnvironment::Salvage)
+ result = ParseHex(" 89 34 56 78");
+ BOOST_CHECK(result.size() == 4 && result[0] == 0x89 && result[1] == 0x34 && result[2] == 0x56 && result[3] == 0x78);
+
+ // Stop parsing at invalid value
+ result = ParseHex("1234 invalid 1234");
+ BOOST_CHECK(result.size() == 2 && result[0] == 0x12 && result[1] == 0x34);
+}
+
+BOOST_AUTO_TEST_CASE(util_HexStr)
+{
+ BOOST_CHECK_EQUAL(
+ HexStr(ParseHex_expected, ParseHex_expected + sizeof(ParseHex_expected)),
+ "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f");
+
+ BOOST_CHECK_EQUAL(
+ HexStr(ParseHex_expected, ParseHex_expected + 5, true),
+ "04 67 8a fd b0");
+
+ BOOST_CHECK_EQUAL(
+ HexStr(ParseHex_expected + sizeof(ParseHex_expected),
+ ParseHex_expected + sizeof(ParseHex_expected)),
+ "");
+
+ BOOST_CHECK_EQUAL(
+ HexStr(ParseHex_expected + sizeof(ParseHex_expected),
+ ParseHex_expected + sizeof(ParseHex_expected), true),
+ "");
+
+ BOOST_CHECK_EQUAL(
+ HexStr(ParseHex_expected, ParseHex_expected),
+ "");
+
+ 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_CHECK_EQUAL(
+ HexStr(ParseHex_vec.rbegin(), ParseHex_vec.rend()),
+ "b0fd8a6704"
+ );
+
+ BOOST_CHECK_EQUAL(
+ HexStr(ParseHex_vec.rbegin(), ParseHex_vec.rend(), true),
+ "b0 fd 8a 67 04"
+ );
+
+ BOOST_CHECK_EQUAL(
+ HexStr(std::reverse_iterator<const uint8_t *>(ParseHex_expected),
+ std::reverse_iterator<const uint8_t *>(ParseHex_expected)),
+ ""
+ );
+
+ BOOST_CHECK_EQUAL(
+ HexStr(std::reverse_iterator<const uint8_t *>(ParseHex_expected),
+ std::reverse_iterator<const uint8_t *>(ParseHex_expected), true),
+ ""
+ );
+
+ BOOST_CHECK_EQUAL(
+ HexStr(std::reverse_iterator<const uint8_t *>(ParseHex_expected + 1),
+ std::reverse_iterator<const uint8_t *>(ParseHex_expected)),
+ "04"
+ );
+
+ BOOST_CHECK_EQUAL(
+ HexStr(std::reverse_iterator<const uint8_t *>(ParseHex_expected + 1),
+ std::reverse_iterator<const uint8_t *>(ParseHex_expected), true),
+ "04"
+ );
+
+ BOOST_CHECK_EQUAL(
+ HexStr(std::reverse_iterator<const uint8_t *>(ParseHex_expected + 5),
+ std::reverse_iterator<const uint8_t *>(ParseHex_expected)),
+ "b0fd8a6704"
+ );
+
+ BOOST_CHECK_EQUAL(
+ HexStr(std::reverse_iterator<const uint8_t *>(ParseHex_expected + 5),
+ std::reverse_iterator<const uint8_t *>(ParseHex_expected), true),
+ "b0 fd 8a 67 04"
+ );
+
+ BOOST_CHECK_EQUAL(
+ HexStr(std::reverse_iterator<const uint8_t *>(ParseHex_expected + 65),
+ std::reverse_iterator<const uint8_t *>(ParseHex_expected)),
+ "5f1df16b2b704c8a578d0bbaf74d385cde12c11ee50455f3c438ef4c3fbcf649b6de611feae06279a60939e028a8d65c10b73071a6f16719274855feb0fd8a6704"
+ );
+}
+
+
+BOOST_AUTO_TEST_CASE(util_FormatISO8601DateTime)
+{
+ BOOST_CHECK_EQUAL(FormatISO8601DateTime(1317425777), "2011-09-30T23:36:17Z");
+}
+
+BOOST_AUTO_TEST_CASE(util_FormatISO8601Date)
+{
+ BOOST_CHECK_EQUAL(FormatISO8601Date(1317425777), "2011-09-30");
+}
+
+BOOST_AUTO_TEST_CASE(util_FormatISO8601Time)
+{
+ BOOST_CHECK_EQUAL(FormatISO8601Time(1317425777), "23:36:17Z");
+}
+
+struct TestArgsManager : public ArgsManager
+{
+ TestArgsManager() { m_network_only_args.clear(); }
+ std::map<std::string, std::vector<std::string> >& GetOverrideArgs() { return m_override_args; }
+ std::map<std::string, std::vector<std::string> >& GetConfigArgs() { return m_config_args; }
+ void ReadConfigString(const std::string str_config)
+ {
+ std::istringstream streamConfig(str_config);
+ {
+ LOCK(cs_args);
+ m_config_args.clear();
+ }
+ std::string error;
+ ReadConfigStream(streamConfig, error);
+ }
+ void SetNetworkOnlyArg(const std::string arg)
+ {
+ LOCK(cs_args);
+ m_network_only_args.insert(arg);
+ }
+ void SetupArgs(int argv, const char* args[])
+ {
+ for (int i = 0; i < argv; ++i) {
+ AddArg(args[i], "", false, OptionsCategory::OPTIONS);
+ }
+ }
+};
+
+BOOST_AUTO_TEST_CASE(util_ParseParameters)
+{
+ TestArgsManager testArgs;
+ const char* avail_args[] = {"-a", "-b", "-ccc", "-d"};
+ const char *argv_test[] = {"-ignored", "-a", "-b", "-ccc=argument", "-ccc=multiple", "f", "-d=e"};
+
+ std::string error;
+ testArgs.SetupArgs(4, avail_args);
+ testArgs.ParseParameters(0, (char**)argv_test, error);
+ BOOST_CHECK(testArgs.GetOverrideArgs().empty() && testArgs.GetConfigArgs().empty());
+
+ testArgs.ParseParameters(1, (char**)argv_test, error);
+ BOOST_CHECK(testArgs.GetOverrideArgs().empty() && testArgs.GetConfigArgs().empty());
+
+ testArgs.ParseParameters(7, (char**)argv_test, error);
+ // expectation: -ignored is ignored (program name argument),
+ // -a, -b and -ccc end up in map, -d ignored because it is after
+ // a non-option argument (non-GNU option parsing)
+ BOOST_CHECK(testArgs.GetOverrideArgs().size() == 3 && testArgs.GetConfigArgs().empty());
+ BOOST_CHECK(testArgs.IsArgSet("-a") && testArgs.IsArgSet("-b") && testArgs.IsArgSet("-ccc")
+ && !testArgs.IsArgSet("f") && !testArgs.IsArgSet("-d"));
+ BOOST_CHECK(testArgs.GetOverrideArgs().count("-a") && testArgs.GetOverrideArgs().count("-b") && testArgs.GetOverrideArgs().count("-ccc")
+ && !testArgs.GetOverrideArgs().count("f") && !testArgs.GetOverrideArgs().count("-d"));
+
+ BOOST_CHECK(testArgs.GetOverrideArgs()["-a"].size() == 1);
+ BOOST_CHECK(testArgs.GetOverrideArgs()["-a"].front() == "");
+ BOOST_CHECK(testArgs.GetOverrideArgs()["-ccc"].size() == 2);
+ BOOST_CHECK(testArgs.GetOverrideArgs()["-ccc"].front() == "argument");
+ BOOST_CHECK(testArgs.GetOverrideArgs()["-ccc"].back() == "multiple");
+ BOOST_CHECK(testArgs.GetArgs("-ccc").size() == 2);
+}
+
+BOOST_AUTO_TEST_CASE(util_GetBoolArg)
+{
+ TestArgsManager testArgs;
+ const char* avail_args[] = {"-a", "-b", "-c", "-d", "-e", "-f"};
+ const char *argv_test[] = {
+ "ignored", "-a", "-nob", "-c=0", "-d=1", "-e=false", "-f=true"};
+ std::string error;
+ testArgs.SetupArgs(6, avail_args);
+ testArgs.ParseParameters(7, (char**)argv_test, error);
+
+ // Each letter should be set.
+ for (char opt : "abcdef")
+ BOOST_CHECK(testArgs.IsArgSet({'-', opt}) || !opt);
+
+ // Nothing else should be in the map
+ BOOST_CHECK(testArgs.GetOverrideArgs().size() == 6 &&
+ testArgs.GetConfigArgs().empty());
+
+ // The -no prefix should get stripped on the way in.
+ BOOST_CHECK(!testArgs.IsArgSet("-nob"));
+
+ // The -b option is flagged as negated, and nothing else is
+ BOOST_CHECK(testArgs.IsArgNegated("-b"));
+ BOOST_CHECK(!testArgs.IsArgNegated("-a"));
+
+ // Check expected values.
+ BOOST_CHECK(testArgs.GetBoolArg("-a", false) == true);
+ BOOST_CHECK(testArgs.GetBoolArg("-b", true) == false);
+ BOOST_CHECK(testArgs.GetBoolArg("-c", true) == false);
+ BOOST_CHECK(testArgs.GetBoolArg("-d", false) == true);
+ BOOST_CHECK(testArgs.GetBoolArg("-e", true) == false);
+ BOOST_CHECK(testArgs.GetBoolArg("-f", true) == false);
+}
+
+BOOST_AUTO_TEST_CASE(util_GetBoolArgEdgeCases)
+{
+ // Test some awful edge cases that hopefully no user will ever exercise.
+ TestArgsManager testArgs;
+
+ // Params test
+ const char* avail_args[] = {"-foo", "-bar"};
+ const char *argv_test[] = {"ignored", "-nofoo", "-foo", "-nobar=0"};
+ testArgs.SetupArgs(2, avail_args);
+ std::string error;
+ testArgs.ParseParameters(4, (char**)argv_test, error);
+
+ // This was passed twice, second one overrides the negative setting.
+ BOOST_CHECK(!testArgs.IsArgNegated("-foo"));
+ BOOST_CHECK(testArgs.GetArg("-foo", "xxx") == "");
+
+ // A double negative is a positive, and not marked as negated.
+ BOOST_CHECK(!testArgs.IsArgNegated("-bar"));
+ BOOST_CHECK(testArgs.GetArg("-bar", "xxx") == "1");
+
+ // Config test
+ const char *conf_test = "nofoo=1\nfoo=1\nnobar=0\n";
+ testArgs.ParseParameters(1, (char**)argv_test, error);
+ testArgs.ReadConfigString(conf_test);
+
+ // This was passed twice, second one overrides the negative setting,
+ // and the value.
+ BOOST_CHECK(!testArgs.IsArgNegated("-foo"));
+ BOOST_CHECK(testArgs.GetArg("-foo", "xxx") == "1");
+
+ // A double negative is a positive, and does not count as negated.
+ BOOST_CHECK(!testArgs.IsArgNegated("-bar"));
+ BOOST_CHECK(testArgs.GetArg("-bar", "xxx") == "1");
+
+ // Combined test
+ const char *combo_test_args[] = {"ignored", "-nofoo", "-bar"};
+ const char *combo_test_conf = "foo=1\nnobar=1\n";
+ testArgs.ParseParameters(3, (char**)combo_test_args, error);
+ testArgs.ReadConfigString(combo_test_conf);
+
+ // Command line overrides, but doesn't erase old setting
+ BOOST_CHECK(testArgs.IsArgNegated("-foo"));
+ BOOST_CHECK(testArgs.GetArg("-foo", "xxx") == "0");
+ BOOST_CHECK(testArgs.GetArgs("-foo").size() == 0);
+
+ // Command line overrides, but doesn't erase old setting
+ BOOST_CHECK(!testArgs.IsArgNegated("-bar"));
+ BOOST_CHECK(testArgs.GetArg("-bar", "xxx") == "");
+ BOOST_CHECK(testArgs.GetArgs("-bar").size() == 1
+ && testArgs.GetArgs("-bar").front() == "");
+}
+
+BOOST_AUTO_TEST_CASE(util_ReadConfigStream)
+{
+ const char *str_config =
+ "a=\n"
+ "b=1\n"
+ "ccc=argument\n"
+ "ccc=multiple\n"
+ "d=e\n"
+ "nofff=1\n"
+ "noggg=0\n"
+ "h=1\n"
+ "noh=1\n"
+ "noi=1\n"
+ "i=1\n"
+ "sec1.ccc=extend1\n"
+ "\n"
+ "[sec1]\n"
+ "ccc=extend2\n"
+ "d=eee\n"
+ "h=1\n"
+ "[sec2]\n"
+ "ccc=extend3\n"
+ "iii=2\n";
+
+ TestArgsManager test_args;
+ const char* avail_args[] = {"-a", "-b", "-ccc", "-d", "-e", "-fff", "-ggg", "-h", "-i", "-iii"};
+ test_args.SetupArgs(10, avail_args);
+
+ test_args.ReadConfigString(str_config);
+ // expectation: a, b, ccc, d, fff, ggg, h, i end up in map
+ // so do sec1.ccc, sec1.d, sec1.h, sec2.ccc, sec2.iii
+
+ BOOST_CHECK(test_args.GetOverrideArgs().empty());
+ BOOST_CHECK(test_args.GetConfigArgs().size() == 13);
+
+ BOOST_CHECK(test_args.GetConfigArgs().count("-a")
+ && test_args.GetConfigArgs().count("-b")
+ && test_args.GetConfigArgs().count("-ccc")
+ && test_args.GetConfigArgs().count("-d")
+ && test_args.GetConfigArgs().count("-fff")
+ && test_args.GetConfigArgs().count("-ggg")
+ && test_args.GetConfigArgs().count("-h")
+ && test_args.GetConfigArgs().count("-i")
+ );
+ BOOST_CHECK(test_args.GetConfigArgs().count("-sec1.ccc")
+ && test_args.GetConfigArgs().count("-sec1.h")
+ && test_args.GetConfigArgs().count("-sec2.ccc")
+ && test_args.GetConfigArgs().count("-sec2.iii")
+ );
+
+ BOOST_CHECK(test_args.IsArgSet("-a")
+ && test_args.IsArgSet("-b")
+ && test_args.IsArgSet("-ccc")
+ && test_args.IsArgSet("-d")
+ && test_args.IsArgSet("-fff")
+ && test_args.IsArgSet("-ggg")
+ && test_args.IsArgSet("-h")
+ && test_args.IsArgSet("-i")
+ && !test_args.IsArgSet("-zzz")
+ && !test_args.IsArgSet("-iii")
+ );
+
+ BOOST_CHECK(test_args.GetArg("-a", "xxx") == ""
+ && test_args.GetArg("-b", "xxx") == "1"
+ && test_args.GetArg("-ccc", "xxx") == "argument"
+ && test_args.GetArg("-d", "xxx") == "e"
+ && test_args.GetArg("-fff", "xxx") == "0"
+ && test_args.GetArg("-ggg", "xxx") == "1"
+ && test_args.GetArg("-h", "xxx") == "0"
+ && test_args.GetArg("-i", "xxx") == "1"
+ && test_args.GetArg("-zzz", "xxx") == "xxx"
+ && test_args.GetArg("-iii", "xxx") == "xxx"
+ );
+
+ for (bool def : {false, true}) {
+ BOOST_CHECK(test_args.GetBoolArg("-a", def)
+ && test_args.GetBoolArg("-b", def)
+ && !test_args.GetBoolArg("-ccc", def)
+ && !test_args.GetBoolArg("-d", def)
+ && !test_args.GetBoolArg("-fff", def)
+ && test_args.GetBoolArg("-ggg", def)
+ && !test_args.GetBoolArg("-h", def)
+ && test_args.GetBoolArg("-i", def)
+ && test_args.GetBoolArg("-zzz", def) == def
+ && test_args.GetBoolArg("-iii", def) == def
+ );
+ }
+
+ BOOST_CHECK(test_args.GetArgs("-a").size() == 1
+ && test_args.GetArgs("-a").front() == "");
+ BOOST_CHECK(test_args.GetArgs("-b").size() == 1
+ && test_args.GetArgs("-b").front() == "1");
+ BOOST_CHECK(test_args.GetArgs("-ccc").size() == 2
+ && test_args.GetArgs("-ccc").front() == "argument"
+ && test_args.GetArgs("-ccc").back() == "multiple");
+ BOOST_CHECK(test_args.GetArgs("-fff").size() == 0);
+ BOOST_CHECK(test_args.GetArgs("-nofff").size() == 0);
+ BOOST_CHECK(test_args.GetArgs("-ggg").size() == 1
+ && test_args.GetArgs("-ggg").front() == "1");
+ BOOST_CHECK(test_args.GetArgs("-noggg").size() == 0);
+ BOOST_CHECK(test_args.GetArgs("-h").size() == 0);
+ BOOST_CHECK(test_args.GetArgs("-noh").size() == 0);
+ BOOST_CHECK(test_args.GetArgs("-i").size() == 1
+ && test_args.GetArgs("-i").front() == "1");
+ BOOST_CHECK(test_args.GetArgs("-noi").size() == 0);
+ BOOST_CHECK(test_args.GetArgs("-zzz").size() == 0);
+
+ BOOST_CHECK(!test_args.IsArgNegated("-a"));
+ BOOST_CHECK(!test_args.IsArgNegated("-b"));
+ BOOST_CHECK(!test_args.IsArgNegated("-ccc"));
+ BOOST_CHECK(!test_args.IsArgNegated("-d"));
+ BOOST_CHECK(test_args.IsArgNegated("-fff"));
+ BOOST_CHECK(!test_args.IsArgNegated("-ggg"));
+ BOOST_CHECK(test_args.IsArgNegated("-h")); // last setting takes precedence
+ BOOST_CHECK(!test_args.IsArgNegated("-i")); // last setting takes precedence
+ BOOST_CHECK(!test_args.IsArgNegated("-zzz"));
+
+ // Test sections work
+ test_args.SelectConfigNetwork("sec1");
+
+ // same as original
+ BOOST_CHECK(test_args.GetArg("-a", "xxx") == ""
+ && test_args.GetArg("-b", "xxx") == "1"
+ && test_args.GetArg("-fff", "xxx") == "0"
+ && test_args.GetArg("-ggg", "xxx") == "1"
+ && test_args.GetArg("-zzz", "xxx") == "xxx"
+ && test_args.GetArg("-iii", "xxx") == "xxx"
+ );
+ // d is overridden
+ BOOST_CHECK(test_args.GetArg("-d", "xxx") == "eee");
+ // section-specific setting
+ BOOST_CHECK(test_args.GetArg("-h", "xxx") == "1");
+ // section takes priority for multiple values
+ BOOST_CHECK(test_args.GetArg("-ccc", "xxx") == "extend1");
+ // check multiple values works
+ const std::vector<std::string> sec1_ccc_expected = {"extend1","extend2","argument","multiple"};
+ const auto& sec1_ccc_res = test_args.GetArgs("-ccc");
+ BOOST_CHECK_EQUAL_COLLECTIONS(sec1_ccc_res.begin(), sec1_ccc_res.end(), sec1_ccc_expected.begin(), sec1_ccc_expected.end());
+
+ test_args.SelectConfigNetwork("sec2");
+
+ // same as original
+ BOOST_CHECK(test_args.GetArg("-a", "xxx") == ""
+ && test_args.GetArg("-b", "xxx") == "1"
+ && test_args.GetArg("-d", "xxx") == "e"
+ && test_args.GetArg("-fff", "xxx") == "0"
+ && test_args.GetArg("-ggg", "xxx") == "1"
+ && test_args.GetArg("-zzz", "xxx") == "xxx"
+ && test_args.GetArg("-h", "xxx") == "0"
+ );
+ // section-specific setting
+ BOOST_CHECK(test_args.GetArg("-iii", "xxx") == "2");
+ // section takes priority for multiple values
+ BOOST_CHECK(test_args.GetArg("-ccc", "xxx") == "extend3");
+ // check multiple values works
+ const std::vector<std::string> sec2_ccc_expected = {"extend3","argument","multiple"};
+ const auto& sec2_ccc_res = test_args.GetArgs("-ccc");
+ BOOST_CHECK_EQUAL_COLLECTIONS(sec2_ccc_res.begin(), sec2_ccc_res.end(), sec2_ccc_expected.begin(), sec2_ccc_expected.end());
+
+ // Test section only options
+
+ test_args.SetNetworkOnlyArg("-d");
+ test_args.SetNetworkOnlyArg("-ccc");
+ test_args.SetNetworkOnlyArg("-h");
+
+ test_args.SelectConfigNetwork(CBaseChainParams::MAIN);
+ BOOST_CHECK(test_args.GetArg("-d", "xxx") == "e");
+ BOOST_CHECK(test_args.GetArgs("-ccc").size() == 2);
+ BOOST_CHECK(test_args.GetArg("-h", "xxx") == "0");
+
+ test_args.SelectConfigNetwork("sec1");
+ BOOST_CHECK(test_args.GetArg("-d", "xxx") == "eee");
+ BOOST_CHECK(test_args.GetArgs("-d").size() == 1);
+ BOOST_CHECK(test_args.GetArgs("-ccc").size() == 2);
+ BOOST_CHECK(test_args.GetArg("-h", "xxx") == "1");
+
+ test_args.SelectConfigNetwork("sec2");
+ BOOST_CHECK(test_args.GetArg("-d", "xxx") == "xxx");
+ BOOST_CHECK(test_args.GetArgs("-d").size() == 0);
+ BOOST_CHECK(test_args.GetArgs("-ccc").size() == 1);
+ BOOST_CHECK(test_args.GetArg("-h", "xxx") == "0");
+}
+
+BOOST_AUTO_TEST_CASE(util_GetArg)
+{
+ TestArgsManager testArgs;
+ testArgs.GetOverrideArgs().clear();
+ testArgs.GetOverrideArgs()["strtest1"] = {"string..."};
+ // strtest2 undefined on purpose
+ testArgs.GetOverrideArgs()["inttest1"] = {"12345"};
+ testArgs.GetOverrideArgs()["inttest2"] = {"81985529216486895"};
+ // inttest3 undefined on purpose
+ testArgs.GetOverrideArgs()["booltest1"] = {""};
+ // booltest2 undefined on purpose
+ testArgs.GetOverrideArgs()["booltest3"] = {"0"};
+ testArgs.GetOverrideArgs()["booltest4"] = {"1"};
+
+ // priorities
+ testArgs.GetOverrideArgs()["pritest1"] = {"a", "b"};
+ testArgs.GetConfigArgs()["pritest2"] = {"a", "b"};
+ testArgs.GetOverrideArgs()["pritest3"] = {"a"};
+ testArgs.GetConfigArgs()["pritest3"] = {"b"};
+ testArgs.GetOverrideArgs()["pritest4"] = {"a","b"};
+ testArgs.GetConfigArgs()["pritest4"] = {"c","d"};
+
+ BOOST_CHECK_EQUAL(testArgs.GetArg("strtest1", "default"), "string...");
+ BOOST_CHECK_EQUAL(testArgs.GetArg("strtest2", "default"), "default");
+ BOOST_CHECK_EQUAL(testArgs.GetArg("inttest1", -1), 12345);
+ BOOST_CHECK_EQUAL(testArgs.GetArg("inttest2", -1), 81985529216486895LL);
+ BOOST_CHECK_EQUAL(testArgs.GetArg("inttest3", -1), -1);
+ BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest1", false), true);
+ BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest2", false), false);
+ BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest3", false), false);
+ BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest4", false), true);
+
+ BOOST_CHECK_EQUAL(testArgs.GetArg("pritest1", "default"), "b");
+ BOOST_CHECK_EQUAL(testArgs.GetArg("pritest2", "default"), "a");
+ BOOST_CHECK_EQUAL(testArgs.GetArg("pritest3", "default"), "a");
+ BOOST_CHECK_EQUAL(testArgs.GetArg("pritest4", "default"), "b");
+}
+
+BOOST_AUTO_TEST_CASE(util_GetChainName)
+{
+ TestArgsManager test_args;
+ const char* avail_args[] = {"-testnet", "-regtest"};
+ test_args.SetupArgs(2, avail_args);
+
+ const char* argv_testnet[] = {"cmd", "-testnet"};
+ const char* argv_regtest[] = {"cmd", "-regtest"};
+ const char* argv_test_no_reg[] = {"cmd", "-testnet", "-noregtest"};
+ const char* argv_both[] = {"cmd", "-testnet", "-regtest"};
+
+ // equivalent to "-testnet"
+ // regtest in testnet section is ignored
+ const char* testnetconf = "testnet=1\nregtest=0\n[test]\nregtest=1";
+ std::string error;
+
+ test_args.ParseParameters(0, (char**)argv_testnet, error);
+ BOOST_CHECK_EQUAL(test_args.GetChainName(), "main");
+
+ test_args.ParseParameters(2, (char**)argv_testnet, error);
+ BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
+
+ test_args.ParseParameters(2, (char**)argv_regtest, error);
+ BOOST_CHECK_EQUAL(test_args.GetChainName(), "regtest");
+
+ test_args.ParseParameters(3, (char**)argv_test_no_reg, error);
+ BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
+
+ test_args.ParseParameters(3, (char**)argv_both, error);
+ BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
+
+ test_args.ParseParameters(0, (char**)argv_testnet, error);
+ test_args.ReadConfigString(testnetconf);
+ BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
+
+ test_args.ParseParameters(2, (char**)argv_testnet, error);
+ test_args.ReadConfigString(testnetconf);
+ BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
+
+ test_args.ParseParameters(2, (char**)argv_regtest, error);
+ test_args.ReadConfigString(testnetconf);
+ BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
+
+ test_args.ParseParameters(3, (char**)argv_test_no_reg, error);
+ test_args.ReadConfigString(testnetconf);
+ BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
+
+ test_args.ParseParameters(3, (char**)argv_both, error);
+ test_args.ReadConfigString(testnetconf);
+ BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
+
+ // check setting the network to test (and thus making
+ // [test] regtest=1 potentially relevant) doesn't break things
+ test_args.SelectConfigNetwork("test");
+
+ test_args.ParseParameters(0, (char**)argv_testnet, error);
+ test_args.ReadConfigString(testnetconf);
+ BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
+
+ test_args.ParseParameters(2, (char**)argv_testnet, error);
+ test_args.ReadConfigString(testnetconf);
+ BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
+
+ test_args.ParseParameters(2, (char**)argv_regtest, error);
+ test_args.ReadConfigString(testnetconf);
+ BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
+
+ test_args.ParseParameters(2, (char**)argv_test_no_reg, error);
+ test_args.ReadConfigString(testnetconf);
+ BOOST_CHECK_EQUAL(test_args.GetChainName(), "test");
+
+ test_args.ParseParameters(3, (char**)argv_both, error);
+ test_args.ReadConfigString(testnetconf);
+ BOOST_CHECK_THROW(test_args.GetChainName(), std::runtime_error);
+}
+
+BOOST_AUTO_TEST_CASE(util_FormatMoney)
+{
+ BOOST_CHECK_EQUAL(FormatMoney(0), "0.00");
+ BOOST_CHECK_EQUAL(FormatMoney((COIN/10000)*123456789), "12345.6789");
+ BOOST_CHECK_EQUAL(FormatMoney(-COIN), "-1.00");
+
+ BOOST_CHECK_EQUAL(FormatMoney(COIN*100000000), "100000000.00");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN*10000000), "10000000.00");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN*1000000), "1000000.00");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN*100000), "100000.00");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN*10000), "10000.00");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN*1000), "1000.00");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN*100), "100.00");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN*10), "10.00");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN), "1.00");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN/10), "0.10");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN/100), "0.01");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN/1000), "0.001");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN/10000), "0.0001");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN/100000), "0.00001");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN/1000000), "0.000001");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN/10000000), "0.0000001");
+ BOOST_CHECK_EQUAL(FormatMoney(COIN/100000000), "0.00000001");
+}
+
+BOOST_AUTO_TEST_CASE(util_ParseMoney)
+{
+ CAmount ret = 0;
+ BOOST_CHECK(ParseMoney("0.0", ret));
+ BOOST_CHECK_EQUAL(ret, 0);
+
+ BOOST_CHECK(ParseMoney("12345.6789", ret));
+ BOOST_CHECK_EQUAL(ret, (COIN/10000)*123456789);
+
+ BOOST_CHECK(ParseMoney("100000000.00", ret));
+ BOOST_CHECK_EQUAL(ret, COIN*100000000);
+ BOOST_CHECK(ParseMoney("10000000.00", ret));
+ BOOST_CHECK_EQUAL(ret, COIN*10000000);
+ BOOST_CHECK(ParseMoney("1000000.00", ret));
+ BOOST_CHECK_EQUAL(ret, COIN*1000000);
+ BOOST_CHECK(ParseMoney("100000.00", ret));
+ BOOST_CHECK_EQUAL(ret, COIN*100000);
+ BOOST_CHECK(ParseMoney("10000.00", ret));
+ BOOST_CHECK_EQUAL(ret, COIN*10000);
+ BOOST_CHECK(ParseMoney("1000.00", ret));
+ BOOST_CHECK_EQUAL(ret, COIN*1000);
+ BOOST_CHECK(ParseMoney("100.00", ret));
+ BOOST_CHECK_EQUAL(ret, COIN*100);
+ BOOST_CHECK(ParseMoney("10.00", ret));
+ BOOST_CHECK_EQUAL(ret, COIN*10);
+ BOOST_CHECK(ParseMoney("1.00", ret));
+ BOOST_CHECK_EQUAL(ret, COIN);
+ BOOST_CHECK(ParseMoney("1", ret));
+ BOOST_CHECK_EQUAL(ret, COIN);
+ BOOST_CHECK(ParseMoney("0.1", ret));
+ BOOST_CHECK_EQUAL(ret, COIN/10);
+ BOOST_CHECK(ParseMoney("0.01", ret));
+ BOOST_CHECK_EQUAL(ret, COIN/100);
+ BOOST_CHECK(ParseMoney("0.001", ret));
+ BOOST_CHECK_EQUAL(ret, COIN/1000);
+ BOOST_CHECK(ParseMoney("0.0001", ret));
+ BOOST_CHECK_EQUAL(ret, COIN/10000);
+ BOOST_CHECK(ParseMoney("0.00001", ret));
+ BOOST_CHECK_EQUAL(ret, COIN/100000);
+ BOOST_CHECK(ParseMoney("0.000001", ret));
+ BOOST_CHECK_EQUAL(ret, COIN/1000000);
+ BOOST_CHECK(ParseMoney("0.0000001", ret));
+ BOOST_CHECK_EQUAL(ret, COIN/10000000);
+ BOOST_CHECK(ParseMoney("0.00000001", ret));
+ BOOST_CHECK_EQUAL(ret, COIN/100000000);
+
+ // Attempted 63 bit overflow should fail
+ BOOST_CHECK(!ParseMoney("92233720368.54775808", ret));
+
+ // Parsing negative amounts must fail
+ BOOST_CHECK(!ParseMoney("-1", ret));
+}
+
+BOOST_AUTO_TEST_CASE(util_IsHex)
+{
+ BOOST_CHECK(IsHex("00"));
+ BOOST_CHECK(IsHex("00112233445566778899aabbccddeeffAABBCCDDEEFF"));
+ BOOST_CHECK(IsHex("ff"));
+ BOOST_CHECK(IsHex("FF"));
+
+ BOOST_CHECK(!IsHex(""));
+ BOOST_CHECK(!IsHex("0"));
+ BOOST_CHECK(!IsHex("a"));
+ BOOST_CHECK(!IsHex("eleven"));
+ BOOST_CHECK(!IsHex("00xx00"));
+ BOOST_CHECK(!IsHex("0x0000"));
+}
+
+BOOST_AUTO_TEST_CASE(util_IsHexNumber)
+{
+ BOOST_CHECK(IsHexNumber("0x0"));
+ BOOST_CHECK(IsHexNumber("0"));
+ BOOST_CHECK(IsHexNumber("0x10"));
+ BOOST_CHECK(IsHexNumber("10"));
+ BOOST_CHECK(IsHexNumber("0xff"));
+ BOOST_CHECK(IsHexNumber("ff"));
+ BOOST_CHECK(IsHexNumber("0xFfa"));
+ BOOST_CHECK(IsHexNumber("Ffa"));
+ BOOST_CHECK(IsHexNumber("0x00112233445566778899aabbccddeeffAABBCCDDEEFF"));
+ BOOST_CHECK(IsHexNumber("00112233445566778899aabbccddeeffAABBCCDDEEFF"));
+
+ BOOST_CHECK(!IsHexNumber("")); // empty string not allowed
+ BOOST_CHECK(!IsHexNumber("0x")); // empty string after prefix not allowed
+ BOOST_CHECK(!IsHexNumber("0x0 ")); // no spaces at end,
+ BOOST_CHECK(!IsHexNumber(" 0x0")); // or beginning,
+ BOOST_CHECK(!IsHexNumber("0x 0")); // or middle,
+ BOOST_CHECK(!IsHexNumber(" ")); // etc.
+ BOOST_CHECK(!IsHexNumber("0x0ga")); // invalid character
+ BOOST_CHECK(!IsHexNumber("x0")); // broken prefix
+ BOOST_CHECK(!IsHexNumber("0x0x00")); // two prefixes not allowed
+
+}
+
+BOOST_AUTO_TEST_CASE(util_seed_insecure_rand)
+{
+ SeedInsecureRand(true);
+ for (int mod=2;mod<11;mod++)
+ {
+ int mask = 1;
+ // Really rough binomial confidence approximation.
+ int err = 30*10000./mod*sqrt((1./mod*(1-1./mod))/10000.);
+ //mask is 2^ceil(log2(mod))-1
+ while(mask<mod-1)mask=(mask<<1)+1;
+
+ int count = 0;
+ //How often does it get a zero from the uniform range [0,mod)?
+ for (int i = 0; i < 10000; i++) {
+ uint32_t rval;
+ do{
+ rval=InsecureRand32()&mask;
+ }while(rval>=(uint32_t)mod);
+ count += rval==0;
+ }
+ BOOST_CHECK(count<=10000/mod+err);
+ BOOST_CHECK(count>=10000/mod-err);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(util_TimingResistantEqual)
+{
+ BOOST_CHECK(TimingResistantEqual(std::string(""), std::string("")));
+ BOOST_CHECK(!TimingResistantEqual(std::string("abc"), std::string("")));
+ BOOST_CHECK(!TimingResistantEqual(std::string(""), std::string("abc")));
+ BOOST_CHECK(!TimingResistantEqual(std::string("a"), std::string("aa")));
+ BOOST_CHECK(!TimingResistantEqual(std::string("aa"), std::string("a")));
+ BOOST_CHECK(TimingResistantEqual(std::string("abc"), std::string("abc")));
+ BOOST_CHECK(!TimingResistantEqual(std::string("abc"), std::string("aba")));
+}
+
+/* Test strprintf formatting directives.
+ * Put a string before and after to ensure sanity of element sizes on stack. */
+#define B "check_prefix"
+#define E "check_postfix"
+BOOST_AUTO_TEST_CASE(strprintf_numbers)
+{
+ int64_t s64t = -9223372036854775807LL; /* signed 64 bit test value */
+ uint64_t u64t = 18446744073709551615ULL; /* unsigned 64 bit test value */
+ BOOST_CHECK(strprintf("%s %d %s", B, s64t, E) == B" -9223372036854775807 " E);
+ BOOST_CHECK(strprintf("%s %u %s", B, u64t, E) == B" 18446744073709551615 " E);
+ BOOST_CHECK(strprintf("%s %x %s", B, u64t, E) == B" ffffffffffffffff " E);
+
+ size_t st = 12345678; /* unsigned size_t test value */
+ ssize_t sst = -12345678; /* signed size_t test value */
+ BOOST_CHECK(strprintf("%s %d %s", B, sst, E) == B" -12345678 " E);
+ BOOST_CHECK(strprintf("%s %u %s", B, st, E) == B" 12345678 " E);
+ BOOST_CHECK(strprintf("%s %x %s", B, st, E) == B" bc614e " E);
+
+ ptrdiff_t pt = 87654321; /* positive ptrdiff_t test value */
+ ptrdiff_t spt = -87654321; /* negative ptrdiff_t test value */
+ BOOST_CHECK(strprintf("%s %d %s", B, spt, E) == B" -87654321 " E);
+ BOOST_CHECK(strprintf("%s %u %s", B, pt, E) == B" 87654321 " E);
+ BOOST_CHECK(strprintf("%s %x %s", B, pt, E) == B" 5397fb1 " E);
+}
+#undef B
+#undef E
+
+/* Check for mingw/wine issue #3494
+ * Remove this test before time.ctime(0xffffffff) == 'Sun Feb 7 07:28:15 2106'
+ */
+BOOST_AUTO_TEST_CASE(gettime)
+{
+ BOOST_CHECK((GetTime() & ~0xFFFFFFFFLL) == 0);
+}
+
+BOOST_AUTO_TEST_CASE(test_IsDigit)
+{
+ BOOST_CHECK_EQUAL(IsDigit('0'), true);
+ BOOST_CHECK_EQUAL(IsDigit('1'), true);
+ BOOST_CHECK_EQUAL(IsDigit('8'), true);
+ BOOST_CHECK_EQUAL(IsDigit('9'), true);
+
+ BOOST_CHECK_EQUAL(IsDigit('0' - 1), false);
+ BOOST_CHECK_EQUAL(IsDigit('9' + 1), false);
+ BOOST_CHECK_EQUAL(IsDigit(0), false);
+ BOOST_CHECK_EQUAL(IsDigit(1), false);
+ BOOST_CHECK_EQUAL(IsDigit(8), false);
+ BOOST_CHECK_EQUAL(IsDigit(9), false);
+}
+
+BOOST_AUTO_TEST_CASE(test_ParseInt32)
+{
+ int32_t n;
+ // Valid values
+ BOOST_CHECK(ParseInt32("1234", nullptr));
+ BOOST_CHECK(ParseInt32("0", &n) && n == 0);
+ BOOST_CHECK(ParseInt32("1234", &n) && n == 1234);
+ BOOST_CHECK(ParseInt32("01234", &n) && n == 1234); // no octal
+ BOOST_CHECK(ParseInt32("2147483647", &n) && n == 2147483647);
+ BOOST_CHECK(ParseInt32("-2147483648", &n) && n == (-2147483647 - 1)); // (-2147483647 - 1) equals INT_MIN
+ BOOST_CHECK(ParseInt32("-1234", &n) && n == -1234);
+ // Invalid values
+ BOOST_CHECK(!ParseInt32("", &n));
+ BOOST_CHECK(!ParseInt32(" 1", &n)); // no padding inside
+ BOOST_CHECK(!ParseInt32("1 ", &n));
+ BOOST_CHECK(!ParseInt32("1a", &n));
+ BOOST_CHECK(!ParseInt32("aap", &n));
+ BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex
+ BOOST_CHECK(!ParseInt32("0x1", &n)); // no hex
+ const char test_bytes[] = {'1', 0, '1'};
+ std::string teststr(test_bytes, sizeof(test_bytes));
+ BOOST_CHECK(!ParseInt32(teststr, &n)); // no embedded NULs
+ // Overflow and underflow
+ BOOST_CHECK(!ParseInt32("-2147483649", nullptr));
+ BOOST_CHECK(!ParseInt32("2147483648", nullptr));
+ BOOST_CHECK(!ParseInt32("-32482348723847471234", nullptr));
+ BOOST_CHECK(!ParseInt32("32482348723847471234", nullptr));
+}
+
+BOOST_AUTO_TEST_CASE(test_ParseInt64)
+{
+ int64_t n;
+ // Valid values
+ BOOST_CHECK(ParseInt64("1234", nullptr));
+ BOOST_CHECK(ParseInt64("0", &n) && n == 0LL);
+ BOOST_CHECK(ParseInt64("1234", &n) && n == 1234LL);
+ BOOST_CHECK(ParseInt64("01234", &n) && n == 1234LL); // no octal
+ BOOST_CHECK(ParseInt64("2147483647", &n) && n == 2147483647LL);
+ BOOST_CHECK(ParseInt64("-2147483648", &n) && n == -2147483648LL);
+ BOOST_CHECK(ParseInt64("9223372036854775807", &n) && n == (int64_t)9223372036854775807);
+ BOOST_CHECK(ParseInt64("-9223372036854775808", &n) && n == (int64_t)-9223372036854775807-1);
+ BOOST_CHECK(ParseInt64("-1234", &n) && n == -1234LL);
+ // Invalid values
+ BOOST_CHECK(!ParseInt64("", &n));
+ BOOST_CHECK(!ParseInt64(" 1", &n)); // no padding inside
+ BOOST_CHECK(!ParseInt64("1 ", &n));
+ BOOST_CHECK(!ParseInt64("1a", &n));
+ BOOST_CHECK(!ParseInt64("aap", &n));
+ BOOST_CHECK(!ParseInt64("0x1", &n)); // no hex
+ const char test_bytes[] = {'1', 0, '1'};
+ std::string teststr(test_bytes, sizeof(test_bytes));
+ BOOST_CHECK(!ParseInt64(teststr, &n)); // no embedded NULs
+ // Overflow and underflow
+ BOOST_CHECK(!ParseInt64("-9223372036854775809", nullptr));
+ BOOST_CHECK(!ParseInt64("9223372036854775808", nullptr));
+ BOOST_CHECK(!ParseInt64("-32482348723847471234", nullptr));
+ BOOST_CHECK(!ParseInt64("32482348723847471234", nullptr));
+}
+
+BOOST_AUTO_TEST_CASE(test_ParseUInt32)
+{
+ uint32_t n;
+ // Valid values
+ BOOST_CHECK(ParseUInt32("1234", nullptr));
+ BOOST_CHECK(ParseUInt32("0", &n) && n == 0);
+ BOOST_CHECK(ParseUInt32("1234", &n) && n == 1234);
+ BOOST_CHECK(ParseUInt32("01234", &n) && n == 1234); // no octal
+ BOOST_CHECK(ParseUInt32("2147483647", &n) && n == 2147483647);
+ BOOST_CHECK(ParseUInt32("2147483648", &n) && n == (uint32_t)2147483648);
+ BOOST_CHECK(ParseUInt32("4294967295", &n) && n == (uint32_t)4294967295);
+ // Invalid values
+ BOOST_CHECK(!ParseUInt32("", &n));
+ BOOST_CHECK(!ParseUInt32(" 1", &n)); // no padding inside
+ BOOST_CHECK(!ParseUInt32(" -1", &n));
+ BOOST_CHECK(!ParseUInt32("1 ", &n));
+ BOOST_CHECK(!ParseUInt32("1a", &n));
+ BOOST_CHECK(!ParseUInt32("aap", &n));
+ BOOST_CHECK(!ParseUInt32("0x1", &n)); // no hex
+ BOOST_CHECK(!ParseUInt32("0x1", &n)); // no hex
+ const char test_bytes[] = {'1', 0, '1'};
+ std::string teststr(test_bytes, sizeof(test_bytes));
+ BOOST_CHECK(!ParseUInt32(teststr, &n)); // no embedded NULs
+ // Overflow and underflow
+ BOOST_CHECK(!ParseUInt32("-2147483648", &n));
+ BOOST_CHECK(!ParseUInt32("4294967296", &n));
+ BOOST_CHECK(!ParseUInt32("-1234", &n));
+ BOOST_CHECK(!ParseUInt32("-32482348723847471234", nullptr));
+ BOOST_CHECK(!ParseUInt32("32482348723847471234", nullptr));
+}
+
+BOOST_AUTO_TEST_CASE(test_ParseUInt64)
+{
+ uint64_t n;
+ // Valid values
+ BOOST_CHECK(ParseUInt64("1234", nullptr));
+ BOOST_CHECK(ParseUInt64("0", &n) && n == 0LL);
+ BOOST_CHECK(ParseUInt64("1234", &n) && n == 1234LL);
+ BOOST_CHECK(ParseUInt64("01234", &n) && n == 1234LL); // no octal
+ BOOST_CHECK(ParseUInt64("2147483647", &n) && n == 2147483647LL);
+ BOOST_CHECK(ParseUInt64("9223372036854775807", &n) && n == 9223372036854775807ULL);
+ BOOST_CHECK(ParseUInt64("9223372036854775808", &n) && n == 9223372036854775808ULL);
+ BOOST_CHECK(ParseUInt64("18446744073709551615", &n) && n == 18446744073709551615ULL);
+ // Invalid values
+ BOOST_CHECK(!ParseUInt64("", &n));
+ BOOST_CHECK(!ParseUInt64(" 1", &n)); // no padding inside
+ BOOST_CHECK(!ParseUInt64(" -1", &n));
+ BOOST_CHECK(!ParseUInt64("1 ", &n));
+ BOOST_CHECK(!ParseUInt64("1a", &n));
+ BOOST_CHECK(!ParseUInt64("aap", &n));
+ BOOST_CHECK(!ParseUInt64("0x1", &n)); // no hex
+ const char test_bytes[] = {'1', 0, '1'};
+ std::string teststr(test_bytes, sizeof(test_bytes));
+ BOOST_CHECK(!ParseUInt64(teststr, &n)); // no embedded NULs
+ // Overflow and underflow
+ BOOST_CHECK(!ParseUInt64("-9223372036854775809", nullptr));
+ BOOST_CHECK(!ParseUInt64("18446744073709551616", nullptr));
+ BOOST_CHECK(!ParseUInt64("-32482348723847471234", nullptr));
+ BOOST_CHECK(!ParseUInt64("-2147483648", &n));
+ BOOST_CHECK(!ParseUInt64("-9223372036854775808", &n));
+ BOOST_CHECK(!ParseUInt64("-1234", &n));
+}
+
+BOOST_AUTO_TEST_CASE(test_ParseDouble)
+{
+ double n;
+ // Valid values
+ BOOST_CHECK(ParseDouble("1234", nullptr));
+ BOOST_CHECK(ParseDouble("0", &n) && n == 0.0);
+ BOOST_CHECK(ParseDouble("1234", &n) && n == 1234.0);
+ BOOST_CHECK(ParseDouble("01234", &n) && n == 1234.0); // no octal
+ BOOST_CHECK(ParseDouble("2147483647", &n) && n == 2147483647.0);
+ BOOST_CHECK(ParseDouble("-2147483648", &n) && n == -2147483648.0);
+ BOOST_CHECK(ParseDouble("-1234", &n) && n == -1234.0);
+ BOOST_CHECK(ParseDouble("1e6", &n) && n == 1e6);
+ BOOST_CHECK(ParseDouble("-1e6", &n) && n == -1e6);
+ // Invalid values
+ BOOST_CHECK(!ParseDouble("", &n));
+ BOOST_CHECK(!ParseDouble(" 1", &n)); // no padding inside
+ BOOST_CHECK(!ParseDouble("1 ", &n));
+ BOOST_CHECK(!ParseDouble("1a", &n));
+ BOOST_CHECK(!ParseDouble("aap", &n));
+ BOOST_CHECK(!ParseDouble("0x1", &n)); // no hex
+ const char test_bytes[] = {'1', 0, '1'};
+ std::string teststr(test_bytes, sizeof(test_bytes));
+ BOOST_CHECK(!ParseDouble(teststr, &n)); // no embedded NULs
+ // Overflow and underflow
+ BOOST_CHECK(!ParseDouble("-1e10000", nullptr));
+ BOOST_CHECK(!ParseDouble("1e10000", nullptr));
+}
+
+BOOST_AUTO_TEST_CASE(test_FormatParagraph)
+{
+ BOOST_CHECK_EQUAL(FormatParagraph("", 79, 0), "");
+ BOOST_CHECK_EQUAL(FormatParagraph("test", 79, 0), "test");
+ BOOST_CHECK_EQUAL(FormatParagraph(" test", 79, 0), " test");
+ BOOST_CHECK_EQUAL(FormatParagraph("test test", 79, 0), "test test");
+ BOOST_CHECK_EQUAL(FormatParagraph("test test", 4, 0), "test\ntest");
+ BOOST_CHECK_EQUAL(FormatParagraph("testerde test", 4, 0), "testerde\ntest");
+ BOOST_CHECK_EQUAL(FormatParagraph("test test", 4, 4), "test\n test");
+
+ // Make sure we don't indent a fully-new line following a too-long line ending
+ BOOST_CHECK_EQUAL(FormatParagraph("test test\nabc", 4, 4), "test\n test\nabc");
+
+ BOOST_CHECK_EQUAL(FormatParagraph("This_is_a_very_long_test_string_without_any_spaces_so_it_should_just_get_returned_as_is_despite_the_length until it gets here", 79), "This_is_a_very_long_test_string_without_any_spaces_so_it_should_just_get_returned_as_is_despite_the_length\nuntil it gets here");
+
+ // Test wrap length is exact
+ BOOST_CHECK_EQUAL(FormatParagraph("a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de f g h i j k l m n o p", 79), "a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de\nf g h i j k l m n o p");
+ BOOST_CHECK_EQUAL(FormatParagraph("x\na b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de f g h i j k l m n o p", 79), "x\na b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de\nf g h i j k l m n o p");
+ // Indent should be included in length of lines
+ BOOST_CHECK_EQUAL(FormatParagraph("x\na b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 a b c d e fg h i j k", 79, 4), "x\na b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de\n f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 a b c d e fg\n h i j k");
+
+ BOOST_CHECK_EQUAL(FormatParagraph("This is a very long test string. This is a second sentence in the very long test string.", 79), "This is a very long test string. This is a second sentence in the very long\ntest string.");
+ BOOST_CHECK_EQUAL(FormatParagraph("This is a very long test string.\nThis is a second sentence in the very long test string. This is a third sentence in the very long test string.", 79), "This is a very long test string.\nThis is a second sentence in the very long test string. This is a third\nsentence in the very long test string.");
+ BOOST_CHECK_EQUAL(FormatParagraph("This is a very long test string.\n\nThis is a second sentence in the very long test string. This is a third sentence in the very long test string.", 79), "This is a very long test string.\n\nThis is a second sentence in the very long test string. This is a third\nsentence in the very long test string.");
+ BOOST_CHECK_EQUAL(FormatParagraph("Testing that normal newlines do not get indented.\nLike here.", 79), "Testing that normal newlines do not get indented.\nLike here.");
+}
+
+BOOST_AUTO_TEST_CASE(test_FormatSubVersion)
+{
+ std::vector<std::string> comments;
+ comments.push_back(std::string("comment1"));
+ std::vector<std::string> comments2;
+ comments2.push_back(std::string("comment1"));
+ comments2.push_back(SanitizeString(std::string("Comment2; .,_?@-; !\"#$%&'()*+/<=>[]\\^`{|}~"), SAFE_CHARS_UA_COMMENT)); // Semicolon is discouraged but not forbidden by BIP-0014
+ BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, std::vector<std::string>()),std::string("/Test:0.9.99/"));
+ BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments),std::string("/Test:0.9.99(comment1)/"));
+ BOOST_CHECK_EQUAL(FormatSubVersion("Test", 99900, comments2),std::string("/Test:0.9.99(comment1; Comment2; .,_?@-; )/"));
+}
+
+BOOST_AUTO_TEST_CASE(test_ParseFixedPoint)
+{
+ int64_t amount = 0;
+ BOOST_CHECK(ParseFixedPoint("0", 8, &amount));
+ BOOST_CHECK_EQUAL(amount, 0LL);
+ BOOST_CHECK(ParseFixedPoint("1", 8, &amount));
+ BOOST_CHECK_EQUAL(amount, 100000000LL);
+ BOOST_CHECK(ParseFixedPoint("0.0", 8, &amount));
+ BOOST_CHECK_EQUAL(amount, 0LL);
+ BOOST_CHECK(ParseFixedPoint("-0.1", 8, &amount));
+ BOOST_CHECK_EQUAL(amount, -10000000LL);
+ BOOST_CHECK(ParseFixedPoint("1.1", 8, &amount));
+ BOOST_CHECK_EQUAL(amount, 110000000LL);
+ BOOST_CHECK(ParseFixedPoint("1.10000000000000000", 8, &amount));
+ BOOST_CHECK_EQUAL(amount, 110000000LL);
+ BOOST_CHECK(ParseFixedPoint("1.1e1", 8, &amount));
+ BOOST_CHECK_EQUAL(amount, 1100000000LL);
+ BOOST_CHECK(ParseFixedPoint("1.1e-1", 8, &amount));
+ BOOST_CHECK_EQUAL(amount, 11000000LL);
+ BOOST_CHECK(ParseFixedPoint("1000", 8, &amount));
+ BOOST_CHECK_EQUAL(amount, 100000000000LL);
+ BOOST_CHECK(ParseFixedPoint("-1000", 8, &amount));
+ BOOST_CHECK_EQUAL(amount, -100000000000LL);
+ BOOST_CHECK(ParseFixedPoint("0.00000001", 8, &amount));
+ BOOST_CHECK_EQUAL(amount, 1LL);
+ BOOST_CHECK(ParseFixedPoint("0.0000000100000000", 8, &amount));
+ BOOST_CHECK_EQUAL(amount, 1LL);
+ BOOST_CHECK(ParseFixedPoint("-0.00000001", 8, &amount));
+ BOOST_CHECK_EQUAL(amount, -1LL);
+ BOOST_CHECK(ParseFixedPoint("1000000000.00000001", 8, &amount));
+ BOOST_CHECK_EQUAL(amount, 100000000000000001LL);
+ BOOST_CHECK(ParseFixedPoint("9999999999.99999999", 8, &amount));
+ BOOST_CHECK_EQUAL(amount, 999999999999999999LL);
+ BOOST_CHECK(ParseFixedPoint("-9999999999.99999999", 8, &amount));
+ BOOST_CHECK_EQUAL(amount, -999999999999999999LL);
+
+ BOOST_CHECK(!ParseFixedPoint("", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("-", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("a-1000", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("-a1000", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("-1000a", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("-01000", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("00.1", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint(".1", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("--0.1", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("0.000000001", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("-0.000000001", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("0.00000001000000001", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("-10000000000.00000000", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("10000000000.00000000", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("-10000000000.00000001", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("10000000000.00000001", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("-10000000000.00000009", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("10000000000.00000009", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("-99999999999.99999999", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("99999909999.09999999", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("92233720368.54775807", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("92233720368.54775808", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("-92233720368.54775808", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("-92233720368.54775809", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("1.1e", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("1.1e-", 8, &amount));
+ BOOST_CHECK(!ParseFixedPoint("1.", 8, &amount));
+}
+
+static void TestOtherThread(fs::path dirname, std::string lockname, bool *result)
+{
+ *result = LockDirectory(dirname, lockname);
+}
+
+#ifndef WIN32 // Cannot do this test on WIN32 due to lack of fork()
+static constexpr char LockCommand = 'L';
+static constexpr char UnlockCommand = 'U';
+static constexpr char ExitCommand = 'X';
+
+static void TestOtherProcess(fs::path dirname, std::string lockname, int fd)
+{
+ char ch;
+ while (true) {
+ int rv = read(fd, &ch, 1); // Wait for command
+ assert(rv == 1);
+ switch(ch) {
+ case LockCommand:
+ ch = LockDirectory(dirname, lockname);
+ rv = write(fd, &ch, 1);
+ assert(rv == 1);
+ break;
+ case UnlockCommand:
+ ReleaseDirectoryLocks();
+ ch = true; // Always succeeds
+ rv = write(fd, &ch, 1);
+ assert(rv == 1);
+ break;
+ case ExitCommand:
+ close(fd);
+ exit(0);
+ default:
+ assert(0);
+ }
+ }
+}
+#endif
+
+BOOST_AUTO_TEST_CASE(test_LockDirectory)
+{
+ fs::path dirname = SetDataDir("test_LockDirectory") / fs::unique_path();
+ const std::string lockname = ".lock";
+#ifndef WIN32
+ // Revert SIGCHLD to default, otherwise boost.test will catch and fail on
+ // it: there is BOOST_TEST_IGNORE_SIGCHLD but that only works when defined
+ // at build-time of the boost library
+ void (*old_handler)(int) = signal(SIGCHLD, SIG_DFL);
+
+ // Fork another process for testing before creating the lock, so that we
+ // won't fork while holding the lock (which might be undefined, and is not
+ // relevant as test case as that is avoided with -daemonize).
+ int fd[2];
+ BOOST_CHECK_EQUAL(socketpair(AF_UNIX, SOCK_STREAM, 0, fd), 0);
+ pid_t pid = fork();
+ if (!pid) {
+ BOOST_CHECK_EQUAL(close(fd[1]), 0); // Child: close parent end
+ TestOtherProcess(dirname, lockname, fd[0]);
+ }
+ BOOST_CHECK_EQUAL(close(fd[0]), 0); // Parent: close child end
+#endif
+ // Lock on non-existent directory should fail
+ BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname), false);
+
+ fs::create_directories(dirname);
+
+ // Probing lock on new directory should succeed
+ BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
+
+ // Persistent lock on new directory should succeed
+ BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname), true);
+
+ // Another lock on the directory from the same thread should succeed
+ BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname), true);
+
+ // Another lock on the directory from a different thread within the same process should succeed
+ bool threadresult;
+ std::thread thr(TestOtherThread, dirname, lockname, &threadresult);
+ thr.join();
+ BOOST_CHECK_EQUAL(threadresult, true);
+#ifndef WIN32
+ // Try to acquire lock in child process while we're holding it, this should fail.
+ char ch;
+ BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
+ BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
+ BOOST_CHECK_EQUAL((bool)ch, false);
+
+ // Give up our lock
+ ReleaseDirectoryLocks();
+ // Probing lock from our side now should succeed, but not hold on to the lock.
+ BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
+
+ // Try to acquire the lock in the child process, this should be successful.
+ BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
+ BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
+ BOOST_CHECK_EQUAL((bool)ch, true);
+
+ // When we try to probe the lock now, it should fail.
+ BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), false);
+
+ // Unlock the lock in the child process
+ BOOST_CHECK_EQUAL(write(fd[1], &UnlockCommand, 1), 1);
+ BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);
+ BOOST_CHECK_EQUAL((bool)ch, true);
+
+ // When we try to probe the lock now, it should succeed.
+ BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
+
+ // Re-lock the lock in the child process, then wait for it to exit, check
+ // successful return. After that, we check that exiting the process
+ // has released the lock as we would expect by probing it.
+ int processstatus;
+ BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);
+ BOOST_CHECK_EQUAL(write(fd[1], &ExitCommand, 1), 1);
+ BOOST_CHECK_EQUAL(waitpid(pid, &processstatus, 0), pid);
+ BOOST_CHECK_EQUAL(processstatus, 0);
+ BOOST_CHECK_EQUAL(LockDirectory(dirname, lockname, true), true);
+
+ // Restore SIGCHLD
+ signal(SIGCHLD, old_handler);
+ BOOST_CHECK_EQUAL(close(fd[1]), 0); // Close our side of the socketpair
+#endif
+ // Clean up
+ ReleaseDirectoryLocks();
+ fs::remove_all(dirname);
+}
+
+BOOST_AUTO_TEST_CASE(test_DirIsWritable)
+{
+ // Should be able to write to the data dir.
+ fs::path tmpdirname = SetDataDir("test_DirIsWritable");
+ BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), true);
+
+ // Should not be able to write to a non-existent dir.
+ tmpdirname = tmpdirname / fs::unique_path();
+ BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), false);
+
+ fs::create_directory(tmpdirname);
+ // Should be able to write to it now.
+ BOOST_CHECK_EQUAL(DirIsWritable(tmpdirname), true);
+ fs::remove(tmpdirname);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp
new file mode 100644
index 0000000000..37c4f79133
--- /dev/null
+++ b/src/test/validation_block_tests.cpp
@@ -0,0 +1,184 @@
+// Copyright (c) 2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <boost/test/unit_test.hpp>
+
+#include <chainparams.h>
+#include <consensus/merkle.h>
+#include <consensus/validation.h>
+#include <miner.h>
+#include <pow.h>
+#include <random.h>
+#include <test/test_bitcoin.h>
+#include <validation.h>
+#include <validationinterface.h>
+
+struct RegtestingSetup : public TestingSetup {
+ RegtestingSetup() : TestingSetup(CBaseChainParams::REGTEST) {}
+};
+
+BOOST_FIXTURE_TEST_SUITE(validation_block_tests, RegtestingSetup)
+
+struct TestSubscriber : public CValidationInterface {
+ uint256 m_expected_tip;
+
+ TestSubscriber(uint256 tip) : m_expected_tip(tip) {}
+
+ void UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload) override
+ {
+ BOOST_CHECK_EQUAL(m_expected_tip, pindexNew->GetBlockHash());
+ }
+
+ void BlockConnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex, const std::vector<CTransactionRef>& txnConflicted) override
+ {
+ BOOST_CHECK_EQUAL(m_expected_tip, block->hashPrevBlock);
+ BOOST_CHECK_EQUAL(m_expected_tip, pindex->pprev->GetBlockHash());
+
+ m_expected_tip = block->GetHash();
+ }
+
+ void BlockDisconnected(const std::shared_ptr<const CBlock>& block) override
+ {
+ BOOST_CHECK_EQUAL(m_expected_tip, block->GetHash());
+
+ m_expected_tip = block->hashPrevBlock;
+ }
+};
+
+std::shared_ptr<CBlock> Block(const uint256& prev_hash)
+{
+ static int i = 0;
+ static uint64_t time = Params().GenesisBlock().nTime;
+
+ CScript pubKey;
+ pubKey << i++ << OP_TRUE;
+
+ auto ptemplate = BlockAssembler(Params()).CreateNewBlock(pubKey, false);
+ auto pblock = std::make_shared<CBlock>(ptemplate->block);
+ pblock->hashPrevBlock = prev_hash;
+ pblock->nTime = ++time;
+
+ CMutableTransaction txCoinbase(*pblock->vtx[0]);
+ txCoinbase.vout.resize(1);
+ txCoinbase.vin[0].scriptWitness.SetNull();
+ pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase));
+
+ return pblock;
+}
+
+std::shared_ptr<CBlock> FinalizeBlock(std::shared_ptr<CBlock> pblock)
+{
+ pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
+
+ while (!CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus())) {
+ ++(pblock->nNonce);
+ }
+
+ return pblock;
+}
+
+// construct a valid block
+const std::shared_ptr<const CBlock> GoodBlock(const uint256& prev_hash)
+{
+ return FinalizeBlock(Block(prev_hash));
+}
+
+// construct an invalid block (but with a valid header)
+const std::shared_ptr<const CBlock> BadBlock(const uint256& prev_hash)
+{
+ auto pblock = Block(prev_hash);
+
+ CMutableTransaction coinbase_spend;
+ coinbase_spend.vin.push_back(CTxIn(COutPoint(pblock->vtx[0]->GetHash(), 0), CScript(), 0));
+ coinbase_spend.vout.push_back(pblock->vtx[0]->vout[0]);
+
+ CTransactionRef tx = MakeTransactionRef(coinbase_spend);
+ pblock->vtx.push_back(tx);
+
+ auto ret = FinalizeBlock(pblock);
+ return ret;
+}
+
+void BuildChain(const uint256& root, int height, const unsigned int invalid_rate, const unsigned int branch_rate, const unsigned int max_size, std::vector<std::shared_ptr<const CBlock>>& blocks)
+{
+ if (height <= 0 || blocks.size() >= max_size) return;
+
+ bool gen_invalid = GetRand(100) < invalid_rate;
+ bool gen_fork = GetRand(100) < branch_rate;
+
+ const std::shared_ptr<const CBlock> pblock = gen_invalid ? BadBlock(root) : GoodBlock(root);
+ blocks.push_back(pblock);
+ if (!gen_invalid) {
+ BuildChain(pblock->GetHash(), height - 1, invalid_rate, branch_rate, max_size, blocks);
+ }
+
+ if (gen_fork) {
+ blocks.push_back(GoodBlock(root));
+ BuildChain(blocks.back()->GetHash(), height - 1, invalid_rate, branch_rate, max_size, blocks);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering)
+{
+ // build a large-ish chain that's likely to have some forks
+ std::vector<std::shared_ptr<const CBlock>> blocks;
+ while (blocks.size() < 50) {
+ blocks.clear();
+ BuildChain(Params().GenesisBlock().GetHash(), 100, 15, 10, 500, blocks);
+ }
+
+ bool ignored;
+ CValidationState state;
+ std::vector<CBlockHeader> headers;
+ std::transform(blocks.begin(), blocks.end(), std::back_inserter(headers), [](std::shared_ptr<const CBlock> b) { return b->GetBlockHeader(); });
+
+ // Process all the headers so we understand the toplogy of the chain
+ BOOST_CHECK(ProcessNewBlockHeaders(headers, state, Params()));
+
+ // Connect the genesis block and drain any outstanding events
+ ProcessNewBlock(Params(), std::make_shared<CBlock>(Params().GenesisBlock()), true, &ignored);
+ SyncWithValidationInterfaceQueue();
+
+ // subscribe to events (this subscriber will validate event ordering)
+ const CBlockIndex* initial_tip = nullptr;
+ {
+ LOCK(cs_main);
+ initial_tip = chainActive.Tip();
+ }
+ TestSubscriber sub(initial_tip->GetBlockHash());
+ RegisterValidationInterface(&sub);
+
+ // create a bunch of threads that repeatedly process a block generated above at random
+ // this will create parallelism and randomness inside validation - the ValidationInterface
+ // will subscribe to events generated during block validation and assert on ordering invariance
+ boost::thread_group threads;
+ for (int i = 0; i < 10; i++) {
+ threads.create_thread([&blocks]() {
+ bool ignored;
+ for (int i = 0; i < 1000; i++) {
+ auto block = blocks[GetRand(blocks.size() - 1)];
+ ProcessNewBlock(Params(), block, true, &ignored);
+ }
+
+ // to make sure that eventually we process the full chain - do it here
+ for (auto block : blocks) {
+ if (block->vtx.size() == 1) {
+ bool processed = ProcessNewBlock(Params(), block, true, &ignored);
+ assert(processed);
+ }
+ }
+ });
+ }
+
+ threads.join_all();
+ while (GetMainSignals().CallbacksPending() > 0) {
+ MilliSleep(100);
+ }
+
+ UnregisterValidationInterface(&sub);
+
+ BOOST_CHECK_EQUAL(sub.m_expected_tip, chainActive.Tip()->GetBlockHash());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp
new file mode 100644
index 0000000000..ca3196454a
--- /dev/null
+++ b/src/test/versionbits_tests.cpp
@@ -0,0 +1,354 @@
+// Copyright (c) 2014-2018 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <chain.h>
+#include <versionbits.h>
+#include <test/test_bitcoin.h>
+#include <chainparams.h>
+#include <validation.h>
+#include <consensus/params.h>
+
+#include <boost/test/unit_test.hpp>
+
+/* Define a virtual block time, one block per 10 minutes after Nov 14 2014, 0:55:36am */
+static int32_t TestTime(int nHeight) { return 1415926536 + 600 * nHeight; }
+
+static const Consensus::Params paramsDummy = Consensus::Params();
+
+class TestConditionChecker : public AbstractThresholdConditionChecker
+{
+private:
+ mutable ThresholdConditionCache cache;
+
+public:
+ int64_t BeginTime(const Consensus::Params& params) const override { return TestTime(10000); }
+ int64_t EndTime(const Consensus::Params& params) const override { return TestTime(20000); }
+ int Period(const Consensus::Params& params) const override { return 1000; }
+ int Threshold(const Consensus::Params& params) const override { return 900; }
+ bool Condition(const CBlockIndex* pindex, const Consensus::Params& params) const override { return (pindex->nVersion & 0x100); }
+
+ ThresholdState GetStateFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateFor(pindexPrev, paramsDummy, cache); }
+ int GetStateSinceHeightFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateSinceHeightFor(pindexPrev, paramsDummy, cache); }
+};
+
+class TestAlwaysActiveConditionChecker : public TestConditionChecker
+{
+public:
+ int64_t BeginTime(const Consensus::Params& params) const override { return Consensus::BIP9Deployment::ALWAYS_ACTIVE; }
+};
+
+#define CHECKERS 6
+
+class VersionBitsTester
+{
+ // A fake blockchain
+ std::vector<CBlockIndex*> vpblock;
+
+ // 6 independent checkers for the same bit.
+ // The first one performs all checks, the second only 50%, the third only 25%, etc...
+ // This is to test whether lack of cached information leads to the same results.
+ TestConditionChecker checker[CHECKERS];
+ // Another 6 that assume always active activation
+ TestAlwaysActiveConditionChecker checker_always[CHECKERS];
+
+ // Test counter (to identify failures)
+ int num;
+
+public:
+ VersionBitsTester() : num(0) {}
+
+ VersionBitsTester& Reset() {
+ for (unsigned int i = 0; i < vpblock.size(); i++) {
+ delete vpblock[i];
+ }
+ for (unsigned int i = 0; i < CHECKERS; i++) {
+ checker[i] = TestConditionChecker();
+ checker_always[i] = TestAlwaysActiveConditionChecker();
+ }
+ vpblock.clear();
+ return *this;
+ }
+
+ ~VersionBitsTester() {
+ Reset();
+ }
+
+ VersionBitsTester& Mine(unsigned int height, int32_t nTime, int32_t nVersion) {
+ while (vpblock.size() < height) {
+ CBlockIndex* pindex = new CBlockIndex();
+ pindex->nHeight = vpblock.size();
+ pindex->pprev = vpblock.size() > 0 ? vpblock.back() : nullptr;
+ pindex->nTime = nTime;
+ pindex->nVersion = nVersion;
+ pindex->BuildSkip();
+ vpblock.push_back(pindex);
+ }
+ return *this;
+ }
+
+ VersionBitsTester& TestStateSinceHeight(int height) {
+ for (int i = 0; i < CHECKERS; i++) {
+ if (InsecureRandBits(i) == 0) {
+ BOOST_CHECK_MESSAGE(checker[i].GetStateSinceHeightFor(vpblock.empty() ? nullptr : vpblock.back()) == height, strprintf("Test %i for StateSinceHeight", num));
+ BOOST_CHECK_MESSAGE(checker_always[i].GetStateSinceHeightFor(vpblock.empty() ? nullptr : vpblock.back()) == 0, strprintf("Test %i for StateSinceHeight (always active)", num));
+ }
+ }
+ num++;
+ return *this;
+ }
+
+ VersionBitsTester& TestDefined() {
+ for (int i = 0; i < CHECKERS; i++) {
+ if (InsecureRandBits(i) == 0) {
+ BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::DEFINED, strprintf("Test %i for DEFINED", num));
+ BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
+ }
+ }
+ num++;
+ return *this;
+ }
+
+ VersionBitsTester& TestStarted() {
+ for (int i = 0; i < CHECKERS; i++) {
+ if (InsecureRandBits(i) == 0) {
+ BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::STARTED, strprintf("Test %i for STARTED", num));
+ BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
+ }
+ }
+ num++;
+ return *this;
+ }
+
+ VersionBitsTester& TestLockedIn() {
+ for (int i = 0; i < CHECKERS; i++) {
+ if (InsecureRandBits(i) == 0) {
+ BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::LOCKED_IN, strprintf("Test %i for LOCKED_IN", num));
+ BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
+ }
+ }
+ num++;
+ return *this;
+ }
+
+ VersionBitsTester& TestActive() {
+ for (int i = 0; i < CHECKERS; i++) {
+ if (InsecureRandBits(i) == 0) {
+ BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE", num));
+ BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
+ }
+ }
+ num++;
+ return *this;
+ }
+
+ VersionBitsTester& TestFailed() {
+ for (int i = 0; i < CHECKERS; i++) {
+ if (InsecureRandBits(i) == 0) {
+ BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::FAILED, strprintf("Test %i for FAILED", num));
+ BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num));
+ }
+ }
+ num++;
+ return *this;
+ }
+
+ CBlockIndex * Tip() { return vpblock.size() ? vpblock.back() : nullptr; }
+};
+
+BOOST_FIXTURE_TEST_SUITE(versionbits_tests, TestingSetup)
+
+BOOST_AUTO_TEST_CASE(versionbits_test)
+{
+ for (int i = 0; i < 64; i++) {
+ // DEFINED -> FAILED
+ VersionBitsTester().TestDefined().TestStateSinceHeight(0)
+ .Mine(1, TestTime(1), 0x100).TestDefined().TestStateSinceHeight(0)
+ .Mine(11, TestTime(11), 0x100).TestDefined().TestStateSinceHeight(0)
+ .Mine(989, TestTime(989), 0x100).TestDefined().TestStateSinceHeight(0)
+ .Mine(999, TestTime(20000), 0x100).TestDefined().TestStateSinceHeight(0)
+ .Mine(1000, TestTime(20000), 0x100).TestFailed().TestStateSinceHeight(1000)
+ .Mine(1999, TestTime(30001), 0x100).TestFailed().TestStateSinceHeight(1000)
+ .Mine(2000, TestTime(30002), 0x100).TestFailed().TestStateSinceHeight(1000)
+ .Mine(2001, TestTime(30003), 0x100).TestFailed().TestStateSinceHeight(1000)
+ .Mine(2999, TestTime(30004), 0x100).TestFailed().TestStateSinceHeight(1000)
+ .Mine(3000, TestTime(30005), 0x100).TestFailed().TestStateSinceHeight(1000)
+
+ // DEFINED -> STARTED -> FAILED
+ .Reset().TestDefined().TestStateSinceHeight(0)
+ .Mine(1, TestTime(1), 0).TestDefined().TestStateSinceHeight(0)
+ .Mine(1000, TestTime(10000) - 1, 0x100).TestDefined().TestStateSinceHeight(0) // One second more and it would be defined
+ .Mine(2000, TestTime(10000), 0x100).TestStarted().TestStateSinceHeight(2000) // So that's what happens the next period
+ .Mine(2051, TestTime(10010), 0).TestStarted().TestStateSinceHeight(2000) // 51 old blocks
+ .Mine(2950, TestTime(10020), 0x100).TestStarted().TestStateSinceHeight(2000) // 899 new blocks
+ .Mine(3000, TestTime(20000), 0).TestFailed().TestStateSinceHeight(3000) // 50 old blocks (so 899 out of the past 1000)
+ .Mine(4000, TestTime(20010), 0x100).TestFailed().TestStateSinceHeight(3000)
+
+ // DEFINED -> STARTED -> FAILED while threshold reached
+ .Reset().TestDefined().TestStateSinceHeight(0)
+ .Mine(1, TestTime(1), 0).TestDefined().TestStateSinceHeight(0)
+ .Mine(1000, TestTime(10000) - 1, 0x101).TestDefined().TestStateSinceHeight(0) // One second more and it would be defined
+ .Mine(2000, TestTime(10000), 0x101).TestStarted().TestStateSinceHeight(2000) // So that's what happens the next period
+ .Mine(2999, TestTime(30000), 0x100).TestStarted().TestStateSinceHeight(2000) // 999 new blocks
+ .Mine(3000, TestTime(30000), 0x100).TestFailed().TestStateSinceHeight(3000) // 1 new block (so 1000 out of the past 1000 are new)
+ .Mine(3999, TestTime(30001), 0).TestFailed().TestStateSinceHeight(3000)
+ .Mine(4000, TestTime(30002), 0).TestFailed().TestStateSinceHeight(3000)
+ .Mine(14333, TestTime(30003), 0).TestFailed().TestStateSinceHeight(3000)
+ .Mine(24000, TestTime(40000), 0).TestFailed().TestStateSinceHeight(3000)
+
+ // DEFINED -> STARTED -> LOCKEDIN at the last minute -> ACTIVE
+ .Reset().TestDefined()
+ .Mine(1, TestTime(1), 0).TestDefined().TestStateSinceHeight(0)
+ .Mine(1000, TestTime(10000) - 1, 0x101).TestDefined().TestStateSinceHeight(0) // One second more and it would be defined
+ .Mine(2000, TestTime(10000), 0x101).TestStarted().TestStateSinceHeight(2000) // So that's what happens the next period
+ .Mine(2050, TestTime(10010), 0x200).TestStarted().TestStateSinceHeight(2000) // 50 old blocks
+ .Mine(2950, TestTime(10020), 0x100).TestStarted().TestStateSinceHeight(2000) // 900 new blocks
+ .Mine(2999, TestTime(19999), 0x200).TestStarted().TestStateSinceHeight(2000) // 49 old blocks
+ .Mine(3000, TestTime(29999), 0x200).TestLockedIn().TestStateSinceHeight(3000) // 1 old block (so 900 out of the past 1000)
+ .Mine(3999, TestTime(30001), 0).TestLockedIn().TestStateSinceHeight(3000)
+ .Mine(4000, TestTime(30002), 0).TestActive().TestStateSinceHeight(4000)
+ .Mine(14333, TestTime(30003), 0).TestActive().TestStateSinceHeight(4000)
+ .Mine(24000, TestTime(40000), 0).TestActive().TestStateSinceHeight(4000)
+
+ // DEFINED multiple periods -> STARTED multiple periods -> FAILED
+ .Reset().TestDefined().TestStateSinceHeight(0)
+ .Mine(999, TestTime(999), 0).TestDefined().TestStateSinceHeight(0)
+ .Mine(1000, TestTime(1000), 0).TestDefined().TestStateSinceHeight(0)
+ .Mine(2000, TestTime(2000), 0).TestDefined().TestStateSinceHeight(0)
+ .Mine(3000, TestTime(10000), 0).TestStarted().TestStateSinceHeight(3000)
+ .Mine(4000, TestTime(10000), 0).TestStarted().TestStateSinceHeight(3000)
+ .Mine(5000, TestTime(10000), 0).TestStarted().TestStateSinceHeight(3000)
+ .Mine(6000, TestTime(20000), 0).TestFailed().TestStateSinceHeight(6000)
+ .Mine(7000, TestTime(20000), 0x100).TestFailed().TestStateSinceHeight(6000);
+ }
+
+ // Sanity checks of version bit deployments
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
+ const Consensus::Params &mainnetParams = chainParams->GetConsensus();
+ for (int i=0; i<(int) Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) {
+ uint32_t bitmask = VersionBitsMask(mainnetParams, static_cast<Consensus::DeploymentPos>(i));
+ // Make sure that no deployment tries to set an invalid bit.
+ BOOST_CHECK_EQUAL(bitmask & ~(uint32_t)VERSIONBITS_TOP_MASK, bitmask);
+
+ // Verify that the deployment windows of different deployment using the
+ // same bit are disjoint.
+ // This test may need modification at such time as a new deployment
+ // is proposed that reuses the bit of an activated soft fork, before the
+ // end time of that soft fork. (Alternatively, the end time of that
+ // activated soft fork could be later changed to be earlier to avoid
+ // overlap.)
+ for (int j=i+1; j<(int) Consensus::MAX_VERSION_BITS_DEPLOYMENTS; j++) {
+ if (VersionBitsMask(mainnetParams, static_cast<Consensus::DeploymentPos>(j)) == bitmask) {
+ BOOST_CHECK(mainnetParams.vDeployments[j].nStartTime > mainnetParams.vDeployments[i].nTimeout ||
+ mainnetParams.vDeployments[i].nStartTime > mainnetParams.vDeployments[j].nTimeout);
+ }
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(versionbits_computeblockversion)
+{
+ // Check that ComputeBlockVersion will set the appropriate bit correctly
+ // on mainnet.
+ const auto chainParams = CreateChainParams(CBaseChainParams::MAIN);
+ const Consensus::Params &mainnetParams = chainParams->GetConsensus();
+
+ // Use the TESTDUMMY deployment for testing purposes.
+ int64_t bit = mainnetParams.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit;
+ int64_t nStartTime = mainnetParams.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime;
+ int64_t nTimeout = mainnetParams.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout;
+
+ assert(nStartTime < nTimeout);
+
+ // In the first chain, test that the bit is set by CBV until it has failed.
+ // In the second chain, test the bit is set by CBV while STARTED and
+ // LOCKED-IN, and then no longer set while ACTIVE.
+ VersionBitsTester firstChain, secondChain;
+
+ // Start generating blocks before nStartTime
+ int64_t nTime = nStartTime - 1;
+
+ // Before MedianTimePast of the chain has crossed nStartTime, the bit
+ // should not be set.
+ CBlockIndex *lastBlock = nullptr;
+ lastBlock = firstChain.Mine(2016, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
+ BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, mainnetParams) & (1<<bit), 0);
+
+ // Mine 2011 more blocks at the old time, and check that CBV isn't setting the bit yet.
+ for (int i=1; i<2012; i++) {
+ lastBlock = firstChain.Mine(2016+i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
+ // This works because VERSIONBITS_LAST_OLD_BLOCK_VERSION happens
+ // to be 4, and the bit we're testing happens to be bit 28.
+ BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, mainnetParams) & (1<<bit), 0);
+ }
+ // Now mine 5 more blocks at the start time -- MTP should not have passed yet, so
+ // CBV should still not yet set the bit.
+ nTime = nStartTime;
+ for (int i=2012; i<=2016; i++) {
+ lastBlock = firstChain.Mine(2016+i, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
+ BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, mainnetParams) & (1<<bit), 0);
+ }
+
+ // Advance to the next period and transition to STARTED,
+ lastBlock = firstChain.Mine(6048, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
+ // so ComputeBlockVersion should now set the bit,
+ BOOST_CHECK((ComputeBlockVersion(lastBlock, mainnetParams) & (1<<bit)) != 0);
+ // and should also be using the VERSIONBITS_TOP_BITS.
+ BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, mainnetParams) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
+
+ // Check that ComputeBlockVersion will set the bit until nTimeout
+ nTime += 600;
+ int blocksToMine = 4032; // test blocks for up to 2 time periods
+ int nHeight = 6048;
+ // These blocks are all before nTimeout is reached.
+ while (nTime < nTimeout && blocksToMine > 0) {
+ lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
+ BOOST_CHECK((ComputeBlockVersion(lastBlock, mainnetParams) & (1<<bit)) != 0);
+ BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, mainnetParams) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
+ blocksToMine--;
+ nTime += 600;
+ nHeight += 1;
+ }
+
+ nTime = nTimeout;
+ // FAILED is only triggered at the end of a period, so CBV should be setting
+ // the bit until the period transition.
+ for (int i=0; i<2015; i++) {
+ lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
+ BOOST_CHECK((ComputeBlockVersion(lastBlock, mainnetParams) & (1<<bit)) != 0);
+ nHeight += 1;
+ }
+ // The next block should trigger no longer setting the bit.
+ lastBlock = firstChain.Mine(nHeight+1, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
+ BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, mainnetParams) & (1<<bit), 0);
+
+ // On a new chain:
+ // verify that the bit will be set after lock-in, and then stop being set
+ // after activation.
+ nTime = nStartTime;
+
+ // Mine one period worth of blocks, and check that the bit will be on for the
+ // next period.
+ lastBlock = secondChain.Mine(2016, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
+ BOOST_CHECK((ComputeBlockVersion(lastBlock, mainnetParams) & (1<<bit)) != 0);
+
+ // Mine another period worth of blocks, signaling the new bit.
+ lastBlock = secondChain.Mine(4032, nTime, VERSIONBITS_TOP_BITS | (1<<bit)).Tip();
+ // After one period of setting the bit on each block, it should have locked in.
+ // We keep setting the bit for one more period though, until activation.
+ BOOST_CHECK((ComputeBlockVersion(lastBlock, mainnetParams) & (1<<bit)) != 0);
+
+ // Now check that we keep mining the block until the end of this period, and
+ // then stop at the beginning of the next period.
+ lastBlock = secondChain.Mine(6047, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
+ BOOST_CHECK((ComputeBlockVersion(lastBlock, mainnetParams) & (1<<bit)) != 0);
+ lastBlock = secondChain.Mine(6048, nTime, VERSIONBITS_LAST_OLD_BLOCK_VERSION).Tip();
+ BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, mainnetParams) & (1<<bit), 0);
+
+ // Finally, verify that after a soft fork has activated, CBV no longer uses
+ // VERSIONBITS_LAST_OLD_BLOCK_VERSION.
+ //BOOST_CHECK_EQUAL(ComputeBlockVersion(lastBlock, mainnetParams) & VERSIONBITS_TOP_MASK, VERSIONBITS_TOP_BITS);
+}
+
+
+BOOST_AUTO_TEST_SUITE_END()