Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Use typesafe Wtxid in compact block encodings #29752

Merged
merged 2 commits into from Apr 9, 2024

Conversation

AngusP
Copy link
Contributor

@AngusP AngusP commented Mar 27, 2024

The first commit replaces uint256 with typesafe Wtxid (or Txid) types introduced in #28107.

The second commit then simplifies the extra tx vector to just be of CTransactionRefs instead of a std::pair<Wtxid, CTransactionRef>, as it's easy to get a Wtxid from a transaction ref.

@DrahtBot
Copy link
Contributor

DrahtBot commented Mar 27, 2024

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Code Coverage

For detailed information about the code coverage, see the test coverage report.

Reviews

See the guideline for information on the review process.

Type Reviewers
ACK glozow, dergoegge

If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

src/blockencodings.cpp Outdated Show resolved Hide resolved
@AngusP AngusP force-pushed the typesafe-txid-in-cmpctblock branch from 58ba422 to ea8570b Compare March 28, 2024 22:29
…ad of ambiguous uint256.

Wtxid/Txid types introduced in bitcoin#28107
@AngusP AngusP force-pushed the typesafe-txid-in-cmpctblock branch from ea8570b to e178a52 Compare March 28, 2024 22:30
@AngusP AngusP requested a review from glozow March 31, 2024 22:42
Copy link
Member

@dergoegge dergoegge left a comment

Choose a reason for hiding this comment

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

Code review ACK e178a52

Comment on lines 137 to 138
if (extra_txn[i] == nullptr)
continue;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added this mullptr check because some functional tests failed -- 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 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.

Also self-nit, a break; instead of continue; may be better as AFAIK this is a ring buffer that'll be sequentially added-to? But again as I'm not that familiar with the code, unsure.

Copy link
Member

Choose a reason for hiding this comment

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

I haven't looked at this, but it may have been intentional to compare against a default constructed uint256 (an array of zeros), so that the runtime is constant and does not depend on the current fill-level of the data structure.

Copy link
Member

Choose a reason for hiding this comment

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

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 uint256s (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: dergoegge@c6580c0.

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)

Copy link
Member

Choose a reason for hiding this comment

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

A relatively simple test could be to a extra_txn.resize(1) within src/test/blockencodings_tests.cpp (currently it is empty)?

This bug description looks correct to me.

Copy link
Member

@glozow glozow left a comment

Choose a reason for hiding this comment

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

ACK e178a52

The second commit seems sensible as wtxid is cached instead of being calculated on the fly since fac1223 (nit maybe mention in the commit message), though I don't think having the pair is that bad either.

Comment on lines 137 to 138
if (extra_txn[i] == nullptr)
continue;
Copy link
Member

Choose a reason for hiding this comment

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

A relatively simple test could be to a extra_txn.resize(1) within src/test/blockencodings_tests.cpp (currently it is empty)?

This bug description looks correct to me.

src/blockencodings.cpp Outdated Show resolved Hide resolved
… of a vec of pair<Wtxid, CTransactionRef>

All `CTransactionRef` have `.GetWitnessHash()` that returns a cached `const Wtxid` (since fac1223),
so we don't need to pass transaction refs around with their IDs as they're easy to get from a ref.
@AngusP AngusP force-pushed the typesafe-txid-in-cmpctblock branch from e178a52 to a8203e9 Compare April 6, 2024 18:35
Copy link
Member

@glozow glozow left a comment

Choose a reason for hiding this comment

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

ACK a8203e9

@DrahtBot DrahtBot requested a review from dergoegge April 6, 2024 21:58
Copy link
Member

@dergoegge dergoegge left a comment

Choose a reason for hiding this comment

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

ACK a8203e9

@glozow glozow merged commit bf031a5 into bitcoin:master Apr 9, 2024
16 checks passed
@AngusP AngusP deleted the typesafe-txid-in-cmpctblock branch April 9, 2024 12:47
Pttn added a commit to RiecoinTeam/Riecoin that referenced this pull request Apr 13, 2024
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.

None yet

5 participants