mirror of
https://github.com/wownero/wownero.git
synced 2026-10-17 07:31:35 +02:00
tests: harden RPC fuzz harness setup
Initialize RPC server state used by direct handler calls, let fuzz input choose restricted or unrestricted mode, and skip iterations when the dummy core fails to initialize. Also update the RPC fuzz harness documentation after removal of the old RPC payment setup.
This commit is contained in:
@@ -120,9 +120,11 @@ namespace cryptonote
|
||||
core_rpc_server::core_rpc_server(
|
||||
core& cr
|
||||
, nodetool::node_server<cryptonote::t_cryptonote_protocol_handler<cryptonote::core> >& p2p
|
||||
, bool restricted
|
||||
)
|
||||
: m_core(cr)
|
||||
, m_p2p(p2p)
|
||||
, m_restricted(restricted)
|
||||
, disable_rpc_ban(false)
|
||||
{}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -73,6 +73,7 @@ namespace cryptonote
|
||||
core_rpc_server(
|
||||
core& cr
|
||||
, nodetool::node_server<cryptonote::t_cryptonote_protocol_handler<cryptonote::core> >& p2p
|
||||
, bool restricted = false
|
||||
);
|
||||
~core_rpc_server();
|
||||
|
||||
|
||||
@@ -9,14 +9,14 @@ These are the main fuzzing entry points, containing `LLVMFuzzerTestOneInput`, wh
|
||||
|
||||
## `initialisation.cpp` / `initialisation.h`
|
||||
|
||||
This set of source files provides initialisation helper functions to configure the `core_rpc_server` class with dummy protocols, P2P, payment modules, and other components. It also includes functions to generate fake random blocks, miners, and transactions for use in fuzzing.
|
||||
This set of source files provides initialisation helper functions to configure the `core_rpc_server` class with dummy protocols, P2P, and other components. It also includes functions to generate fake random blocks, miners, and transactions for use in fuzzing.
|
||||
|
||||
## `rpc_endpoints.cpp` / `rpc_endpoints.h` / `zmq_endpoints.cpp` / `zmq_endpoints.h`
|
||||
|
||||
These source files handle the creation of the necessary request and response objects and the invocation of specific endpoint functions. These simulate real RPC requests / ZMQ requests for the purpose of fuzzing. There are three categories of RPC endpoint functions and only one for ZMQ endpoint functions:
|
||||
|
||||
* **Safe**: Considered stable and unlikely to fail.
|
||||
* **Risky**: More prone to failure and early exits, especially if no valid blockchain is generated or no payment modules are configured.
|
||||
* **Risky**: More prone to failure and early exits, especially if no valid blockchain is generated.
|
||||
* **Priority**: Most critical RPC endpoint functions that will at least run once per iteration.
|
||||
|
||||
# Building the Fuzzing Harnesses
|
||||
@@ -24,7 +24,7 @@ These source files handle the creation of the necessary request and response obj
|
||||
The same `fuzz_rpc.cpp` is compiled into two versions of the fuzzer, one with the `SAFE` macro defined and one without. Meanwhile, `fuzz_zmq` is compiled into a single version.
|
||||
|
||||
* With `SAFE` defined: Only safe endpoint functions are fuzzed.
|
||||
* Without `SAFE`: Both safe and risky functions are included in the fuzzing process, and payment modules are configured.
|
||||
* Without `SAFE`: Both safe and risky functions are included in the fuzzing process.
|
||||
|
||||
# Fuzzing Harness Flow
|
||||
|
||||
@@ -35,8 +35,7 @@ Random data is used to generate selectors that choose an RPC endpoint function /
|
||||
|
||||
## `initialise_rpc_core` / `initialise_rpc_server`
|
||||
|
||||
At the start of each fuzzing iteration, a `core_rpc_server` object is created and initialised with dummy protocols, P2P, payment modules, and more.
|
||||
If the `SAFE` macro is not defined, the payment module will also be initialised.
|
||||
At the start of each fuzzing iteration, a `core_rpc_server` object is created and initialised with dummy protocols and P2P. The fuzz input selects whether the server runs in restricted or unrestricted RPC mode.
|
||||
This step is skipped for `fuzz_zmq`.
|
||||
|
||||
## `generate_random_blocks`
|
||||
|
||||
@@ -57,8 +57,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
|
||||
// Initialise core and core_rpc_server
|
||||
auto core_env = initialise_rpc_core();
|
||||
if (!core_env) {
|
||||
return 0;
|
||||
}
|
||||
auto& dummy_core = core_env->core;
|
||||
auto rpc_handler = initialise_rpc_server(*dummy_core, provider, !is_safe_mode);
|
||||
auto rpc_handler = initialise_rpc_server(*dummy_core, provider.ConsumeBool());
|
||||
|
||||
// Generate random blocks/miners/transactions and push to the core blockchains
|
||||
if (!generate_random_blocks(*dummy_core, provider)) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "serialization/binary_utils.h"
|
||||
#include "serialization/variant.h"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/program_options/variables_map.hpp>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
@@ -51,21 +52,29 @@ std::unique_ptr<CoreEnv> initialise_rpc_core() {
|
||||
cryptonote::core::init_options(desc);
|
||||
boost::program_options::variables_map vm;
|
||||
|
||||
// Add command line argument to configure the rpc core object to use regression testing mode (FAKECHAIN)
|
||||
// Enabling FAKECHAIN mode allows skipping validation logic of the authors signature and transactions ID
|
||||
// on valid blocks and transactions while keeping other logic
|
||||
std::vector<const char*> argv = {"fuzz", "--regtest"};
|
||||
// Add command line arguments to configure the rpc core object to use regression testing mode (FAKECHAIN)
|
||||
// and a throwaway data directory. Enabling FAKECHAIN mode allows skipping validation logic of the authors
|
||||
// signature and transactions ID on valid blocks and transactions while keeping other logic.
|
||||
const boost::filesystem::path data_dir = boost::filesystem::temp_directory_path() / "monero-fuzz-rpc";
|
||||
std::vector<std::string> args = {"fuzz", "--regtest", "--offline", "--data-dir", data_dir.string()};
|
||||
std::vector<const char*> argv;
|
||||
argv.reserve(args.size());
|
||||
for (const auto& arg : args) {
|
||||
argv.push_back(arg.c_str());
|
||||
}
|
||||
boost::program_options::store(boost::program_options::parse_command_line(argv.size(), argv.data(), desc), vm);
|
||||
boost::program_options::notify(vm);
|
||||
|
||||
// Initialise the dummy core with all the above settings
|
||||
env->core->init(vm);
|
||||
if (!env->core->init(vm)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
// Build the core_rpc_server handler object with the configured dummy core object
|
||||
std::unique_ptr<RpcServerBundle> initialise_rpc_server(cryptonote::core& dummy_core, FuzzedDataProvider& provider, bool need_payment) {
|
||||
std::unique_ptr<RpcServerBundle> initialise_rpc_server(cryptonote::core& dummy_core, bool restricted) {
|
||||
// Create rpc server bundle object
|
||||
auto bundle = std::make_unique<RpcServerBundle>();
|
||||
|
||||
@@ -73,7 +82,7 @@ std::unique_ptr<RpcServerBundle> initialise_rpc_server(cryptonote::core& dummy_c
|
||||
bundle->proto_handler = std::make_unique<cryptonote::t_cryptonote_protocol_handler<cryptonote::core>>(dummy_core, nullptr, true);
|
||||
bundle->proto_handler->set_no_sync(false);
|
||||
bundle->dummy_p2p = std::make_unique<nodetool::node_server<cryptonote::t_cryptonote_protocol_handler<cryptonote::core>>>(*bundle->proto_handler);
|
||||
bundle->rpc = std::make_unique<cryptonote::core_rpc_server>(dummy_core, *bundle->dummy_p2p);
|
||||
bundle->rpc = std::make_unique<cryptonote::core_rpc_server>(dummy_core, *bundle->dummy_p2p, restricted);
|
||||
|
||||
return bundle;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// Define templates for dummy protocol object
|
||||
template class nodetool::node_server<cryptonote::t_cryptonote_protocol_handler<cryptonote::core>>;
|
||||
|
||||
struct DummyProtocol : public cryptonote::i_cryptonote_protocol {
|
||||
struct DummyProtocol final : public cryptonote::i_cryptonote_protocol {
|
||||
public:
|
||||
bool is_synchronized() const;
|
||||
bool relay_transactions(cryptonote::NOTIFY_NEW_TRANSACTIONS::request&, const boost::uuids::uuid&, epee::net_utils::zone, cryptonote::relay_method);
|
||||
@@ -25,7 +25,7 @@ struct CoreEnv {
|
||||
};
|
||||
|
||||
std::unique_ptr<CoreEnv> initialise_rpc_core();
|
||||
std::unique_ptr<RpcServerBundle> initialise_rpc_server(cryptonote::core&, FuzzedDataProvider&, bool);
|
||||
std::unique_ptr<RpcServerBundle> initialise_rpc_server(cryptonote::core&, bool);
|
||||
bool generate_random_blocks(cryptonote::core&, FuzzedDataProvider&);
|
||||
|
||||
extern std::vector<crypto::hash> cached_tx_hashes;
|
||||
|
||||
Reference in New Issue
Block a user