Skip to content

Commit 3439c88

Browse files
tests: Add fuzzing harness for CBlockPolicyEstimator
1 parent 00c1a4d commit 3439c88

File tree

3 files changed

+91
-0
lines changed

3 files changed

+91
-0
lines changed

src/Makefile.test.include

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ FUZZ_TARGETS = \
6767
test/fuzz/parse_univalue \
6868
test/fuzz/partial_merkle_tree_deserialize \
6969
test/fuzz/partially_signed_transaction_deserialize \
70+
test/fuzz/policy_estimator \
7071
test/fuzz/pow \
7172
test/fuzz/prefilled_transaction_deserialize \
7273
test/fuzz/prevector \
@@ -683,6 +684,12 @@ test_fuzz_partially_signed_transaction_deserialize_LDADD = $(FUZZ_SUITE_LD_COMMO
683684
test_fuzz_partially_signed_transaction_deserialize_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
684685
test_fuzz_partially_signed_transaction_deserialize_SOURCES = test/fuzz/deserialize.cpp
685686

687+
test_fuzz_policy_estimator_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
688+
test_fuzz_policy_estimator_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
689+
test_fuzz_policy_estimator_LDADD = $(FUZZ_SUITE_LD_COMMON)
690+
test_fuzz_policy_estimator_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
691+
test_fuzz_policy_estimator_SOURCES = test/fuzz/policy_estimator.cpp
692+
686693
test_fuzz_pow_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
687694
test_fuzz_pow_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
688695
test_fuzz_pow_LDADD = $(FUZZ_SUITE_LD_COMMON)

src/test/fuzz/policy_estimator.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright (c) 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 <optional.h>
6+
#include <policy/fees.h>
7+
#include <primitives/transaction.h>
8+
#include <test/fuzz/FuzzedDataProvider.h>
9+
#include <test/fuzz/fuzz.h>
10+
#include <test/fuzz/util.h>
11+
#include <txmempool.h>
12+
13+
#include <cstdint>
14+
#include <string>
15+
#include <vector>
16+
17+
void test_one_input(const std::vector<uint8_t>& buffer)
18+
{
19+
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
20+
CBlockPolicyEstimator block_policy_estimator;
21+
while (fuzzed_data_provider.ConsumeBool()) {
22+
switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 3)) {
23+
case 0: {
24+
const Optional<CMutableTransaction> mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
25+
if (!mtx) {
26+
break;
27+
}
28+
const CTransaction tx{*mtx};
29+
block_policy_estimator.processTransaction(ConsumeTxMemPoolEntry(fuzzed_data_provider, tx), fuzzed_data_provider.ConsumeBool());
30+
if (fuzzed_data_provider.ConsumeBool()) {
31+
(void)block_policy_estimator.removeTx(tx.GetHash(), /* inBlock */ fuzzed_data_provider.ConsumeBool());
32+
}
33+
break;
34+
}
35+
case 1: {
36+
std::vector<CTxMemPoolEntry> mempool_entries;
37+
while (fuzzed_data_provider.ConsumeBool()) {
38+
const Optional<CMutableTransaction> mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
39+
if (!mtx) {
40+
break;
41+
}
42+
const CTransaction tx{*mtx};
43+
mempool_entries.push_back(ConsumeTxMemPoolEntry(fuzzed_data_provider, tx));
44+
}
45+
std::vector<const CTxMemPoolEntry*> ptrs;
46+
ptrs.reserve(mempool_entries.size());
47+
for (const CTxMemPoolEntry& mempool_entry : mempool_entries) {
48+
ptrs.push_back(&mempool_entry);
49+
}
50+
block_policy_estimator.processBlock(fuzzed_data_provider.ConsumeIntegral<unsigned int>(), ptrs);
51+
break;
52+
}
53+
case 2: {
54+
(void)block_policy_estimator.removeTx(ConsumeUInt256(fuzzed_data_provider), /* inBlock */ fuzzed_data_provider.ConsumeBool());
55+
break;
56+
}
57+
case 3: {
58+
block_policy_estimator.FlushUnconfirmed();
59+
break;
60+
}
61+
}
62+
(void)block_policy_estimator.estimateFee(fuzzed_data_provider.ConsumeIntegral<int>());
63+
EstimationResult result;
64+
(void)block_policy_estimator.estimateRawFee(fuzzed_data_provider.ConsumeIntegral<int>(), fuzzed_data_provider.ConsumeFloatingPoint<double>(), fuzzed_data_provider.PickValueInArray({FeeEstimateHorizon::SHORT_HALFLIFE, FeeEstimateHorizon::MED_HALFLIFE, FeeEstimateHorizon::LONG_HALFLIFE}), fuzzed_data_provider.ConsumeBool() ? &result : nullptr);
65+
FeeCalculation fee_calculation;
66+
(void)block_policy_estimator.estimateSmartFee(fuzzed_data_provider.ConsumeIntegral<int>(), fuzzed_data_provider.ConsumeBool() ? &fee_calculation : nullptr, fuzzed_data_provider.ConsumeBool());
67+
(void)block_policy_estimator.HighestTargetTracked(fuzzed_data_provider.PickValueInArray({FeeEstimateHorizon::SHORT_HALFLIFE, FeeEstimateHorizon::MED_HALFLIFE, FeeEstimateHorizon::LONG_HALFLIFE}));
68+
}
69+
}

src/test/fuzz/util.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,15 @@
88
#include <amount.h>
99
#include <arith_uint256.h>
1010
#include <attributes.h>
11+
#include <consensus/consensus.h>
1112
#include <optional.h>
13+
#include <primitives/transaction.h>
1214
#include <script/script.h>
1315
#include <serialize.h>
1416
#include <streams.h>
1517
#include <test/fuzz/FuzzedDataProvider.h>
1618
#include <test/fuzz/fuzz.h>
19+
#include <txmempool.h>
1720
#include <uint256.h>
1821
#include <version.h>
1922

@@ -97,6 +100,18 @@ NODISCARD inline arith_uint256 ConsumeArithUInt256(FuzzedDataProvider& fuzzed_da
97100
return UintToArith256(ConsumeUInt256(fuzzed_data_provider));
98101
}
99102

103+
NODISCARD inline CTxMemPoolEntry ConsumeTxMemPoolEntry(FuzzedDataProvider& fuzzed_data_provider, const CTransaction& tx) noexcept
104+
{
105+
// Avoid:
106+
// policy/feerate.cpp:28:34: runtime error: signed integer overflow: 34873208148477500 * 1000 cannot be represented in type 'long'
107+
const CAmount fee = ConsumeMoney(fuzzed_data_provider) / static_cast<CAmount>(100);
108+
const int64_t time = fuzzed_data_provider.ConsumeIntegral<int64_t>();
109+
const unsigned int entry_height = fuzzed_data_provider.ConsumeIntegral<unsigned int>();
110+
const bool spends_coinbase = fuzzed_data_provider.ConsumeBool();
111+
const unsigned int sig_op_cost = fuzzed_data_provider.ConsumeIntegralInRange<unsigned int>(0, MAX_BLOCK_SIGOPS_COST);
112+
return CTxMemPoolEntry{MakeTransactionRef(tx), fee, time, entry_height, spends_coinbase, sig_op_cost, {}};
113+
}
114+
100115
template <typename T>
101116
NODISCARD bool MultiplicationOverflow(const T i, const T j) noexcept
102117
{

0 commit comments

Comments
 (0)