Skip to content

Conversation

jonatack
Copy link
Member

@jonatack jonatack commented Mar 22, 2021

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.

@DrahtBot
Copy link
Contributor

DrahtBot commented Mar 22, 2021

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

Conflicts

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.

@practicalswift
Copy link
Contributor

Strong Concept ACK

enum class is strictly better :)

@jonatack jonatack force-pushed the NetPermissionFlags-enum-class branch from 4eb2ada to 02270a1 Compare March 24, 2021 12:50
@kiminuo
Copy link
Contributor

kiminuo commented Mar 24, 2021

Concept ACK, nice change

@jonatack
Copy link
Member Author

Could you please explain what was the motivation to add HasAnyFlag?

Thanks for the review @kiminuo! I extracted the NetPermissions::HasAnyFlag() addition to a separate commit with a detailed explanation in the commit message and updated with your other feedback.

@jonatack jonatack force-pushed the NetPermissionFlags-enum-class branch from 02270a1 to a29876a Compare March 25, 2021 15:22
@jonatack
Copy link
Member Author

rebased

@jonatack jonatack force-pushed the NetPermissionFlags-enum-class branch from a29876a to 717108b Compare March 29, 2021 10:24
@jonatack
Copy link
Member Author

rebased

@jonatack jonatack force-pushed the NetPermissionFlags-enum-class branch from 717108b to fa73a18 Compare March 30, 2021 18:33
Copy link
Member

@hebasto hebasto left a comment

Choose a reason for hiding this comment

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

Approach ACK fa73a18.

The first commit "p2p, refactor: add NetPermissionFlags scopes where not already present" could be a scripted-diff:

s() { git grep -l "$1" -- 'src' ':!src/net_permissions.h' | xargs sed -i -E "s/([^:])$1/\1NetPermissionFlags::$1/"; }

s 'PF_NONE'
s 'PF_BLOOMFILTER'
s 'PF_RELAY'
s 'PF_FORCERELAY'
s 'PF_DOWNLOAD'
s 'PF_NOBAN'
s 'PF_MEMPOOL'
s 'PF_ADDR'
s 'PF_ISIMPLICIT'
s 'PF_ALL'

@jonatack jonatack force-pushed the NetPermissionFlags-enum-class branch from fa73a18 to fad51cb Compare April 2, 2021 13:56
@jonatack
Copy link
Member Author

jonatack commented Apr 2, 2021

The first commit "p2p, refactor: add NetPermissionFlags scopes where not already present" could be a scripted-diff:

s() { git grep -l "$1" -- 'src' ':!src/net_permissions.h' | xargs sed -i -E "s/([^:])$1/\1NetPermissionFlags::$1/"; }

Thanks! That's a co-credit :) Done in 043a4c5.

laanwj added a commit that referenced this pull request May 11, 2021
…: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 #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 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
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request May 11, 2021
…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
@Rspigler
Copy link
Contributor

Mark up for grabs?

jonatack and others added 2 commits May 12, 2021 10:50
-BEGIN VERIFY SCRIPT-
s() { git grep -l "$1" -- 'src' ':!src/net_permissions.h' | xargs sed -i -E "s/([^:])$1/\1NetPermissionFlags::$1/"; }

s 'PF_NONE'
s 'PF_BLOOMFILTER'
s 'PF_RELAY'
s 'PF_FORCERELAY'
s 'PF_DOWNLOAD'
s 'PF_NOBAN'
s 'PF_MEMPOOL'
s 'PF_ADDR'
s 'PF_ISIMPLICIT'
s 'PF_ALL'
-END VERIFY SCRIPT-

Co-authored-by: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com>
@jonatack
Copy link
Member Author

Re-opening and rebased now that #21644, that this is based on, was merged.

@jonatack jonatack reopened this May 12, 2021
@jonatack jonatack force-pushed the NetPermissionFlags-enum-class branch from 24b294a to d53c70e Compare May 12, 2021 09:26
Copy link
Contributor

