Cuprate Consensus-Rule Differential Fuzzing
What
We propose a one-month trial engagement to stand up structured-input consensus fuzzing for Cuprate, using monero-oxide as a typed transaction generator and cuprate-consensus as the validation target. We deliberately choose to fuzz Cuprate's consensus code directly, as the RPC layer for Cuprate is still being implemented.
The first targets we'd write would cover the rule modules under consensus/rules/src/transactions/,
particularly ring_ct.rs, ring_signatures.rs, and contextual_data.rs.
We are fundraising 62 XMR for this development work, split across 4 milestones.
Who
We, Runtime Verification, are a formal methods–driven security team specializing in complex, mission-critical codebases since 2018 across both Web2 and Web3 industries. We have substantial prior experience with fuzz testing and differential fuzzing across blockchain and language-runtime systems. Select public related projects include:
- Mithril Validator Node (Solana): differential fuzzing between two Solana validator implementations, Mithril (Go) and Agave (Rust).
- wasmi: differential fuzzing of Wasmi interpreter vs multiple other Wasm interpreter implementations.
- Stellar Soroban: fuzz testing of Stellar's Soroban smart contract platform.
- Kora (Solana paymaster service): fuzzing for Kora, a Rust-based paymaster service for Solana.
This work would be carried out by our lead fuzzing engineer, supported by the wider team and shared resources.
Why
Cuprate's existing fuzzing covers six cargo-fuzz targets, all of which are at the parsing/codec
layer. Nothing currently exercises the consensus rules (consensus/rules/src/), including block
verification, transaction verification, or reorg/alt-chain logic.
Ada Logics has been doing C++ fuzzing on monerod and that work is focused on identifying crashes in the monerod implementation, which is complementary to, but distinct from the consensus-rule differential coverage this engagement would deliver — which requires structured inputs that get past parser-stage rejection.
After a review of the available Rust infrastructure and feedback from the Cuprate developers, we propose to deliver the infrastructure for in-process structured fuzzing of Cuprate's consensus crate, with monerod set up as a differential oracle via its RPC, where time permits.
How
We suggest using monerod as a differential oracle, given that monero-daemon-rpc already implements
PublishTransaction, which submits a typed monero-oxide transaction to monerod's
send_raw_transaction endpoint.
That endpoint runs the full consensus pipeline (handle_incoming_tx) and returns structured reason
codes (double_spend, fee_too_low, invalid_input, etc.), which will help localize specific
consensus rules in case of disagreements with Cuprate.
Within the trial month, we will further investigate and start building out the infrastructure for this path: a monerod driver, a thin comparison layer between Cuprate's verdict and monero-daemon-rpc's structured response, and the wiring needed to feed the same monero-oxide- generated transaction into both.
We will target a working end-to-end differential harness, but recognize the potential unknown unknowns around setup, state coordination, and keeping the response struct in sync with monero-daemon-rpc's current field set.
Scope Boundaries
-
Transactions only, not blocks: we will focus on the
publish_transactionendpoint exposed by monero-daemon-rpc, leaving the unsupportedsubmit_blockequivalent to follow-on work. - Valid transactions only: limit testing to valid transactions, identifying any bugs or crashes with Cuprate's consensus or differences between Cuprate and monerod.
-
FCMP++ is out of scope: FCMP++ isn't a target we can usefully hit today, as it is not yet
supported in monero-oxide or Cuprate's consensus crate — generating FCMP++ transactions and
validating them on the Cuprate side are both blocked upstream. The harness architecture itself
would stay usable through the upgrade (
send_raw_transactionstill callshandle_incoming_txon the fcmp++-stage branch), but the actual FCMP++ surface only becomes reachable once monero-oxide adds FCMP++ transaction support and Cuprate adds FCMP++ rules. Extending the harness to coversrc/fcmp_pp/validation paths is a natural follow-on once those upstream pieces land.
Milestones
- Fuzz harness over cuprate-consensus transaction-validation, with monero-oxide-generated valid transactions as inputs.
- Research and scaffolding for the end-to-end differential harness against monerod: regtest driver, comparison layer between Cuprate's verdict and monero-daemon-rpc's structured response, and the setup to feed the same generated transaction into both.
- Documented coverage report.
- Clearly specified on-ramp for follow-on work (full end-to-end differential mode, invalid-tx generation, block-level differential, FCMP++ rules, OSS-Fuzz integration).
An expiration date for the proposal is set for 60 days from now, on July 14th, 2026.
We are very much open to feedback and have spent the last 3 weeks consulting with the Cuprate community to understand which specific developments in this area would be most-welcomed and a priority in the first funding round for this work, for which the required funding is significantly reduced from our usual weekly rates.