diff options
Diffstat (limited to 'src/test/fuzz')
-rw-r--r-- | src/test/fuzz/crypto_chacha20.cpp | 20 | ||||
-rw-r--r-- | src/test/fuzz/crypto_diff_fuzz_chacha20.cpp | 39 | ||||
-rw-r--r-- | src/test/fuzz/key.cpp | 80 | ||||
-rw-r--r-- | src/test/fuzz/mini_miner.cpp | 5 | ||||
-rw-r--r-- | src/test/fuzz/p2p_transport_serialization.cpp | 2 | ||||
-rw-r--r-- | src/test/fuzz/policy_estimator.cpp | 2 | ||||
-rw-r--r-- | src/test/fuzz/policy_estimator_io.cpp | 2 | ||||
-rw-r--r-- | src/test/fuzz/rpc.cpp | 2 | ||||
-rw-r--r-- | src/test/fuzz/string.cpp | 4 | ||||
-rw-r--r-- | src/test/fuzz/transaction.cpp | 13 | ||||
-rw-r--r-- | src/test/fuzz/utxo_total_supply.cpp | 10 |
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()); } |