Skip to content

Conversation

@jeffro256
Copy link
Contributor

@jeffro256 jeffro256 commented Oct 10, 2025

This replaces ver_rct_non_semantics_simple_cached() with an API that offloads
the responsibility of tracking input verification successes to the caller. The
main caller of this function in the codebase, cryptonote::Blockchain() instead
keeps track of the verification results for transaction in the mempool by
storing a "verification ID" in the mempool metadata table (with txpool_tx_meta_t).
This has several benefits, including:

  • When the mempool is large (>8192 txs), we no longer experience cache misses and unnecessarily re-verify ring signatures. This greatly improves block propagation time for FCMP++ blocks under load
  • For the same reason, reorg handling can be sped up by storing verification IDs of transactions popped from the chain
  • Speeds up re-validating every mempool transaction on fork change (monerod revalidates the whole tx-pool on HFs #10142)
  • Caches results for every single type of Monero transaction, not just latest RCT type
  • Cache persists over a node restart
  • Uses 512KiB less RAM ($8192 * 2 * 32B$)
  • No additional storage or DB migration required since txpool_tx_meta_t already had padding allocated
  • Moves more verification logic out of cryptonote::Blockchain

Furthermore, this opens the door to future multi-threaded block verification
speed-ups. Right now, transactions' input proof verification is limited to one
transaction at a time. However, one can imagine a scenario with verification IDs
where input proofs are optimistically multi-threaded in advance of block
processing. Then, even though ring member fetching and verification is
single-threaded inside of cryptonote::Blockchain::check_tx_inputs(), the
single thread can skip the CPU-intensive cryptographic code if the verification
ID allows it.

Also changes the default log category in tx_verification_utils.cpp from "blockchain" to "verify".

To run the benchmarks for large mempool block propagation, simply change the ENABLED variable in bench_p2p_heavy_block_propagation_speed() to True, then run the p2p functional test. You can then
compare performance against the master branch.

Depends on #10156, #10172

@jeffro256
Copy link
Contributor Author

jeffro256 commented Oct 10, 2025

The way that this would work together with the FCMP++ integration is that two new functions would be created in tx_verifications_utils: ver_input_proofs_fcmps(), and an overload of make_input_verification_id() taking the deferenced FCMP tree root instead of the mix rings. The new make_input_verification_id() overload would use a different domain separator. Blockchain::check_tx_inputs() and Blockchain::pop_block_from_blockchain() would be modified to deference the FCMP tree root instead to calculate the verification ID for a FCMP++ transaction. And then obviously, Blockchain::check_tx_inputs() would call ver_input_proofs_fcmps() instead of ver_input_proofs_rings() for FCMP++ transactions. ver_input_proofs_rings() would call Blockchain::expand_transaction_2() internally and necessary FCMP++ verify functions.

Copy link
Collaborator

@j-berman j-berman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is clean. I also appreciate the new verification utils. I have only nits on first pass (looks like you're also still working on tests), the design looks good to me. I also wrote some sanity tests for my own comfort.

@jeffro256
Copy link
Contributor Author

jeffro256 commented Oct 16, 2025

Here was my results of the benchmark on against master:

Bench: mine and propagate blocks until mempool is empty of profitable txs
        * Mined 54 txs in 0.57s, propagated in 0.48s
        * Mined 54 txs in 0.45s, propagated in 0.46s
        * Mined 54 txs in 0.66s, propagated in 0.47s
        * Mined 54 txs in 0.50s, propagated in 0.48s
        * Mined 54 txs in 0.58s, propagated in 0.47s
        * Mined 54 txs in 0.36s, propagated in 0.47s
        * Mined 54 txs in 0.38s, propagated in 0.46s
        * Mined 54 txs in 0.59s, propagated in 0.48s
        * Mined 54 txs in 0.69s, propagated in 0.48s
        * Mined 54 txs in 0.53s, propagated in 0.46s
        * Mined 54 txs in 0.41s, propagated in 0.50s
        * Mined 54 txs in 0.63s, propagated in 0.47s
        * Mined 54 txs in 0.40s, propagated in 0.47s
        * Mined 54 txs in 0.78s, propagated in 0.47s
        * Mined 54 txs in 0.55s, propagated in 0.48s
        * Mined 54 txs in 0.43s, propagated in 0.49s
        * Mined 54 txs in 0.69s, propagated in 0.47s
        * Mined 54 txs in 0.57s, propagated in 0.50s
        * Mined 54 txs in 0.48s, propagated in 0.47s
        * Mined 54 txs in 0.76s, propagated in 0.46s
        * Mined 54 txs in 0.53s, propagated in 0.47s
        * Mined 55 txs in 0.42s, propagated in 0.48s
        * Mined 55 txs in 0.45s, propagated in 0.48s
        * Mined 55 txs in 0.51s, propagated in 0.49s
        * Mined 55 txs in 0.49s, propagated in 0.47s
        * Mined 55 txs in 0.40s, propagated in 0.47s
        * Mined 55 txs in 0.52s, propagated in 0.47s
        * Mined 55 txs in 0.53s, propagated in 0.48s
        * Mined 55 txs in 0.43s, propagated in 0.47s
        * Mined 55 txs in 0.55s, propagated in 0.48s
        * Mined 55 txs in 0.39s, propagated in 0.48s
        * Mined 55 txs in 0.48s, propagated in 0.49s
        * Mined 55 txs in 0.50s, propagated in 0.47s
        * Mined 55 txs in 0.40s, propagated in 0.49s
        * Mined 55 txs in 0.51s, propagated in 0.48s
        * Mined 55 txs in 0.53s, propagated in 0.48s
        * Mined 55 txs in 0.43s, propagated in 0.48s
        * Mined 55 txs in 0.49s, propagated in 0.47s
        * Mined 55 txs in 0.54s, propagated in 0.47s
        * Mined 55 txs in 0.75s, propagated in 0.49s
        * Mined 55 txs in 0.52s, propagated in 0.48s
        * Mined 55 txs in 0.42s, propagated in 0.49s
        * Mined 55 txs in 0.48s, propagated in 0.49s
        * Mined 55 txs in 0.46s, propagated in 0.47s
        * Mined 55 txs in 0.82s, propagated in 0.47s
        * Mined 55 txs in 0.55s, propagated in 0.47s
        * Mined 55 txs in 0.44s, propagated in 0.47s
        * Mined 55 txs in 0.44s, propagated in 0.49s
        * Mined 55 txs in 0.57s, propagated in 0.47s
        * Mined 55 txs in 0.39s, propagated in 0.47s
        * Mined 55 txs in 0.37s, propagated in 0.54s
        * Mined 55 txs in 0.47s, propagated in 0.48s
        * Mined 55 txs in 0.48s, propagated in 0.47s
        * Mined 55 txs in 0.40s, propagated in 0.48s
        * Mined 55 txs in 0.45s, propagated in 0.47s
        * Mined 55 txs in 0.37s, propagated in 0.49s
        * Mined 55 txs in 0.41s, propagated in 0.48s
        * Mined 55 txs in 0.52s, propagated in 0.49s
        * Mined 55 txs in 0.80s, propagated in 0.48s
        * Mined 55 txs in 0.70s, propagated in 0.48s
        * Mined 55 txs in 0.61s, propagated in 0.48s
        * Mined 55 txs in 0.55s, propagated in 0.47s
        * Mined 55 txs in 0.52s, propagated in 0.47s
        * Mined 55 txs in 0.41s, propagated in 0.49s
        * Mined 55 txs in 0.39s, propagated in 0.48s
        * Mined 55 txs in 0.55s, propagated in 0.48s
        * Mined 55 txs in 0.39s, propagated in 0.48s
        * Mined 55 txs in 0.42s, propagated in 0.48s
        * Mined 55 txs in 1.11s, propagated in 0.47s
        * Mined 55 txs in 0.40s, propagated in 0.48s
        * Mined 55 txs in 0.41s, propagated in 0.48s
        * Mined 56 txs in 0.46s, propagated in 0.49s
        * Mined 56 txs in 0.71s, propagated in 0.49s
        * Mined 56 txs in 0.30s, propagated in 0.43s
        * Mined 56 txs in 0.53s, propagated in 0.49s
        * Mined 56 txs in 0.40s, propagated in 0.49s
        * Mined 56 txs in 0.41s, propagated in 0.49s
        * Mined 56 txs in 0.42s, propagated in 0.48s
        * Mined 56 txs in 0.39s, propagated in 0.50s
        * Mined 56 txs in 0.42s, propagated in 0.51s
        * Mined 56 txs in 0.54s, propagated in 0.48s
        * Mined 56 txs in 0.73s, propagated in 0.48s
        * Mined 56 txs in 0.39s, propagated in 0.48s
        * Mined 56 txs in 0.53s, propagated in 0.48s
        * Mined 56 txs in 0.44s, propagated in 0.50s
        * Mined 56 txs in 0.46s, propagated in 0.48s
        * Mined 56 txs in 0.51s, propagated in 0.48s
        * Mined 56 txs in 0.47s, propagated in 0.50s
        * Mined 56 txs in 0.44s, propagated in 0.49s
        * Mined 56 txs in 0.43s, propagated in 0.48s
        * Mined 56 txs in 0.93s, propagated in 0.49s
        * Mined 56 txs in 0.60s, propagated in 0.48s
        * Mined 56 txs in 0.59s, propagated in 0.49s
        * Mined 56 txs in 0.55s, propagated in 0.48s
        * Mined 56 txs in 0.55s, propagated in 0.48s
        * Mined 56 txs in 0.57s, propagated in 0.50s
        * Mined 56 txs in 0.56s, propagated in 0.48s
        * Mined 56 txs in 0.76s, propagated in 0.49s
        * Mined 56 txs in 0.52s, propagated in 0.49s
        * Mined 56 txs in 0.50s, propagated in 0.48s
        * Mined 56 txs in 0.45s, propagated in 0.48s
        * Mined 56 txs in 0.38s, propagated in 0.48s
        * Mined 56 txs in 0.54s, propagated in 0.49s
        * Mined 56 txs in 0.42s, propagated in 0.50s
        * Mined 56 txs in 0.42s, propagated in 0.48s
        * Mined 56 txs in 0.60s, propagated in 0.49s
        * Mined 56 txs in 0.68s, propagated in 0.53s
        * Mined 56 txs in 0.50s, propagated in 0.49s
        * Mined 56 txs in 0.56s, propagated in 0.49s
        * Mined 56 txs in 0.45s, propagated in 0.49s
        * Mined 56 txs in 0.51s, propagated in 0.49s
        * Mined 56 txs in 0.81s, propagated in 0.50s
        * Mined 56 txs in 0.39s, propagated in 0.52s
        * Mined 56 txs in 0.43s, propagated in 0.48s
        * Mined 56 txs in 0.40s, propagated in 0.48s
        * Mined 56 txs in 0.41s, propagated in 0.49s
        * Mined 56 txs in 0.57s, propagated in 0.48s
        * Mined 56 txs in 0.59s, propagated in 0.49s
        * Mined 56 txs in 0.47s, propagated in 0.49s
        * Mined 56 txs in 0.40s, propagated in 0.50s
        * Mined 56 txs in 0.54s, propagated in 0.48s
        * Mined 57 txs in 0.39s, propagated in 0.50s
        * Mined 57 txs in 0.44s, propagated in 0.50s
        * Mined 57 txs in 0.65s, propagated in 0.49s
        * Mined 57 txs in 0.40s, propagated in 0.50s
        * Mined 57 txs in 0.91s, propagated in 0.49s
        * Mined 57 txs in 0.40s, propagated in 0.49s
        * Mined 57 txs in 0.49s, propagated in 0.51s
        * Mined 57 txs in 0.58s, propagated in 0.49s
        * Mined 57 txs in 0.68s, propagated in 0.50s
        * Mined 57 txs in 0.44s, propagated in 0.49s
        * Mined 57 txs in 0.74s, propagated in 0.48s
        * Mined 57 txs in 1.23s, propagated in 0.49s
        * Mined 57 txs in 0.73s, propagated in 0.49s
        * Mined 57 txs in 0.45s, propagated in 0.52s
        * Mined 57 txs in 0.42s, propagated in 1.24s
        * Mined 57 txs in 1.10s, propagated in 0.50s
        * Mined 57 txs in 0.40s, propagated in 0.49s
        * Mined 57 txs in 0.48s, propagated in 0.51s
        * Mined 57 txs in 0.50s, propagated in 0.83s
        * Mined 57 txs in 1.09s, propagated in 0.49s
        * Mined 57 txs in 1.00s, propagated in 0.49s
        * Mined 57 txs in 0.65s, propagated in 0.49s
        * Mined 57 txs in 0.71s, propagated in 0.51s
        * Mined 57 txs in 0.49s, propagated in 0.78s
        * Mined 57 txs in 0.42s, propagated in 0.49s
        * Mined 57 txs in 0.55s, propagated in 0.58s
        * Mined 57 txs in 1.25s, propagated in 0.51s
        * Mined 57 txs in 0.66s, propagated in 0.51s
        * Mined 57 txs in 0.75s, propagated in 0.52s
        * Mined 57 txs in 0.42s, propagated in 0.49s
        * Mined 57 txs in 0.48s, propagated in 0.51s
        * Mined 57 txs in 0.48s, propagated in 0.49s
        * Mined 57 txs in 0.48s, propagated in 0.49s
        * Mined 57 txs in 0.40s, propagated in 0.49s
        * Mined 57 txs in 0.47s, propagated in 0.49s
        * Mined 57 txs in 0.43s, propagated in 0.49s
        * Mined 57 txs in 0.39s, propagated in 0.49s
        * Mined 57 txs in 0.52s, propagated in 0.49s
        * Mined 57 txs in 0.54s, propagated in 0.50s
        * Mined 57 txs in 0.40s, propagated in 0.49s
        * Mined 57 txs in 0.61s, propagated in 0.49s
        * Mined 57 txs in 0.48s, propagated in 0.49s
        * Mined 57 txs in 0.79s, propagated in 0.50s
        * Mined 57 txs in 0.46s, propagated in 0.53s
        * Mined 57 txs in 0.66s, propagated in 0.49s
        * Mined 57 txs in 0.46s, propagated in 0.50s
        * Mined 57 txs in 0.42s, propagated in 0.51s
        * Mined 57 txs in 0.63s, propagated in 0.50s
        * Mined 57 txs in 0.67s, propagated in 0.49s
        * Mined 57 txs in 0.64s, propagated in 0.49s
        * Mined 58 txs in 0.44s, propagated in 0.51s
        * Mined 58 txs in 0.39s, propagated in 0.49s
        * Mined 58 txs in 0.69s, propagated in 0.49s
        * Mined 58 txs in 0.45s, propagated in 0.49s
        * Mined 58 txs in 0.47s, propagated in 0.51s
        * Mined 58 txs in 0.49s, propagated in 0.49s
        * Mined 58 txs in 0.49s, propagated in 0.50s
        * Mined 58 txs in 0.67s, propagated in 0.50s
        * Mined 58 txs in 0.51s, propagated in 0.50s
        * Mined 58 txs in 0.68s, propagated in 0.50s
        * Mined 58 txs in 0.56s, propagated in 0.52s
        * Mined 58 txs in 0.40s, propagated in 0.50s
        * Mined 58 txs in 0.39s, propagated in 0.51s
        * Mined 58 txs in 0.47s, propagated in 0.50s
        * Mined 58 txs in 0.66s, propagated in 0.50s
        * Mined 58 txs in 0.43s, propagated in 0.50s
        * Mined 58 txs in 0.50s, propagated in 0.50s
        * Mined 58 txs in 0.43s, propagated in 0.50s
        * Mined 58 txs in 0.46s, propagated in 0.49s
        * Mined 58 txs in 0.47s, propagated in 0.49s
        * Mined 58 txs in 0.65s, propagated in 0.51s
        * Mined 58 txs in 0.45s, propagated in 0.50s
        * Mined 58 txs in 0.43s, propagated in 0.49s
        * Mined 58 txs in 0.54s, propagated in 0.49s
        * Mined 58 txs in 0.64s, propagated in 0.50s
        * Mined 58 txs in 0.45s, propagated in 0.50s
        * Mined 58 txs in 0.67s, propagated in 0.50s
        * Mined 58 txs in 0.47s, propagated in 0.53s
        * Mined 58 txs in 0.40s, propagated in 0.52s
        * Mined 58 txs in 0.42s, propagated in 0.52s
        * Mined 58 txs in 0.45s, propagated in 0.50s
        * Mined 58 txs in 0.38s, propagated in 0.49s
        * Mined 58 txs in 0.39s, propagated in 0.50s
        * Mined 58 txs in 0.50s, propagated in 0.50s
        * Mined 58 txs in 0.50s, propagated in 0.50s
        * Mined 58 txs in 0.41s, propagated in 0.50s
        * Mined 58 txs in 0.48s, propagated in 0.52s
        * Mined 58 txs in 0.46s, propagated in 0.50s
        * Mined 58 txs in 0.47s, propagated in 0.49s
        * Mined 58 txs in 0.77s, propagated in 0.50s
        * Mined 58 txs in 0.43s, propagated in 0.50s
        * Mined 58 txs in 0.64s, propagated in 0.50s
        * Mined 58 txs in 0.70s, propagated in 0.50s
        * Mined 58 txs in 0.40s, propagated in 0.50s
        * Mined 58 txs in 0.74s, propagated in 0.51s
        * Mined 58 txs in 1.64s, propagated in 0.50s
        * Mined 58 txs in 0.57s, propagated in 0.50s
        * Mined 58 txs in 0.40s, propagated in 0.50s
        * Mined 58 txs in 0.45s, propagated in 0.49s
        * Mined 58 txs in 0.43s, propagated in 0.50s
        * Mined 59 txs in 0.45s, propagated in 0.50s
        * Mined 59 txs in 0.55s, propagated in 0.51s
        * Mined 59 txs in 0.45s, propagated in 0.52s
        * Mined 59 txs in 0.47s, propagated in 0.51s
        * Mined 59 txs in 0.58s, propagated in 0.53s
        * Mined 59 txs in 0.41s, propagated in 0.50s
        * Mined 59 txs in 0.40s, propagated in 0.51s
        * Mined 59 txs in 0.52s, propagated in 0.51s
        * Mined 59 txs in 0.82s, propagated in 0.52s
        * Mined 59 txs in 0.88s, propagated in 0.51s
        * Mined 59 txs in 0.40s, propagated in 0.52s
        * Mined 59 txs in 0.41s, propagated in 0.50s
        * Mined 59 txs in 0.46s, propagated in 0.50s
        * Mined 59 txs in 0.43s, propagated in 0.50s
        * Mined 59 txs in 0.40s, propagated in 0.50s
        * Mined 59 txs in 0.42s, propagated in 0.52s
        * Mined 59 txs in 0.40s, propagated in 0.50s
        * Mined 59 txs in 0.41s, propagated in 0.51s
        * Mined 59 txs in 0.67s, propagated in 0.52s
        * Mined 59 txs in 0.64s, propagated in 0.50s
        * Mined 59 txs in 0.50s, propagated in 0.50s
        * Mined 59 txs in 0.41s, propagated in 0.52s
        * Mined 59 txs in 0.59s, propagated in 0.51s
        * Mined 59 txs in 0.96s, propagated in 0.51s
        * Mined 59 txs in 0.49s, propagated in 0.55s
        * Mined 59 txs in 0.45s, propagated in 0.52s
        * Mined 59 txs in 0.62s, propagated in 0.53s
        * Mined 59 txs in 0.54s, propagated in 1.73s
        * Mined 59 txs in 0.64s, propagated in 0.50s
        * Mined 59 txs in 0.52s, propagated in 0.50s
        * Mined 59 txs in 0.53s, propagated in 0.50s
        * Mined 59 txs in 0.52s, propagated in 0.51s
        * Mined 59 txs in 0.66s, propagated in 0.50s
        * Mined 59 txs in 0.58s, propagated in 0.51s
        * Mined 59 txs in 0.48s, propagated in 0.52s
        * Mined 59 txs in 0.50s, propagated in 0.51s
        * Mined 59 txs in 0.54s, propagated in 0.51s
        * Mined 59 txs in 0.57s, propagated in 0.53s
        * Mined 59 txs in 0.40s, propagated in 0.51s
        * Mined 59 txs in 0.50s, propagated in 0.53s
        * Mined 59 txs in 0.84s, propagated in 0.51s
        * Mined 59 txs in 0.55s, propagated in 0.50s
        * Mined 59 txs in 0.40s, propagated in 0.53s
        * Mined 59 txs in 1.28s, propagated in 0.52s
        * Mined 59 txs in 0.42s, propagated in 0.51s
        * Mined 59 txs in 0.46s, propagated in 0.51s
        * Mined 59 txs in 0.45s, propagated in 0.50s
        * Mined 59 txs in 0.41s, propagated in 0.51s
        * Mined 59 txs in 0.45s, propagated in 0.51s
        * Mined 59 txs in 0.40s, propagated in 0.51s
        * Mined 60 txs in 0.65s, propagated in 0.53s
        * Mined 60 txs in 0.76s, propagated in 0.51s
        * Mined 60 txs in 0.43s, propagated in 0.52s
        * Mined 60 txs in 0.51s, propagated in 0.51s
        * Mined 60 txs in 0.92s, propagated in 0.52s
        * Mined 60 txs in 0.60s, propagated in 0.52s
        * Mined 60 txs in 0.43s, propagated in 0.51s
        * Mined 60 txs in 0.58s, propagated in 0.51s
        * Mined 60 txs in 0.58s, propagated in 0.52s
        * Mined 60 txs in 0.43s, propagated in 0.52s
        * Mined 60 txs in 0.69s, propagated in 0.52s
        * Mined 60 txs in 0.57s, propagated in 0.51s
        * Mined 60 txs in 0.58s, propagated in 0.51s
        * Mined 60 txs in 0.37s, propagated in 0.52s
        * Mined 60 txs in 0.82s, propagated in 0.52s
        * Mined 60 txs in 0.31s, propagated in 0.40s
        * Mined 40 txs in 0.12s, propagated in 0.22s
    Analysis of 16384-tx mempool handling:
        Average mining time: 0.54
        Median mining time: 0.49
        Average block propagation time: 0.50
        Median block propagation time: 0.49

Here's my results against this PR:

Bench: mine and propagate blocks until mempool is empty of profitable txs
        * Mined 54 txs in 0.28s, propagated in 0.31s
        * Mined 54 txs in 0.48s, propagated in 0.31s
        * Mined 54 txs in 0.29s, propagated in 0.32s
        * Mined 54 txs in 0.24s, propagated in 0.32s
        * Mined 54 txs in 0.53s, propagated in 0.31s
        * Mined 54 txs in 0.30s, propagated in 0.31s
        * Mined 54 txs in 0.26s, propagated in 0.33s
        * Mined 54 txs in 0.33s, propagated in 0.31s
        * Mined 54 txs in 0.27s, propagated in 0.31s
        * Mined 54 txs in 0.25s, propagated in 0.31s
        * Mined 54 txs in 0.34s, propagated in 0.31s
        * Mined 54 txs in 0.22s, propagated in 0.31s
        * Mined 54 txs in 0.30s, propagated in 0.31s
        * Mined 54 txs in 0.33s, propagated in 0.31s
        * Mined 54 txs in 0.79s, propagated in 0.32s
        * Mined 54 txs in 0.31s, propagated in 0.32s
        * Mined 54 txs in 0.36s, propagated in 0.31s
        * Mined 54 txs in 0.23s, propagated in 0.31s
        * Mined 54 txs in 0.36s, propagated in 0.32s
        * Mined 54 txs in 1.26s, propagated in 0.34s
        * Mined 54 txs in 0.61s, propagated in 0.31s
        * Mined 54 txs in 0.23s, propagated in 0.31s
        * Mined 54 txs in 0.37s, propagated in 0.33s
        * Mined 54 txs in 0.39s, propagated in 0.31s
        * Mined 54 txs in 0.35s, propagated in 0.31s
        * Mined 54 txs in 0.26s, propagated in 0.31s
        * Mined 54 txs in 0.63s, propagated in 0.31s
        * Mined 54 txs in 0.51s, propagated in 0.31s
        * Mined 54 txs in 0.33s, propagated in 0.31s
        * Mined 54 txs in 0.62s, propagated in 0.32s
        * Mined 54 txs in 0.37s, propagated in 0.33s
        * Mined 54 txs in 0.62s, propagated in 0.31s
        * Mined 54 txs in 0.24s, propagated in 0.32s
        * Mined 55 txs in 0.36s, propagated in 0.49s
        * Mined 55 txs in 0.41s, propagated in 0.43s
        * Mined 55 txs in 0.25s, propagated in 0.32s
        * Mined 55 txs in 0.22s, propagated in 0.32s
        * Mined 55 txs in 0.31s, propagated in 0.32s
        * Mined 55 txs in 0.25s, propagated in 0.33s
        * Mined 55 txs in 0.25s, propagated in 0.32s
        * Mined 55 txs in 0.28s, propagated in 0.32s
        * Mined 55 txs in 0.31s, propagated in 0.32s
        * Mined 55 txs in 0.54s, propagated in 0.32s
        * Mined 55 txs in 0.25s, propagated in 0.32s
        * Mined 55 txs in 0.29s, propagated in 0.32s
        * Mined 55 txs in 0.28s, propagated in 0.32s
        * Mined 55 txs in 0.38s, propagated in 0.33s
        * Mined 55 txs in 0.25s, propagated in 0.32s
        * Mined 55 txs in 0.23s, propagated in 0.32s
        * Mined 55 txs in 0.44s, propagated in 0.32s
        * Mined 55 txs in 0.34s, propagated in 0.32s
        * Mined 55 txs in 0.24s, propagated in 0.32s
        * Mined 55 txs in 0.48s, propagated in 0.32s
        * Mined 55 txs in 0.24s, propagated in 0.32s
        * Mined 55 txs in 0.38s, propagated in 0.33s
        * Mined 55 txs in 0.53s, propagated in 0.32s
        * Mined 55 txs in 0.26s, propagated in 0.32s
        * Mined 55 txs in 0.34s, propagated in 0.32s
        * Mined 55 txs in 0.47s, propagated in 0.33s
        * Mined 55 txs in 0.27s, propagated in 0.33s
        * Mined 55 txs in 0.27s, propagated in 0.32s
        * Mined 55 txs in 0.31s, propagated in 0.32s
        * Mined 55 txs in 0.24s, propagated in 0.33s
        * Mined 55 txs in 0.38s, propagated in 0.32s
        * Mined 55 txs in 0.25s, propagated in 0.32s
        * Mined 55 txs in 0.34s, propagated in 0.32s
        * Mined 55 txs in 0.27s, propagated in 0.32s
        * Mined 55 txs in 0.25s, propagated in 0.32s
        * Mined 55 txs in 0.38s, propagated in 0.32s
        * Mined 55 txs in 0.56s, propagated in 0.32s
        * Mined 55 txs in 0.43s, propagated in 0.34s
        * Mined 55 txs in 0.34s, propagated in 0.32s
        * Mined 55 txs in 0.25s, propagated in 0.32s
        * Mined 55 txs in 0.44s, propagated in 0.32s
        * Mined 55 txs in 0.32s, propagated in 0.32s
        * Mined 55 txs in 0.24s, propagated in 0.32s
        * Mined 55 txs in 0.52s, propagated in 0.32s
        * Mined 55 txs in 0.25s, propagated in 0.31s
        * Mined 55 txs in 0.30s, propagated in 0.33s
        * Mined 55 txs in 0.32s, propagated in 0.32s
        * Mined 55 txs in 0.29s, propagated in 0.32s
        * Mined 55 txs in 0.25s, propagated in 0.35s
        * Mined 55 txs in 0.28s, propagated in 0.32s
        * Mined 56 txs in 0.25s, propagated in 0.32s
        * Mined 56 txs in 0.25s, propagated in 0.32s
        * Mined 56 txs in 0.57s, propagated in 0.32s
        * Mined 56 txs in 0.25s, propagated in 0.34s
        * Mined 56 txs in 0.38s, propagated in 0.32s
        * Mined 56 txs in 0.34s, propagated in 0.33s
        * Mined 56 txs in 0.22s, propagated in 0.33s
        * Mined 56 txs in 0.24s, propagated in 0.32s
        * Mined 56 txs in 0.33s, propagated in 0.32s
        * Mined 56 txs in 0.25s, propagated in 0.32s
        * Mined 56 txs in 0.46s, propagated in 0.32s
        * Mined 56 txs in 0.54s, propagated in 0.34s
        * Mined 56 txs in 0.47s, propagated in 0.32s
        * Mined 56 txs in 0.38s, propagated in 0.32s
        * Mined 56 txs in 0.34s, propagated in 0.33s
        * Mined 56 txs in 0.24s, propagated in 0.32s
        * Mined 56 txs in 0.24s, propagated in 0.35s
        * Mined 56 txs in 0.22s, propagated in 0.32s
        * Mined 56 txs in 0.29s, propagated in 0.32s
        * Mined 56 txs in 0.35s, propagated in 0.34s
        * Mined 56 txs in 0.35s, propagated in 0.32s
        * Mined 56 txs in 0.44s, propagated in 0.32s
        * Mined 56 txs in 0.23s, propagated in 0.32s
        * Mined 56 txs in 0.32s, propagated in 0.32s
        * Mined 56 txs in 0.68s, propagated in 0.33s
        * Mined 56 txs in 0.53s, propagated in 0.33s
        * Mined 56 txs in 0.32s, propagated in 0.32s
        * Mined 56 txs in 0.30s, propagated in 0.34s
        * Mined 56 txs in 0.74s, propagated in 0.32s
        * Mined 56 txs in 0.30s, propagated in 0.37s
        * Mined 56 txs in 0.24s, propagated in 0.33s
        * Mined 56 txs in 0.25s, propagated in 0.33s
        * Mined 56 txs in 0.25s, propagated in 0.32s
        * Mined 56 txs in 0.36s, propagated in 0.32s
        * Mined 56 txs in 0.30s, propagated in 0.32s
        * Mined 56 txs in 0.77s, propagated in 0.35s
        * Mined 56 txs in 0.25s, propagated in 0.32s
        * Mined 56 txs in 0.40s, propagated in 0.32s
        * Mined 56 txs in 0.40s, propagated in 0.32s
        * Mined 56 txs in 0.30s, propagated in 0.32s
        * Mined 56 txs in 0.48s, propagated in 0.32s
        * Mined 56 txs in 0.35s, propagated in 0.32s
        * Mined 56 txs in 0.44s, propagated in 0.32s
        * Mined 56 txs in 0.41s, propagated in 0.33s
        * Mined 56 txs in 0.34s, propagated in 0.32s
        * Mined 56 txs in 0.47s, propagated in 0.32s
        * Mined 56 txs in 0.27s, propagated in 0.32s
        * Mined 56 txs in 0.24s, propagated in 0.32s
        * Mined 56 txs in 0.34s, propagated in 0.32s
        * Mined 56 txs in 0.26s, propagated in 0.32s
        * Mined 57 txs in 0.45s, propagated in 0.33s
        * Mined 57 txs in 0.39s, propagated in 0.34s
        * Mined 57 txs in 0.25s, propagated in 0.33s
        * Mined 57 txs in 0.27s, propagated in 0.33s
        * Mined 57 txs in 0.29s, propagated in 0.33s
        * Mined 57 txs in 0.36s, propagated in 0.34s
        * Mined 57 txs in 0.28s, propagated in 0.32s
        * Mined 57 txs in 0.46s, propagated in 0.33s
        * Mined 57 txs in 0.26s, propagated in 0.33s
        * Mined 57 txs in 0.27s, propagated in 0.34s
        * Mined 57 txs in 0.30s, propagated in 0.33s
        * Mined 57 txs in 0.25s, propagated in 0.33s
        * Mined 57 txs in 0.42s, propagated in 0.33s
        * Mined 57 txs in 0.41s, propagated in 0.33s
        * Mined 57 txs in 0.31s, propagated in 0.33s
        * Mined 57 txs in 0.45s, propagated in 0.33s
        * Mined 57 txs in 0.35s, propagated in 0.33s
        * Mined 57 txs in 0.38s, propagated in 0.35s
        * Mined 57 txs in 0.25s, propagated in 0.33s
        * Mined 57 txs in 0.22s, propagated in 0.33s
        * Mined 57 txs in 0.37s, propagated in 0.33s
        * Mined 57 txs in 0.57s, propagated in 0.33s
        * Mined 57 txs in 0.36s, propagated in 0.33s
        * Mined 57 txs in 0.36s, propagated in 0.33s
        * Mined 57 txs in 0.40s, propagated in 0.33s
        * Mined 57 txs in 0.26s, propagated in 0.35s
        * Mined 57 txs in 0.65s, propagated in 0.32s
        * Mined 57 txs in 0.37s, propagated in 0.33s
        * Mined 57 txs in 0.35s, propagated in 0.33s
        * Mined 57 txs in 0.32s, propagated in 0.32s
        * Mined 57 txs in 0.31s, propagated in 0.33s
        * Mined 57 txs in 0.72s, propagated in 0.33s
        * Mined 57 txs in 0.33s, propagated in 0.33s
        * Mined 57 txs in 0.26s, propagated in 0.35s
        * Mined 57 txs in 0.44s, propagated in 0.33s
        * Mined 57 txs in 0.30s, propagated in 0.33s
        * Mined 57 txs in 0.44s, propagated in 0.33s
        * Mined 57 txs in 0.37s, propagated in 0.33s
        * Mined 57 txs in 0.33s, propagated in 0.34s
        * Mined 57 txs in 0.60s, propagated in 0.33s
        * Mined 57 txs in 0.22s, propagated in 0.33s
        * Mined 57 txs in 0.23s, propagated in 0.35s
        * Mined 57 txs in 0.39s, propagated in 0.33s
        * Mined 57 txs in 0.25s, propagated in 0.34s
        * Mined 57 txs in 0.47s, propagated in 0.33s
        * Mined 57 txs in 0.35s, propagated in 0.33s
        * Mined 57 txs in 0.27s, propagated in 0.33s
        * Mined 57 txs in 0.32s, propagated in 0.88s
        * Mined 57 txs in 0.29s, propagated in 0.33s
        * Mined 57 txs in 0.38s, propagated in 0.35s
        * Mined 58 txs in 0.26s, propagated in 0.35s
        * Mined 58 txs in 0.33s, propagated in 0.35s
        * Mined 58 txs in 0.84s, propagated in 0.33s
        * Mined 58 txs in 0.23s, propagated in 0.33s
        * Mined 58 txs in 0.40s, propagated in 0.33s
        * Mined 58 txs in 0.46s, propagated in 0.33s
        * Mined 58 txs in 0.25s, propagated in 0.35s
        * Mined 58 txs in 1.46s, propagated in 0.34s
        * Mined 58 txs in 0.50s, propagated in 0.33s
        * Mined 58 txs in 0.27s, propagated in 0.33s
        * Mined 58 txs in 0.32s, propagated in 0.33s
        * Mined 58 txs in 0.23s, propagated in 0.33s
        * Mined 58 txs in 0.26s, propagated in 0.33s
        * Mined 58 txs in 0.73s, propagated in 0.33s
        * Mined 58 txs in 0.42s, propagated in 0.33s
        * Mined 58 txs in 0.43s, propagated in 0.35s
        * Mined 58 txs in 0.27s, propagated in 0.33s
        * Mined 58 txs in 0.31s, propagated in 0.34s
        * Mined 58 txs in 0.96s, propagated in 0.34s
        * Mined 58 txs in 0.55s, propagated in 0.34s
        * Mined 58 txs in 0.57s, propagated in 0.33s
        * Mined 58 txs in 0.28s, propagated in 0.33s
        * Mined 58 txs in 0.42s, propagated in 0.35s
        * Mined 58 txs in 0.31s, propagated in 2.29s
        * Mined 58 txs in 0.37s, propagated in 0.34s
        * Mined 58 txs in 0.30s, propagated in 0.33s
        * Mined 58 txs in 0.64s, propagated in 0.33s
        * Mined 58 txs in 0.27s, propagated in 0.33s
        * Mined 58 txs in 0.23s, propagated in 0.33s
        * Mined 58 txs in 0.29s, propagated in 0.33s
        * Mined 58 txs in 0.44s, propagated in 0.33s
        * Mined 58 txs in 0.56s, propagated in 0.35s
        * Mined 58 txs in 0.27s, propagated in 0.33s
        * Mined 58 txs in 0.36s, propagated in 0.33s
        * Mined 58 txs in 0.31s, propagated in 0.33s
        * Mined 58 txs in 0.26s, propagated in 0.33s
        * Mined 58 txs in 0.53s, propagated in 0.33s
        * Mined 58 txs in 0.29s, propagated in 0.33s
        * Mined 58 txs in 0.27s, propagated in 0.33s
        * Mined 58 txs in 0.49s, propagated in 0.35s
        * Mined 58 txs in 0.31s, propagated in 0.33s
        * Mined 58 txs in 0.28s, propagated in 0.33s
        * Mined 58 txs in 0.71s, propagated in 0.33s
        * Mined 58 txs in 0.26s, propagated in 0.34s
        * Mined 58 txs in 0.25s, propagated in 0.33s
        * Mined 58 txs in 0.35s, propagated in 0.33s
        * Mined 58 txs in 0.36s, propagated in 0.33s
        * Mined 58 txs in 0.26s, propagated in 0.35s
        * Mined 58 txs in 0.27s, propagated in 0.33s
        * Mined 58 txs in 0.35s, propagated in 0.34s
        * Mined 59 txs in 0.28s, propagated in 0.34s
        * Mined 59 txs in 0.33s, propagated in 0.34s
        * Mined 59 txs in 0.35s, propagated in 0.34s
        * Mined 59 txs in 0.47s, propagated in 0.34s
        * Mined 59 txs in 0.37s, propagated in 0.33s
        * Mined 59 txs in 0.40s, propagated in 0.35s
        * Mined 59 txs in 0.28s, propagated in 0.34s
        * Mined 59 txs in 0.26s, propagated in 0.34s
        * Mined 59 txs in 0.36s, propagated in 0.34s
        * Mined 59 txs in 0.27s, propagated in 0.34s
        * Mined 59 txs in 0.73s, propagated in 0.34s
        * Mined 59 txs in 0.29s, propagated in 0.34s
        * Mined 59 txs in 0.26s, propagated in 0.34s
        * Mined 59 txs in 0.44s, propagated in 0.35s
        * Mined 59 txs in 0.45s, propagated in 0.35s
        * Mined 59 txs in 0.49s, propagated in 0.34s
        * Mined 59 txs in 0.29s, propagated in 0.34s
        * Mined 59 txs in 0.31s, propagated in 0.34s
        * Mined 59 txs in 0.36s, propagated in 0.34s
        * Mined 59 txs in 0.27s, propagated in 0.34s
        * Mined 59 txs in 0.27s, propagated in 0.34s
        * Mined 59 txs in 0.28s, propagated in 0.35s
        * Mined 59 txs in 0.49s, propagated in 0.34s
        * Mined 59 txs in 0.35s, propagated in 0.36s
        * Mined 59 txs in 0.38s, propagated in 0.34s
        * Mined 59 txs in 0.25s, propagated in 0.33s
        * Mined 59 txs in 0.58s, propagated in 0.34s
        * Mined 59 txs in 0.29s, propagated in 0.34s
        * Mined 59 txs in 0.34s, propagated in 0.34s
        * Mined 59 txs in 0.42s, propagated in 0.35s
        * Mined 59 txs in 0.45s, propagated in 0.34s
        * Mined 59 txs in 0.36s, propagated in 0.34s
        * Mined 59 txs in 0.27s, propagated in 0.34s
        * Mined 59 txs in 0.37s, propagated in 0.34s
        * Mined 59 txs in 0.40s, propagated in 0.34s
        * Mined 59 txs in 0.35s, propagated in 0.34s
        * Mined 59 txs in 0.29s, propagated in 0.34s
        * Mined 59 txs in 0.23s, propagated in 0.35s
        * Mined 59 txs in 0.44s, propagated in 0.34s
        * Mined 59 txs in 0.57s, propagated in 0.34s
        * Mined 59 txs in 0.23s, propagated in 0.34s
        * Mined 59 txs in 0.27s, propagated in 0.33s
        * Mined 59 txs in 0.29s, propagated in 0.34s
        * Mined 59 txs in 0.30s, propagated in 0.34s
        * Mined 59 txs in 0.39s, propagated in 0.34s
        * Mined 59 txs in 0.28s, propagated in 0.35s
        * Mined 59 txs in 0.62s, propagated in 0.34s
        * Mined 59 txs in 0.59s, propagated in 0.33s
        * Mined 59 txs in 0.29s, propagated in 0.33s
        * Mined 59 txs in 0.27s, propagated in 0.33s
        * Mined 60 txs in 0.35s, propagated in 0.34s
        * Mined 60 txs in 0.23s, propagated in 0.35s
        * Mined 60 txs in 0.42s, propagated in 0.35s
        * Mined 60 txs in 0.21s, propagated in 0.36s
        * Mined 60 txs in 0.24s, propagated in 0.32s
        * Mined 52 txs in 0.11s, propagated in 0.24s
    Analysis of 16384-tx mempool handling:
        Average mining time: 0.37
        Median mining time: 0.33
        Average block propagation time: 0.34
        Median block propagation time: 0.33

This puts this PR as having a 33% faster block propagation time.

@jeffro256
Copy link
Contributor Author

jeffro256 commented Oct 17, 2025

I expect the result to be higher than 33% for FCMP++ transactions since their input verification A) takes much more CPU time, and B) require many fewer random DB reads (just 1 for FCMP root). So the ratio of CPU time in doing input verification to total block propagation time should be higher. This benchmark I made also "only" gets up to 16K transactions in the mempool, whereas stressnet is at >50K, with a lot of transactions having more than 1 input.

