p2p, refactor: make NetPermissionFlags an enum class #21506

pull jonatack wants to merge 5 commits into bitcoin:master from jonatack:NetPermissionFlags-enum-class changing 9 files +126 −118
  1. jonatack commented at 10:17 pm on March 22, 2021: member

    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 (review) and #21644, as only defined operations on the flags would compile.

  2. fanquake added the label P2P on Mar 22, 2021
  3. DrahtBot commented at 10:57 pm on March 22, 2021: member

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

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #21992 (Feefilter cleanups by amadeuszpawlik)
    • #21879 (Wrap accept() and extend usage of Sock by vasild)
    • #21878 (Make all networking code mockable by vasild)
    • #21843 (p2p, rpc: enable GetAddr, GetAddresses, and getnodeaddresses by network by jonatack)
    • #20234 (net: don’t extra bind for Tor if binds are restricted by vasild)

    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.

  4. MarcoFalke added the label Refactoring on Mar 23, 2021
  5. practicalswift commented at 4:03 pm on March 23, 2021: contributor
  6. in src/net.cpp:1008 in 98daee8f32 outdated
    967@@ -968,7 +968,7 @@ bool CConnman::AttemptToEvictConnection()
    968 
    969         LOCK(cs_vNodes);
    970         for (const CNode* node : vNodes) {
    971-            if (node->HasPermission(NetPermissionFlags::PF_NOBAN))
    972+            if (node->HasPermission(NetPermissionFlags::NoBan))
    


    MarcoFalke commented at 5:01 pm on March 23, 2021:
    meta: Could the rename be a scripted-diff?

    jonatack commented at 12:51 pm on March 24, 2021:
    done
  7. jonatack force-pushed on Mar 24, 2021
  8. in src/test/netbase_tests.cpp:390 in 02270a1ea4 outdated
    392+    BOOST_CHECK(NetPermissions::HasFlag(whitebindPermissions.m_flags, NetPermissionFlags::Implicit));
    393+    BOOST_CHECK(NetPermissions::HasAnyFlag(whitebindPermissions.m_flags, NetPermissionFlags::Implicit));
    394+
    395+    NetPermissions::ClearFlag(whitebindPermissions.m_flags, NetPermissionFlags::Implicit);
    396+    BOOST_CHECK(!NetPermissions::HasFlag(whitebindPermissions.m_flags, NetPermissionFlags::Implicit));
    397+    BOOST_CHECK(!NetPermissions::HasAnyFlag(whitebindPermissions.m_flags, NetPermissionFlags::Implicit));;
    


    kiminuo commented at 8:52 pm on March 24, 2021:
    0    BOOST_CHECK(!NetPermissions::HasAnyFlag(whitebindPermissions.m_flags, NetPermissionFlags::Implicit));
    

    ?


    jonatack commented at 2:47 pm on March 25, 2021:
    good eye, thanks! the compiler didn’t mind but we do. fixed.
  9. kiminuo commented at 9:05 pm on March 24, 2021: contributor
    Concept ACK, nice change
  10. in src/test/netbase_tests.cpp:442 in 02270a1ea4 outdated
    438+    BOOST_CHECK(NetPermissions::HasFlag(whitelistPermissions.m_flags, NetPermissionFlags::NoBan));
    439+    BOOST_CHECK(NetPermissions::HasAnyFlag(whitelistPermissions.m_flags, NetPermissionFlags::NoBan));
    440+
    441+    NetPermissions::ClearFlag(whitelistPermissions.m_flags, NetPermissionFlags::Download);
    442+    BOOST_CHECK(!NetPermissions::HasFlag(whitelistPermissions.m_flags, NetPermissionFlags::Download));
    443+    BOOST_CHECK(!NetPermissions::HasFlag(whitelistPermissions.m_flags, NetPermissionFlags::NoBan));
    


    kiminuo commented at 9:38 pm on March 24, 2021:
    Maybe move this line one line below? So that it is clear how HasFlag and HasAnyFlag differ.

    jonatack commented at 2:47 pm on March 25, 2021:
    sure, done
  11. jonatack commented at 3:22 pm on March 25, 2021: member

    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.

  12. jonatack force-pushed on Mar 25, 2021
  13. DrahtBot added the label Needs rebase on Mar 29, 2021
  14. jonatack commented at 10:24 am on March 29, 2021: member
    rebased
  15. jonatack force-pushed on Mar 29, 2021
  16. DrahtBot removed the label Needs rebase on Mar 29, 2021
  17. DrahtBot added the label Needs rebase on Mar 30, 2021
  18. jonatack commented at 6:33 pm on March 30, 2021: member
    rebased
  19. jonatack force-pushed on Mar 30, 2021
  20. DrahtBot removed the label Needs rebase on Mar 30, 2021
  21. hebasto commented at 8:56 pm on April 1, 2021: member

    Approach ACK fa73a18ad874cc076a9201678ff25686766c24d0.

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

     0s() { git grep -l "$1" -- 'src' ':!src/net_permissions.h' | xargs sed -i -E "s/([^:])$1/\1NetPermissionFlags::$1/"; }
     1
     2s 'PF_NONE'
     3s 'PF_BLOOMFILTER'
     4s 'PF_RELAY'
     5s 'PF_FORCERELAY'
     6s 'PF_DOWNLOAD'
     7s 'PF_NOBAN'
     8s 'PF_MEMPOOL'
     9s 'PF_ADDR'
    10s 'PF_ISIMPLICIT'
    11s 'PF_ALL'
    
  22. in src/net.cpp:2413 in fa73a18ad8 outdated
    2413@@ -2410,7 +2414,7 @@ bool CConnman::Bind(const CService &addr, unsigned int flags, NetPermissionFlags
    2414         return false;
    2415     }
    2416 
    2417-    if (addr.IsRoutable() && fDiscover && !(flags & BF_DONT_ADVERTISE) && !(permissions & PF_NOBAN)) {
    2418+    if (addr.IsRoutable() && fDiscover && !(flags & BF_DONT_ADVERTISE) && !NetPermissions::HasAnyFlag(permissions, NetPermissionFlags::NoBan)) {
    


    hebasto commented at 9:03 pm on April 1, 2021:
    Why not NetPermissions::HasFlag ?

    jonatack commented at 1:55 pm on April 2, 2021:

    Hm, the tests pass with HasFlag() but ISTM that would represent a potential change in behavior in a refactoring pull, as HasFlag() returns (flags & f) == f instead of flags & f and NetPermissionFlags::NoBan is a multi-flag (NoBan = (1U << 4) | Download). LMK if I’m confused here though.

    Aside, this line was last changed in commit bb145c90502:

    0-    if (addr.IsRoutable() && fDiscover && (permissions & PF_NOBAN) == 0) {
    1+    if (addr.IsRoutable() && fDiscover && !(flags & BF_DONT_ADVERTISE) && !(permissions & PF_NOBAN)) {
    

    hebasto commented at 1:17 am on April 5, 2021:

    You are right. Your change is equivalent to the current code. But this raises additional questions:

    1. current tests are not reliable if they

    pass with HasFlag()

    1. HasAnyFlag(permissions, flag_a | flag_b) is much easier to read and reason about than HasAnyFlag(permissions, fancy_multiflag)

    2. in general, with named multiflags, negation of HasFlag could have ambiguous meaning. Does this code do what it is supposed to do in all cases: https://github.com/bitcoin/bitcoin/blob/590e49ccf2af27c6c1f1e0eb8be3a4bf4d92ce8b/src/net.cpp#L1110-L1117 ?


    jonatack commented at 1:36 pm on April 8, 2021:

    After looking at #16248 and #19191, the current code seems correct.

    This line was changed in e5b26deaaa6, which pre-dates the download permission being extracted from noban in #19191:

    0-    if (addrBind.IsRoutable() && fDiscover && !fWhitelisted)
    1+    if (addrBind.IsRoutable() && fDiscover && (permissions & PF_NOBAN) == 0)
    

    The intent of adding the Download flag in #19191 was: “It should be possible to grant nodes in a local network (e.g. home, university, enterprise, …) permission to download blocks even after the maxuploadtarget is hit. Currently this is only possible by setting the noban permission, which has some adverse effects, especially if the peers can’t be fully trusted. Fix this by extracting a download permission from noban.”

    So, in reply to your questions:

    1. (If I understand correctly) the existing lone bitwise AND here, e.g. HasAnyFlag(Noban) is correct (but the precise behavior is not covered by tests)

    2. I guess we could replace HasAnyFlag(Noban) with the more verbose HasFlag(Noban) || HasFlag(Download) if that seems clearer

    3. Elsewhere, HasFlag() appears to be what we want in the cases where it is used, AFAICT


    MarcoFalke commented at 2:21 pm on April 8, 2021:

    Ugh, looks like this is a bug that I introduced in #19191

    (The download permission set shouldn’t affect places where noban is checked for)


    jonatack commented at 2:32 pm on April 8, 2021:
    I first thought that too, but here in Bind() I’m not sure. Confirm that HasFlag(NoBan) is fine here?

    MarcoFalke commented at 2:45 pm on April 8, 2021:
    Well, fixing a bug should indeed be done in a separate pull from one that is tagged with [refactoring]

    jonatack commented at 4:49 pm on April 8, 2021:
    Ok will open a separate patch for that.

    jonatack commented at 7:50 pm on April 9, 2021:
    Done in #21644. Resolving here and will simplify this PR, dropping the HasAnyFlags() and unit test commits.
  23. jonatack force-pushed on Apr 2, 2021
  24. jonatack commented at 1:57 pm on April 2, 2021: member

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

    0s() { 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 043a4c5163909d0.

  25. jonatack force-pushed on Apr 10, 2021
  26. jonatack commented at 11:35 am on April 10, 2021: member
    Simplified, dropped the HasAnyFlag() and test commits that are replaced by the bugfix in #21644 on which this patch is now based, and updated the PR description.
  27. vasild commented at 8:42 am on April 14, 2021: member

    There is still the following “strange” behavior:

    0// expected to have "noban" and "download" in flags, true
    1flags = TryParse("noban,download");
    2
    3// expected to have just "noban" in flags, given that "download" has been removed, not true :(
    4ClearFlag(flags, PF_DOWNLOAD);
    5
    6// what happens actually is that now flags is in a "bricked" state
    7// where it does not equal any of the PF_* flags or a bitwise-OR of them.
    

    Could it be avoided to have the download flag included in the noban flag (i.e. to have each PF_* flag have exactly one bit set) and #19191 resolved in some other way?

  28. jonatack commented at 8:54 am on April 14, 2021: member

    I don’t disagree, though it might be out of scope for this change (which has indeed exposed some issues!)

    ClearFlag is currently only used in src/net.cpp::CConnman::CreateNodeFromAcceptedSocket() to clear the NetPermissionFlags implicit flag.

    Edit: addressed for now in #21644.

  29. in src/net_permissions.h:41 in 24b294ac75 outdated
    47-    PF_ISIMPLICIT = (1U << 31),
    48-    PF_ALL = PF_BLOOMFILTER | PF_FORCERELAY | PF_RELAY | PF_NOBAN | PF_MEMPOOL | PF_DOWNLOAD | PF_ADDR,
    49+    Implicit = (1U << 31),
    50+    All = BloomFilter | ForceRelay | Relay | NoBan | Mempool | Download | Addr,
    51 };
    52+static inline constexpr NetPermissionFlags operator|(NetPermissionFlags a, NetPermissionFlags b) {
    


    vasild commented at 11:21 am on April 14, 2021:
    nit: the opening { should be on a new line

    jonatack commented at 9:10 am on May 12, 2021:
    done
  30. in src/net_permissions.h:51 in 24b294ac75 outdated
    60     NetPermissionFlags m_flags;
    61     static std::vector<std::string> ToStrings(NetPermissionFlags flags);
    62-    static inline bool HasFlag(const NetPermissionFlags& flags, NetPermissionFlags f)
    63-    {
    64-        return (flags & f) == f;
    65+    static inline bool HasFlag(NetPermissionFlags flags, NetPermissionFlags f) {
    


    vasild commented at 11:22 am on April 14, 2021:
    nit: the opening { should be on a new line

    jonatack commented at 9:10 am on May 12, 2021:
    done, thanks!
  31. vasild approved
  32. vasild commented at 11:30 am on April 14, 2021: member
    ACK 24b294ac7519d6989d9746edd9e6643a4adbe88a
  33. DrahtBot commented at 9:33 am on May 3, 2021: member

    🕵️ @sipa has been requested to review this pull request as specified in the REVIEWERS file.

  34. jonatack commented at 10:18 am on May 11, 2021: member
    Thanks everyone for the ACKs but this isn’t being merged and I am tying up loose ends before being less present here for some seminars.
  35. jonatack closed this on May 11, 2021

  36. laanwj referenced this in commit e175a20769 on May 11, 2021
  37. sidhujag referenced this in commit beef02c60d on May 11, 2021
  38. Rspigler commented at 10:57 pm on May 11, 2021: contributor
    Mark up for grabs?
  39. scripted-diff: add NetPermissionFlags scopes where not already present
    -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>
    91f6e6e6d1
  40. p2p: NetPermissions::HasFlag() pass flags param by value 7b55a94497
  41. jonatack commented at 9:12 am on May 12, 2021: member
    Re-opening and rebased now that #21644, that this is based on, was merged.
  42. jonatack reopened this on May 12, 2021

  43. jonatack force-pushed on May 12, 2021
  44. vasild approved
  45. vasild commented at 12:51 pm on May 12, 2021: member
    ACK d53c70e775e56c4e4c30728262121c9f7e4bcc23
  46. in src/net_permissions.h:41 in d53c70e775 outdated
    47-    PF_ISIMPLICIT = (1U << 31),
    48-    PF_ALL = PF_BLOOMFILTER | PF_FORCERELAY | PF_RELAY | PF_NOBAN | PF_MEMPOOL | PF_DOWNLOAD | PF_ADDR,
    49+    Implicit = (1U << 31),
    50+    All = BloomFilter | ForceRelay | Relay | NoBan | Mempool | Download | Addr,
    51 };
    52+static inline constexpr NetPermissionFlags operator|(NetPermissionFlags a, NetPermissionFlags b)
    


    laanwj commented at 1:05 pm on May 12, 2021:
    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.)

    MarcoFalke commented at 1:10 pm on May 12, 2021:
    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)

    MarcoFalke commented at 1:11 pm on May 12, 2021:
    That is, callers should use HasFlag instead of &.
  47. in src/net_permissions.h:59 in d53c70e775 outdated
    68+        return (static_cast<t>(flags) & static_cast<t>(f)) == static_cast<t>(f);
    69     }
    70     static inline void AddFlag(NetPermissionFlags& flags, NetPermissionFlags f)
    71     {
    72-        flags = static_cast<NetPermissionFlags>(flags | f);
    73+        flags = (flags | f);
    


    laanwj commented at 1:06 pm on May 12, 2021:
    nit: unnecessary parenthesis

    jonatack commented at 2:14 pm on May 12, 2021:
    fixed
  48. MarcoFalke approved
  49. MarcoFalke commented at 1:12 pm on May 12, 2021: member
  50. MarcoFalke commented at 1:13 pm on May 12, 2021: member
    cr ACK d53c70e775e56c4e4c30728262121c9f7e4bcc23
  51. MarcoFalke added this to the milestone 22.0 on May 12, 2021
  52. p2p, refactor: make NetPermissionFlags a uint32 enum class
    and define/update operation methods to handle type conversions explicitly. See
    https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Renum-oper
    for more info.
    810d0929c1
  53. scripted-diff: rename NetPermissionFlags enumerators
    - 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-
    a95540cf43
  54. scripted-diff: update noban documentation in net_processing.cpp
    -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-
    7075f604e8
  55. jonatack force-pushed on May 12, 2021
  56. jonatack commented at 2:16 pm on May 12, 2021: member

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

     0diff --git a/src/net_permissions.h b/src/net_permissions.h
     1index 9cb59bd85f..7a158aa6c5 100644
     2--- a/src/net_permissions.h
     3+++ b/src/net_permissions.h
     4@@ -56,7 +56,7 @@ public:
     5     }
     6     static inline void AddFlag(NetPermissionFlags& flags, NetPermissionFlags f)
     7     {
     8-        flags = (flags | f);
     9+        flags = flags | f;
    10     }
    
  57. vasild approved
  58. vasild commented at 4:19 pm on May 12, 2021: member
    ACK 7075f604e8d0b21b2255fa57e20cd365dc10a288
  59. luke-jr approved
  60. luke-jr commented at 10:56 pm on May 13, 2021: member
    utACK
  61. laanwj commented at 9:51 am on May 19, 2021: member
    Code review ACK 7075f604e8d0b21b2255fa57e20cd365dc10a288
  62. laanwj merged this on May 19, 2021
  63. laanwj closed this on May 19, 2021

  64. jonatack deleted the branch on May 19, 2021
  65. sidhujag referenced this in commit 41ce7f72bb on May 19, 2021
  66. gwillen referenced this in commit 3074da475f on Jun 1, 2022
  67. DrahtBot locked this on Aug 18, 2022

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-07-05 19:13 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me