aboutsummaryrefslogtreecommitdiff
path: root/src/test/fuzz
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/fuzz')
-rw-r--r--src/test/fuzz/crypto_chacha20.cpp20
-rw-r--r--src/test/fuzz/crypto_diff_fuzz_chacha20.cpp39
-rw-r--r--src/test/fuzz/key.cpp80
-rw-r--r--src/test/fuzz/mini_miner.cpp5
-rw-r--r--src/test/fuzz/p2p_transport_serialization.cpp2
-rw-r--r--src/test/fuzz/policy_estimator.cpp2
-rw-r--r--src/test/fuzz/policy_estimator_io.cpp2
-rw-r--r--src/test/fuzz/rpc.cpp2
-rw-r--r--src/test/fuzz/string.cpp4
-rw-r--r--src/test/fuzz/transaction.cpp13
-rw-r--r--src/test/fuzz/utxo_total_supply.cpp10
11 files changed, 141 insertions, 38 deletions
diff --git a/src/test/fuzz/crypto_chacha20.cpp b/src/test/fuzz/crypto_chacha20.cpp
index 3fa445096a..63c7bf3b45 100644
--- a/src/test/fuzz/crypto_chacha20.cpp
+++ b/src/test/fuzz/crypto_chacha20.cpp
@@ -28,10 +28,11 @@ FUZZ_TARGET(crypto_chacha20)
chacha20.SetKey32(key.data());
},
[&] {
- chacha20.SetIV(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
- },
- [&] {
- chacha20.Seek64(fuzzed_data_provider.ConsumeIntegral<uint64_t>());
+ chacha20.Seek64(
+ {
+ fuzzed_data_provider.ConsumeIntegral<uint32_t>(),
+ fuzzed_data_provider.ConsumeIntegral<uint64_t>()
+ }, fuzzed_data_provider.ConsumeIntegral<uint32_t>());
},
[&] {
std::vector<uint8_t> output(fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096));
@@ -63,17 +64,16 @@ void ChaCha20SplitFuzz(FuzzedDataProvider& provider)
auto key_bytes = provider.ConsumeBytes<unsigned char>(32);
std::copy(key_bytes.begin(), key_bytes.end(), key);
uint64_t iv = provider.ConsumeIntegral<uint64_t>();
+ uint32_t iv_prefix = provider.ConsumeIntegral<uint32_t>();
uint64_t total_bytes = provider.ConsumeIntegralInRange<uint64_t>(0, 1000000);
- /* ~x = 2^64 - 1 - x, so ~(total_bytes >> 6) is the maximal seek position. */
- uint64_t seek = provider.ConsumeIntegralInRange<uint64_t>(0, ~(total_bytes >> 6));
+ /* ~x = 2^BITS - 1 - x, so ~(total_bytes >> 6) is the maximal seek position. */
+ uint32_t seek = provider.ConsumeIntegralInRange<uint32_t>(0, ~(uint32_t)(total_bytes >> 6));
// Initialize two ChaCha20 ciphers, with the same key/iv/position.
ChaCha20 crypt1(key);
ChaCha20 crypt2(key);
- crypt1.SetIV(iv);
- crypt1.Seek64(seek);
- crypt2.SetIV(iv);
- crypt2.Seek64(seek);
+ crypt1.Seek64({iv_prefix, iv}, seek);
+ crypt2.Seek64({iv_prefix, iv}, seek);
// Construct vectors with data.
std::vector<unsigned char> data1, data2;
diff --git a/src/test/fuzz/crypto_diff_fuzz_chacha20.cpp b/src/test/fuzz/crypto_diff_fuzz_chacha20.cpp
index 78fee48de6..285ea2dfe0 100644
--- a/src/test/fuzz/crypto_diff_fuzz_chacha20.cpp
+++ b/src/test/fuzz/crypto_diff_fuzz_chacha20.cpp
@@ -284,6 +284,8 @@ FUZZ_TARGET(crypto_diff_fuzz_chacha20)
// ECRYPT_keysetup() doesn't set the counter and nonce to 0 while SetKey32() does
static const uint8_t iv[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+ ChaCha20::Nonce96 nonce{0, 0};
+ uint32_t counter{0};
ECRYPT_ivsetup(&ctx, iv);
LIMITED_WHILE (fuzzed_data_provider.ConsumeBool(), 3000) {
@@ -292,45 +294,56 @@ FUZZ_TARGET(crypto_diff_fuzz_chacha20)
[&] {
const std::vector<unsigned char> key = ConsumeFixedLengthByteVector(fuzzed_data_provider, 32);
chacha20.SetKey32(key.data());
+ nonce = {0, 0};
+ counter = 0;
ECRYPT_keysetup(&ctx, key.data(), key.size() * 8, 0);
// ECRYPT_keysetup() doesn't set the counter and nonce to 0 while SetKey32() does
uint8_t iv[8] = {0, 0, 0, 0, 0, 0, 0, 0};
ECRYPT_ivsetup(&ctx, iv);
},
[&] {
+ uint32_t iv_prefix = fuzzed_data_provider.ConsumeIntegral<uint32_t>();
uint64_t iv = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
- chacha20.SetIV(iv);
+ nonce = {iv_prefix, iv};
+ counter = fuzzed_data_provider.ConsumeIntegral<uint32_t>();
+ chacha20.Seek64(nonce, counter);
+ ctx.input[12] = counter;
+ ctx.input[13] = iv_prefix;
ctx.input[14] = iv;
ctx.input[15] = iv >> 32;
},
[&] {
- uint64_t counter = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
- chacha20.Seek64(counter);
- ctx.input[12] = counter;
- ctx.input[13] = counter >> 32;
- },
- [&] {
uint32_t integralInRange = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096);
- // DJB's version seeks forward to a multiple of 64 bytes after every operation. Correct for that.
- uint64_t pos = ctx.input[12] + (((uint64_t)ctx.input[13]) << 32) + ((integralInRange + 63) >> 6);
std::vector<uint8_t> output(integralInRange);
chacha20.Keystream(output.data(), output.size());
std::vector<uint8_t> djb_output(integralInRange);
ECRYPT_keystream_bytes(&ctx, djb_output.data(), djb_output.size());
assert(output == djb_output);
- chacha20.Seek64(pos);
+ // DJB's version seeks forward to a multiple of 64 bytes after every operation. Correct for that.
+ uint32_t old_counter = counter;
+ counter += (integralInRange + 63) >> 6;
+ if (counter < old_counter) ++nonce.first;
+ if (integralInRange & 63) {
+ chacha20.Seek64(nonce, counter);
+ }
+ assert(counter == ctx.input[12]);
},
[&] {
uint32_t integralInRange = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, 4096);
- // DJB's version seeks forward to a multiple of 64 bytes after every operation. Correct for that.
- uint64_t pos = ctx.input[12] + (((uint64_t)ctx.input[13]) << 32) + ((integralInRange + 63) >> 6);
std::vector<uint8_t> output(integralInRange);
const std::vector<uint8_t> input = ConsumeFixedLengthByteVector(fuzzed_data_provider, output.size());
chacha20.Crypt(input.data(), output.data(), input.size());
std::vector<uint8_t> djb_output(integralInRange);
ECRYPT_encrypt_bytes(&ctx, input.data(), djb_output.data(), input.size());
assert(output == djb_output);
- chacha20.Seek64(pos);
+ // DJB's version seeks forward to a multiple of 64 bytes after every operation. Correct for that.
+ uint32_t old_counter = counter;
+ counter += (integralInRange + 63) >> 6;
+ if (counter < old_counter) ++nonce.first;
+ if (integralInRange & 63) {
+ chacha20.Seek64(nonce, counter);
+ }
+ assert(counter == ctx.input[12]);
});
}
}
diff --git a/src/test/fuzz/key.cpp b/src/test/fuzz/key.cpp
index 3eab2e20c0..25ea547435 100644
--- a/src/test/fuzz/key.cpp
+++ b/src/test/fuzz/key.cpp
@@ -15,13 +15,17 @@
#include <script/signingprovider.h>
#include <script/standard.h>
#include <streams.h>
+#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <util/chaintype.h>
#include <util/strencodings.h>
+#include <array>
#include <cassert>
+#include <cstddef>
#include <cstdint>
#include <numeric>
+#include <optional>
#include <string>
#include <vector>
@@ -303,3 +307,79 @@ FUZZ_TARGET_INIT(key, initialize_key)
}
}
}
+
+FUZZ_TARGET_INIT(ellswift_roundtrip, initialize_key)
+{
+ FuzzedDataProvider fdp{buffer.data(), buffer.size()};
+
+ auto key_bytes = fdp.ConsumeBytes<uint8_t>(32);
+ key_bytes.resize(32);
+ CKey key;
+ key.Set(key_bytes.begin(), key_bytes.end(), true);
+ if (!key.IsValid()) return;
+
+ auto ent32 = fdp.ConsumeBytes<std::byte>(32);
+ ent32.resize(32);
+
+ auto encoded_ellswift = key.EllSwiftCreate(ent32);
+ auto decoded_pubkey = encoded_ellswift.Decode();
+
+ assert(key.VerifyPubKey(decoded_pubkey));
+}
+
+FUZZ_TARGET_INIT(bip324_ecdh, initialize_key)
+{
+ FuzzedDataProvider fdp{buffer.data(), buffer.size()};
+
+ // We generate private key, k1.
+ auto rnd32 = fdp.ConsumeBytes<uint8_t>(32);
+ rnd32.resize(32);
+ CKey k1;
+ k1.Set(rnd32.begin(), rnd32.end(), true);
+ if (!k1.IsValid()) return;
+
+ // They generate private key, k2.
+ rnd32 = fdp.ConsumeBytes<uint8_t>(32);
+ rnd32.resize(32);
+ CKey k2;
+ k2.Set(rnd32.begin(), rnd32.end(), true);
+ if (!k2.IsValid()) return;
+
+ // We construct an ellswift encoding for our key, k1_ellswift.
+ auto ent32_1 = fdp.ConsumeBytes<std::byte>(32);
+ ent32_1.resize(32);
+ auto k1_ellswift = k1.EllSwiftCreate(ent32_1);
+
+ // They construct an ellswift encoding for their key, k2_ellswift.
+ auto ent32_2 = fdp.ConsumeBytes<std::byte>(32);
+ ent32_2.resize(32);
+ auto k2_ellswift = k2.EllSwiftCreate(ent32_2);
+
+ // They construct another (possibly distinct) ellswift encoding for their key, k2_ellswift_bad.
+ auto ent32_2_bad = fdp.ConsumeBytes<std::byte>(32);
+ ent32_2_bad.resize(32);
+ auto k2_ellswift_bad = k2.EllSwiftCreate(ent32_2_bad);
+ assert((ent32_2_bad == ent32_2) == (k2_ellswift_bad == k2_ellswift));
+
+ // Determine who is who.
+ bool initiating = fdp.ConsumeBool();
+
+ // We compute our shared secret using our key and their public key.
+ auto ecdh_secret_1 = k1.ComputeBIP324ECDHSecret(k2_ellswift, k1_ellswift, initiating);
+ // They compute their shared secret using their key and our public key.
+ auto ecdh_secret_2 = k2.ComputeBIP324ECDHSecret(k1_ellswift, k2_ellswift, !initiating);
+ // Those must match, as everyone is behaving correctly.
+ assert(ecdh_secret_1 == ecdh_secret_2);
+
+ if (k1_ellswift != k2_ellswift) {
+ // Unless the two keys are exactly identical, acting as the wrong party breaks things.
+ auto ecdh_secret_bad = k1.ComputeBIP324ECDHSecret(k2_ellswift, k1_ellswift, !initiating);
+ assert(ecdh_secret_bad != ecdh_secret_1);
+ }
+
+ if (k2_ellswift_bad != k2_ellswift) {
+ // Unless both encodings created by them are identical, using the second one breaks things.
+ auto ecdh_secret_bad = k1.ComputeBIP324ECDHSecret(k2_ellswift_bad, k1_ellswift, initiating);
+ assert(ecdh_secret_bad != ecdh_secret_1);
+ }
+}
diff --git a/src/test/fuzz/mini_miner.cpp b/src/test/fuzz/mini_miner.cpp
index f49d940393..2b371f6d5f 100644
--- a/src/test/fuzz/mini_miner.cpp
+++ b/src/test/fuzz/mini_miner.cpp
@@ -118,10 +118,11 @@ FUZZ_TARGET_INIT(mini_miner_selection, initialize_miner)
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 100)
{
CMutableTransaction mtx = CMutableTransaction();
- const size_t num_inputs = 2;
+ assert(!available_coins.empty());
+ const size_t num_inputs = std::min(size_t{2}, available_coins.size());
const size_t num_outputs = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(2, 5);
for (size_t n{0}; n < num_inputs; ++n) {
- auto prevout = available_coins.front();
+ auto prevout = available_coins.at(0);
mtx.vin.push_back(CTxIn(prevout, CScript()));
available_coins.pop_front();
}
diff --git a/src/test/fuzz/p2p_transport_serialization.cpp b/src/test/fuzz/p2p_transport_serialization.cpp
index ec3cdbff5a..a6fe3037e6 100644
--- a/src/test/fuzz/p2p_transport_serialization.cpp
+++ b/src/test/fuzz/p2p_transport_serialization.cpp
@@ -77,7 +77,7 @@ FUZZ_TARGET_INIT(p2p_transport_serialization, initialize_p2p_transport_serializa
assert(msg.m_time == m_time);
std::vector<unsigned char> header;
- auto msg2 = CNetMsgMaker{msg.m_recv.GetVersion()}.Make(msg.m_type, MakeUCharSpan(msg.m_recv));
+ auto msg2 = CNetMsgMaker{msg.m_recv.GetVersion()}.Make(msg.m_type, Span{msg.m_recv});
serializer.prepareForTransport(msg2, header);
}
}
diff --git a/src/test/fuzz/policy_estimator.cpp b/src/test/fuzz/policy_estimator.cpp
index 116fbd9015..aa3cfe81df 100644
--- a/src/test/fuzz/policy_estimator.cpp
+++ b/src/test/fuzz/policy_estimator.cpp
@@ -31,7 +31,7 @@ void initialize_policy_estimator()
FUZZ_TARGET_INIT(policy_estimator, initialize_policy_estimator)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
- CBlockPolicyEstimator block_policy_estimator{FeeestPath(*g_setup->m_node.args)};
+ CBlockPolicyEstimator block_policy_estimator{FeeestPath(*g_setup->m_node.args), DEFAULT_ACCEPT_STALE_FEE_ESTIMATES};
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) {
CallOneOf(
fuzzed_data_provider,
diff --git a/src/test/fuzz/policy_estimator_io.cpp b/src/test/fuzz/policy_estimator_io.cpp
index 7c3289cd26..3df40197d8 100644
--- a/src/test/fuzz/policy_estimator_io.cpp
+++ b/src/test/fuzz/policy_estimator_io.cpp
@@ -28,7 +28,7 @@ FUZZ_TARGET_INIT(policy_estimator_io, initialize_policy_estimator_io)
FuzzedAutoFileProvider fuzzed_auto_file_provider = ConsumeAutoFile(fuzzed_data_provider);
AutoFile fuzzed_auto_file{fuzzed_auto_file_provider.open()};
// Re-using block_policy_estimator across runs to avoid costly creation of CBlockPolicyEstimator object.
- static CBlockPolicyEstimator block_policy_estimator{FeeestPath(*g_setup->m_node.args)};
+ static CBlockPolicyEstimator block_policy_estimator{FeeestPath(*g_setup->m_node.args), DEFAULT_ACCEPT_STALE_FEE_ESTIMATES};
if (block_policy_estimator.Read(fuzzed_auto_file)) {
block_policy_estimator.Write(fuzzed_auto_file);
}
diff --git a/src/test/fuzz/rpc.cpp b/src/test/fuzz/rpc.cpp
index 6424f756a0..45a2294081 100644
--- a/src/test/fuzz/rpc.cpp
+++ b/src/test/fuzz/rpc.cpp
@@ -73,6 +73,7 @@ const std::vector<std::string> RPC_COMMANDS_NOT_SAFE_FOR_FUZZING{
"addpeeraddress", // avoid DNS lookups
"dumptxoutset", // avoid writing to disk
"dumpwallet", // avoid writing to disk
+ "enumeratesigners",
"echoipc", // avoid assertion failure (Assertion `"EnsureAnyNodeContext(request.context).init" && check' failed.)
"generatetoaddress", // avoid prohibitively slow execution (when `num_blocks` is large)
"generatetodescriptor", // avoid prohibitively slow execution (when `nblocks` is large)
@@ -136,6 +137,7 @@ const std::vector<std::string> RPC_COMMANDS_SAFE_FOR_FUZZING{
"getnetworkinfo",
"getnodeaddresses",
"getpeerinfo",
+ "getprioritisedtransactions",
"getrawmempool",
"getrawtransaction",
"getrpcinfo",
diff --git a/src/test/fuzz/string.cpp b/src/test/fuzz/string.cpp
index fd96b6e3b2..e81efac6e0 100644
--- a/src/test/fuzz/string.cpp
+++ b/src/test/fuzz/string.cpp
@@ -5,6 +5,7 @@
#include <blockfilter.h>
#include <clientversion.h>
#include <common/args.h>
+#include <common/settings.h>
#include <common/system.h>
#include <common/url.h>
#include <netbase.h>
@@ -22,7 +23,6 @@
#include <test/fuzz/util.h>
#include <util/error.h>
#include <util/fees.h>
-#include <util/settings.h>
#include <util/strencodings.h>
#include <util/string.h>
#include <util/translation.h>
@@ -63,7 +63,7 @@ FUZZ_TARGET(string)
(void)IsDeprecatedRPCEnabled(random_string_1);
(void)Join(random_string_vector, random_string_1);
(void)JSONRPCError(fuzzed_data_provider.ConsumeIntegral<int>(), random_string_1);
- const util::Settings settings;
+ const common::Settings settings;
(void)OnlyHasDefaultSectionSetting(settings, random_string_1, random_string_2);
(void)ParseNetwork(random_string_1);
(void)ParseOutputType(random_string_1);
diff --git a/src/test/fuzz/transaction.cpp b/src/test/fuzz/transaction.cpp
index 7035c53d13..c561675d1a 100644
--- a/src/test/fuzz/transaction.cpp
+++ b/src/test/fuzz/transaction.cpp
@@ -101,7 +101,14 @@ FUZZ_TARGET_INIT(transaction, initialize_transaction)
(void)AreInputsStandard(tx, coins_view_cache);
(void)IsWitnessStandard(tx, coins_view_cache);
- UniValue u(UniValue::VOBJ);
- TxToUniv(tx, /*block_hash=*/uint256::ZERO, /*entry=*/u);
- TxToUniv(tx, /*block_hash=*/uint256::ONE, /*entry=*/u);
+ if (tx.GetTotalSize() < 250'000) { // Avoid high memory usage (with msan) due to json encoding
+ {
+ UniValue u{UniValue::VOBJ};
+ TxToUniv(tx, /*block_hash=*/uint256::ZERO, /*entry=*/u);
+ }
+ {
+ UniValue u{UniValue::VOBJ};
+ TxToUniv(tx, /*block_hash=*/uint256::ONE, /*entry=*/u);
+ }
+ }
}
diff --git a/src/test/fuzz/utxo_total_supply.cpp b/src/test/fuzz/utxo_total_supply.cpp
index ea78edd05f..318797faf2 100644
--- a/src/test/fuzz/utxo_total_supply.cpp
+++ b/src/test/fuzz/utxo_total_supply.cpp
@@ -144,13 +144,13 @@ FUZZ_TARGET(utxo_total_supply)
node::RegenerateCommitments(*current_block, chainman);
const bool was_valid = !MineBlock(node, current_block).IsNull();
- if (duplicate_coinbase_height == ActiveHeight()) {
- // we mined the duplicate coinbase
- assert(current_block->vtx.at(0)->vin.at(0).scriptSig == duplicate_coinbase_script);
- }
-
const auto prev_utxo_stats = utxo_stats;
if (was_valid) {
+ if (duplicate_coinbase_height == ActiveHeight()) {
+ // we mined the duplicate coinbase
+ assert(current_block->vtx.at(0)->vin.at(0).scriptSig == duplicate_coinbase_script);
+ }
+
circulation += GetBlockSubsidy(ActiveHeight(), Params().GetConsensus());
}