diff options
Diffstat (limited to 'src/test')
27 files changed, 1123 insertions, 280 deletions
diff --git a/src/test/Checkpoints_tests.cpp b/src/test/Checkpoints_tests.cpp index c3125d76dc..703cf307d1 100644 --- a/src/test/Checkpoints_tests.cpp +++ b/src/test/Checkpoints_tests.cpp @@ -10,6 +10,7 @@ #include "uint256.h" #include "test/test_bitcoin.h" +#include "chainparams.h" #include <boost/test/unit_test.hpp> @@ -19,21 +20,8 @@ BOOST_FIXTURE_TEST_SUITE(Checkpoints_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(sanity) { - uint256 p11111 = uint256S("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d"); - uint256 p134444 = uint256S("0x00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe"); - BOOST_CHECK(Checkpoints::CheckBlock(11111, p11111)); - BOOST_CHECK(Checkpoints::CheckBlock(134444, p134444)); - - - // Wrong hashes at checkpoints should fail: - BOOST_CHECK(!Checkpoints::CheckBlock(11111, p134444)); - BOOST_CHECK(!Checkpoints::CheckBlock(134444, p11111)); - - // ... but any hash not at a checkpoint should succeed: - BOOST_CHECK(Checkpoints::CheckBlock(11111+1, p134444)); - BOOST_CHECK(Checkpoints::CheckBlock(134444+1, p11111)); - - BOOST_CHECK(Checkpoints::GetTotalBlocksEstimate() >= 134444); -} + const Checkpoints::CCheckpointData& checkpoints = Params(CBaseChainParams::MAIN).Checkpoints(); + BOOST_CHECK(Checkpoints::GetTotalBlocksEstimate(checkpoints) >= 134444); +} BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index 6b6df5199a..38dcc6023c 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -7,10 +7,12 @@ // #include "alert.h" +#include "chain.h" +#include "chainparams.h" #include "clientversion.h" #include "data/alertTests.raw.h" -#include "chainparams.h" +#include "main.h" #include "serialize.h" #include "streams.h" #include "util.h" @@ -193,4 +195,63 @@ BOOST_AUTO_TEST_CASE(AlertNotify) SetMockTime(0); } +static bool falseFunc() { return false; } + +BOOST_AUTO_TEST_CASE(PartitionAlert) +{ + // Test PartitionCheck + CCriticalSection csDummy; + CBlockIndex indexDummy[100]; + CChainParams& params = Params(CBaseChainParams::MAIN); + int64_t nPowTargetSpacing = params.GetConsensus().nPowTargetSpacing; + + // Generate fake blockchain timestamps relative to + // an arbitrary time: + int64_t now = 1427379054; + SetMockTime(now); + for (int i = 0; i < 100; i++) + { + indexDummy[i].phashBlock = NULL; + if (i == 0) indexDummy[i].pprev = NULL; + else indexDummy[i].pprev = &indexDummy[i-1]; + indexDummy[i].nHeight = i; + indexDummy[i].nTime = now - (100-i)*nPowTargetSpacing; + // Other members don't matter, the partition check code doesn't + // use them + } + + // Test 1: chain with blocks every nPowTargetSpacing seconds, + // as normal, no worries: + PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); + BOOST_CHECK(strMiscWarning.empty()); + + // Test 2: go 3.5 hours without a block, expect a warning: + now += 3*60*60+30*60; + SetMockTime(now); + PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); + BOOST_CHECK(!strMiscWarning.empty()); + BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); + strMiscWarning = ""; + + // Test 3: test the "partition alerts only go off once per day" + // code: + now += 60*10; + SetMockTime(now); + PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); + BOOST_CHECK(strMiscWarning.empty()); + + // Test 4: get 2.5 times as many blocks as expected: + now += 60*60*24; // Pretend it is a day later + SetMockTime(now); + int64_t quickSpacing = nPowTargetSpacing*2/5; + for (int i = 0; i < 100; i++) // Tweak chain timestamps: + indexDummy[i].nTime = now - (100-i)*quickSpacing; + PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); + BOOST_CHECK(!strMiscWarning.empty()); + BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); + strMiscWarning = ""; + + SetMockTime(0); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index f07dd7a7db..9e74f5f427 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -17,23 +17,20 @@ #include <boost/foreach.hpp> #include <boost/test/unit_test.hpp> -#include "json/json_spirit_reader_template.h" -#include "json/json_spirit_utils.h" -#include "json/json_spirit_writer_template.h" -using namespace json_spirit; -extern Array read_json(const std::string& jsondata); +#include "univalue/univalue.h" + +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) { - Array tests = read_json(std::string(json_tests::base58_encode_decode, json_tests::base58_encode_decode + sizeof(json_tests::base58_encode_decode))); - BOOST_FOREACH(Value& tv, tests) - { - Array test = tv.get_array(); - std::string strTest = write_string(tv, false); + 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); @@ -50,13 +47,12 @@ BOOST_AUTO_TEST_CASE(base58_EncodeBase58) // Goal: test low-level base58 decoding functionality BOOST_AUTO_TEST_CASE(base58_DecodeBase58) { - Array tests = read_json(std::string(json_tests::base58_encode_decode, json_tests::base58_encode_decode + sizeof(json_tests::base58_encode_decode))); + 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; - BOOST_FOREACH(Value& tv, tests) - { - Array test = tv.get_array(); - std::string strTest = write_string(tv, false); + 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); @@ -124,16 +120,15 @@ public: // Goal: check that parsed keys match test payload BOOST_AUTO_TEST_CASE(base58_keys_valid_parse) { - Array tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid))); + UniValue tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid))); std::vector<unsigned char> result; CBitcoinSecret secret; CBitcoinAddress addr; SelectParams(CBaseChainParams::MAIN); - BOOST_FOREACH(Value& tv, tests) - { - Array test = tv.get_array(); - std::string strTest = write_string(tv, false); + 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); @@ -141,7 +136,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse) } std::string exp_base58string = test[0].get_str(); std::vector<unsigned char> exp_payload = ParseHex(test[1].get_str()); - const Object &metadata = test[2].get_obj(); + const UniValue &metadata = test[2].get_obj(); bool isPrivkey = find_value(metadata, "isPrivkey").get_bool(); bool isTestnet = find_value(metadata, "isTestnet").get_bool(); if (isTestnet) @@ -183,12 +178,12 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse) // Goal: check that generated keys match test vectors BOOST_AUTO_TEST_CASE(base58_keys_valid_gen) { - Array tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid))); + UniValue tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid))); std::vector<unsigned char> result; - BOOST_FOREACH(Value& tv, tests) - { - Array test = tv.get_array(); - std::string strTest = write_string(tv, false); + + 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); @@ -196,7 +191,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen) } std::string exp_base58string = test[0].get_str(); std::vector<unsigned char> exp_payload = ParseHex(test[1].get_str()); - const Object &metadata = test[2].get_obj(); + const UniValue &metadata = test[2].get_obj(); bool isPrivkey = find_value(metadata, "isPrivkey").get_bool(); bool isTestnet = find_value(metadata, "isTestnet").get_bool(); if (isTestnet) @@ -251,15 +246,14 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen) // Goal: check that base58 parsing code is robust against a variety of corrupted data BOOST_AUTO_TEST_CASE(base58_keys_invalid) { - Array tests = read_json(std::string(json_tests::base58_keys_invalid, json_tests::base58_keys_invalid + sizeof(json_tests::base58_keys_invalid))); // Negative testcases + UniValue tests = read_json(std::string(json_tests::base58_keys_invalid, json_tests::base58_keys_invalid + sizeof(json_tests::base58_keys_invalid))); // Negative testcases std::vector<unsigned char> result; CBitcoinSecret secret; CBitcoinAddress addr; - BOOST_FOREACH(Value& tv, tests) - { - Array test = tv.get_array(); - std::string strTest = write_string(tv, false); + 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); diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp index d738851c1f..0d815c27fd 100644 --- a/src/test/bip32_tests.cpp +++ b/src/test/bip32_tests.cpp @@ -8,6 +8,7 @@ #include "key.h" #include "uint256.h" #include "util.h" +#include "utilstrencodings.h" #include "test/test_bitcoin.h" #include <string> diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp index 73a146f05c..1bda8a7ea1 100644 --- a/src/test/bloom_tests.cpp +++ b/src/test/bloom_tests.cpp @@ -8,6 +8,7 @@ #include "clientversion.h" #include "key.h" #include "merkleblock.h" +#include "random.h" #include "serialize.h" #include "streams.h" #include "uint256.h" @@ -459,4 +460,81 @@ BOOST_AUTO_TEST_CASE(merkle_block_4_test_update_none) BOOST_CHECK(!filter.contains(COutPoint(uint256S("0x02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041"), 0))); } +static std::vector<unsigned char> RandomData() +{ + uint256 r = GetRandHash(); + 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, 0); + + // 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.clear(); + 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]); + } + + // Insert 999 more random entries: + for (int i = 0; i < 999; i++) { + rb1.insert(RandomData()); + } + // 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, 0); + 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/checkblock_tests.cpp b/src/test/checkblock_tests.cpp index 7abfad151e..51530c4de5 100644 --- a/src/test/checkblock_tests.cpp +++ b/src/test/checkblock_tests.cpp @@ -2,16 +2,11 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -// -// Unit tests for block.CheckBlock() -// - - - #include "clientversion.h" +#include "consensus/validation.h" #include "main.h" -#include "utiltime.h" #include "test/test_bitcoin.h" +#include "utiltime.h" #include <cstdio> diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 2e2cc2214b..34b311b804 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -59,6 +59,24 @@ public: bool GetStats(CCoinsStats& stats) const { return false; } }; + +class CCoinsViewCacheTest : public CCoinsViewCache +{ +public: + 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); + for (CCoinsMap::iterator it = cacheCoins.begin(); it != cacheCoins.end(); it++) { + ret += memusage::DynamicUsage(it->second.coins); + } + BOOST_CHECK_EQUAL(memusage::DynamicUsage(*this), ret); + } + +}; + } BOOST_FIXTURE_TEST_SUITE(coins_tests, BasicTestingSetup) @@ -90,8 +108,8 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) // The cache stack. CCoinsViewTest base; // A CCoinsViewTest at the bottom. - std::vector<CCoinsViewCache*> stack; // A stack of CCoinsViewCaches on top. - stack.push_back(new CCoinsViewCache(&base)); // Start with one cache. + 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; @@ -136,6 +154,9 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) missed_an_entry = true; } } + BOOST_FOREACH(const CCoinsViewCacheTest *test, stack) { + test->SelfTest(); + } } if (insecure_rand() % 100 == 0) { @@ -152,7 +173,7 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) } else { removed_all_caches = true; } - stack.push_back(new CCoinsViewCache(tip)); + stack.push_back(new CCoinsViewCacheTest(tip)); if (stack.size() == 4) { reached_4_caches = true; } diff --git a/src/test/data/script_invalid.json b/src/test/data/script_invalid.json index 271bc70f73..7afa2abf49 100644 --- a/src/test/data/script_invalid.json +++ b/src/test/data/script_invalid.json @@ -141,6 +141,8 @@ ["2 2 0 IF LSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "LSHIFT disabled"], ["2 2 0 IF RSHIFT ELSE 1 ENDIF", "NOP", "P2SH,STRICTENC", "RSHIFT disabled"], +["", "EQUAL NOT", "P2SH,STRICTENC", "EQUAL must error when there are no stack items"], +["0", "EQUAL NOT", "P2SH,STRICTENC", "EQUAL must error when there are not 2 stack items"], ["0 1","EQUAL", "P2SH,STRICTENC"], ["1 1 ADD", "0 EQUAL", "P2SH,STRICTENC"], ["11 1 ADD 12 SUB", "11 EQUAL", "P2SH,STRICTENC"], @@ -368,6 +370,16 @@ ["NOP", "HASH160 1", "P2SH,STRICTENC"], ["NOP", "HASH256 1", "P2SH,STRICTENC"], +["Increase CHECKSIG and CHECKMULTISIG negative test coverage"], +["", "CHECKSIG NOT", "STRICTENC", "CHECKSIG must error when there are no stack items"], +["0", "CHECKSIG NOT", "STRICTENC", "CHECKSIG must error when there are not 2 stack items"], +["", "CHECKMULTISIG NOT", "STRICTENC", "CHECKMULTISIG must error when there are no stack items"], +["", "-1 CHECKMULTISIG NOT", "STRICTENC", "CHECKMULTISIG must error when the specified number of pubkeys is negative"], +["", "1 CHECKMULTISIG NOT", "STRICTENC", "CHECKMULTISIG must error when there are not enough pubkeys on the stack"], +["", "-1 0 CHECKMULTISIG NOT", "STRICTENC", "CHECKMULTISIG must error when the specified number of signatures is negative"], +["", "1 'pk1' 1 CHECKMULTISIG NOT", "STRICTENC", "CHECKMULTISIG must error when there are not enough signatures on the stack"], +["", "'dummy' 'sig1' 1 'pk1' 1 CHECKMULTISIG IF 1 ENDIF", "", "CHECKMULTISIG must push false to stack when signature is invalid when NOT in strict enc mode"], + ["", "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", @@ -426,7 +438,7 @@ ["0x4d 0xFF00 0x111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA", "PUSHDATA2 of 255 bytes minimally represented by PUSHDATA1"], -["0x4f 0x00100000 0x11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA", +["0x4e 0x00010000 0x11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", "DROP 1", "MINIMALDATA", "PUSHDATA4 of 256 bytes minimally represented by PUSHDATA2"], @@ -780,6 +792,12 @@ "P2SH(P2PK) with non-push scriptSig" ], [ + "0 0x47 0x304402205451ce65ad844dbb978b8bdedf5082e33b43cae8279c30f2c74d9e9ee49a94f802203fe95a7ccf74da7a232ee523ef4a53cb4d14bdd16289680cdb97a63819b8f42f01 0x46 0x304402205451ce65ad844dbb978b8bdedf5082e33b43cae8279c30f2c74d9e9ee49a94f802203fe95a7ccf74da7a232ee523ef4a53cb4d14bdd16289680cdb97a63819b8f42f", + "2 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 0x21 0x02a673638cb9587cb68ea08dbef685c6f2d2a751a8b3c6f2a7e9a4999e6e4bfaf5 3 CHECKMULTISIG", + "P2SH,STRICTENC", + "2-of-3 with one valid and one invalid signature due to parse error, nSigs > validSigs" +], +[ "11 0x47 0x304402200a5c6163f07b8d3b013c4d1d6dba25e780b39658d79ba37af7057a3b7f15ffa102201fd9b4eaa9943f734928b99a83592c2e7bf342ea2680f6a2bb705167966b742001", "0x41 0x0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 CHECKSIG", "CLEANSTACK,P2SH", diff --git a/src/test/data/script_valid.json b/src/test/data/script_valid.json index 064dde8464..a4e15faeaf 100644 --- a/src/test/data/script_valid.json +++ b/src/test/data/script_valid.json @@ -74,12 +74,14 @@ ["1 1", "VERIFY", "P2SH,STRICTENC"], ["1 0x05 0x01 0x00 0x00 0x00 0x00", "VERIFY", "P2SH,STRICTENC", "values >4 bytes can be cast to boolean"], +["1 0x01 0x80", "IF 0 ENDIF", "P2SH,STRICTENC", "negative 0 is false"], ["10 0 11 TOALTSTACK DROP FROMALTSTACK", "ADD 21 EQUAL", "P2SH,STRICTENC"], ["'gavin_was_here' TOALTSTACK 11 FROMALTSTACK", "'gavin_was_here' EQUALVERIFY 11 EQUAL", "P2SH,STRICTENC"], ["0 IFDUP", "DEPTH 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC"], ["1 IFDUP", "DEPTH 2 EQUALVERIFY 1 EQUALVERIFY 1 EQUAL", "P2SH,STRICTENC"], +["0x05 0x0100000000 IFDUP", "DEPTH 2 EQUALVERIFY 0x05 0x0100000000 EQUAL", "P2SH,STRICTENC", "IFDUP dups non ints"], ["0 DROP", "DEPTH 0 EQUAL", "P2SH,STRICTENC"], ["0", "DUP 1 ADD 1 EQUALVERIFY 0 EQUAL", "P2SH,STRICTENC"], ["0 1", "NIP", "P2SH,STRICTENC"], @@ -408,6 +410,7 @@ ["0 0", "EQUAL", "P2SH,STRICTENC"], ["0 0", "EQUALVERIFY 1", "P2SH,STRICTENC"], +["0 0 1", "EQUAL EQUAL", "P2SH,STRICTENC", "OP_0 and bools must have identical byte representations"], ["0", "1ADD", "P2SH,STRICTENC"], ["2", "1SUB", "P2SH,STRICTENC"], diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json index 456e0d2f7b..9def4042da 100644 --- a/src/test/data/tx_invalid.json +++ b/src/test/data/tx_invalid.json @@ -19,6 +19,12 @@ [[["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"], @@ -114,6 +120,70 @@ [[["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 NOP2 1"]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 NOP2 1"]], +"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000fe64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], + +["By-time locks, with argument just beyond tx nLockTime (but within numerical boundries)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000001 NOP2 1"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP2 1"]], +"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000feffffff", "P2SH,CHECKLOCKTIMEVERIFY"], + +["Argument missing"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "NOP2 1"]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], + +["Argument negative with by-blockheight nLockTime=0"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 NOP2 1"]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], + +["Argument negative with by-blocktime nLockTime=500,000,000"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "-1 NOP2 1"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], + +["Input locked"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP2 1"]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], + +["Another input being unlocked isn't sufficient; the CHECKLOCKTIMEVERIFY-using input must be unlocked"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP2 1"] , + ["0000000000000000000000000000000000000000000000000000000000000200", 1, "1"]], +"010000000200010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00020000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], + +["Argument/tx height/time mismatch, both versions"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP2 1"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 NOP2 1"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 NOP2 1"]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 NOP2 1"]], +"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ff64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], + +["Argument 2^32 with nLockTime=2^32-1"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967296 NOP2 1"]], +"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffffff", "P2SH,CHECKLOCKTIMEVERIFY"], + +["Same, but with nLockTime=2^31-1"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 NOP2 1"]], +"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffff7f", "P2SH,CHECKLOCKTIMEVERIFY"], + +["6 byte non-minimally-encoded arguments are invalid even in their contents are valid"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x06 0x000000000000 NOP2 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"], ["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 index 182b88ef67..24fff575c1 100644 --- a/src/test/data/tx_valid.json +++ b/src/test/data/tx_valid.json @@ -187,5 +187,47 @@ "0100000002dbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce000000006b4830450221009627444320dc5ef8d7f68f35010b4c050a6ed0d96b67a84db99fda9c9de58b1e02203e4b4aaa019e012e65d69b487fdf8719df72f488fa91506a80c49a33929f1fd50121022b78b756e2258af13779c1a1f37ea6800259716ca4b7f0b87610e0bf3ab52a01ffffffffdbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce010000009300483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303ffffffff01a0860100000000001976a9149bc0bbdd3024da4d0c38ed1aecf5c68dd1d3fa1288ac00000000", "P2SH"], +["CHECKLOCKTIMEVERIFY tests"], + +["By-height locks, with argument == 0 and == tx nLockTime"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP2 1"]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 NOP2 1"]], +"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ff64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP2 1"]], +"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ff64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], + +["By-time locks, with argument just beyond tx nLockTime (but within numerical boundries)"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 NOP2 1"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 NOP2 1"]], +"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffffff", "P2SH,CHECKLOCKTIMEVERIFY"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 NOP2 1"]], +"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffffff", "P2SH,CHECKLOCKTIMEVERIFY"], + +["Any non-maxint nSequence is fine"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 NOP2 1"]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], + +["The argument can be calculated rather than created directly by a PUSHDATA"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 1ADD NOP2 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 NOP2 1"]], +"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000feffffff", "P2SH,CHECKLOCKTIMEVERIFY"], + +["5 byte non-minimally-encoded arguments are valid"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x05 0x0000000000 NOP2 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"], + ["Make diffs cleaner by leaving a comment here without comma at the end"] ] diff --git a/src/test/main_tests.cpp b/src/test/main_tests.cpp index 9ec533bcca..21ae46d6e9 100644 --- a/src/test/main_tests.cpp +++ b/src/test/main_tests.cpp @@ -2,25 +2,58 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "primitives/transaction.h" +#include "chainparams.h" #include "main.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) +{ + TestBlockSubsidyHalvings(Params(CBaseChainParams::MAIN).GetConsensus()); // As in main + TestBlockSubsidyHalvings(150); // As in regtest + TestBlockSubsidyHalvings(1000); // Just another interval +} + BOOST_AUTO_TEST_CASE(subsidy_limit_test) { + const Consensus::Params& consensusParams = Params(CBaseChainParams::MAIN).GetConsensus(); CAmount nSum = 0; for (int nHeight = 0; nHeight < 14000000; nHeight += 1000) { - CAmount nSubsidy = GetBlockValue(nHeight, 0); + CAmount nSubsidy = GetBlockSubsidy(nHeight, consensusParams); BOOST_CHECK(nSubsidy <= 50 * COIN); nSum += nSubsidy * 1000; BOOST_CHECK(MoneyRange(nSum)); } - BOOST_CHECK(nSum == 2099999997690000ULL); + BOOST_CHECK_EQUAL(nSum, 2099999997690000ULL); } bool ReturnFalse() { return false; } diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 6ab9cb8a44..212be0d2d6 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -2,6 +2,7 @@ // 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 "main.h" #include "miner.h" #include "pubkey.h" @@ -59,7 +60,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) uint256 hash; LOCK(cs_main); - Checkpoints::fEnabled = false; + fCheckpointsEnabled = false; // Simple block creation, nothing special yet: BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); @@ -73,6 +74,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) 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()); @@ -83,7 +85,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) pblock->hashMerkleRoot = pblock->BuildMerkleTree(); pblock->nNonce = blockinfo[i].nonce; CValidationState state; - BOOST_CHECK(ProcessNewBlock(state, NULL, pblock)); + BOOST_CHECK(ProcessNewBlock(state, NULL, pblock, true, NULL)); BOOST_CHECK(state.IsValid()); pblock->hashPrevBlock = pblock->GetHash(); } @@ -222,7 +224,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx.nLockTime = chainActive.Tip()->nHeight+1; hash = tx.GetHash(); mempool.addUnchecked(hash, CTxMemPoolEntry(tx, 11, GetTime(), 111.0, 11)); - BOOST_CHECK(!IsFinalTx(tx, chainActive.Tip()->nHeight + 1)); + BOOST_CHECK(!CheckFinalTx(tx)); // time locked tx2.vin.resize(1); @@ -236,7 +238,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) tx2.nLockTime = chainActive.Tip()->GetMedianTimePast()+1; hash = tx2.GetHash(); mempool.addUnchecked(hash, CTxMemPoolEntry(tx2, 11, GetTime(), 111.0, 11)); - BOOST_CHECK(!IsFinalTx(tx2)); + BOOST_CHECK(!CheckFinalTx(tx2)); BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); @@ -248,8 +250,10 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) chainActive.Tip()->nHeight++; SetMockTime(chainActive.Tip()->GetMedianTimePast()+2); - BOOST_CHECK(IsFinalTx(tx, chainActive.Tip()->nHeight + 1)); - BOOST_CHECK(IsFinalTx(tx2)); + // FIXME: we should *actually* create a new block so the following test + // works; CheckFinalTx() isn't fooled by monkey-patching nHeight. + //BOOST_CHECK(CheckFinalTx(tx)); + //BOOST_CHECK(CheckFinalTx(tx2)); BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey)); BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 3); @@ -262,7 +266,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) BOOST_FOREACH(CTransaction *tx, txFirst) delete tx; - Checkpoints::fEnabled = true; + fCheckpointsEnabled = true; } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/mruset_tests.cpp b/src/test/mruset_tests.cpp index bd4e9c1d38..2b68f8899e 100644 --- a/src/test/mruset_tests.cpp +++ b/src/test/mruset_tests.cpp @@ -17,83 +17,65 @@ using namespace std; -class mrutester -{ -private: - mruset<int> mru; - std::set<int> set; - -public: - mrutester() { mru.max_size(MAX_SIZE); } - int size() const { return set.size(); } - - void insert(int n) - { - mru.insert(n); - set.insert(n); - BOOST_CHECK(mru == set); - } -}; - BOOST_FIXTURE_TEST_SUITE(mruset_tests, BasicTestingSetup) -// Test that an mruset behaves like a set, as long as no more than MAX_SIZE elements are in it -BOOST_AUTO_TEST_CASE(mruset_like_set) -{ - - for (int nTest=0; nTest<NUM_TESTS; nTest++) - { - mrutester tester; - while (tester.size() < MAX_SIZE) - tester.insert(GetRandInt(2 * MAX_SIZE)); - } - -} - -// Test that an mruset's size never exceeds its max_size -BOOST_AUTO_TEST_CASE(mruset_limited_size) +BOOST_AUTO_TEST_CASE(mruset_test) { - for (int nTest=0; nTest<NUM_TESTS; nTest++) - { - mruset<int> mru(MAX_SIZE); - for (int nAction=0; nAction<3*MAX_SIZE; nAction++) - { - int n = GetRandInt(2 * MAX_SIZE); - mru.insert(n); - BOOST_CHECK(mru.size() <= MAX_SIZE); + // The mruset being tested. + mruset<int> mru(5000); + + // Run the test 10 times. + for (int test = 0; test < 10; test++) { + // Reset mru. + mru.clear(); + + // A deque + set to simulate the mruset. + std::deque<int> rep; + std::set<int> all; + + // Insert 10000 random integers below 15000. + for (int j=0; j<10000; j++) { + int add = GetRandInt(15000); + mru.insert(add); + + // Add the number to rep/all as well. + if (all.count(add) == 0) { + all.insert(add); + rep.push_back(add); + if (all.size() == 5001) { + all.erase(rep.front()); + rep.pop_front(); + } + } + + // Do a full comparison between mru and the simulated mru every 1000 and every 5001 elements. + if (j % 1000 == 0 || j % 5001 == 0) { + mruset<int> mru2 = mru; // Also try making a copy + + // Check that all elements that should be in there, are in there. + BOOST_FOREACH(int x, rep) { + BOOST_CHECK(mru.count(x)); + BOOST_CHECK(mru2.count(x)); + } + + // Check that all elements that are in there, should be in there. + BOOST_FOREACH(int x, mru) { + BOOST_CHECK(all.count(x)); + } + + // Check that all elements that are in there, should be in there. + BOOST_FOREACH(int x, mru2) { + BOOST_CHECK(all.count(x)); + } + + for (int t = 0; t < 10; t++) { + int r = GetRandInt(15000); + BOOST_CHECK(all.count(r) == mru.count(r)); + BOOST_CHECK(all.count(r) == mru2.count(r)); + } + } } } } -// 16-bit permutation function -int static permute(int n) -{ - // hexadecimals of pi; verified to be linearly independent - static const int table[16] = {0x243F, 0x6A88, 0x85A3, 0x08D3, 0x1319, 0x8A2E, 0x0370, 0x7344, - 0xA409, 0x3822, 0x299F, 0x31D0, 0x082E, 0xFA98, 0xEC4E, 0x6C89}; - - int ret = 0; - for (int bit=0; bit<16; bit++) - if (n & (1<<bit)) - ret ^= table[bit]; - - return ret; -} - -// Test that an mruset acts like a moving window, if no duplicate elements are added -BOOST_AUTO_TEST_CASE(mruset_window) -{ - mruset<int> mru(MAX_SIZE); - for (int n=0; n<10*MAX_SIZE; n++) - { - mru.insert(permute(n)); - - set<int> tester; - for (int m=max(0,n-MAX_SIZE+1); m<=n; m++) - tester.insert(permute(m)); - - BOOST_CHECK(mru == tester); - } -} - BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index cb357d295c..0f5e1615c6 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -117,6 +117,11 @@ BOOST_AUTO_TEST_CASE(subnet_test) BOOST_CHECK(CSubNet("1:2:3:4:5:6:7:8").Match(CNetAddr("1:2:3:4:5:6:7:8"))); BOOST_CHECK(!CSubNet("1:2:3:4:5:6:7:8").Match(CNetAddr("1:2:3:4:5:6:7:9"))); BOOST_CHECK(CSubNet("1:2:3:4:5:6:7:0/112").Match(CNetAddr("1:2:3:4:5:6:7:1234"))); + BOOST_CHECK(CSubNet("192.168.0.1/24").Match(CNetAddr("192.168.0.2"))); + BOOST_CHECK(CSubNet("192.168.0.20/29").Match(CNetAddr("192.168.0.18"))); + BOOST_CHECK(CSubNet("1.2.2.1/24").Match(CNetAddr("1.2.2.4"))); + BOOST_CHECK(CSubNet("1.2.2.110/31").Match(CNetAddr("1.2.2.111"))); + BOOST_CHECK(CSubNet("1.2.2.20/26").Match(CNetAddr("1.2.2.63"))); // All-Matching IPv6 Matches arbitrary IPv4 and IPv6 BOOST_CHECK(CSubNet("::/0").Match(CNetAddr("1:2:3:4:5:6:7:1234"))); BOOST_CHECK(CSubNet("::/0").Match(CNetAddr("1.2.3.4"))); diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp new file mode 100644 index 0000000000..cb64ee7c69 --- /dev/null +++ b/src/test/policyestimator_tests.cpp @@ -0,0 +1,186 @@ +// Copyright (c) 2011-2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "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) +{ + CTxMemPool mpool(CFeeRate(1000)); + CAmount basefee(2000); + double basepri = 1e6; + CAmount deltaFee(100); + double deltaPri=5e5; + std::vector<CAmount> feeV[2]; + std::vector<double> priV[2]; + + // Populate vectors of increasing fees or priorities + for (int j = 0; j < 10; j++) { + //V[0] is for fee transactions + feeV[0].push_back(basefee * (j+1)); + priV[0].push_back(0); + //V[1] is for priority transactions + feeV[1].push_back(CAmount(0)); + priV[1].push_back(basepri * pow(10, j+1)); + } + + // Store the hashes of transactions that have been + // added to the mempool by their associate fee/pri + // txHashes[j] is populated with transactions either of + // fee = basefee * (j+1) OR pri = 10^6 * 10^(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; + std::list<CTransaction> dummyConflicted; + tx.vin.resize(1); + tx.vin[0].scriptSig = garbage; + tx.vout.resize(1); + tx.vout[0].nValue=0LL; + CFeeRate baseRate(basefee, ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION)); + + // Create a fake block + std::vector<CTransaction> block; + int blocknum = 0; + + // Loop through 200 blocks + // At a decay .998 and 4 fee transactions per block + // This makes the tx count about 1.33 per bucket, above the 1 threshold + while (blocknum < 200) { + for (int j = 0; j < 10; j++) { // For each fee/pri multiple + for (int k = 0; k < 5; k++) { // add 4 fee txs for every priority tx + tx.vin[0].prevout.n = 10000*blocknum+100*j+k; // make transaction unique + uint256 hash = tx.GetHash(); + mpool.addUnchecked(hash, CTxMemPoolEntry(tx, feeV[k/4][j], GetTime(), priV[k/4][j], blocknum, mpool.HasNoInputsOf(tx))); + txHashes[j].push_back(hash); + } + } + //Create blocks where higher fee/pri txs are included more often + for (int h = 0; h <= blocknum%10; h++) { + // 10/10 blocks add highest fee/pri transactions + // 9/10 blocks add 2nd highest and so on until ... + // 1/10 blocks add lowest fee/pri transactions + while (txHashes[9-h].size()) { + CTransaction btx; + if (mpool.lookup(txHashes[9-h].back(), btx)) + block.push_back(btx); + txHashes[9-h].pop_back(); + } + } + mpool.removeForBlock(block, ++blocknum, dummyConflicted); + block.clear(); + if (blocknum == 30) { + // At this point we should need to combine 5 buckets to get enough data points + // So estimateFee(1) should fail and estimateFee(2) should return somewhere around + // 8*baserate + BOOST_CHECK(mpool.estimateFee(1) == CFeeRate(0)); + BOOST_CHECK(mpool.estimateFee(2).GetFeePerK() < 8*baseRate.GetFeePerK() + deltaFee); + BOOST_CHECK(mpool.estimateFee(2).GetFeePerK() > 8*baseRate.GetFeePerK() - deltaFee); + } + } + + std::vector<CAmount> origFeeEst; + std::vector<double> origPriEst; + // 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) should return 9*baseRate. + // Third highest feerate has 90% chance of being included by 2 blocks, + // so estimateFee(2) should return 8*baseRate etc... + for (int i = 1; i < 10;i++) { + origFeeEst.push_back(mpool.estimateFee(i).GetFeePerK()); + origPriEst.push_back(mpool.estimatePriority(i)); + if (i > 1) { // Fee estimates should be monotonically decreasing + BOOST_CHECK(origFeeEst[i-1] <= origFeeEst[i-2]); + BOOST_CHECK(origPriEst[i-1] <= origPriEst[i-2]); + } + BOOST_CHECK(origFeeEst[i-1] < (10-i)*baseRate.GetFeePerK() + deltaFee); + BOOST_CHECK(origFeeEst[i-1] > (10-i)*baseRate.GetFeePerK() - deltaFee); + BOOST_CHECK(origPriEst[i-1] < pow(10,10-i) * basepri + deltaPri); + BOOST_CHECK(origPriEst[i-1] > pow(10,10-i) * basepri - deltaPri); + } + + // 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, dummyConflicted); + + for (int i = 1; i < 10;i++) { + BOOST_CHECK(mpool.estimateFee(i).GetFeePerK() < origFeeEst[i-1] + deltaFee); + BOOST_CHECK(mpool.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee); + BOOST_CHECK(mpool.estimatePriority(i) < origPriEst[i-1] + deltaPri); + BOOST_CHECK(mpool.estimatePriority(i) > origPriEst[i-1] - deltaPri); + } + + + // 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/pri multiple + for (int k = 0; k < 5; k++) { // add 4 fee txs for every priority tx + tx.vin[0].prevout.n = 10000*blocknum+100*j+k; + uint256 hash = tx.GetHash(); + mpool.addUnchecked(hash, CTxMemPoolEntry(tx, feeV[k/4][j], GetTime(), priV[k/4][j], blocknum, mpool.HasNoInputsOf(tx))); + txHashes[j].push_back(hash); + } + } + mpool.removeForBlock(block, ++blocknum, dummyConflicted); + } + + for (int i = 1; i < 10;i++) { + BOOST_CHECK(mpool.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee); + BOOST_CHECK(mpool.estimatePriority(i) > origPriEst[i-1] - deltaPri); + } + + // Mine all those transactions + // Estimates should still not be below original + for (int j = 0; j < 10; j++) { + while(txHashes[j].size()) { + CTransaction btx; + if (mpool.lookup(txHashes[j].back(), btx)) + block.push_back(btx); + txHashes[j].pop_back(); + } + } + mpool.removeForBlock(block, 265, dummyConflicted); + block.clear(); + for (int i = 1; i < 10;i++) { + BOOST_CHECK(mpool.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee); + BOOST_CHECK(mpool.estimatePriority(i) > origPriEst[i-1] - deltaPri); + } + + // Mine 100 more blocks where everything is mined every block + // Estimates should be below original estimates (not possible for last estimate) + while (blocknum < 365) { + for (int j = 0; j < 10; j++) { // For each fee/pri multiple + for (int k = 0; k < 5; k++) { // add 4 fee txs for every priority tx + tx.vin[0].prevout.n = 10000*blocknum+100*j+k; + uint256 hash = tx.GetHash(); + mpool.addUnchecked(hash, CTxMemPoolEntry(tx, feeV[k/4][j], GetTime(), priV[k/4][j], blocknum, mpool.HasNoInputsOf(tx))); + CTransaction btx; + if (mpool.lookup(hash, btx)) + block.push_back(btx); + } + } + mpool.removeForBlock(block, ++blocknum, dummyConflicted); + block.clear(); + } + for (int i = 1; i < 9; i++) { + BOOST_CHECK(mpool.estimateFee(i).GetFeePerK() < origFeeEst[i-1] - deltaFee); + BOOST_CHECK(mpool.estimatePriority(i) < origPriEst[i-1] - deltaPri); + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index 4ce1591c35..a436749287 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -69,4 +69,28 @@ BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual) BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, params), 0x1d00e1fd); } +BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test) +{ + SelectParams(CBaseChainParams::MAIN); + const Consensus::Params& params = Params().GetConsensus(); + + std::vector<CBlockIndex> blocks(10000); + for (int i = 0; i < 10000; i++) { + blocks[i].pprev = i ? &blocks[i - 1] : NULL; + blocks[i].nHeight = i; + blocks[i].nTime = 1269211443 + i * params.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[GetRand(10000)]; + CBlockIndex *p2 = &blocks[GetRand(10000)]; + CBlockIndex *p3 = &blocks[GetRand(10000)]; + + int64_t tdiff = GetBlockProofEquivalentTime(*p1, *p2, *p3, params); + BOOST_CHECK_EQUAL(tdiff, p1->GetBlockTime() - p2->GetBlockTime()); + } +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 45cb551d04..c38df0ecf3 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -13,35 +13,36 @@ #include <boost/algorithm/string.hpp> #include <boost/test/unit_test.hpp> +#include "univalue/univalue.h" + using namespace std; -using namespace json_spirit; -Array +UniValue createArgs(int nRequired, const char* address1=NULL, const char* address2=NULL) { - Array result; + UniValue result(UniValue::VARR); result.push_back(nRequired); - Array addresses; + UniValue addresses(UniValue::VARR); if (address1) addresses.push_back(address1); if (address2) addresses.push_back(address2); result.push_back(addresses); return result; } -Value CallRPC(string args) +UniValue CallRPC(string args) { vector<string> vArgs; boost::split(vArgs, args, boost::is_any_of(" \t")); string strMethod = vArgs[0]; vArgs.erase(vArgs.begin()); - Array params = RPCConvertValues(strMethod, vArgs); + UniValue params = RPCConvertValues(strMethod, vArgs); rpcfn_type method = tableRPC[strMethod]->actor; try { - Value result = (*method)(params, false); + UniValue result = (*method)(params, false); return result; } - catch (const Object& objError) { + catch (const UniValue& objError) { throw runtime_error(find_value(objError, "message").get_str()); } } @@ -52,7 +53,7 @@ BOOST_FIXTURE_TEST_SUITE(rpc_tests, TestingSetup) BOOST_AUTO_TEST_CASE(rpc_rawparams) { // Test raw transaction API argument handling - Value r; + UniValue r; BOOST_CHECK_THROW(CallRPC("getrawtransaction"), runtime_error); BOOST_CHECK_THROW(CallRPC("getrawtransaction not_hex"), runtime_error); @@ -92,7 +93,7 @@ BOOST_AUTO_TEST_CASE(rpc_rawparams) BOOST_AUTO_TEST_CASE(rpc_rawsign) { - Value r; + UniValue r; // input is a 1-of-2 multisig (so is output): string prevout = "[{\"txid\":\"b4cc287e58f87cdae59417329f710f3ecd75a4ee1d2872b7248f50977c8493f3\"," @@ -111,25 +112,28 @@ BOOST_AUTO_TEST_CASE(rpc_rawsign) BOOST_AUTO_TEST_CASE(rpc_format_monetary_values) { - BOOST_CHECK_EQUAL(write_string(ValueFromAmount(0LL), false), "0.00000000"); - BOOST_CHECK_EQUAL(write_string(ValueFromAmount(1LL), false), "0.00000001"); - BOOST_CHECK_EQUAL(write_string(ValueFromAmount(17622195LL), false), "0.17622195"); - BOOST_CHECK_EQUAL(write_string(ValueFromAmount(50000000LL), false), "0.50000000"); - BOOST_CHECK_EQUAL(write_string(ValueFromAmount(89898989LL), false), "0.89898989"); - BOOST_CHECK_EQUAL(write_string(ValueFromAmount(100000000LL), false), "1.00000000"); - BOOST_CHECK_EQUAL(write_string(ValueFromAmount(2099999999999990LL), false), "20999999.99999990"); - BOOST_CHECK_EQUAL(write_string(ValueFromAmount(2099999999999999LL), false), "20999999.99999999"); + 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"); } -static Value ValueFromString(const std::string &str) +static UniValue ValueFromString(const std::string &str) { - Value value; - BOOST_CHECK(read_string(str, value)); + 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); @@ -140,6 +144,24 @@ BOOST_AUTO_TEST_CASE(rpc_parse_monetary_values) BOOST_CHECK_EQUAL(AmountFromValue(ValueFromString("20999999.99999999")), 2099999999999999LL); } +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); + // 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_boostasiotocnetaddr) { // Check IPv4 addresses @@ -155,4 +177,87 @@ BOOST_AUTO_TEST_CASE(rpc_boostasiotocnetaddr) BOOST_CHECK_EQUAL(BoostAsioToCNetAddr(boost::asio::ip::address::from_string("::ffff:127.0.0.1")).ToString(), "127.0.0.1"); } +BOOST_AUTO_TEST_CASE(rpc_ban) +{ + BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned"))); + + UniValue r; + BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 127.0.0.0 add"))); + BOOST_CHECK_THROW(r = CallRPC(string("setban 127.0.0.0:8334")), runtime_error); //portnumber for setban not allowed + BOOST_CHECK_NO_THROW(r = CallRPC(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/255.255.255.255"); + BOOST_CHECK_NO_THROW(CallRPC(string("setban 127.0.0.0 remove")));; + BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); + ar = r.get_array(); + BOOST_CHECK_EQUAL(ar.size(), 0); + + BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 127.0.0.0/24 add 1607731200 true"))); + BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); + ar = r.get_array(); + o1 = ar[0].get_obj(); + adr = find_value(o1, "address"); + UniValue banned_until = find_value(o1, "banned_untill"); + BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/255.255.255.0"); + BOOST_CHECK_EQUAL(banned_until.get_int64(), 1607731200); // absolute time check + + BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned"))); + + BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 127.0.0.0/24 add 200"))); + BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); + ar = r.get_array(); + o1 = ar[0].get_obj(); + adr = find_value(o1, "address"); + banned_until = find_value(o1, "banned_untill"); + BOOST_CHECK_EQUAL(adr.get_str(), "127.0.0.0/255.255.255.0"); + 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 suubnet range + BOOST_CHECK_THROW(r = CallRPC(string("setban 127.0.0.1 add")), runtime_error); + + BOOST_CHECK_NO_THROW(CallRPC(string("setban 127.0.0.0/24 remove")));; + BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); + ar = r.get_array(); + BOOST_CHECK_EQUAL(ar.size(), 0); + + BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 127.0.0.0/255.255.0.0 add"))); + BOOST_CHECK_THROW(r = CallRPC(string("setban 127.0.1.1 add")), runtime_error); + + BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned"))); + BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); + ar = r.get_array(); + BOOST_CHECK_EQUAL(ar.size(), 0); + + + BOOST_CHECK_THROW(r = CallRPC(string("setban test add")), runtime_error); //invalid IP + + //IPv6 tests + BOOST_CHECK_NO_THROW(r = CallRPC(string("setban FE80:0000:0000:0000:0202:B3FF:FE1E:8329 add"))); + BOOST_CHECK_NO_THROW(r = CallRPC(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/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); + + BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned"))); + BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 2001:db8::/30 add"))); + BOOST_CHECK_NO_THROW(r = CallRPC(string("listbanned"))); + ar = r.get_array(); + o1 = ar[0].get_obj(); + adr = find_value(o1, "address"); + BOOST_CHECK_EQUAL(adr.get_str(), "2001:db8::/ffff:fffc:0:0:0:0:0:0"); + + BOOST_CHECK_NO_THROW(CallRPC(string("clearbanned"))); + BOOST_CHECK_NO_THROW(r = CallRPC(string("setban 2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/128 add"))); + BOOST_CHECK_NO_THROW(r = CallRPC(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/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp index 4d5e92cbd4..9368963ff2 100644 --- a/src/test/rpc_wallet_tests.cpp +++ b/src/test/rpc_wallet_tests.cpp @@ -14,11 +14,12 @@ #include <boost/algorithm/string.hpp> #include <boost/test/unit_test.hpp> +#include "univalue/univalue.h" + using namespace std; -using namespace json_spirit; -extern Array createArgs(int nRequired, const char* address1 = NULL, const char* address2 = NULL); -extern Value CallRPC(string args); +extern UniValue createArgs(int nRequired, const char* address1 = NULL, const char* address2 = NULL); +extern UniValue CallRPC(string args); extern CWallet* pwalletMain; @@ -35,7 +36,7 @@ BOOST_AUTO_TEST_CASE(rpc_addmultisig) // new, compressed: const char address2Hex[] = "0388c2037017c62240b6b72ac1a2a5f94da790596ebd06177c8572752922165cb4"; - Value v; + UniValue v; CBitcoinAddress address; BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex), false)); address.SetString(v.get_str()); @@ -66,13 +67,13 @@ BOOST_AUTO_TEST_CASE(rpc_addmultisig) BOOST_AUTO_TEST_CASE(rpc_wallet) { // Test RPC calls for various wallet statistics - Value r; + UniValue r; LOCK2(cs_main, pwalletMain->cs_wallet); CPubKey demoPubkey = pwalletMain->GenerateNewKey(); CBitcoinAddress demoAddress = CBitcoinAddress(CTxDestination(demoPubkey.GetID())); - Value retValue; + UniValue retValue; string strAccount = "walletDemoAccount"; string strPurpose = "receive"; BOOST_CHECK_NO_THROW({ /*Initialize Wallet with an account */ @@ -213,9 +214,15 @@ BOOST_AUTO_TEST_CASE(rpc_wallet) *********************************/ BOOST_CHECK_THROW(CallRPC("getaddressesbyaccount"), runtime_error); BOOST_CHECK_NO_THROW(retValue = CallRPC("getaddressesbyaccount " + strAccount)); - Array arr = retValue.get_array(); + UniValue arr = retValue.get_array(); BOOST_CHECK(arr.size() > 0); BOOST_CHECK(CBitcoinAddress(arr[0].get_str()).Get() == demoAddress.Get()); + + /********************************* + * fundrawtransaction + *********************************/ + BOOST_CHECK_THROW(CallRPC("fundrawtransaction 28z"), runtime_error); + BOOST_CHECK_THROW(CallRPC("fundrawtransaction 01000000000180969800000000001976a91450ce0a4b0ee0ddeb633da85199728b940ac3fe9488ac00000000"), runtime_error); } 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..cb1a427db0 --- /dev/null +++ b/src/test/scheduler_tests.cpp @@ -0,0 +1,119 @@ +// Copyright (c) 2012-2013 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/random/mersenne_twister.hpp> +#include <boost/random/uniform_int_distribution.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(µTask, 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) +{ + seed_insecure_rand(false); + + // 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 from one of the counters a + // random amount, 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 }; + boost::random::mt19937 rng(insecure_rand()); + boost::random::uniform_int_distribution<> zeroToNine(0, 9); + boost::random::uniform_int_distribution<> randomMsec(-11, 1000); + boost::random::uniform_int_distribution<> randomDelta(-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(µTask, 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, µTasks)); + + 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, µTasks)); + 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(µTask, 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_SUITE_END() diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index c0614cca43..3733425699 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -26,12 +26,10 @@ #include <boost/foreach.hpp> #include <boost/test/unit_test.hpp> -#include "json/json_spirit_reader_template.h" -#include "json/json_spirit_utils.h" -#include "json/json_spirit_writer_template.h" + +#include "univalue/univalue.h" using namespace std; -using namespace json_spirit; // Uncomment if you want to output updated JSON tests. // #define UPDATE_JSON_TESTS @@ -41,15 +39,15 @@ static const unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC; unsigned int ParseScriptFlags(string strFlags); string FormatScriptFlags(unsigned int flags); -Array +UniValue read_json(const std::string& jsondata) { - Value v; + UniValue v; - if (!read_string(jsondata, v) || v.type() != array_type) + if (!v.read(jsondata) || !v.isArray()) { BOOST_ERROR("Parse error."); - return Array(); + return UniValue(UniValue::VARR); } return v.get_array(); } @@ -295,10 +293,10 @@ public: return *this; } - Array GetJSON() + UniValue GetJSON() { DoPush(); - Array array; + UniValue array(UniValue::VARR); array.push_back(FormatScript(spendTx.vin[0].scriptSig)); array.push_back(FormatScript(creditTx.vout[0].scriptPubKey)); array.push_back(FormatScriptFlags(flags)); @@ -582,14 +580,16 @@ BOOST_AUTO_TEST_CASE(script_build) std::set<std::string> tests_bad; { - Array json_good = read_json(std::string(json_tests::script_valid, json_tests::script_valid + sizeof(json_tests::script_valid))); - Array json_bad = read_json(std::string(json_tests::script_invalid, json_tests::script_invalid + sizeof(json_tests::script_invalid))); + UniValue json_good = read_json(std::string(json_tests::script_valid, json_tests::script_valid + sizeof(json_tests::script_valid))); + UniValue json_bad = read_json(std::string(json_tests::script_invalid, json_tests::script_invalid + sizeof(json_tests::script_invalid))); - BOOST_FOREACH(Value& tv, json_good) { - tests_good.insert(write_string(Value(tv.get_array()), true)); + for (unsigned int idx = 0; idx < json_good.size(); idx++) { + const UniValue& tv = json_good[idx]; + tests_good.insert(tv.get_array().write()); } - BOOST_FOREACH(Value& tv, json_bad) { - tests_bad.insert(write_string(Value(tv.get_array()), true)); + for (unsigned int idx = 0; idx < json_bad.size(); idx++) { + const UniValue& tv = json_bad[idx]; + tests_bad.insert(tv.get_array().write()); } } @@ -598,7 +598,7 @@ BOOST_AUTO_TEST_CASE(script_build) BOOST_FOREACH(TestBuilder& test, good) { test.Test(true); - std::string str = write_string(Value(test.GetJSON()), true); + std::string str = test.GetJSON().write(); #ifndef UPDATE_JSON_TESTS if (tests_good.count(str) == 0) { BOOST_CHECK_MESSAGE(false, "Missing auto script_valid test: " + test.GetComment()); @@ -608,7 +608,7 @@ BOOST_AUTO_TEST_CASE(script_build) } BOOST_FOREACH(TestBuilder& test, bad) { test.Test(false); - std::string str = write_string(Value(test.GetJSON()), true); + std::string str = test.GetJSON().write(); #ifndef UPDATE_JSON_TESTS if (tests_bad.count(str) == 0) { BOOST_CHECK_MESSAGE(false, "Missing auto script_invalid test: " + test.GetComment()); @@ -634,12 +634,11 @@ BOOST_AUTO_TEST_CASE(script_valid) // Inner arrays are [ "scriptSig", "scriptPubKey", "flags" ] // ... where scriptSig and scriptPubKey are stringified // scripts. - Array tests = read_json(std::string(json_tests::script_valid, json_tests::script_valid + sizeof(json_tests::script_valid))); + UniValue tests = read_json(std::string(json_tests::script_valid, json_tests::script_valid + sizeof(json_tests::script_valid))); - BOOST_FOREACH(Value& tv, tests) - { - Array test = tv.get_array(); - string strTest = write_string(tv, false); + for (unsigned int idx = 0; idx < tests.size(); idx++) { + UniValue test = tests[idx]; + string strTest = test.write(); if (test.size() < 3) // Allow size > 3; extra stuff ignored (useful for comments) { if (test.size() != 1) { @@ -660,13 +659,12 @@ BOOST_AUTO_TEST_CASE(script_valid) BOOST_AUTO_TEST_CASE(script_invalid) { // Scripts that should evaluate as invalid - Array tests = read_json(std::string(json_tests::script_invalid, json_tests::script_invalid + sizeof(json_tests::script_invalid))); + UniValue tests = read_json(std::string(json_tests::script_invalid, json_tests::script_invalid + sizeof(json_tests::script_invalid))); - BOOST_FOREACH(Value& tv, tests) - { - Array test = tv.get_array(); - string strTest = write_string(tv, false); - if (test.size() < 3) // Allow size > 3; extra stuff ignored (useful for comments) + for (unsigned int idx = 0; idx < tests.size(); idx++) { + UniValue test = tests[idx]; + string strTest = test.write(); + if (test.size() < 3) // Allow size > 2; extra stuff ignored (useful for comments) { if (test.size() != 1) { BOOST_ERROR("Bad test: " << strTest); diff --git a/src/test/scriptnum_tests.cpp b/src/test/scriptnum_tests.cpp index 24c7dd3d5a..d95724dbe1 100644 --- a/src/test/scriptnum_tests.cpp +++ b/src/test/scriptnum_tests.cpp @@ -145,7 +145,7 @@ static void RunCreate(const int64_t& num) { CheckCreateInt(num); CScriptNum scriptnum(num); - if (scriptnum.getvch().size() <= CScriptNum::nMaxNumSize) + if (scriptnum.getvch().size() <= CScriptNum::nDefaultMaxNumSize) CheckCreateVch(num); else { diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index afb7a41bbd..a0797d5f3f 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -2,25 +2,24 @@ // 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 "data/sighash.json.h" #include "main.h" #include "random.h" -#include "serialize.h" -#include "script/script.h" #include "script/interpreter.h" +#include "script/script.h" +#include "serialize.h" +#include "test/test_bitcoin.h" #include "util.h" #include "version.h" -#include "test/test_bitcoin.h" #include <iostream> #include <boost/test/unit_test.hpp> -#include "json/json_spirit_reader_template.h" -#include "json/json_spirit_utils.h" -#include "json/json_spirit_writer_template.h" -using namespace json_spirit; -extern Array read_json(const std::string& jsondata); +#include "univalue/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) @@ -167,12 +166,11 @@ BOOST_AUTO_TEST_CASE(sighash_test) // Goal: check that SignatureHash generates correct hash BOOST_AUTO_TEST_CASE(sighash_from_data) { - Array tests = read_json(std::string(json_tests::sighash, json_tests::sighash + sizeof(json_tests::sighash))); + UniValue tests = read_json(std::string(json_tests::sighash, json_tests::sighash + sizeof(json_tests::sighash))); - BOOST_FOREACH(Value& tv, tests) - { - Array test = tv.get_array(); - std::string strTest = write_string(tv, false); + 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); diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index a2cb78c989..c727303ea1 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -6,6 +6,7 @@ #include "test_bitcoin.h" +#include "key.h" #include "main.h" #include "random.h" #include "txdb.h" @@ -20,7 +21,7 @@ #include <boost/test/unit_test.hpp> #include <boost/thread.hpp> -CClientUIInterface uiInterface; +CClientUIInterface uiInterface; // Declared but not defined in ui_interface.h CWallet* pwalletMain; extern bool fPrintToConsole; @@ -28,6 +29,7 @@ extern void noui_connect(); BasicTestingSetup::BasicTestingSetup() { + ECC_Start(); SetupEnvironment(); fPrintToDebugLog = false; // don't want to write to debug.log file fCheckBlockIndex = true; @@ -35,6 +37,7 @@ BasicTestingSetup::BasicTestingSetup() } BasicTestingSetup::~BasicTestingSetup() { + ECC_Stop(); } TestingSetup::TestingSetup() diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 2a3083316e..9ce7aae966 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -7,27 +7,29 @@ #include "test/test_bitcoin.h" #include "clientversion.h" +#include "consensus/validation.h" +#include "core_io.h" #include "key.h" #include "keystore.h" #include "main.h" #include "script/script.h" #include "script/script_error.h" -#include "core_io.h" #include <map> #include <string> #include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/split.hpp> +#include <boost/assign/list_of.hpp> #include <boost/test/unit_test.hpp> #include <boost/assign/list_of.hpp> -#include "json/json_spirit_writer_template.h" + +#include "univalue/univalue.h" using namespace std; -using namespace json_spirit; // In script_tests.cpp -extern Array read_json(const std::string& jsondata); +extern UniValue read_json(const std::string& jsondata); static std::map<string, unsigned int> mapFlagNames = boost::assign::map_list_of (string("NONE"), (unsigned int)SCRIPT_VERIFY_NONE) @@ -39,7 +41,8 @@ static std::map<string, unsigned int> mapFlagNames = boost::assign::map_list_of (string("MINIMALDATA"), (unsigned int)SCRIPT_VERIFY_MINIMALDATA) (string("NULLDUMMY"), (unsigned int)SCRIPT_VERIFY_NULLDUMMY) (string("DISCOURAGE_UPGRADABLE_NOPS"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) - (string("CLEANSTACK"), (unsigned int)SCRIPT_VERIFY_CLEANSTACK); + (string("CLEANSTACK"), (unsigned int)SCRIPT_VERIFY_CLEANSTACK) + (string("CHECKLOCKTIMEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY); unsigned int ParseScriptFlags(string strFlags) { @@ -87,32 +90,31 @@ BOOST_AUTO_TEST_CASE(tx_valid) // ... where all scripts are stringified scripts. // // verifyFlags is a comma separated list of script verification flags to apply, or "NONE" - Array tests = read_json(std::string(json_tests::tx_valid, json_tests::tx_valid + sizeof(json_tests::tx_valid))); + UniValue tests = read_json(std::string(json_tests::tx_valid, json_tests::tx_valid + sizeof(json_tests::tx_valid))); ScriptError err; - BOOST_FOREACH(Value& tv, tests) - { - Array test = tv.get_array(); - string strTest = write_string(tv, false); - if (test[0].type() == array_type) + for (unsigned int idx = 0; idx < tests.size(); idx++) { + UniValue test = tests[idx]; + string strTest = test.write(); + if (test[0].isArray()) { - if (test.size() != 3 || test[1].type() != str_type || test[2].type() != str_type) + if (test.size() != 3 || !test[1].isStr() || !test[2].isStr()) { BOOST_ERROR("Bad test: " << strTest); continue; } map<COutPoint, CScript> mapprevOutScriptPubKeys; - Array inputs = test[0].get_array(); + UniValue inputs = test[0].get_array(); bool fValid = true; - BOOST_FOREACH(Value& input, inputs) - { - if (input.type() != array_type) + for (unsigned int inpIdx = 0; inpIdx < inputs.size(); inpIdx++) { + const UniValue& input = inputs[inpIdx]; + if (!input.isArray()) { fValid = false; break; } - Array vinput = input.get_array(); + UniValue vinput = input.get_array(); if (vinput.size() != 3) { fValid = false; @@ -163,32 +165,31 @@ BOOST_AUTO_TEST_CASE(tx_invalid) // ... where all scripts are stringified scripts. // // verifyFlags is a comma separated list of script verification flags to apply, or "NONE" - Array tests = read_json(std::string(json_tests::tx_invalid, json_tests::tx_invalid + sizeof(json_tests::tx_invalid))); + UniValue tests = read_json(std::string(json_tests::tx_invalid, json_tests::tx_invalid + sizeof(json_tests::tx_invalid))); ScriptError err; - BOOST_FOREACH(Value& tv, tests) - { - Array test = tv.get_array(); - string strTest = write_string(tv, false); - if (test[0].type() == array_type) + for (unsigned int idx = 0; idx < tests.size(); idx++) { + UniValue test = tests[idx]; + string strTest = test.write(); + if (test[0].isArray()) { - if (test.size() != 3 || test[1].type() != str_type || test[2].type() != str_type) + if (test.size() != 3 || !test[1].isStr() || !test[2].isStr()) { BOOST_ERROR("Bad test: " << strTest); continue; } map<COutPoint, CScript> mapprevOutScriptPubKeys; - Array inputs = test[0].get_array(); + UniValue inputs = test[0].get_array(); bool fValid = true; - BOOST_FOREACH(Value& input, inputs) - { - if (input.type() != array_type) + for (unsigned int inpIdx = 0; inpIdx < inputs.size(); inpIdx++) { + const UniValue& input = inputs[inpIdx]; + if (!input.isArray()) { fValid = false; break; } - Array vinput = input.get_array(); + UniValue vinput = input.get_array(); if (vinput.size() != 3) { fValid = false; diff --git a/src/test/univalue_tests.cpp b/src/test/univalue_tests.cpp index 8cecfbf651..16bc8d30f6 100644 --- a/src/test/univalue_tests.cpp +++ b/src/test/univalue_tests.cpp @@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE(univalue_constructor) double vd = -7.21; UniValue v7(vd); - BOOST_CHECK(v7.isNum()); + BOOST_CHECK(v7.isReal()); BOOST_CHECK_EQUAL(v7.getValStr(), "-7.21"); string vs("yawn"); @@ -63,6 +63,48 @@ BOOST_AUTO_TEST_CASE(univalue_constructor) BOOST_CHECK_EQUAL(v9.getValStr(), "zappa"); } +BOOST_AUTO_TEST_CASE(univalue_typecheck) +{ + UniValue v1; + BOOST_CHECK(v1.setNumStr("1")); + BOOST_CHECK(v1.isNum()); + BOOST_CHECK_THROW(v1.get_bool(), runtime_error); + + UniValue v2; + BOOST_CHECK(v2.setBool(true)); + BOOST_CHECK_EQUAL(v2.get_bool(), true); + BOOST_CHECK_THROW(v2.get_int(), runtime_error); + + UniValue v3; + BOOST_CHECK(v3.setNumStr("32482348723847471234")); + BOOST_CHECK_THROW(v3.get_int64(), runtime_error); + BOOST_CHECK(v3.setNumStr("1000")); + BOOST_CHECK_EQUAL(v3.get_int64(), 1000); + + UniValue v4; + BOOST_CHECK(v4.setNumStr("2147483648")); + BOOST_CHECK_EQUAL(v4.get_int64(), 2147483648); + BOOST_CHECK_THROW(v4.get_int(), runtime_error); + BOOST_CHECK(v4.setNumStr("1000")); + BOOST_CHECK_EQUAL(v4.get_int(), 1000); + BOOST_CHECK_THROW(v4.get_str(), runtime_error); + BOOST_CHECK_EQUAL(v4.get_real(), 1000); + BOOST_CHECK_THROW(v4.get_array(), runtime_error); + BOOST_CHECK_THROW(v4.getKeys(), runtime_error); + BOOST_CHECK_THROW(v4.getValues(), runtime_error); + BOOST_CHECK_THROW(v4.get_obj(), runtime_error); + + UniValue v5; + BOOST_CHECK(v5.read("[true, 10]")); + BOOST_CHECK_NO_THROW(v5.get_array()); + std::vector<UniValue> vals = v5.getValues(); + BOOST_CHECK_THROW(vals[0].get_int(), runtime_error); + BOOST_CHECK_EQUAL(vals[0].get_bool(), true); + + BOOST_CHECK_EQUAL(vals[1].get_int(), 10); + BOOST_CHECK_THROW(vals[1].get_bool(), runtime_error); +} + BOOST_AUTO_TEST_CASE(univalue_set) { UniValue v(UniValue::VSTR, "foo"); @@ -72,20 +114,20 @@ BOOST_AUTO_TEST_CASE(univalue_set) BOOST_CHECK(v.setObject()); BOOST_CHECK(v.isObject()); - BOOST_CHECK_EQUAL(v.count(), 0); + BOOST_CHECK_EQUAL(v.size(), 0); BOOST_CHECK_EQUAL(v.getType(), UniValue::VOBJ); BOOST_CHECK(v.empty()); BOOST_CHECK(v.setArray()); BOOST_CHECK(v.isArray()); - BOOST_CHECK_EQUAL(v.count(), 0); + BOOST_CHECK_EQUAL(v.size(), 0); BOOST_CHECK(v.setStr("zum")); BOOST_CHECK(v.isStr()); BOOST_CHECK_EQUAL(v.getValStr(), "zum"); BOOST_CHECK(v.setFloat(-1.01)); - BOOST_CHECK(v.isNum()); + BOOST_CHECK(v.isReal()); BOOST_CHECK_EQUAL(v.getValStr(), "-1.01"); BOOST_CHECK(v.setInt((int)1023)); @@ -145,7 +187,7 @@ BOOST_AUTO_TEST_CASE(univalue_array) BOOST_CHECK(arr.push_backV(vec)); BOOST_CHECK_EQUAL(arr.empty(), false); - BOOST_CHECK_EQUAL(arr.count(), 5); + BOOST_CHECK_EQUAL(arr.size(), 5); BOOST_CHECK_EQUAL(arr[0].getValStr(), "1023"); BOOST_CHECK_EQUAL(arr[1].getValStr(), "zippy"); @@ -157,7 +199,7 @@ BOOST_AUTO_TEST_CASE(univalue_array) arr.clear(); BOOST_CHECK(arr.empty()); - BOOST_CHECK_EQUAL(arr.count(), 0); + BOOST_CHECK_EQUAL(arr.size(), 0); } BOOST_AUTO_TEST_CASE(univalue_object) @@ -197,7 +239,7 @@ BOOST_AUTO_TEST_CASE(univalue_object) BOOST_CHECK(obj.pushKVs(obj2)); BOOST_CHECK_EQUAL(obj.empty(), false); - BOOST_CHECK_EQUAL(obj.count(), 9); + BOOST_CHECK_EQUAL(obj.size(), 9); BOOST_CHECK_EQUAL(obj["age"].getValStr(), "100"); BOOST_CHECK_EQUAL(obj["first"].getValStr(), "John"); @@ -230,7 +272,7 @@ BOOST_AUTO_TEST_CASE(univalue_object) objTypes["distance"] = UniValue::VNUM; objTypes["time"] = UniValue::VNUM; objTypes["calories"] = UniValue::VNUM; - objTypes["temperature"] = UniValue::VNUM; + objTypes["temperature"] = UniValue::VREAL; objTypes["cat1"] = UniValue::VNUM; objTypes["cat2"] = UniValue::VNUM; BOOST_CHECK(obj.checkObject(objTypes)); @@ -240,11 +282,11 @@ BOOST_AUTO_TEST_CASE(univalue_object) obj.clear(); BOOST_CHECK(obj.empty()); - BOOST_CHECK_EQUAL(obj.count(), 0); + BOOST_CHECK_EQUAL(obj.size(), 0); } static const char *json1 = -"[1.1,{\"key1\":\"str\",\"key2\":800,\"key3\":{\"name\":\"martian\"}}]"; +"[1.10000000,{\"key1\":\"str\\u0000\",\"key2\":800,\"key3\":{\"name\":\"martian http://test.com\"}}]"; BOOST_AUTO_TEST_CASE(univalue_readwrite) { @@ -255,16 +297,18 @@ BOOST_AUTO_TEST_CASE(univalue_readwrite) BOOST_CHECK(v.read(strJson1)); BOOST_CHECK(v.isArray()); - BOOST_CHECK_EQUAL(v.count(), 2); + BOOST_CHECK_EQUAL(v.size(), 2); - BOOST_CHECK_EQUAL(v[0].getValStr(), "1.1"); + BOOST_CHECK_EQUAL(v[0].getValStr(), "1.10000000"); UniValue obj = v[1]; BOOST_CHECK(obj.isObject()); - BOOST_CHECK_EQUAL(obj.count(), 3); + BOOST_CHECK_EQUAL(obj.size(), 3); BOOST_CHECK(obj["key1"].isStr()); - BOOST_CHECK_EQUAL(obj["key1"].getValStr(), "str"); + std::string correctValue("str"); + correctValue.push_back('\0'); + BOOST_CHECK_EQUAL(obj["key1"].getValStr(), correctValue); BOOST_CHECK(obj["key2"].isNum()); BOOST_CHECK_EQUAL(obj["key2"].getValStr(), "800"); BOOST_CHECK(obj["key3"].isObject()); diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 3309e2e387..5cb5894251 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -146,29 +146,27 @@ BOOST_AUTO_TEST_CASE(util_GetArg) BOOST_AUTO_TEST_CASE(util_FormatMoney) { - BOOST_CHECK_EQUAL(FormatMoney(0, false), "0.00"); - BOOST_CHECK_EQUAL(FormatMoney((COIN/10000)*123456789, false), "12345.6789"); - BOOST_CHECK_EQUAL(FormatMoney(COIN, true), "+1.00"); - BOOST_CHECK_EQUAL(FormatMoney(-COIN, false), "-1.00"); - BOOST_CHECK_EQUAL(FormatMoney(-COIN, true), "-1.00"); - - BOOST_CHECK_EQUAL(FormatMoney(COIN*100000000, false), "100000000.00"); - BOOST_CHECK_EQUAL(FormatMoney(COIN*10000000, false), "10000000.00"); - BOOST_CHECK_EQUAL(FormatMoney(COIN*1000000, false), "1000000.00"); - BOOST_CHECK_EQUAL(FormatMoney(COIN*100000, false), "100000.00"); - BOOST_CHECK_EQUAL(FormatMoney(COIN*10000, false), "10000.00"); - BOOST_CHECK_EQUAL(FormatMoney(COIN*1000, false), "1000.00"); - BOOST_CHECK_EQUAL(FormatMoney(COIN*100, false), "100.00"); - BOOST_CHECK_EQUAL(FormatMoney(COIN*10, false), "10.00"); - BOOST_CHECK_EQUAL(FormatMoney(COIN, false), "1.00"); - BOOST_CHECK_EQUAL(FormatMoney(COIN/10, false), "0.10"); - BOOST_CHECK_EQUAL(FormatMoney(COIN/100, false), "0.01"); - BOOST_CHECK_EQUAL(FormatMoney(COIN/1000, false), "0.001"); - BOOST_CHECK_EQUAL(FormatMoney(COIN/10000, false), "0.0001"); - BOOST_CHECK_EQUAL(FormatMoney(COIN/100000, false), "0.00001"); - BOOST_CHECK_EQUAL(FormatMoney(COIN/1000000, false), "0.000001"); - BOOST_CHECK_EQUAL(FormatMoney(COIN/10000000, false), "0.0000001"); - BOOST_CHECK_EQUAL(FormatMoney(COIN/100000000, false), "0.00000001"); + 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) @@ -322,9 +320,16 @@ BOOST_AUTO_TEST_CASE(test_ParseInt32) BOOST_CHECK(ParseInt32("-2147483648", &n) && n == -2147483648); 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", NULL)); BOOST_CHECK(!ParseInt32("2147483648", NULL)); @@ -332,6 +337,64 @@ BOOST_AUTO_TEST_CASE(test_ParseInt32) BOOST_CHECK(!ParseInt32("32482348723847471234", NULL)); } +BOOST_AUTO_TEST_CASE(test_ParseInt64) +{ + int64_t n; + // Valid values + BOOST_CHECK(ParseInt64("1234", NULL)); + 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", NULL)); + BOOST_CHECK(!ParseInt64("9223372036854775808", NULL)); + BOOST_CHECK(!ParseInt64("-32482348723847471234", NULL)); + BOOST_CHECK(!ParseInt64("32482348723847471234", NULL)); +} + +BOOST_AUTO_TEST_CASE(test_ParseDouble) +{ + double n; + // Valid values + BOOST_CHECK(ParseDouble("1234", NULL)); + 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", NULL)); + BOOST_CHECK(!ParseDouble("1e10000", NULL)); +} + BOOST_AUTO_TEST_CASE(test_FormatParagraph) { BOOST_CHECK_EQUAL(FormatParagraph("", 79, 0), ""); |