net: assert CNode::m_inbound_onion is inbound in ctor, add getter, unit tests #20210

pull jonatack wants to merge 3 commits into bitcoin:master from jonatack:CNode-IsInboundOnion changing 4 files +12 −4
  1. jonatack commented at 10:14 am on October 21, 2020: member

    The goal of this PR is to be able to depend on m_inbound_onion in AttemptToEvictConnection in #20197:

    • asserts CNode::m_inbound_onion is inbound in the CNode ctor to have a validity check at the class boundary
    • fixes a unit test and a fuzz utility that were passing invalid inbound onion values to the CNode ctor
    • drops an unneeded check in CNode::ConnectedThroughNetwork() for its inbound status
    • adds a public getter IsInboundOnion() that also allows unit testing it
    • adds unit test coverage
  2. hebasto approved
  3. hebasto commented at 10:51 am on October 21, 2020: member
    ACK 39286b3c6f2bae7d3ea77185689469bb22572189, tested on Linux Mint 20 (x86_64).
  4. fanquake added the label P2P on Oct 21, 2020
  5. practicalswift commented at 12:51 pm on October 21, 2020: contributor

    Concept ACK

    Thanks for improving testing!

  6. DrahtBot commented at 1:20 am on November 12, 2020: 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:

    • #20789 (fuzz: Rework strong and weak net enum fuzzing by MarcoFalke)
    • #20786 (net: [refactor] Prefer integral types in CNodeStats by MarcoFalke)
    • #20729 (p2p: standardize on outbound-{full, block}-relay connection type naming by jonatack)
    • #20721 (Net: Move ping data to net_processing by jnewbery)
    • #20649 (refactor: Remove nMyStartingHeight from CNode/Connman by MarcoFalke)
    • #20373 (refactor, net: Increase CNode data member encapsulation by hebasto)

    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.

  7. jonatack force-pushed on Nov 13, 2020
  8. jonatack commented at 5:27 pm on November 13, 2020: member
    Rebased.
  9. in src/net.h:1114 in 43bd1882ad outdated
    1094@@ -1095,7 +1095,7 @@ class CNode
    1095     CService addrLocal GUARDED_BY(cs_addrLocal);
    1096     mutable RecursiveMutex cs_addrLocal;
    1097 
    1098-    //! Whether this peer connected via our Tor onion service.
    1099+    //! Whether this peer is an inbound onion, e.g. connected via our Tor onion service.
    1100     const bool m_inbound_onion{false};
    


    theStack commented at 6:17 pm on November 22, 2020:
    yocto-nit (not directly related to this PR though, feel free to ignore): not sure if we have any guidelines (or dominant opinions) on this subject, but isn’t it overkill to have two initializations for a class member: once via in-class initialization and once via initializer list in the ctor? (And yes, I’m aware that initializer lists have higher priority in C++). As reader of the class interface I’d not assume an in-class initialization is overruled in the ctor. Also, without the in-class initialization the compiler has the chance to throw an error if the const member was forgot to be initialized in the ctor.

    jonatack commented at 4:28 pm on November 23, 2020:

    Hm, good eye.

    -> In this case, ISTM we could remove the default false argument in the constructor declaration

    -> As to your last point, it suggests the default member m_inbound_onion initializer not set a value, since we are doing it dynamically in the ctor. It’s true that I see a build error in this case, but not without the change in net.h:1099

    0/src/net.cpp
    1-    nMyStartingHeight(nMyStartingHeightIn),
    2-    m_inbound_onion(inbound_onion && conn_type_in == ConnectionType::INBOUND)
    3+    nMyStartingHeight(nMyStartingHeightIn)
    4
    5/src/net.h
    6     //! Whether this peer is an inbound onion, e.g. connected via our Tor onion service.
    7-    const bool m_inbound_onion{false};
    8+    const bool m_inbound_onion;
    
    0net.cpp:2947:1: error: uninitialized const member in const bool [-fpermissive]
    1 2947 | CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress& addrBindIn, const std::string& addrNameIn, ConnectionType conn_type_in, bool inbound_onion)
    2      | ^~~~~
    3In file included from net.cpp:10:
    4./net.h:1099:16: note: const bool CNode::m_inbound_onion should be initialized
    5 1099 |     const bool m_inbound_onion;
    6      |                ^~~~~~~~~~~~~~~
    

    I don’t mind pulling in a commit from your branch if you’d like to adjust this.


    More generally, from what I can gather, the ideas behind in-class default member initializers added in C++11 were (a) to allow a non-static data member to be initialized where it is declared, e.g. in its class. A constructor can then use the initializer when run-time initialization is needed, which can then (b) tidy up the code up by avoiding doing it in the member initializer list of the constructor. This provides extra benefits in classes with multiple constructors.

    I guess one can see the default member initializer as the general default, particularly useful for constant initializers, that can be overridden by any specific ones in member initializer lists in the constructors.

    Some resources (send me any good ones you might suggest; my understanding on this is evolving):


    jonatack commented at 10:40 pm on February 12, 2021:

    not sure if we have any guidelines (or dominant opinions) on this subject, but isn’t it overkill to have two initializations for a class member: once via in-class initialization and once via initializer list in the ctor? (And yes, I’m aware that initializer lists have higher priority in C++). As reader of the class interface I’d not assume an in-class initialization is overruled in the ctor. Also, without the in-class initialization the compiler has the chance to throw an error if the const member was forgot to be initialized in the ctor. @theStack: done in #21167

  10. theStack approved
  11. theStack commented at 6:20 pm on November 22, 2020: member
    ACK 0a30f5d9b44abaed2f08f33ad2bcaa20ab5cbdba 🏞️
  12. in src/net.cpp:2960 in 0a30f5d9b4 outdated
    2956@@ -2957,7 +2957,7 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn
    2957     m_conn_type(conn_type_in),
    2958     nLocalServices(nLocalServicesIn),
    2959     nMyStartingHeight(nMyStartingHeightIn),
    2960-    m_inbound_onion(inbound_onion)
    2961+    m_inbound_onion(inbound_onion && conn_type_in == ConnectionType::INBOUND)
    


    laanwj commented at 2:15 pm on December 3, 2020:
    I might be misunderstanding but in what case would the caller pass inbound_onion parameter as true but lie about this, as it is an outbound connection? Is this a code bug? Wouldn’t this be better as an assertion?

    MarcoFalke commented at 4:57 pm on December 15, 2020:
    Or an Assume, if Assert is too strong and risky

    jonatack commented at 11:44 am on December 17, 2020:
    Good idea, inbound_onion should only be true when a new CNode is instantiated from CConnman::AcceptConnection(), so this should only fail if a bug is added. Made it an assert.

    jonatack commented at 12:45 pm on December 17, 2020:

    in what case would the caller pass inbound_onion parameter as true but lie about this

    So, adding the assertion found one! Our net_tests had a case that lied; updating it.


    jonatack commented at 3:22 pm on December 17, 2020:
    Hm, a couple of fuzzers need to be updated, too. Edit: done
  13. DrahtBot added the label Needs rebase on Dec 15, 2020
  14. jonatack force-pushed on Dec 17, 2020
  15. jonatack renamed this:
    net: ensure CNode::m_inbound_onion is inbound, add getter, unit tests
    net: assert CNode::m_inbound_onion is inbound in ctor, add getter, unit tests
    on Dec 17, 2020
  16. jonatack force-pushed on Dec 17, 2020
  17. DrahtBot removed the label Needs rebase on Dec 17, 2020
  18. jonatack force-pushed on Dec 17, 2020
  19. jonatack force-pushed on Dec 17, 2020
  20. MarcoFalke referenced this in commit b7136c11ab on Dec 17, 2020
  21. test, fuzz: fix constructing CNode with invalid inbound_onion
    as CNode ctor should only be passed inbound_onion = true
    when the connection is inbound
    993d1ecd19
  22. net: assert CNode::m_inbound_onion is inbound in ctor
    and drop an unneeded check in CNode::ConnectedThroughNetwork()
    6609eb8cb5
  23. net: add CNode::IsInboundOnion() public getter and unit tests 86c495223f
  24. jonatack force-pushed on Dec 17, 2020
  25. jonatack commented at 7:00 pm on December 17, 2020: member
    Rebased/simplified after merge of #20686.
  26. sidhujag referenced this in commit 5898e35af5 on Dec 17, 2020
  27. sipa commented at 5:06 am on December 27, 2020: member
    utACK 86c495223f048e5ca2cf0d8730af7db3b76f7aba
  28. LarryRuane commented at 5:50 am on December 29, 2020: contributor
    ACK 86c495223f048e5ca2cf0d8730af7db3b76f7aba Compiled, ran unit tests.
  29. in src/test/fuzz/util.h:301 in 993d1ecd19 outdated
    297@@ -298,7 +298,7 @@ CNode ConsumeNode(FuzzedDataProvider& fuzzed_data_provider) noexcept
    298     const CAddress addr_bind = ConsumeAddress(fuzzed_data_provider);
    299     const std::string addr_name = fuzzed_data_provider.ConsumeRandomLengthString(64);
    300     const ConnectionType conn_type = fuzzed_data_provider.PickValueInArray({ConnectionType::INBOUND, ConnectionType::OUTBOUND_FULL_RELAY, ConnectionType::MANUAL, ConnectionType::FEELER, ConnectionType::BLOCK_RELAY, ConnectionType::ADDR_FETCH});
    301-    const bool inbound_onion = fuzzed_data_provider.ConsumeBool();
    302+    const bool inbound_onion{conn_type == ConnectionType::INBOUND ? fuzzed_data_provider.ConsumeBool() : false};
    


    vasild commented at 1:05 pm on December 30, 2020:
    nit: same as ConnectionType::INBOUND && fuzzed_data_provider.ConsumeBool()

    jonatack commented at 2:01 pm on December 30, 2020:
    indeed, will update if need to retouch or rebase

    MarcoFalke commented at 9:02 am on January 2, 2021:
    difference is that it needs to store one additional redundant byte for every non-inbound fuzz input file, so I think this can be kept as is
  30. in src/net.h:1239 in 86c495223f
    1233@@ -1234,6 +1234,9 @@ class CNode
    1234     void MaybeSetAddrName(const std::string& addrNameIn);
    1235 
    1236     std::string ConnectionTypeAsString() const;
    1237+
    1238+    /** Whether this peer is an inbound onion, e.g. connected via our Tor onion service. */
    1239+    bool IsInboundOnion() const { return m_inbound_onion; }
    


    vasild commented at 1:26 pm on December 30, 2020:
    Given that this method is added only to be used in tests, could the tests use pnode->IsInboundConn() && pnode->ConnectedThroughNetwork() == NET_ONION which is equivalent to the newly added pnode->IsInboundOnion()?

    jonatack commented at 1:48 pm on December 30, 2020:
    The goal is to test m_inbound_onion to be able to depend on it in #20197.

    jonatack commented at 2:23 pm on December 30, 2020:
    (the unit tests already assert on IsInboundConn(), so this would shift the coverage from m_inbound_onion directly, to indirectly via ConnectedThroughNetwork() == NET_ONION, which would avoid the getter but seems less robust? In AttemptToEvictConnection, outbound peers return early, so technically we could use the latter…but I like it less.)

    vasild commented at 2:56 pm on December 30, 2020:
    Yeah, it will test it indirectly, less robust. Feel free to ditch this conversation :)
  31. vasild approved
  32. vasild commented at 1:28 pm on December 30, 2020: member

    ACK 86c495223f048e5ca2cf0d8730af7db3b76f7aba

    Two minor comments below, feel free to ignore.

  33. in src/net.h:1238 in 86c495223f
    1233@@ -1234,6 +1234,9 @@ class CNode
    1234     void MaybeSetAddrName(const std::string& addrNameIn);
    1235 
    1236     std::string ConnectionTypeAsString() const;
    1237+
    1238+    /** Whether this peer is an inbound onion, e.g. connected via our Tor onion service. */
    


    MarcoFalke commented at 8:52 am on January 2, 2021:
    nit question: should this say “i.e.”? I mean are there any other ways to establish an inbound onion other than via the tor onion service?

    jonatack commented at 8:58 am on January 2, 2021:
    I don’t mind updating this and taking @vasild’s suggestion at the same time.

    MarcoFalke commented at 9:00 am on January 2, 2021:
    Can do as a follow-up. The merge script is already running and this should land in master in the next couple of minutes.

    jonatack commented at 9:01 am on January 2, 2021:
    Oh ok, will do in #20197.

    jonatack commented at 10:40 pm on February 12, 2021:

    nit question: should this say “i.e.”? I mean are there any other ways to establish an inbound onion other than via the tor onion service?

    Done in #21167

  34. MarcoFalke approved
  35. MarcoFalke commented at 8:52 am on January 2, 2021: member

    review ACK 86c495223f048e5ca2cf0d8730af7db3b76f7aba 🐍

    Signature:

     0-----BEGIN PGP SIGNED MESSAGE-----
     1Hash: SHA512
     2
     3review ACK 86c495223f048e5ca2cf0d8730af7db3b76f7aba 🐍
     4-----BEGIN PGP SIGNATURE-----
     5
     6iQGzBAEBCgAdFiEE+rVPoUahrI9sLGYTzit1aX5ppUgFAlwqrYAACgkQzit1aX5p
     7pUjcBAwAyH/ZAIoBmnAriDbYf2IdudHCi55YS3Gb2Viv4ujVLCCt+dTDj6OOg6RR
     8fsTKJe3f0g3eHdss1KkMxTGQm1WP6MDl7Iqpkuuar7eH4F7WslFSamnnRStDZXcG
     9vUQvrGSKNakc20PT0wT8bP7UxA2+z8/gVS9V40+lKma8VmwZgYE0EcKztdfUiPL5
    100v+whP/aUPxjEleeG4aec0FkOEwELAdoC6gTtn2+hBBv2x+Kj6KmeheusTNBpP7P
    11jYbMqz5K+qEd10yFc+4yH7gdVyKmAuNunToURLz2SZcQmla2iMinRIXboLEhRcvm
    12pS4YuY62sQ+3bOxxTi3Td7vRMKFmDJfy92vkXgDcQvvpHw72M+k+3ieuzYNvJFUq
    13maOT4trYzF79M5F4Pd18ywIkgz8v50uddPVEVhl4LGeZyAN47WOH0vIoSZBhmuNN
    14IdGom1GuBOMsztoXEZDLYEPr9X9HDB8CgGW5t02g4cf/EoqbtZHzIM2VOXDkiVYe
    15Y5IbMXDV
    16=O80S
    17-----END PGP SIGNATURE-----
    

    Timestamp of file with hash 683c8f1c6754ede192ead999e54c0440e14b98b058b5f69d6e0b9817be2c17bb -

  36. MarcoFalke merged this on Jan 2, 2021
  37. MarcoFalke closed this on Jan 2, 2021

  38. jonatack deleted the branch on Jan 2, 2021
  39. sidhujag referenced this in commit 1a9cf218d6 on Jan 2, 2021
  40. jnewbery commented at 3:11 pm on January 23, 2021: member
    Is there any benefit to adding getter boilerplate code to the header class instead of just making this const member public?
  41. jonatack commented at 6:25 pm on January 26, 2021: member
    @jnewbery Unless additional semantics will be needed for future changes or refactoring, no, probably not. I was being prudent.
  42. jnewbery commented at 6:40 pm on January 26, 2021: member
    oooh thanks for referencing the cpp core guidelines! I’d say that any getter of a const value is trivial :)
  43. jonatack commented at 10:41 pm on February 12, 2021: member

    oooh thanks for referencing the cpp core guidelines! I’d say that any getter of a const value is trivial :) @jnewbery thanks! done in #21167

  44. MarcoFalke referenced this in commit cb073bed00 on Feb 15, 2021
  45. laanwj referenced this in commit dede9eb924 on Mar 30, 2021
  46. Fabcien referenced this in commit cbe8f6a3a0 on Feb 3, 2022
  47. DrahtBot locked this on Aug 16, 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-12-18 21:12 UTC

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