as I understand it, this was sort-of a bug in the previous implementation but didn’t cause a crash, just ‘potentially bad’ behaviour?
It would actually be a crash. Just to recap the bug that exists on master:
- If the ring buffer is not fully filled, then it contains default initialized
uint256
s (as the first pair element)
- We loop over the entire ring buffer in
PartiallyDownloadedBlock::InitData
, compute the short id from the wtxid stored in the first pair element and check if that short id exists for the current compact block.
- If a short id computed from the default initialized
uint256
collides with an existing short id, then we might end up de-referencing a nullptr
here.
This would only happen if the ring buffer has not been fully filled (i.e. there are nullptrs present) and there is a short id collision (short ids are 6 bytes in size), so this is extremely rare and it can also not be remotely triggered by a peer.
To verify this bug I’ve amended our partially_downloaded_block
fuzz harness and changed the short id size to 1 byte here: https://github.com/dergoegge/bitcoin/commit/c6580c058a541f3a0c94172d2b0db99d77e79285.
It may be worth adding a new test to explicitly check this case (and see what the previous impl did with the pair<uint256, CTransactionRef>), but I’d need someone to point to where that test should live.
I like that thought. As noted above, I’ve verified the bug on master by amending one of our fuzz tests. On master, that test does not include default initialized pairs in the ring buffer, which is probably why that bug wasn’t found so far (It would still be very rare with 6 byte short ids).
I think allowing the short id creation to be mocked (or maybe just the short id size) would be helpful to create a test. This would also generally help with getting various other short id collision edge cases under test (through unit or fuzz testing). My amended fuzz test might be a good starting point but the changes I have made to blockencodings.cpp
should be configurable by a test instead of being hard-coded.
(I don’t think adding a test is a blocker for this PR but perhaps a nice follow up)