jeffro256 added a commit to jeffro256/monero that referenced this pull request Oct 17, 2025
@jeffro256
Copy link
Contributor Author

Added debug statements in Blockchain::check_tx_inputs() then rebased to squash main commits together and put dependencies before the main commit.

Copy link
Collaborator

@j-berman j-berman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a minor comment on the ver_rct_non_semantics_simple_cached.cpp unit test, but the PR generally looks good to me

jeffro256 added a commit to jeffro256/monero that referenced this pull request Oct 20, 2025
@jeffro256
Copy link
Contributor Author

Resolved @j-berman comments and added new unit tests for ver_input_proofs_rings().

else
{
MDEBUG("Previously valid verID for tx " << txid << " does not match current. Perhaps there was a reorg? "
"Continuing to input verification even though this is not likely to succeed...");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can also happen because you are reusing padding bytes, so valid_input_verification_id_inout can have some garbage in it for the old DB entries.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True

Copy link
Contributor Author

@jeffro256 jeffro256 Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually the bytes should be 0 since the padding is an explicit field of the struct and txpool_tx_meta_t is value-initialized when added to the DB:

cryptonote::txpool_tx_meta_t meta{};

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, and that line of code has been there for a long time. All good then.

};

static_assert(sizeof(txpool_tx_meta_t) == 192, "possible DB migration needed for changes to txpool_tx_meta_t");
static_assert(offsetof(txpool_tx_meta_t, valid_input_verification_id) % 32 == 0, "verif ID wrong alignment");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why % 32 when the comment above says til 160 bytes? Maybe just check that the offset is exactly 160 bytes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fair

