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",
131 "gettxspendingprevout",
156 "sendrawtransaction",
159 "signmessagewithprivkey",
160 "signrawtransactionwithkey",
164 "syncwithvalidationinterfacequeue",
173 "waitforblockheight",
179 const size_t max_string_length = 4096;
180 const size_t max_base58_bytes_length{64};
183 fuzzed_data_provider,
198 r = fuzzed_data_provider.
ConsumeBool() ?
"true" :
"false";
242 std::optional<CBlock> opt_block = ConsumeDeserializable<CBlock>(fuzzed_data_provider);
247 data_stream << *opt_block;
252 std::optional<CBlockHeader> opt_block_header = ConsumeDeserializable<CBlockHeader>(fuzzed_data_provider);
253 if (!opt_block_header) {
257 data_stream << *opt_block_header;
262 std::optional<CMutableTransaction> opt_tx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider);
267 data_stream << *opt_tx;
272 std::optional<PartiallySignedTransaction> opt_psbt = ConsumeDeserializable<PartiallySignedTransaction>(fuzzed_data_provider);
277 data_stream << *opt_psbt;
282 const std::vector<uint8_t> random_bytes = fuzzed_data_provider.
ConsumeBytes<uint8_t>(32);
284 key.
Set(random_bytes.begin(), random_bytes.end(), fuzzed_data_provider.
ConsumeBool());
285 if (!key.IsValid()) {
292 const std::vector<uint8_t> random_bytes = fuzzed_data_provider.
ConsumeBytes<uint8_t>(32);
294 key.
Set(random_bytes.begin(), random_bytes.end(), fuzzed_data_provider.
ConsumeBool());
295 if (!key.IsValid()) {
298 r =
HexStr(key.GetPubKey());
305 std::vector<std::string> scalar_arguments;
307 scalar_arguments.push_back(ConsumeScalarRPCArgument(fuzzed_data_provider));
309 return "[\"" +
Join(scalar_arguments,
"\",\"") +
"\"]";
314 return fuzzed_data_provider.
ConsumeBool() ? ConsumeScalarRPCArgument(fuzzed_data_provider) : ConsumeArrayRPCArgument(fuzzed_data_provider);
317 RPCFuzzTestingSetup* InitializeRPCFuzzTestingSetup()
319 static const auto setup = MakeNoLogFileContext<RPCFuzzTestingSetup>();
327 rpc_testing_setup = InitializeRPCFuzzTestingSetup();
328 const std::vector<std::string> supported_rpc_commands = rpc_testing_setup->GetRPCCommands();
329 for (
const std::string& rpc_command : supported_rpc_commands) {
330 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();
331 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();
332 if (!(safe_for_fuzzing || not_safe_for_fuzzing)) {
333 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";
336 if (safe_for_fuzzing && not_safe_for_fuzzing) {
337 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";
341 const char* limit_to_rpc_command_env = std::getenv(
"LIMIT_TO_RPC_COMMAND");
342 if (limit_to_rpc_command_env !=
nullptr) {
343 g_limit_to_rpc_command = std::string{limit_to_rpc_command_env};
352 if (!g_limit_to_rpc_command.empty() && rpc_command != g_limit_to_rpc_command) {
355 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();
356 if (!safe_for_fuzzing) {
359 std::vector<std::string> arguments;
361 arguments.push_back(ConsumeRPCArgument(fuzzed_data_provider));
364 rpc_testing_setup->CallRPC(rpc_command, arguments);
365 }
catch (
const UniValue& json_rpc_error) {
369 if (0 == error_msg.rfind(
"Internal bug detected", 0)) {
371 assert(error_msg.find(
"trigger_internal_bug") != std::string::npos);
std::string EncodeBase58(Span< const unsigned char > input)
Why base-58 instead of standard base-64 encoding?
std::string EncodeBase58Check(Span< const unsigned char > input)
Encode a byte span into a base58-encoded string, including checksum.
static UniValue CallRPC(BaseRequestHandler *rh, const std::string &strMethod, const std::vector< std::string > &args, const std::optional< std::string > &rpcwallet={})
An encapsulated private key.
void Set(const T pbegin, const T pend, bool fCompressedIn)
Initialize using begin and end iterators to byte data.
std::vector< std::string > listCommands() const
Returns a list of registered commands.
UniValue execute(const JSONRPCRequest &request) const
Execute a method.
Double ended buffer combining vector and stream-like interfaces.
std::string ConsumeRandomLengthString(size_t max_length)
std::vector< T > ConsumeBytes(size_t num_bytes)
const std::string & get_str() const
std::string ToString() const
UniValue RPCConvertValues(const std::string &strMethod, const std::vector< std::string > &strParams)
Convert positional arguments to command-specific RPC representation.
#define LIMITED_WHILE(condition, limit)
Can be used to limit a theoretically unbounded loop.
std::string EncodeSecret(const CKey &key)
std::string EncodeDestination(const CTxDestination &dest)
static const int SERIALIZE_TRANSACTION_NO_WITNESS
A flag that is ORed into the protocol version to designate that a transaction should be (un)serialize...
FUZZ_TARGET_INIT(rpc, initialize_rpc)
void SetRPCWarmupFinished()
constexpr auto MakeUCharSpan(V &&v) -> decltype(UCharSpanCast(Span{std::forward< V >(v)}))
Like the Span constructor, but for (const) unsigned char member types only.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
auto Join(const C &container, const S &separator, UnaryOp unary_op)
Join all container items.
Testing setup that configures a complete environment.
int64_t ConsumeTime(FuzzedDataProvider &fuzzed_data_provider, const std::optional< int64_t > &min, const std::optional< int64_t > &max) noexcept
CTxDestination ConsumeTxDestination(FuzzedDataProvider &fuzzed_data_provider) noexcept
uint256 ConsumeUInt256(FuzzedDataProvider &fuzzed_data_provider) noexcept
size_t CallOneOf(FuzzedDataProvider &fuzzed_data_provider, Callables... callables)
uint160 ConsumeUInt160(FuzzedDataProvider &fuzzed_data_provider) noexcept
void SetMockTime(int64_t nMockTimeIn)
DEPRECATED Use SetMockTime with chrono type.
const UniValue & find_value(const UniValue &obj, const std::string &name)
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
std::string EncodeBase64(Span< const unsigned char > input)
std::string EncodeBase32(Span< const unsigned char > input, bool pad)
Base32 encode.
static const int PROTOCOL_VERSION
network protocol versioning