This PR adds a regression fuzz test for #26355 and some of the bugs found during review of #25717.
Should give us more confidence in doing #25725.
This PR adds a regression fuzz test for #26355 and some of the bugs found during review of #25717.
Should give us more confidence in doing #25725.
<!--e57a25ab6845829454e8d69fc972939a-->
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
<!--006a51241073e994b41acfe9ec718e94-->
For detailed information about the code coverage, see the test coverage report.
<!--021abf342d371248e50ceaed478a90ca-->
See the guideline for information on the review process.
| Type | Reviewers |
|---|---|
| Concept ACK | darosior |
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.
<!--174a7506f384e20aa4161008e828411d-->
Reviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.
51 | + bool ignore_incoming_txs{false}; 52 | + bool reconcile_txs{false}; 53 | + uint32_t max_orphan_txs{DEFAULT_MAX_ORPHAN_TRANSACTIONS}; 54 | + size_t max_extra_txs{DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN}; 55 | + bool capture_messages{false}; 56 | + uint32_t max_headers_result{MAX_HEADERS_RESULTS};
Looks like this is the only option that is required by the fuzz target, so maybe remove the others for now to hopefully reduce the number of conflicting pulls and remove the dependency on the other pull?
3 of the PRs are mine (I don't care about rebasing) and the package relay stuff is gonna conflict either way, so I'd prefer keeping it as is.
122 | +void initialize() 123 | +{ 124 | + // Reduce proof-of-work check to one bit. 125 | + g_check_pow_mock = [](uint256 hash, unsigned int, const Consensus::Params&) { 126 | + return (hash.data()[31] & 0x80) == 0; 127 | + };
Why not disabling it completely instead of mocking it?
My thinking was that this should result in more coverage because we'll also cover paths for invalid PoW.
Rebased and un-drafted, ready for review!
154 | + CBlock block = ConsumeBlock(fuzzed_data_provider, prev.GetHash(), prev.nBits); 155 | + FinalizeHeader(block); 156 | + return block; 157 | + }; 158 | + 159 | + std::vector<std::function<void()>> actions = {
How is this different from CallOneOf?
it's not, iirc I had some trouble with thread safety annotations but I'll give CallOneOf another try
I don't think you can use annotations one way or the other. As soon as you assign to std::function<void()>, the annotations are dropped, so you might as well not have them in the first place.
If you want them, and use CallOneOf, you can use the same trick to wrap each annotated lambda into a std::function<void()>{lambda_bla} temporary to achieve the same result of dropping any annotations.
switched to CallOneOf and used NO_THREAD_SAFETY_ANALYSIS.
test/fuzz/p2p_headers_sync.cpp:187:96: required from here
./primitives/transaction.h:327:42: error: ‘class CVectorWriter’ has no member named ‘GetParams’
327 | SerializeTransaction(*this, s, s.GetParams());
| ~~^~~~~~~~~
make[2]: *** [Makefile:17531: test/fuzz/fuzz-p2p_headers_sync.o] Error 1
make[2]: Leaving directory '/ci_container_base/ci/scratch/build/bitcoin-x86_64-pc-linux-gnu/src'
make[1]: *** [Makefile:20246: install-recursive] Error 1
make[1]: Leaving directory '/ci_container_base/ci/scratch/build/bitcoin-x86_64-pc-linux-gnu/src'
make: *** [Makefile:811: install-recursive] Error 1
Exit status: 2������������������������������������������������������������������������������������������������������������������������
Thanks! rebased.
Concept ACK. Planning on reviewing soon.
Needs rebase (silent merge conflict).
Needs rebase (silent merge conflict).
Thanks, rebased
121 | @@ -122,8 +122,14 @@ bool PermittedDifficultyTransition(const Consensus::Params& params, int64_t heig 122 | return true; 123 | } 124 | 125 | +std::function<bool(uint256, unsigned int, const Consensus::Params&)> g_check_pow_mock = nullptr; 126 | + 127 | bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params) 128 | { 129 | + if (g_check_pow_mock) {
Should probably have some belt-and-suspenders check that we're 100% not running on mainnet, maybe based on the contents of params and whatever applicable global.
An alternative to the mocking would be to use FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION in all places that call CheckProofOfWork (i.e. validation, mining) since there is literally zero benefit in having this be a blocker for fuzzing.
It's been more than 6 months since I opened this without substantial review, so closing. Let me know if anyone is actually interested in reviewing and I'll reopen.
just fyi, I started reviewing at some point, my problem was that I don't like test-specific / mocking code in production code (especially the consensus-critical parts), so I wasn't really comfortable (concept)-acking it. On the other hand, I didn't see a better way to do it and fuzzing is great obviously...
As a result, I was undecided and didn't write anything. Maybe it'd be worth to have a general discussion about the extent of mocking / test-specific production code we want as a project, since there are obviously both advantages and disadvantages to it. If there was a general consensus that these kind of mocks are fine I'd be happy to review/ack the actual fuzz target.
I'd say they are fine, if there is no better way. With global functions and variables, I think the only way to mock them is also via a global approach. Here, adding the assert(params!=main) (https://github.com/bitcoin/bitcoin/pull/28043#discussion_r1446512814) should be fine.
Milestone
27.0