Seeking feedback on whether abstracting away ChainstateManager (and Chainstate) in net_processing is worthwhile. This was previously discussed in #27502. Using a wrapper class, here's where I am currently:
net_processing.hdefines an abstract classNetValidationInterface(name TODO)net_processing.cppdefines a derived classChainManAdapterthat takesChainstateManager&and wraps calls to it. This hides members likem_blockman,m_best_header, etc.PeerManagerImplstores astd::unique_ptr<NetValidationInterface>that is nevernullptrand replaces all previous calls tom_chainman.
With this, it becomes possible to reach most (all?) branches gated on m_chainman in net_processing when fuzzing without a TestingSetup. For example, this lets us toggle IsPruneMode, mock reorgs easier, and report the full set of BlockValidationState / MempoolAcceptResult. This should give speed and coverage wins (determinism too?). The same approach could be applied to m_mempool, though I want to see if the general approach is acceptable.
Questions:
- My rough draft diff to
net_processing.his ~+81, tonet_processing.cppis ~+268,-130. Is the benefit worth the cost? - Is there a clearer design pattern that works?
- Could the interface be somewhere else and more general so other callers may use it?
- Is there ongoing work in kernel that can address the same problem?
- Is there a way to also reduce
cs_mainlocking at the same time? - Abstracting away
m_chainmanbut notm_mempoolis a bit weird for a fuzz test since the mempool will always be empty yet net_processing may think that a transaction should exist in the mempool based onProcessTransaction. Should we abstract both?
Rough branch that does this (helped by Claude, though I re-wrote it). The first commit introduces + uses the interface in net_processing, the second is a copy of the process_messages harness that uses FuzzedNetValidation instead of TestingSetup. The interface is a bit weird currently: it has a GetMutex function and it hacks around ProcessNewPackage being a free function accepting a Chainstate. The fuzz test is sparse because I don't know all invariants that need to hold while mocking to avoid a crash.
Inspired by #27502 (comment).