aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/denialofservice_tests.cpp10
-rw-r--r--src/test/fuzz/addrman.cpp119
-rw-r--r--src/test/fuzz/coins_view.cpp3
-rw-r--r--src/test/fuzz/connman.cpp162
-rw-r--r--src/test/fuzz/decode_tx.cpp7
-rw-r--r--src/test/fuzz/descriptor_parse.cpp3
-rw-r--r--src/test/fuzz/deserialize.cpp57
-rw-r--r--src/test/fuzz/merkleblock.cpp34
-rw-r--r--src/test/fuzz/net.cpp2
-rw-r--r--src/test/fuzz/process_message.cpp7
-rw-r--r--src/test/fuzz/process_messages.cpp6
-rw-r--r--src/test/fuzz/script_flags.cpp8
-rw-r--r--src/test/fuzz/transaction.cpp3
-rw-r--r--src/test/fuzz/util.h41
-rw-r--r--src/test/script_p2sh_tests.cpp6
-rw-r--r--src/test/script_tests.cpp21
-rw-r--r--src/test/transaction_tests.cpp2
-rw-r--r--src/test/util/setup_common.h9
-rw-r--r--src/test/util/validation.cpp22
-rw-r--r--src/test/util/validation.h17
-rw-r--r--src/test/util_tests.cpp22
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