jeffro256 added a commit to jeffro256/monero that referenced this pull request Oct 24, 2025
jeffro256 and others added 2 commits October 27, 2025 16:33
This replaces `ver_rct_non_semantics_simple_cached()` with an API that offloads
the responsibility of tracking input verification successes to the caller. The
main caller of this function in the codebase, `cryptonote::Blockchain()` instead
keeps track of the verification results for transaction in the mempool by
storing a "verification ID" in the mempool metadata table (with `txpool_tx_meta_t`).
This has several benefits, including:

* When the mempool is large (>8192 txs), we no longer experience cache misses and unnecessarily re-verify ring signatures. This greatly improves block propagation time for FCMP++ blocks under load
* For the same reason, reorg handling can be sped up by storing verification IDs of transactions popped from the chain
* Speeds up re-validating every mempool transaction on fork change (monerod revalidates the whole tx-pool on HFs monero-project#10142)
* Caches results for every single type of Monero transaction, not just latest RCT type
* Cache persists over a node restart
* Uses 512KiB less RAM (8192*2*32B)
* No additional storage or DB migration required since `txpool_tx_meta_t` already had padding allocated
* Moves more verification logic out of `cryptonote::Blockchain`

Furthermore, this opens the door to future multi-threaded block verification
speed-ups. Right now, transactions' input proof verification is limited to one
transaction at a time. However, one can imagine a scenario with verification IDs
where input proofs are optimistically multi-threaded in advance of block
processing. Then, even though ring member fetching and verification is
single-threaded inside of `cryptonote::Blockchain::check_tx_inputs()`, the
single thread can skip the CPU-intensive cryptographic code if the verification
ID allows it.

Also changes the default log category in `tx_verification_utils.cpp` from "blockchain" to "verify".
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants