We don’t have a fuzzing harness for our main consensus engine [0]. This PR introduces two new targets which respectively fuzz the BlockManager
and ChainstateManager
(process headers, blocks, reorgs and assert some invariants in doing so).
There is two main obstacles to achieving this: PoW and io. The blocks and chainstate databases can be stored in memory but blocks still need a valid proof of work and to be stored on disk. Niklas solved the first issue in #28043 by simply introducing a global which makes it possible to mock the PoW check (his commit is cherry-picked here). After considering other approaches, i also used globals to mock disk io.
I’m interested with this PR in getting feedback on the concept and the approach, but also in suggestions of more invariants to be asserting in the chainstate
fuzz target.
Regarding other approaches i tried the most potentially promising was to leverage ld
’s --wrap
option to mock the syscalls without having to modify non-test code. But i didn’t try too hard to make it work: better to have a demo of what can be achieved first with a more trivial way of mocking filesystem calls. If there is interest in these fuzz targets, i can give this approach another look.
Regarding efficiency, the chainstate fuzz target is quite slow at the moment but i’ve at least 2x its performance by rebasing on #28960 and making CheckBlockIndex
callable externally even if !ShouldCheckBlockIndex()
. Suggestions for performance improvements welcome too.
[0] Well there is utxo_total_supply
but it’s very specialized toward exercising a specific past bug.