@vasild vasild left a comment

Choose a reason for hiding this comment

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

ACK d53c70e

};
static inline constexpr NetPermissionFlags operator|(NetPermissionFlags a, NetPermissionFlags b)
Copy link
Member

@laanwj laanwj May 12, 2021

Choose a reason for hiding this comment

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

Nice! Why not do this for & as well?
(More generally, I wonder if there is a nice way in C++ to define a reusable metatype that is 'enum with bitfield properties'—it seems that this is more generally useful. Not necessarily in this PR though.)

Copy link
Member

Choose a reason for hiding this comment

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

I think the goal of this pull is to forbid the & operator, because it won't do what you think it does. (See the preceding bugfix)

Copy link
Member

Choose a reason for hiding this comment

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

That is, callers should use HasFlag instead of &.

Copy link
Member

@maflcko maflcko left a comment

Choose a reason for hiding this comment

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

@maflcko
Copy link
Member

maflcko commented May 12, 2021

cr ACK d53c70e

@maflcko maflcko added this to the 22.0 milestone May 12, 2021
jonatack added 3 commits May 12, 2021 16:13
and define/update operation methods to handle type conversions explicitly. See
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Renum-oper
for more info.
- drop redundant PF_ permission flags prefixes
- drop ALL_CAPS naming per https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Renum-caps
- rename IsImplicit to Implicit

-BEGIN VERIFY SCRIPT-
s() { git grep -l "$1" src | xargs sed -i "s/$1/$2/g"; }

s 'PF_NONE'        'None'
s 'PF_BLOOMFILTER' 'BloomFilter'
s 'PF_RELAY'       'Relay'
s 'PF_FORCERELAY'  'ForceRelay'
s 'PF_DOWNLOAD'    'Download'
s 'PF_NOBAN'       'NoBan'
s 'PF_MEMPOOL'     'Mempool'
s 'PF_ADDR'        'Addr'
s 'PF_ISIMPLICIT'  'Implicit'
s 'PF_ALL'         'All'
-END VERIFY SCRIPT-
-BEGIN VERIFY SCRIPT-
s() { git grep -l "$1" src/net_processing.cpp | xargs sed -i "s/$1/$2/g"; }
s 'the noban permission'      'NetPermissionFlags::NoBan permission'
s 'the NOBAN permission flag' 'NetPermissionFlags::NoBan permission'
s 'noban permission'          'NetPermissionFlags::NoBan permission'
-END VERIFY SCRIPT-
@jonatack jonatack force-pushed the NetPermissionFlags-enum-class branch from d53c70e to 7075f60 Compare May 12, 2021 14:14
@jonatack
Copy link
Member Author

Dropped unneeded parentheses, only change is git diff d53c70e 7075f60

diff --git a/src/net_permissions.h b/src/net_permissions.h
index 9cb59bd85f..7a158aa6c5 100644
--- a/src/net_permissions.h
+++ b/src/net_permissions.h
@@ -56,7 +56,7 @@ public:
     }
     static inline void AddFlag(NetPermissionFlags& flags, NetPermissionFlags f)
     {
-        flags = (flags | f);
+        flags = flags | f;
     }

Copy link
Contributor

@vasild vasild left a comment

Choose a reason for hiding this comment

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

ACK 7075f60

Copy link
Member

@luke-jr luke-jr left a comment

Choose a reason for hiding this comment

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

utACK

@laanwj
Copy link
Member

laanwj commented May 19, 2021

Code review ACK 7075f60

@laanwj laanwj merged commit 4da26fb into bitcoin:master May 19, 2021
@jonatack jonatack deleted the NetPermissionFlags-enum-class branch May 19, 2021 10:04
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request May 19, 2021
gwillen pushed a commit to ElementsProject/elements that referenced this pull request Jun 1, 2022
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Aug 18, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.