40 RPCFuzzTestingSetup(
const std::string& chain_name,
const std::vector<const char*>& extra_args) :
TestingSetup{chain_name, extra_args}
44 void CallRPC(
const std::string& rpc_method,
const std::vector<std::string>& arguments)
51 }
catch (
const std::runtime_error&) {
57 std::vector<std::string> GetRPCCommands()
const
63 RPCFuzzTestingSetup* rpc_testing_setup =
nullptr;
64 std::string g_limit_to_rpc_command;
69 const std::vector<std::string> RPC_COMMANDS_NOT_SAFE_FOR_FUZZING{
78 "generatetodescriptor",
82 "prioritisetransaction",
89 const std::vector<std::string> RPC_COMMANDS_SAFE_FOR_FUZZING{
92 "combinerawtransaction",
96 "createrawtransaction",
98 "decoderawtransaction",
122 "getconnectioncount",
128 "getmempoolancestors",
129 "getmempooldescendants",
154 "sendrawtransaction",
157 "signmessagewithprivkey",
158 "signrawtransactionwithkey",
161 "syncwithvalidationinterfacequeue",
170 "waitforblockheight",
176 const size_t max_string_length = 4096;
177 const size_t max_base58_bytes_length{64};
180 fuzzed_data_provider,
195 r = fuzzed_data_provider.
ConsumeBool() ?
"true" :
"false";
239 std::optional<CBlock> opt_block = ConsumeDeserializable<CBlock>(fuzzed_data_provider);
244 data_stream << *opt_block;
249 std::optional<CBlockHeader> opt_block_header = ConsumeDeserializable<CBlockHeader>(fuzzed_data_provider);
250 if (!opt_block_header) {
254 data_stream << *opt_block_header;
259 std::optional<CMutableTransaction> opt_tx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
264 data_stream << *opt_tx;
269 std::optional<PartiallySignedTransaction> opt_psbt = ConsumeDeserializable<PartiallySignedTransaction>(fuzzed_data_provider);
274 data_stream << *opt_psbt;
279 const std::vector<uint8_t> random_bytes = fuzzed_data_provider.
ConsumeBytes<uint8_t>(32);
281 key.
Set(random_bytes.begin(), random_bytes.end(), fuzzed_data_provider.
ConsumeBool());
282 if (!key.IsValid()) {
289 const std::vector<uint8_t> random_bytes = fuzzed_data_provider.
ConsumeBytes<uint8_t>(32);
291 key.
Set(random_bytes.begin(), random_bytes.end(), fuzzed_data_provider.
ConsumeBool());
292 if (!key.IsValid()) {
295 r =
HexStr(key.GetPubKey());
302 std::vector<std::string> scalar_arguments;
304 scalar_arguments.push_back(ConsumeScalarRPCArgument(fuzzed_data_provider));
306 return "[\"" +
Join(scalar_arguments,
"\",\"") +
"\"]";
311 return fuzzed_data_provider.
ConsumeBool() ? ConsumeScalarRPCArgument(fuzzed_data_provider) : ConsumeArrayRPCArgument(fuzzed_data_provider);
314 RPCFuzzTestingSetup* InitializeRPCFuzzTestingSetup()
316 static const auto setup = MakeNoLogFileContext<RPCFuzzTestingSetup>();
324 rpc_testing_setup = InitializeRPCFuzzTestingSetup();
325 const std::vector<std::string> supported_rpc_commands = rpc_testing_setup->GetRPCCommands();
326 for (
const std::string& rpc_command : supported_rpc_commands) {
327 const bool safe_for_fuzzing = std::find(RPC_COMMANDS_SAFE_FOR_FUZZING.begin(), RPC_COMMANDS_SAFE_FOR_FUZZING.end(), rpc_command) != RPC_COMMANDS_SAFE_FOR_FUZZING.end();
328 const bool not_safe_for_fuzzing = std::find(RPC_COMMANDS_NOT_SAFE_FOR_FUZZING.begin(), RPC_COMMANDS_NOT_SAFE_FOR_FUZZING.end(), rpc_command) != RPC_COMMANDS_NOT_SAFE_FOR_FUZZING.end();
329 if (!(safe_for_fuzzing || not_safe_for_fuzzing)) {
330 std::cerr <<
"Error: RPC command \"" << rpc_command <<
"\" not found in RPC_COMMANDS_SAFE_FOR_FUZZING or RPC_COMMANDS_NOT_SAFE_FOR_FUZZING. Please update " << __FILE__ <<
".\n";
333 if (safe_for_fuzzing && not_safe_for_fuzzing) {
334 std::cerr <<
"Error: RPC command \"" << rpc_command <<
"\" found in *both* RPC_COMMANDS_SAFE_FOR_FUZZING and RPC_COMMANDS_NOT_SAFE_FOR_FUZZING. Please update " << __FILE__ <<
".\n";
338 const char* limit_to_rpc_command_env = std::getenv(
"LIMIT_TO_RPC_COMMAND");
339 if (limit_to_rpc_command_env !=
nullptr) {
340 g_limit_to_rpc_command = std::string{limit_to_rpc_command_env};
349 if (!g_limit_to_rpc_command.empty() && rpc_command != g_limit_to_rpc_command) {
352 const bool safe_for_fuzzing = std::find(RPC_COMMANDS_SAFE_FOR_FUZZING.begin(), RPC_COMMANDS_SAFE_FOR_FUZZING.end(), rpc_command) != RPC_COMMANDS_SAFE_FOR_FUZZING.end();
353 if (!safe_for_fuzzing) {
356 std::vector<std::string> arguments;
358 arguments.push_back(ConsumeRPCArgument(fuzzed_data_provider));
361 rpc_testing_setup->CallRPC(rpc_command, arguments);
362 }
catch (
const UniValue& json_rpc_error) {
366 if (0 == error_msg.rfind(
"Internal bug detected", 0)) {
368 assert(error_msg.find(
"trigger_internal_bug") != std::string::npos);