Branch data Line data Source code
# 1 : : // Copyright (c) 2018-2020 The Bitcoin Core developers
# 2 : : // Distributed under the MIT software license, see the accompanying
# 3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
# 4 : :
# 5 : : #include <test/data/blockfilters.json.h>
# 6 : : #include <test/util/setup_common.h>
# 7 : :
# 8 : : #include <blockfilter.h>
# 9 : : #include <core_io.h>
# 10 : : #include <serialize.h>
# 11 : : #include <streams.h>
# 12 : : #include <univalue.h>
# 13 : : #include <util/strencodings.h>
# 14 : :
# 15 : : #include <boost/test/unit_test.hpp>
# 16 : :
# 17 : : BOOST_AUTO_TEST_SUITE(blockfilter_tests)
# 18 : :
# 19 : : BOOST_AUTO_TEST_CASE(gcsfilter_test)
# 20 : 2 : {
# 21 : 2 : GCSFilter::ElementSet included_elements, excluded_elements;
# 22 [ + + ]: 202 : for (int i = 0; i < 100; ++i) {
# 23 : 200 : GCSFilter::Element element1(32);
# 24 : 200 : element1[0] = i;
# 25 : 200 : included_elements.insert(std::move(element1));
# 26 : :
# 27 : 200 : GCSFilter::Element element2(32);
# 28 : 200 : element2[1] = i;
# 29 : 200 : excluded_elements.insert(std::move(element2));
# 30 : 200 : }
# 31 : :
# 32 : 2 : GCSFilter filter({0, 0, 10, 1 << 10}, included_elements);
# 33 [ + + ]: 200 : for (const auto& element : included_elements) {
# 34 : 200 : BOOST_CHECK(filter.Match(element));
# 35 : :
# 36 : 200 : auto insertion = excluded_elements.insert(element);
# 37 : 200 : BOOST_CHECK(filter.MatchAny(excluded_elements));
# 38 : 200 : excluded_elements.erase(insertion.first);
# 39 : 200 : }
# 40 : 2 : }
# 41 : :
# 42 : : BOOST_AUTO_TEST_CASE(gcsfilter_default_constructor)
# 43 : 2 : {
# 44 : 2 : GCSFilter filter;
# 45 : 2 : BOOST_CHECK_EQUAL(filter.GetN(), 0U);
# 46 : 2 : BOOST_CHECK_EQUAL(filter.GetEncoded().size(), 1U);
# 47 : :
# 48 : 2 : const GCSFilter::Params& params = filter.GetParams();
# 49 : 2 : BOOST_CHECK_EQUAL(params.m_siphash_k0, 0U);
# 50 : 2 : BOOST_CHECK_EQUAL(params.m_siphash_k1, 0U);
# 51 : 2 : BOOST_CHECK_EQUAL(params.m_P, 0);
# 52 : 2 : BOOST_CHECK_EQUAL(params.m_M, 1U);
# 53 : 2 : }
# 54 : :
# 55 : : BOOST_AUTO_TEST_CASE(blockfilter_basic_test)
# 56 : 2 : {
# 57 : 2 : CScript included_scripts[5], excluded_scripts[4];
# 58 : :
# 59 : : // First two are outputs on a single transaction.
# 60 : 2 : included_scripts[0] << std::vector<unsigned char>(0, 65) << OP_CHECKSIG;
# 61 : 2 : included_scripts[1] << OP_DUP << OP_HASH160 << std::vector<unsigned char>(1, 20) << OP_EQUALVERIFY << OP_CHECKSIG;
# 62 : :
# 63 : : // Third is an output on in a second transaction.
# 64 : 2 : included_scripts[2] << OP_1 << std::vector<unsigned char>(2, 33) << OP_1 << OP_CHECKMULTISIG;
# 65 : :
# 66 : : // Last two are spent by a single transaction.
# 67 : 2 : included_scripts[3] << OP_0 << std::vector<unsigned char>(3, 32);
# 68 : 2 : included_scripts[4] << OP_4 << OP_ADD << OP_8 << OP_EQUAL;
# 69 : :
# 70 : : // OP_RETURN output is an output on the second transaction.
# 71 : 2 : excluded_scripts[0] << OP_RETURN << std::vector<unsigned char>(4, 40);
# 72 : :
# 73 : : // This script is not related to the block at all.
# 74 : 2 : excluded_scripts[1] << std::vector<unsigned char>(5, 33) << OP_CHECKSIG;
# 75 : :
# 76 : : // OP_RETURN is non-standard since it's not followed by a data push, but is still excluded from
# 77 : : // filter.
# 78 : 2 : excluded_scripts[2] << OP_RETURN << OP_4 << OP_ADD << OP_8 << OP_EQUAL;
# 79 : :
# 80 : 2 : CMutableTransaction tx_1;
# 81 : 2 : tx_1.vout.emplace_back(100, included_scripts[0]);
# 82 : 2 : tx_1.vout.emplace_back(200, included_scripts[1]);
# 83 : 2 : tx_1.vout.emplace_back(0, excluded_scripts[0]);
# 84 : :
# 85 : 2 : CMutableTransaction tx_2;
# 86 : 2 : tx_2.vout.emplace_back(300, included_scripts[2]);
# 87 : 2 : tx_2.vout.emplace_back(0, excluded_scripts[2]);
# 88 : 2 : tx_2.vout.emplace_back(400, excluded_scripts[3]); // Script is empty
# 89 : :
# 90 : 2 : CBlock block;
# 91 : 2 : block.vtx.push_back(MakeTransactionRef(tx_1));
# 92 : 2 : block.vtx.push_back(MakeTransactionRef(tx_2));
# 93 : :
# 94 : 2 : CBlockUndo block_undo;
# 95 : 2 : block_undo.vtxundo.emplace_back();
# 96 : 2 : block_undo.vtxundo.back().vprevout.emplace_back(CTxOut(500, included_scripts[3]), 1000, true);
# 97 : 2 : block_undo.vtxundo.back().vprevout.emplace_back(CTxOut(600, included_scripts[4]), 10000, false);
# 98 : 2 : block_undo.vtxundo.back().vprevout.emplace_back(CTxOut(700, excluded_scripts[3]), 100000, false);
# 99 : :
# 100 : 2 : BlockFilter block_filter(BlockFilterType::BASIC, block, block_undo);
# 101 : 2 : const GCSFilter& filter = block_filter.GetFilter();
# 102 : :
# 103 [ + + ]: 10 : for (const CScript& script : included_scripts) {
# 104 : 10 : BOOST_CHECK(filter.Match(GCSFilter::Element(script.begin(), script.end())));
# 105 : 10 : }
# 106 [ + + ]: 8 : for (const CScript& script : excluded_scripts) {
# 107 : 8 : BOOST_CHECK(!filter.Match(GCSFilter::Element(script.begin(), script.end())));
# 108 : 8 : }
# 109 : :
# 110 : : // Test serialization/unserialization.
# 111 : 2 : BlockFilter block_filter2;
# 112 : :
# 113 : 2 : CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
# 114 : 2 : stream << block_filter;
# 115 : 2 : stream >> block_filter2;
# 116 : :
# 117 : 2 : BOOST_CHECK_EQUAL(block_filter.GetFilterType(), block_filter2.GetFilterType());
# 118 : 2 : BOOST_CHECK_EQUAL(block_filter.GetBlockHash(), block_filter2.GetBlockHash());
# 119 : 2 : BOOST_CHECK(block_filter.GetEncodedFilter() == block_filter2.GetEncodedFilter());
# 120 : :
# 121 : 2 : BlockFilter default_ctor_block_filter_1;
# 122 : 2 : BlockFilter default_ctor_block_filter_2;
# 123 : 2 : BOOST_CHECK_EQUAL(default_ctor_block_filter_1.GetFilterType(), default_ctor_block_filter_2.GetFilterType());
# 124 : 2 : BOOST_CHECK_EQUAL(default_ctor_block_filter_1.GetBlockHash(), default_ctor_block_filter_2.GetBlockHash());
# 125 : 2 : BOOST_CHECK(default_ctor_block_filter_1.GetEncodedFilter() == default_ctor_block_filter_2.GetEncodedFilter());
# 126 : 2 : }
# 127 : :
# 128 : : BOOST_AUTO_TEST_CASE(blockfilters_json_test)
# 129 : 2 : {
# 130 : 2 : UniValue json;
# 131 : 2 : std::string json_data(json_tests::blockfilters,
# 132 : 2 : json_tests::blockfilters + sizeof(json_tests::blockfilters));
# 133 [ - + ][ - + ]: 2 : if (!json.read(json_data) || !json.isArray()) {
# 134 : 0 : BOOST_ERROR("Parse error.");
# 135 : 0 : return;
# 136 : 0 : }
# 137 : :
# 138 : 2 : const UniValue& tests = json.get_array();
# 139 [ + + ]: 24 : for (unsigned int i = 0; i < tests.size(); i++) {
# 140 : 22 : UniValue test = tests[i];
# 141 : 22 : std::string strTest = test.write();
# 142 : :
# 143 [ + + ]: 22 : if (test.size() == 1) {
# 144 : 2 : continue;
# 145 [ - + ]: 20 : } else if (test.size() < 7) {
# 146 : 0 : BOOST_ERROR("Bad test: " << strTest);
# 147 : 0 : continue;
# 148 : 0 : }
# 149 : :
# 150 : 20 : unsigned int pos = 0;
# 151 : 20 : /*int block_height =*/ test[pos++].get_int();
# 152 : 20 : uint256 block_hash;
# 153 : 20 : BOOST_CHECK(ParseHashStr(test[pos++].get_str(), block_hash));
# 154 : :
# 155 : 20 : CBlock block;
# 156 : 20 : BOOST_REQUIRE(DecodeHexBlk(block, test[pos++].get_str()));
# 157 : :
# 158 : 20 : CBlockUndo block_undo;
# 159 : 20 : block_undo.vtxundo.emplace_back();
# 160 : 20 : CTxUndo& tx_undo = block_undo.vtxundo.back();
# 161 : 20 : const UniValue& prev_scripts = test[pos++].get_array();
# 162 [ + + ]: 70 : for (unsigned int ii = 0; ii < prev_scripts.size(); ii++) {
# 163 : 50 : std::vector<unsigned char> raw_script = ParseHex(prev_scripts[ii].get_str());
# 164 : 50 : CTxOut txout(0, CScript(raw_script.begin(), raw_script.end()));
# 165 : 50 : tx_undo.vprevout.emplace_back(txout, 0, false);
# 166 : 50 : }
# 167 : :
# 168 : 20 : uint256 prev_filter_header_basic;
# 169 : 20 : BOOST_CHECK(ParseHashStr(test[pos++].get_str(), prev_filter_header_basic));
# 170 : 20 : std::vector<unsigned char> filter_basic = ParseHex(test[pos++].get_str());
# 171 : 20 : uint256 filter_header_basic;
# 172 : 20 : BOOST_CHECK(ParseHashStr(test[pos++].get_str(), filter_header_basic));
# 173 : :
# 174 : 20 : BlockFilter computed_filter_basic(BlockFilterType::BASIC, block, block_undo);
# 175 : 20 : BOOST_CHECK(computed_filter_basic.GetFilter().GetEncoded() == filter_basic);
# 176 : :
# 177 : 20 : uint256 computed_header_basic = computed_filter_basic.ComputeHeader(prev_filter_header_basic);
# 178 : 20 : BOOST_CHECK(computed_header_basic == filter_header_basic);
# 179 : 20 : }
# 180 : 2 : }
# 181 : :
# 182 : : BOOST_AUTO_TEST_CASE(blockfilter_type_names)
# 183 : 2 : {
# 184 : 2 : BOOST_CHECK_EQUAL(BlockFilterTypeName(BlockFilterType::BASIC), "basic");
# 185 : 2 : BOOST_CHECK_EQUAL(BlockFilterTypeName(static_cast<BlockFilterType>(255)), "");
# 186 : :
# 187 : 2 : BlockFilterType filter_type;
# 188 : 2 : BOOST_CHECK(BlockFilterTypeByName("basic", filter_type));
# 189 : 2 : BOOST_CHECK_EQUAL(filter_type, BlockFilterType::BASIC);
# 190 : :
# 191 : 2 : BOOST_CHECK(!BlockFilterTypeByName("unknown", filter_type));
# 192 : 2 : }
# 193 : :
# 194 : : BOOST_AUTO_TEST_SUITE_END()
|