diff options
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/denialofservice_tests.cpp | 10 | ||||
-rw-r--r-- | src/test/fuzz/addrman.cpp | 119 | ||||
-rw-r--r-- | src/test/fuzz/coins_view.cpp | 3 | ||||
-rw-r--r-- | src/test/fuzz/connman.cpp | 162 | ||||
-rw-r--r-- | src/test/fuzz/decode_tx.cpp | 7 | ||||
-rw-r--r-- | src/test/fuzz/descriptor_parse.cpp | 3 | ||||
-rw-r--r-- | src/test/fuzz/deserialize.cpp | 57 | ||||
-rw-r--r-- | src/test/fuzz/merkleblock.cpp | 34 | ||||
-rw-r--r-- | src/test/fuzz/net.cpp | 2 | ||||
-rw-r--r-- | src/test/fuzz/process_message.cpp | 7 | ||||
-rw-r--r-- | src/test/fuzz/process_messages.cpp | 6 | ||||
-rw-r--r-- | src/test/fuzz/script_flags.cpp | 8 | ||||
-rw-r--r-- | src/test/fuzz/transaction.cpp | 3 | ||||
-rw-r--r-- | src/test/fuzz/util.h | 41 | ||||
-rw-r--r-- | src/test/script_p2sh_tests.cpp | 6 | ||||
-rw-r--r-- | src/test/script_tests.cpp | 21 | ||||
-rw-r--r-- | src/test/transaction_tests.cpp | 2 | ||||
-rw-r--r-- | src/test/util/setup_common.h | 9 | ||||
-rw-r--r-- | src/test/util/validation.cpp | 22 | ||||
-rw-r--r-- | src/test/util/validation.h | 17 | ||||
-rw-r--r-- | src/test/util_tests.cpp | 22 |
21 files changed, 509 insertions, 52 deletions
diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp index 6743dc0070..c399da900f 100644 --- a/src/test/denialofservice_tests.cpp +++ b/src/test/denialofservice_tests.cpp @@ -129,7 +129,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction) SetMockTime(0); bool dummy; - peerLogic->FinalizeNode(dummyNode1.GetId(), dummy); + peerLogic->FinalizeNode(dummyNode1, dummy); } static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerManager &peerLogic, CConnmanTest* connman) @@ -211,7 +211,7 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management) bool dummy; for (const CNode *node : vNodes) { - peerLogic->FinalizeNode(node->GetId(), dummy); + peerLogic->FinalizeNode(*node, dummy); } connman->ClearNodes(); @@ -259,8 +259,8 @@ BOOST_AUTO_TEST_CASE(peer_discouragement) BOOST_CHECK(banman->IsDiscouraged(addr2)); // to be discouraged now bool dummy; - peerLogic->FinalizeNode(dummyNode1.GetId(), dummy); - peerLogic->FinalizeNode(dummyNode2.GetId(), dummy); + peerLogic->FinalizeNode(dummyNode1, dummy); + peerLogic->FinalizeNode(dummyNode2, dummy); } BOOST_AUTO_TEST_CASE(DoS_bantime) @@ -288,7 +288,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) BOOST_CHECK(banman->IsDiscouraged(addr)); bool dummy; - peerLogic->FinalizeNode(dummyNode.GetId(), dummy); + peerLogic->FinalizeNode(dummyNode, dummy); } static CTransactionRef RandomOrphan() diff --git a/src/test/fuzz/addrman.cpp b/src/test/fuzz/addrman.cpp new file mode 100644 index 0000000000..0ceeea2d36 --- /dev/null +++ b/src/test/fuzz/addrman.cpp @@ -0,0 +1,119 @@ +// Copyright (c) 2020 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 <addrdb.h> +#include <addrman.h> +#include <chainparams.h> +#include <merkleblock.h> +#include <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <test/fuzz/util.h> +#include <time.h> +#include <util/asmap.h> + +#include <cstdint> +#include <optional> +#include <string> +#include <vector> + +void initialize() +{ + SelectParams(CBaseChainParams::REGTEST); +} + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); + + SetMockTime(ConsumeTime(fuzzed_data_provider)); + CAddrMan addr_man; + if (fuzzed_data_provider.ConsumeBool()) { + addr_man.m_asmap = ConsumeRandomLengthBitVector(fuzzed_data_provider); + if (!SanityCheckASMap(addr_man.m_asmap)) { + addr_man.m_asmap.clear(); + } + } + while (fuzzed_data_provider.ConsumeBool()) { + switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 11)) { + case 0: { + addr_man.Clear(); + break; + } + case 1: { + addr_man.ResolveCollisions(); + break; + } + case 2: { + (void)addr_man.SelectTriedCollision(); + break; + } + case 3: { + (void)addr_man.Select(fuzzed_data_provider.ConsumeBool()); + break; + } + case 4: { + (void)addr_man.GetAddr(fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096), fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096)); + break; + } + case 5: { + const std::optional<CAddress> opt_address = ConsumeDeserializable<CAddress>(fuzzed_data_provider); + const std::optional<CNetAddr> opt_net_addr = ConsumeDeserializable<CNetAddr>(fuzzed_data_provider); + if (opt_address && opt_net_addr) { + addr_man.Add(*opt_address, *opt_net_addr, fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(0, 100000000)); + } + break; + } + case 6: { + std::vector<CAddress> addresses; + while (fuzzed_data_provider.ConsumeBool()) { + const std::optional<CAddress> opt_address = ConsumeDeserializable<CAddress>(fuzzed_data_provider); + if (!opt_address) { + break; + } + addresses.push_back(*opt_address); + } + const std::optional<CNetAddr> opt_net_addr = ConsumeDeserializable<CNetAddr>(fuzzed_data_provider); + if (opt_net_addr) { + addr_man.Add(addresses, *opt_net_addr, fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(0, 100000000)); + } + break; + } + case 7: { + const std::optional<CService> opt_service = ConsumeDeserializable<CService>(fuzzed_data_provider); + if (opt_service) { + addr_man.Good(*opt_service, fuzzed_data_provider.ConsumeBool(), ConsumeTime(fuzzed_data_provider)); + } + break; + } + case 8: { + const std::optional<CService> opt_service = ConsumeDeserializable<CService>(fuzzed_data_provider); + if (opt_service) { + addr_man.Attempt(*opt_service, fuzzed_data_provider.ConsumeBool(), ConsumeTime(fuzzed_data_provider)); + } + break; + } + case 9: { + const std::optional<CService> opt_service = ConsumeDeserializable<CService>(fuzzed_data_provider); + if (opt_service) { + addr_man.Connected(*opt_service, ConsumeTime(fuzzed_data_provider)); + } + break; + } + case 10: { + const std::optional<CService> opt_service = ConsumeDeserializable<CService>(fuzzed_data_provider); + if (opt_service) { + addr_man.SetServices(*opt_service, ServiceFlags{fuzzed_data_provider.ConsumeIntegral<uint64_t>()}); + } + break; + } + case 11: { + (void)addr_man.Check(); + break; + } + } + } + (void)addr_man.size(); + CDataStream data_stream(SER_NETWORK, PROTOCOL_VERSION); + data_stream << addr_man; +} diff --git a/src/test/fuzz/coins_view.cpp b/src/test/fuzz/coins_view.cpp index c186bef7ae..ac034809b0 100644 --- a/src/test/fuzz/coins_view.cpp +++ b/src/test/fuzz/coins_view.cpp @@ -229,7 +229,8 @@ void test_one_input(const std::vector<uint8_t>& buffer) break; } case 1: { - (void)AreInputsStandard(CTransaction{random_mutable_transaction}, coins_view_cache); + (void)AreInputsStandard(CTransaction{random_mutable_transaction}, coins_view_cache, false); + (void)AreInputsStandard(CTransaction{random_mutable_transaction}, coins_view_cache, true); break; } case 2: { diff --git a/src/test/fuzz/connman.cpp b/src/test/fuzz/connman.cpp new file mode 100644 index 0000000000..6521c3f3b2 --- /dev/null +++ b/src/test/fuzz/connman.cpp @@ -0,0 +1,162 @@ +// Copyright (c) 2020 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <chainparams.h> +#include <chainparamsbase.h> +#include <net.h> +#include <netaddress.h> +#include <protocol.h> +#include <test/fuzz/FuzzedDataProvider.h> +#include <test/fuzz/fuzz.h> +#include <test/fuzz/util.h> +#include <util/translation.h> + +#include <cstdint> +#include <vector> + +void initialize() +{ + InitializeFuzzingContext(); +} + +void test_one_input(const std::vector<uint8_t>& buffer) +{ + FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; + CConnman connman{fuzzed_data_provider.ConsumeIntegral<uint64_t>(), fuzzed_data_provider.ConsumeIntegral<uint64_t>(), fuzzed_data_provider.ConsumeBool()}; + CAddress random_address; + CNetAddr random_netaddr; + CNode random_node = ConsumeNode(fuzzed_data_provider); + CService random_service; + CSubNet random_subnet; + std::string random_string; + while (fuzzed_data_provider.ConsumeBool()) { + switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 30)) { + case 0: + random_address = ConsumeAddress(fuzzed_data_provider); + break; + case 1: + random_netaddr = ConsumeNetAddr(fuzzed_data_provider); + break; + case 2: + random_service = ConsumeService(fuzzed_data_provider); + break; + case 3: + random_subnet = ConsumeSubNet(fuzzed_data_provider); + break; + case 4: + random_string = fuzzed_data_provider.ConsumeRandomLengthString(64); + break; + case 5: { + std::vector<CAddress> addresses; + while (fuzzed_data_provider.ConsumeBool()) { + addresses.push_back(ConsumeAddress(fuzzed_data_provider)); + } + // Limit nTimePenalty to int32_t to avoid signed integer overflow + (void)connman.AddNewAddresses(addresses, ConsumeAddress(fuzzed_data_provider), fuzzed_data_provider.ConsumeIntegral<int32_t>()); + break; + } + case 6: + connman.AddNode(random_string); + break; + case 7: + connman.CheckIncomingNonce(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); + break; + case 8: + connman.DisconnectNode(fuzzed_data_provider.ConsumeIntegral<NodeId>()); + break; + case 9: + connman.DisconnectNode(random_netaddr); + break; + case 10: + connman.DisconnectNode(random_string); + break; + case 11: + connman.DisconnectNode(random_subnet); + break; + case 12: + connman.ForEachNode([](auto) {}); + break; + case 13: + connman.ForEachNodeThen([](auto) {}, []() {}); + break; + case 14: + (void)connman.ForNode(fuzzed_data_provider.ConsumeIntegral<NodeId>(), [&](auto) { return fuzzed_data_provider.ConsumeBool(); }); + break; + case 15: + (void)connman.GetAddresses(fuzzed_data_provider.ConsumeIntegral<size_t>(), fuzzed_data_provider.ConsumeIntegral<size_t>()); + break; + case 16: { + (void)connman.GetAddresses(random_node, fuzzed_data_provider.ConsumeIntegral<size_t>(), fuzzed_data_provider.ConsumeIntegral<size_t>()); + break; + } + case 17: + (void)connman.GetDeterministicRandomizer(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); + break; + case 18: + (void)connman.GetNodeCount(fuzzed_data_provider.PickValueInArray({CConnman::CONNECTIONS_NONE, CConnman::CONNECTIONS_IN, CConnman::CONNECTIONS_OUT, CConnman::CONNECTIONS_ALL})); + break; + case 19: + connman.MarkAddressGood(random_address); + break; + case 20: + (void)connman.OutboundTargetReached(fuzzed_data_provider.ConsumeBool()); + break; + case 21: + // Limit now to int32_t to avoid signed integer overflow + (void)connman.PoissonNextSendInbound(fuzzed_data_provider.ConsumeIntegral<int32_t>(), fuzzed_data_provider.ConsumeIntegral<int>()); + break; + case 22: { + CSerializedNetMsg serialized_net_msg; + serialized_net_msg.m_type = fuzzed_data_provider.ConsumeRandomLengthString(CMessageHeader::COMMAND_SIZE); + serialized_net_msg.data = ConsumeRandomLengthByteVector(fuzzed_data_provider); + connman.PushMessage(&random_node, std::move(serialized_net_msg)); + break; + } + case 23: + connman.RemoveAddedNode(random_string); + break; + case 24: { + const std::vector<bool> asmap = ConsumeRandomLengthBitVector(fuzzed_data_provider); + if (SanityCheckASMap(asmap)) { + connman.SetAsmap(asmap); + } + break; + } + case 25: + connman.SetBestHeight(fuzzed_data_provider.ConsumeIntegral<int>()); + break; + case 26: + connman.SetMaxOutboundTarget(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); + break; + case 27: + connman.SetMaxOutboundTimeframe(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); + break; + case 28: + connman.SetNetworkActive(fuzzed_data_provider.ConsumeBool()); + break; + case 29: + connman.SetServices(random_service, static_cast<ServiceFlags>(fuzzed_data_provider.ConsumeIntegral<uint64_t>())); + break; + case 30: + connman.SetTryNewOutboundPeer(fuzzed_data_provider.ConsumeBool()); + break; + } + } + (void)connman.GetAddedNodeInfo(); + (void)connman.GetBestHeight(); + (void)connman.GetExtraOutboundCount(); + (void)connman.GetLocalServices(); + (void)connman.GetMaxOutboundTarget(); + (void)connman.GetMaxOutboundTimeframe(); + (void)connman.GetMaxOutboundTimeLeftInCycle(); + (void)connman.GetNetworkActive(); + std::vector<CNodeStats> stats; + connman.GetNodeStats(stats); + (void)connman.GetOutboundTargetBytesLeft(); + (void)connman.GetReceiveFloodSize(); + (void)connman.GetTotalBytesRecv(); + (void)connman.GetTotalBytesSent(); + (void)connman.GetTryNewOutboundPeer(); + (void)connman.GetUseAddrmanOutgoing(); +} diff --git a/src/test/fuzz/decode_tx.cpp b/src/test/fuzz/decode_tx.cpp index 0d89d4228a..a2b18c0365 100644 --- a/src/test/fuzz/decode_tx.cpp +++ b/src/test/fuzz/decode_tx.cpp @@ -19,13 +19,14 @@ void test_one_input(const std::vector<uint8_t>& buffer) const bool result_none = DecodeHexTx(mtx, tx_hex, false, false); const bool result_try_witness = DecodeHexTx(mtx, tx_hex, false, true); const bool result_try_witness_and_maybe_no_witness = DecodeHexTx(mtx, tx_hex, true, true); - const bool result_try_no_witness = DecodeHexTx(mtx, tx_hex, true, false); + CMutableTransaction no_witness_mtx; + const bool result_try_no_witness = DecodeHexTx(no_witness_mtx, tx_hex, true, false); assert(!result_none); if (result_try_witness_and_maybe_no_witness) { assert(result_try_no_witness || result_try_witness); } - // if (result_try_no_witness) { // Uncomment when https://github.com/bitcoin/bitcoin/pull/17775 is merged - if (result_try_witness) { // Remove stop-gap when https://github.com/bitcoin/bitcoin/pull/17775 is merged + if (result_try_no_witness) { + assert(!no_witness_mtx.HasWitness()); assert(result_try_witness_and_maybe_no_witness); } } diff --git a/src/test/fuzz/descriptor_parse.cpp b/src/test/fuzz/descriptor_parse.cpp index 001758ffdb..7b57a2c1e2 100644 --- a/src/test/fuzz/descriptor_parse.cpp +++ b/src/test/fuzz/descriptor_parse.cpp @@ -11,7 +11,8 @@ void initialize() { static const ECCVerifyHandle verify_handle; - SelectParams(CBaseChainParams::REGTEST); + ECC_Start(); + SelectParams(CBaseChainParams::MAIN); } void test_one_input(const std::vector<uint8_t>& buffer) diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp index b799d3b43b..8ca5366c8a 100644 --- a/src/test/fuzz/deserialize.cpp +++ b/src/test/fuzz/deserialize.cpp @@ -13,7 +13,9 @@ #include <key.h> #include <merkleblock.h> #include <net.h> +#include <netbase.h> #include <node/utxo_snapshot.h> +#include <optional.h> #include <primitives/block.h> #include <protocol.h> #include <psbt.h> @@ -44,9 +46,9 @@ struct invalid_fuzzing_input_exception : public std::exception { }; template <typename T> -CDataStream Serialize(const T& obj) +CDataStream Serialize(const T& obj, const int version = INIT_PROTO_VERSION) { - CDataStream ds(SER_NETWORK, INIT_PROTO_VERSION); + CDataStream ds(SER_NETWORK, version); ds << obj; return ds; } @@ -60,15 +62,19 @@ T Deserialize(CDataStream ds) } template <typename T> -void DeserializeFromFuzzingInput(const std::vector<uint8_t>& buffer, T& obj) +void DeserializeFromFuzzingInput(const std::vector<uint8_t>& buffer, T& obj, const Optional<int> protocol_version = nullopt) { CDataStream ds(buffer, SER_NETWORK, INIT_PROTO_VERSION); - try { - int version; - ds >> version; - ds.SetVersion(version); - } catch (const std::ios_base::failure&) { - throw invalid_fuzzing_input_exception(); + if (protocol_version) { + ds.SetVersion(*protocol_version); + } else { + try { + int version; + ds >> version; + ds.SetVersion(version); + } catch (const std::ios_base::failure&) { + throw invalid_fuzzing_input_exception(); + } } try { ds >> obj; @@ -79,9 +85,9 @@ void DeserializeFromFuzzingInput(const std::vector<uint8_t>& buffer, T& obj) } template <typename T> -void AssertEqualAfterSerializeDeserialize(const T& obj) +void AssertEqualAfterSerializeDeserialize(const T& obj, const int version = INIT_PROTO_VERSION) { - assert(Deserialize<T>(Serialize(obj)) == obj); + assert(Deserialize<T>(Serialize(obj, version)) == obj); } } // namespace @@ -124,9 +130,15 @@ void test_one_input(const std::vector<uint8_t>& buffer) CScript script; DeserializeFromFuzzingInput(buffer, script); #elif SUB_NET_DESERIALIZE - CSubNet sub_net; - DeserializeFromFuzzingInput(buffer, sub_net); - AssertEqualAfterSerializeDeserialize(sub_net); + CSubNet sub_net_1; + DeserializeFromFuzzingInput(buffer, sub_net_1, INIT_PROTO_VERSION); + AssertEqualAfterSerializeDeserialize(sub_net_1, INIT_PROTO_VERSION); + CSubNet sub_net_2; + DeserializeFromFuzzingInput(buffer, sub_net_2, INIT_PROTO_VERSION | ADDRV2_FORMAT); + AssertEqualAfterSerializeDeserialize(sub_net_2, INIT_PROTO_VERSION | ADDRV2_FORMAT); + CSubNet sub_net_3; + DeserializeFromFuzzingInput(buffer, sub_net_3); + AssertEqualAfterSerializeDeserialize(sub_net_3, INIT_PROTO_VERSION | ADDRV2_FORMAT); #elif TX_IN_DESERIALIZE CTxIn tx_in; DeserializeFromFuzzingInput(buffer, tx_in); @@ -183,11 +195,24 @@ void test_one_input(const std::vector<uint8_t>& buffer) #elif NETADDR_DESERIALIZE CNetAddr na; DeserializeFromFuzzingInput(buffer, na); - AssertEqualAfterSerializeDeserialize(na); + if (na.IsAddrV1Compatible()) { + AssertEqualAfterSerializeDeserialize(na); + } + AssertEqualAfterSerializeDeserialize(na, INIT_PROTO_VERSION | ADDRV2_FORMAT); #elif SERVICE_DESERIALIZE CService s; DeserializeFromFuzzingInput(buffer, s); - AssertEqualAfterSerializeDeserialize(s); + if (s.IsAddrV1Compatible()) { + AssertEqualAfterSerializeDeserialize(s); + } + AssertEqualAfterSerializeDeserialize(s, INIT_PROTO_VERSION | ADDRV2_FORMAT); + CService s1; + DeserializeFromFuzzingInput(buffer, s1, INIT_PROTO_VERSION); + AssertEqualAfterSerializeDeserialize(s1, INIT_PROTO_VERSION); + assert(s1.IsAddrV1Compatible()); + CService s2; + DeserializeFromFuzzingInput(buffer, s2, INIT_PROTO_VERSION | ADDRV2_FORMAT); + AssertEqualAfterSerializeDeserialize(s2, INIT_PROTO_VERSION | ADDRV2_FORMAT); #elif MESSAGEHEADER_DESERIALIZE CMessageHeader mh; DeserializeFromFuzzingInput(buffer, mh); diff --git a/src/test/fuzz/merkleblock.cpp b/src/test/fuzz/merkleblock.cpp index c44e334272..4710e75757 100644 --- a/src/test/fuzz/merkleblock.cpp +++ b/src/test/fuzz/merkleblock.cpp @@ -16,12 +16,36 @@ void test_one_input(const std::vector<uint8_t>& buffer) { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); - std::optional<CPartialMerkleTree> partial_merkle_tree = ConsumeDeserializable<CPartialMerkleTree>(fuzzed_data_provider); - if (!partial_merkle_tree) { - return; + CPartialMerkleTree partial_merkle_tree; + switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 1)) { + case 0: { + const std::optional<CPartialMerkleTree> opt_partial_merkle_tree = ConsumeDeserializable<CPartialMerkleTree>(fuzzed_data_provider); + if (opt_partial_merkle_tree) { + partial_merkle_tree = *opt_partial_merkle_tree; + } + break; } - (void)partial_merkle_tree->GetNumTransactions(); + case 1: { + CMerkleBlock merkle_block; + const std::optional<CBlock> opt_block = ConsumeDeserializable<CBlock>(fuzzed_data_provider); + CBloomFilter bloom_filter; + std::set<uint256> txids; + if (opt_block && !opt_block->vtx.empty()) { + if (fuzzed_data_provider.ConsumeBool()) { + merkle_block = CMerkleBlock{*opt_block, bloom_filter}; + } else if (fuzzed_data_provider.ConsumeBool()) { + while (fuzzed_data_provider.ConsumeBool()) { + txids.insert(ConsumeUInt256(fuzzed_data_provider)); + } + merkle_block = CMerkleBlock{*opt_block, txids}; + } + } + partial_merkle_tree = merkle_block.txn; + break; + } + } + (void)partial_merkle_tree.GetNumTransactions(); std::vector<uint256> matches; std::vector<unsigned int> indices; - (void)partial_merkle_tree->ExtractMatches(matches, indices); + (void)partial_merkle_tree.ExtractMatches(matches, indices); } diff --git a/src/test/fuzz/net.cpp b/src/test/fuzz/net.cpp index 3818838765..c61d406291 100644 --- a/src/test/fuzz/net.cpp +++ b/src/test/fuzz/net.cpp @@ -63,7 +63,7 @@ void test_one_input(const std::vector<uint8_t>& buffer) break; } case 3: { - const std::vector<bool> asmap = ConsumeRandomLengthIntegralVector<bool>(fuzzed_data_provider, 128); + const std::vector<bool> asmap = ConsumeRandomLengthBitVector(fuzzed_data_provider); if (!SanityCheckASMap(asmap)) { break; } diff --git a/src/test/fuzz/process_message.cpp b/src/test/fuzz/process_message.cpp index 3ef03137ec..9390399878 100644 --- a/src/test/fuzz/process_message.cpp +++ b/src/test/fuzz/process_message.cpp @@ -16,6 +16,7 @@ #include <test/util/mining.h> #include <test/util/net.h> #include <test/util/setup_common.h> +#include <test/util/validation.h> #include <util/memory.h> #include <validationinterface.h> #include <version.h> @@ -63,10 +64,14 @@ void test_one_input(const std::vector<uint8_t>& buffer) { FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); ConnmanTestMsg& connman = *(ConnmanTestMsg*)g_setup->m_node.connman.get(); + TestChainState& chainstate = *(TestChainState*)&g_setup->m_node.chainman->ActiveChainstate(); + chainstate.ResetIbd(); const std::string random_message_type{fuzzed_data_provider.ConsumeBytesAsString(CMessageHeader::COMMAND_SIZE).c_str()}; if (!LIMIT_TO_MESSAGE_TYPE.empty() && random_message_type != LIMIT_TO_MESSAGE_TYPE) { return; } + const bool jump_out_of_ibd{fuzzed_data_provider.ConsumeBool()}; + if (jump_out_of_ibd) chainstate.JumpOutOfIbd(); CDataStream random_bytes_data_stream{fuzzed_data_provider.ConsumeRemainingBytes<unsigned char>(), SER_NETWORK, PROTOCOL_VERSION}; CNode& p2p_node = *MakeUnique<CNode>(0, ServiceFlags(NODE_NETWORK | NODE_WITNESS | NODE_BLOOM), 0, INVALID_SOCKET, CAddress{CService{in_addr{0x0100007f}, 7777}, NODE_NETWORK}, 0, 0, CAddress{}, std::string{}, ConnectionType::OUTBOUND_FULL_RELAY).release(); p2p_node.fSuccessfullyConnected = true; @@ -76,7 +81,7 @@ void test_one_input(const std::vector<uint8_t>& buffer) g_setup->m_node.peerman->InitializeNode(&p2p_node); try { g_setup->m_node.peerman->ProcessMessage(p2p_node, random_message_type, random_bytes_data_stream, - GetTime<std::chrono::microseconds>(), std::atomic<bool>{false}); + GetTime<std::chrono::microseconds>(), std::atomic<bool>{false}); } catch (const std::ios_base::failure&) { } SyncWithValidationInterfaceQueue(); diff --git a/src/test/fuzz/process_messages.cpp b/src/test/fuzz/process_messages.cpp index f722eeac3a..19ea92b750 100644 --- a/src/test/fuzz/process_messages.cpp +++ b/src/test/fuzz/process_messages.cpp @@ -12,6 +12,7 @@ #include <test/util/mining.h> #include <test/util/net.h> #include <test/util/setup_common.h> +#include <test/util/validation.h> #include <util/memory.h> #include <validation.h> #include <validationinterface.h> @@ -39,7 +40,10 @@ void test_one_input(const std::vector<uint8_t>& buffer) FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size()); ConnmanTestMsg& connman = *(ConnmanTestMsg*)g_setup->m_node.connman.get(); + TestChainState& chainstate = *(TestChainState*)&g_setup->m_node.chainman->ActiveChainstate(); + chainstate.ResetIbd(); std::vector<CNode*> peers; + bool jump_out_of_ibd{false}; const auto num_peers_to_add = fuzzed_data_provider.ConsumeIntegralInRange(1, 3); for (int i = 0; i < num_peers_to_add; ++i) { @@ -58,6 +62,8 @@ void test_one_input(const std::vector<uint8_t>& buffer) } while (fuzzed_data_provider.ConsumeBool()) { + if (!jump_out_of_ibd) jump_out_of_ibd = fuzzed_data_provider.ConsumeBool(); + if (jump_out_of_ibd && chainstate.IsInitialBlockDownload()) chainstate.JumpOutOfIbd(); const std::string random_message_type{fuzzed_data_provider.ConsumeBytesAsString(CMessageHeader::COMMAND_SIZE).c_str()}; CSerializedNetMsg net_msg; diff --git a/src/test/fuzz/script_flags.cpp b/src/test/fuzz/script_flags.cpp index ffc65eedc0..300c78fca0 100644 --- a/src/test/fuzz/script_flags.cpp +++ b/src/test/fuzz/script_flags.cpp @@ -31,7 +31,6 @@ void test_one_input(const std::vector<uint8_t>& buffer) try { const CTransaction tx(deserialize, ds); - const PrecomputedTransactionData txdata(tx); unsigned int verify_flags; ds >> verify_flags; @@ -41,10 +40,17 @@ void test_one_input(const std::vector<uint8_t>& buffer) unsigned int fuzzed_flags; ds >> fuzzed_flags; + std::vector<CTxOut> spent_outputs; for (unsigned i = 0; i < tx.vin.size(); ++i) { CTxOut prevout; ds >> prevout; + spent_outputs.push_back(prevout); + } + PrecomputedTransactionData txdata; + txdata.Init(tx, std::move(spent_outputs)); + for (unsigned i = 0; i < tx.vin.size(); ++i) { + const CTxOut& prevout = txdata.m_spent_outputs.at(i); const TransactionSignatureChecker checker{&tx, i, prevout.nValue, txdata}; ScriptError serror; diff --git a/src/test/fuzz/transaction.cpp b/src/test/fuzz/transaction.cpp index d6deb7fc3d..4f972dea1c 100644 --- a/src/test/fuzz/transaction.cpp +++ b/src/test/fuzz/transaction.cpp @@ -95,7 +95,8 @@ void test_one_input(const std::vector<uint8_t>& buffer) CCoinsView coins_view; const CCoinsViewCache coins_view_cache(&coins_view); - (void)AreInputsStandard(tx, coins_view_cache); + (void)AreInputsStandard(tx, coins_view_cache, false); + (void)AreInputsStandard(tx, coins_view_cache, true); (void)IsWitnessStandard(tx, coins_view_cache); UniValue u(UniValue::VOBJ); diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h index ed6093a8a8..e99ed8d72d 100644 --- a/src/test/fuzz/util.h +++ b/src/test/fuzz/util.h @@ -11,6 +11,8 @@ #include <chainparamsbase.h> #include <coins.h> #include <consensus/consensus.h> +#include <merkleblock.h> +#include <net.h> #include <netaddress.h> #include <netbase.h> #include <primitives/transaction.h> @@ -23,6 +25,7 @@ #include <test/util/setup_common.h> #include <txmempool.h> #include <uint256.h> +#include <util/time.h> #include <version.h> #include <algorithm> @@ -38,6 +41,11 @@ NODISCARD inline std::vector<uint8_t> ConsumeRandomLengthByteVector(FuzzedDataPr return {s.begin(), s.end()}; } +NODISCARD inline std::vector<bool> ConsumeRandomLengthBitVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept +{ + return BytesToBits(ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length)); +} + NODISCARD inline CDataStream ConsumeDataStream(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept { return {ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length), SER_NETWORK, INIT_PROTO_VERSION}; @@ -88,6 +96,13 @@ NODISCARD inline CAmount ConsumeMoney(FuzzedDataProvider& fuzzed_data_provider) return fuzzed_data_provider.ConsumeIntegralInRange<CAmount>(0, MAX_MONEY); } +NODISCARD inline int64_t ConsumeTime(FuzzedDataProvider& fuzzed_data_provider) noexcept +{ + static const int64_t time_min = ParseISO8601DateTime("1970-01-01T00:00:00Z"); + static const int64_t time_max = ParseISO8601DateTime("9999-12-31T23:59:59Z"); + return fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(time_min, time_max); +} + NODISCARD inline CScript ConsumeScript(FuzzedDataProvider& fuzzed_data_provider) noexcept { const std::vector<uint8_t> b = ConsumeRandomLengthByteVector(fuzzed_data_provider); @@ -260,6 +275,32 @@ CSubNet ConsumeSubNet(FuzzedDataProvider& fuzzed_data_provider) noexcept return {ConsumeNetAddr(fuzzed_data_provider), fuzzed_data_provider.ConsumeIntegral<uint8_t>()}; } +CService ConsumeService(FuzzedDataProvider& fuzzed_data_provider) noexcept +{ + return {ConsumeNetAddr(fuzzed_data_provider), fuzzed_data_provider.ConsumeIntegral<uint16_t>()}; +} + +CAddress ConsumeAddress(FuzzedDataProvider& fuzzed_data_provider) noexcept +{ + return {ConsumeService(fuzzed_data_provider), static_cast<ServiceFlags>(fuzzed_data_provider.ConsumeIntegral<uint64_t>()), fuzzed_data_provider.ConsumeIntegral<uint32_t>()}; +} + +CNode ConsumeNode(FuzzedDataProvider& fuzzed_data_provider) noexcept +{ + const NodeId node_id = fuzzed_data_provider.ConsumeIntegral<NodeId>(); + const ServiceFlags local_services = static_cast<ServiceFlags>(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); + const int my_starting_height = fuzzed_data_provider.ConsumeIntegral<int>(); + const SOCKET socket = INVALID_SOCKET; + const CAddress address = ConsumeAddress(fuzzed_data_provider); + const uint64_t keyed_net_group = fuzzed_data_provider.ConsumeIntegral<uint64_t>(); + const uint64_t local_host_nonce = fuzzed_data_provider.ConsumeIntegral<uint64_t>(); + const CAddress addr_bind = ConsumeAddress(fuzzed_data_provider); + const std::string addr_name = fuzzed_data_provider.ConsumeRandomLengthString(64); + const ConnectionType conn_type = fuzzed_data_provider.PickValueInArray({ConnectionType::INBOUND, ConnectionType::OUTBOUND_FULL_RELAY, ConnectionType::MANUAL, ConnectionType::FEELER, ConnectionType::BLOCK_RELAY, ConnectionType::ADDR_FETCH}); + const bool inbound_onion = fuzzed_data_provider.ConsumeBool(); + return {node_id, local_services, my_starting_height, socket, address, keyed_net_group, local_host_nonce, addr_bind, addr_name, conn_type, inbound_onion}; +} + void InitializeFuzzingContext(const std::string& chain_name = CBaseChainParams::REGTEST) { static const BasicTestingSetup basic_testing_setup{chain_name, {"-nodebuglogfile"}}; diff --git a/src/test/script_p2sh_tests.cpp b/src/test/script_p2sh_tests.cpp index f6824a4e5e..856ec6346d 100644 --- a/src/test/script_p2sh_tests.cpp +++ b/src/test/script_p2sh_tests.cpp @@ -343,7 +343,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard) txTo.vin[3].scriptSig << OP_11 << OP_11 << std::vector<unsigned char>(oneAndTwo.begin(), oneAndTwo.end()); txTo.vin[4].scriptSig << std::vector<unsigned char>(fifteenSigops.begin(), fifteenSigops.end()); - BOOST_CHECK(::AreInputsStandard(CTransaction(txTo), coins)); + BOOST_CHECK(::AreInputsStandard(CTransaction(txTo), coins, false)); // 22 P2SH sigops for all inputs (1 for vin[0], 6 for vin[3], 15 for vin[4] BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txTo), coins), 22U); @@ -356,7 +356,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard) txToNonStd1.vin[0].prevout.hash = txFrom.GetHash(); txToNonStd1.vin[0].scriptSig << std::vector<unsigned char>(sixteenSigops.begin(), sixteenSigops.end()); - BOOST_CHECK(!::AreInputsStandard(CTransaction(txToNonStd1), coins)); + BOOST_CHECK(!::AreInputsStandard(CTransaction(txToNonStd1), coins, false)); BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txToNonStd1), coins), 16U); CMutableTransaction txToNonStd2; @@ -368,7 +368,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard) txToNonStd2.vin[0].prevout.hash = txFrom.GetHash(); txToNonStd2.vin[0].scriptSig << std::vector<unsigned char>(twentySigops.begin(), twentySigops.end()); - BOOST_CHECK(!::AreInputsStandard(CTransaction(txToNonStd2), coins)); + BOOST_CHECK(!::AreInputsStandard(CTransaction(txToNonStd2), coins, false)); BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txToNonStd2), coins), 20U); } diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 7c53bd0002..25ca171b33 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -106,18 +106,18 @@ static ScriptErrorDesc script_errors[]={ static std::string FormatScriptError(ScriptError_t err) { - for (unsigned int i=0; i<ARRAYLEN(script_errors); ++i) - if (script_errors[i].err == err) - return script_errors[i].name; + for (const auto& se : script_errors) + if (se.err == err) + return se.name; BOOST_ERROR("Unknown scripterror enumeration value, update script_errors in script_tests.cpp."); return ""; } -static ScriptError_t ParseScriptError(const std::string &name) +static ScriptError_t ParseScriptError(const std::string& name) { - for (unsigned int i=0; i<ARRAYLEN(script_errors); ++i) - if (script_errors[i].name == name) - return script_errors[i].err; + for (const auto& se : script_errors) + if (se.name == name) + return se.err; BOOST_ERROR("Unknown scripterror \"" << name << "\" in test description"); return SCRIPT_ERR_UNKNOWN_ERROR; } @@ -1470,8 +1470,6 @@ BOOST_AUTO_TEST_CASE(script_HasValidOps) BOOST_CHECK(!script.HasValidOps()); } -#if defined(HAVE_CONSENSUS_LIB) - static CMutableTransaction TxFromHex(const std::string& str) { CMutableTransaction tx; @@ -1502,6 +1500,8 @@ static CScriptWitness ScriptWitnessFromJSON(const UniValue& univalue) return scriptwitness; } +#if defined(HAVE_CONSENSUS_LIB) + /* Test simple (successful) usage of bitcoinconsensus_verify_script */ BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_returns_true) { @@ -1640,6 +1640,8 @@ BOOST_AUTO_TEST_CASE(bitcoinconsensus_verify_script_invalid_flags) BOOST_CHECK_EQUAL(err, bitcoinconsensus_ERR_INVALID_FLAGS); } +#endif // defined(HAVE_CONSENSUS_LIB) + static std::vector<unsigned int> AllConsensusFlags() { std::vector<unsigned int> ret; @@ -1742,5 +1744,4 @@ BOOST_AUTO_TEST_CASE(script_assets_test) file.close(); } -#endif BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index b7ee280336..1f520074b1 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -305,7 +305,7 @@ BOOST_AUTO_TEST_CASE(test_Get) t1.vout[0].nValue = 90*CENT; t1.vout[0].scriptPubKey << OP_1; - BOOST_CHECK(AreInputsStandard(CTransaction(t1), coins)); + BOOST_CHECK(AreInputsStandard(CTransaction(t1), coins, false)); } static void CreateCreditAndSpend(const FillableSigningProvider& keystore, const CScript& outscript, CTransactionRef& output, CMutableTransaction& input, bool success = true) diff --git a/src/test/util/setup_common.h b/src/test/util/setup_common.h index a09c8c122d..1812ce1666 100644 --- a/src/test/util/setup_common.h +++ b/src/test/util/setup_common.h @@ -11,6 +11,7 @@ #include <node/context.h> #include <pubkey.h> #include <random.h> +#include <stdexcept> #include <txmempool.h> #include <util/check.h> #include <util/string.h> @@ -158,13 +159,15 @@ std::ostream& operator<<(std::ostream& os, const uint256& num); * Use as * BOOST_CHECK_EXCEPTION(code that throws, exception type, HasReason("foo")); */ -class HasReason { +class HasReason +{ public: explicit HasReason(const std::string& reason) : m_reason(reason) {} - template <typename E> - bool operator() (const E& e) const { + bool operator()(const std::exception& e) const + { return std::string(e.what()).find(m_reason) != std::string::npos; }; + private: const std::string m_reason; }; diff --git a/src/test/util/validation.cpp b/src/test/util/validation.cpp new file mode 100644 index 0000000000..1aed492c3c --- /dev/null +++ b/src/test/util/validation.cpp @@ -0,0 +1,22 @@ +// Copyright (c) 2020 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <test/util/validation.h> + +#include <util/check.h> +#include <util/time.h> +#include <validation.h> + +void TestChainState::ResetIbd() +{ + m_cached_finished_ibd = false; + assert(IsInitialBlockDownload()); +} + +void TestChainState::JumpOutOfIbd() +{ + Assert(IsInitialBlockDownload()); + m_cached_finished_ibd = true; + Assert(!IsInitialBlockDownload()); +} diff --git a/src/test/util/validation.h b/src/test/util/validation.h new file mode 100644 index 0000000000..b13aa0be60 --- /dev/null +++ b/src/test/util/validation.h @@ -0,0 +1,17 @@ +// Copyright (c) 2020 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_TEST_UTIL_VALIDATION_H +#define BITCOIN_TEST_UTIL_VALIDATION_H + +#include <validation.h> + +struct TestChainState : public CChainState { + /** Reset the ibd cache to its initial state */ + void ResetIbd(); + /** Toggle IsInitialBlockDownload from true to false */ + void JumpOutOfIbd(); +}; + +#endif // BITCOIN_TEST_UTIL_VALIDATION_H diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 241c56934e..010b6adf1f 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -42,6 +42,28 @@ namespace BCLog { BOOST_FIXTURE_TEST_SUITE(util_tests, BasicTestingSetup) +BOOST_AUTO_TEST_CASE(util_datadir) +{ + ClearDatadirCache(); + const fs::path dd_norm = GetDataDir(); + + gArgs.ForceSetArg("-datadir", dd_norm.string() + "/"); + ClearDatadirCache(); + BOOST_CHECK_EQUAL(dd_norm, GetDataDir()); + + gArgs.ForceSetArg("-datadir", dd_norm.string() + "/."); + ClearDatadirCache(); + BOOST_CHECK_EQUAL(dd_norm, GetDataDir()); + + gArgs.ForceSetArg("-datadir", dd_norm.string() + "/./"); + ClearDatadirCache(); + BOOST_CHECK_EQUAL(dd_norm, GetDataDir()); + + gArgs.ForceSetArg("-datadir", dd_norm.string() + "/.//"); + ClearDatadirCache(); + BOOST_CHECK_EQUAL(dd_norm, GetDataDir()); +} + BOOST_AUTO_TEST_CASE(util_check) { // Check that Assert can forward |