-
Notifications
You must be signed in to change notification settings - Fork 37.7k
p2p, bugfix: use NetPermissions::HasFlag() in CConnman::Bind() #21644
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
p2p, bugfix: use NetPermissions::HasFlag() in CConnman::Bind() #21644
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 693af71
Some non-blocker comments below.
I think it is - the reasoning must be that we do not want to advertise our listen address if it has |
PF_NOBAN is a multi-flag that includes PF_DOWNLOAD, so the conditional in CConnman::Bind() using a bitwise AND will return the same result for both the "noban" status and the "download" status. Example: `PF_DOWNLOAD` is `0b1000000` `PF_NOBAN` is `0b1010000` This makes a check like `flags & PF_NOBAN` return `true` even if `flags` is equal to `PF_DOWNLOAD`. If `-whitebind=download@1.1.1.1:8765` is specified, then `1.1.1.1:8765` should be added to the list of local addresses. We only want to avoid adding to local addresses (that are advertised) a whitebind that has a `noban@` flag. As a result of a mis-check in `CConnman::Bind()` we would not have added `1.1.1.1:8765` to the local addresses in the example above. Co-authored-by: Vasil Dimov <vd@FreeBSD.org>
693af71
to
acef962
Compare
Thanks for the excellent review, @vasild. I added your commit description example from #21668, incorporated your suggestions, followed up on your #21644 (comment) with the last commit, and updated all the commit messages and the PR description. |
ab2a398
to
2d34c48
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 2d34c48
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 2d34c48
Thanks for fixing!
nit: It's generally better to have more tests rather than less, but personally I don't see much gain in also repeatedly testing the flags with bitmasks, e.g. this part
BOOST_CHECK_EQUAL(download.m_flags, NetPermissionFlags::PF_DOWNLOAD);
BOOST_CHECK(download.m_flags != NetPermissionFlags::PF_NOBAN);
BOOST_CHECK(download.m_flags & NetPermissionFlags::PF_DOWNLOAD);
BOOST_CHECK(download.m_flags & NetPermissionFlags::PF_NOBAN);
is semantically equivalent to
BOOST_CHECK_EQUAL(download.m_flags, NetPermissionFlags::PF_DOWNLOAD);
BOOST_CHECK(NetPermissionFlags::PF_DOWNLOAD != NetPermissionsFlags::PF_NOBAN);
BOOST_CHECK(NetPermissionFlags::PF_DOWNLOAD & NetPermissionsFlags::PF_DOWNLOAD); // tautology?
BOOST_CHECK(NetPermissionFlags::PF_DOWNLOAD & NetPermissionsFlags::PF_NOBAN);
i.e. everything after the first line doesn't test the result related to the previous tryParse
-call, but only what bits the PF_
enums consist of internally, which could potentially be confusing to readers of this test at this place.
to clarify/test the relationship and NetPermissions operations involving the NetPermissionFlags PF_NOBAN and PF_DOWNLOAD. Co-authored-by: Vasil Dimov <vd@FreeBSD.org>
NetPermissions::ClearFlag() is currently only called in the codebase with an `f` value of NetPermissionFlags::PF_ISIMPLICIT. If that should change in the future, ClearFlag() should not be called with `f` being a subflag of a multiflag, e.g. NetPermissionFlags::PF_RELAY or NetPermissionFlags::PF_DOWNLOAD, as that would leave `flags` in an invalid state corresponding to none of the existing NetPermissionFlags. Therefore, allow only calling ClearFlag with the implicit flag for now. Co-authored-by: Vasil Dimov <vd@FreeBSD.org>
2d34c48
to
36fb036
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
re-ACK 36fb036 ☕
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 36fb036
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approach ACK 36fb036.
This PR clearly shows how fragile "multibit flags" are. We definitely shouldn't introduce new ones.
From the second "test: add net permissions noban/download unit test coverage" commit I expected that it will fail without the first one. Is it possible to improve tests to prevent regressions in the future?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK 36fb036, I have reviewed the code and it looks OK, I agree it can be merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code review ACK 36fb036
Seems like ClearFlag
could be renamed ClearImplicitFlag
and remove 2nd argument instead of the assert stuff, but that would make the diff bigger, so no big deal.
@kallewoof agree, I thought about removing the argument too, could go one way or the other. |
…onnman::Bind() 36fb036 p2p: allow NetPermissions::ClearFlag() only with PF_ISIMPLICIT (Jon Atack) 4e0d578 test: add net permissions noban/download unit test coverage (Jon Atack) dde69f2 p2p, bugfix: use NetPermissions::HasFlag() in CConnman::Bind() (Jon Atack) Pull request description: This is a bugfix follow-up to bitcoin#16248 and bitcoin#19191 that was noticed in bitcoin#21506. Both v0.21 and master are affected. Since bitcoin#19191, noban is a multi-flag that implies download, so the conditional in `CConnman::Bind()` using a bitwise AND on noban will return the same result for both the noban status and the download status. This means that download peers are incorrectly not being added to local addresses because they are mistakenly seen as noban peers. The second commit adds unit test coverage to illustrate and test the noban/download relationship and the `NetPermissions` operations involving them. The final commit adds documentation and disallows calling `NetPermissions::ClearFlag()` with any second param other than `NetPermissionFlags` "implicit" -- per current usage in the codebase -- because `ClearFlag()` should not be called with any second param that is a subflag of a multiflag, e.g. "relay" or "download," as that would leave the result in an invalid state corresponding to none of the existing NetPermissionFlags. Thanks to Vasil Dimov for noticing this. ACKs for top commit: theStack: re-ACK 36fb036 ☕ vasild: ACK 36fb036 hebasto: ACK 36fb036, I have reviewed the code and it looks OK, I agree it can be merged. kallewoof: Code review ACK 36fb036 Tree-SHA512: 5fbc7ddbf31d06b35bf238f4d77ef311e6b6ef2e1bb9893f32f889c1a0f65774a3710dcb21d94317fe6166df9334a9f2d42630809e7fe8cbd797dd6f6fc49491
7075f60 scripted-diff: update noban documentation in net_processing.cpp (Jon Atack) a95540c scripted-diff: rename NetPermissionFlags enumerators (Jon Atack) 810d092 p2p, refactor: make NetPermissionFlags a uint32 enum class (Jon Atack) 7b55a94 p2p: NetPermissions::HasFlag() pass flags param by value (Jon Atack) 91f6e6e scripted-diff: add NetPermissionFlags scopes where not already present (Jon Atack) Pull request description: While reviewing #20196, I noticed the `NetPermissionFlags` enums are frequently called as if they were scoped, yet are still global. This patch upgrades `NetPermissionFlags` to a scoped class enum and updates the enumerator naming, similarly to #19771. See https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#enum-enumerations for more info. This change would eliminate the class of bugs like #20196 (comment) and #21644, as only defined operations on the flags would compile. ACKs for top commit: laanwj: Code review ACK 7075f60 vasild: ACK 7075f60 Tree-SHA512: 7fcea66ee499f059efc78c934b5f729b3c8573fe304dee2c27c837c2f662b89324790568246d75b2a574cf9f059b42d3551d928996862f4358055eb43521e6f4
Only backport to 0.21 needed |
PF_NOBAN is a multi-flag that includes PF_DOWNLOAD, so the conditional in CConnman::Bind() using a bitwise AND will return the same result for both the "noban" status and the "download" status. Example: `PF_DOWNLOAD` is `0b1000000` `PF_NOBAN` is `0b1010000` This makes a check like `flags & PF_NOBAN` return `true` even if `flags` is equal to `PF_DOWNLOAD`. If `-whitebind=download@1.1.1.1:8765` is specified, then `1.1.1.1:8765` should be added to the list of local addresses. We only want to avoid adding to local addresses (that are advertised) a whitebind that has a `noban@` flag. As a result of a mis-check in `CConnman::Bind()` we would not have added `1.1.1.1:8765` to the local addresses in the example above. Co-authored-by: Vasil Dimov <vd@FreeBSD.org> Github-Pull: bitcoin#21644 Rebased-From: dde69f2
Backported in #22022 |
PF_NOBAN is a multi-flag that includes PF_DOWNLOAD, so the conditional in CConnman::Bind() using a bitwise AND will return the same result for both the "noban" status and the "download" status. Example: `PF_DOWNLOAD` is `0b1000000` `PF_NOBAN` is `0b1010000` This makes a check like `flags & PF_NOBAN` return `true` even if `flags` is equal to `PF_DOWNLOAD`. If `-whitebind=download@1.1.1.1:8765` is specified, then `1.1.1.1:8765` should be added to the list of local addresses. We only want to avoid adding to local addresses (that are advertised) a whitebind that has a `noban@` flag. As a result of a mis-check in `CConnman::Bind()` we would not have added `1.1.1.1:8765` to the local addresses in the example above. Co-authored-by: Vasil Dimov <vd@FreeBSD.org> Github-Pull: bitcoin#21644 Rebased-From: dde69f2
This is a bugfix follow-up to #16248 and #19191 that was noticed in #21506. Both v0.21 and master are affected.
Since #19191, noban is a multi-flag that implies download, so the conditional in
CConnman::Bind()
using a bitwise AND on noban will return the same result for both the noban status and the download status. This means that download peers are incorrectly not being added to local addresses because they are mistakenly seen as noban peers.The second commit adds unit test coverage to illustrate and test the noban/download relationship and the
NetPermissions
operations involving them.The final commit adds documentation and disallows calling
NetPermissions::ClearFlag()
with any second param other thanNetPermissionFlags
"implicit" -- per current usage in the codebase -- becauseClearFlag()
should not be called with any second param that is a subflag of a multiflag, e.g. "relay" or "download," as that would leave the result in an invalid state corresponding to none of the existing NetPermissionFlags. Thanks to Vasil Dimov for noticing this.