Enforce expected outbound services #7749

pull sipa wants to merge 6 commits into bitcoin:master from sipa:checkservices changing 11 files +142 −78
  1. sipa commented at 8:18 pm on March 26, 2016: member

    At this point, we do not:

    • check that relayed/stored addr messages have the NODE_NETWORK bit set.
    • check that nodes selected for outbound connection have NODE_NETWORK advertized.
    • check that the nServices flag in the “version” message by a node corresponds to what we expected when deciding to connect to it.
    • store the updated nServices flag from the “version” message in addrman.

    Fix this.

  2. jonasschnelli added the label P2P on Mar 27, 2016
  3. laanwj commented at 10:15 am on March 28, 2016: member
    Travis fail was unrelated (#7463), retriggering.
  4. petertodd commented at 12:30 pm on March 30, 2016: contributor
    utACK
  5. jonasschnelli commented at 12:57 pm on March 30, 2016: contributor
    utACK d4b854dccfd6afef4a1daf056b15d4f3f0d52eaa
  6. paveljanik commented at 1:22 pm on March 30, 2016: contributor

    ACK https://github.com/bitcoin/bitcoin/pull/7749/commits/d4b854dccfd6afef4a1daf056b15d4f3f0d52eaa

    btctest addnode 188.226.202.220 onetry producing:

    02016-03-30 13:17:37 trying connection 188.226.202.220 lastseen=0.0hrs
    12016-03-30 13:17:37 Added connection to 188.226.202.220 peer=12
    22016-03-30 13:17:37 send version message: version 70013, blocks=754598, us=0.0.0.0:18333, them=188.226.202.220:18333, peer=12
    32016-03-30 13:17:37 sending: version (103 bytes) peer=12
    42016-03-30 13:17:38 received: version (102 bytes) peer=12
    52016-03-30 13:17:38 peer=12 does not offer the expected services (00000004 offered, 00000001 expected); disconnecting
    62016-03-30 13:17:38 sending: reject (45 bytes) peer=12
    72016-03-30 13:17:38 sending: verack (0 bytes) peer=12
    82016-03-30 13:17:38 sending: getaddr (0 bytes) peer=12
    

    Minor nit: remove ’the’ before ’expected services’ (I’m not native English speaker though)?

  7. gmaxwell commented at 4:17 pm on March 30, 2016: contributor
    utACK. @paveljanik “the” is appropriate there.
  8. in src/main.cpp: in d4b854dccf outdated
    4512+        if (pfrom->nServicesExpected & ~pfrom->nServices)
    4513+        {
    4514+            LogPrint("net", "peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom->id, pfrom->nServices, pfrom->nServicesExpected);
    4515+            pfrom->PushMessage(NetMsgType::REJECT, strCommand, REJECT_NONSTANDARD,
    4516+                               strprintf("Expected to offer services %08x", pfrom->nServicesExpected));
    4517+            pfrom->fDisconnect = true;
    


    kazcw commented at 4:42 am on April 16, 2016:
    return here?

    sipa commented at 9:50 pm on June 12, 2016:
    Fixed.
  9. sdaftuar commented at 2:58 pm on April 22, 2016: member
    Is the behavior that @paveljanik observed with his test the intended behavior? I would have guessed that we’d want addnode (or connect) to bypass the expected services requirement.
  10. sipa commented at 7:19 am on May 17, 2016: member
    Mental note: we should do an exact assignment (rather than or’ing) when directly connected to a peer and it tells us its nVersion.
  11. sipa force-pushed on May 25, 2016
  12. sipa commented at 3:26 pm on May 25, 2016: member
    Rebased, and fixed the behaviour @paveljanik saw.
  13. sipa force-pushed on May 25, 2016
  14. in src/protocol.h: in 68146f6217 outdated
    250@@ -251,7 +251,7 @@ class CAddress : public CService
    251 {
    252 public:
    253     CAddress();
    254-    explicit CAddress(CService ipIn, uint64_t nServicesIn = NODE_NETWORK);
    255+    explicit CAddress(CService ipIn, uint64_t nServicesIn);
    


    MarcoFalke commented at 1:17 pm on June 5, 2016:

    @sipa Have you made sure the test are not using the default?

    I get a failure in test/addrman_tests.cpp:71

    0test/addrman_tests.cpp: In member function void addrman_tests::addrman_simple::test_method():
    1test/addrman_tests.cpp:71:31: error: no matching function for call to CAddress::CAddress(CService&)
    2     addrman.Add(CAddress(addr1), source);
    3                               ^
    

    sipa commented at 9:41 am on June 6, 2016:
    Fixed!
  15. sipa force-pushed on Jun 6, 2016
  16. sipa force-pushed on Jun 8, 2016
  17. sipa commented at 12:12 pm on June 8, 2016: member
    Rebased.
  18. sipa force-pushed on Jun 8, 2016
  19. sipa commented at 4:19 pm on June 8, 2016: member
    Rebased on top of #8083, and making it use this PR’s nRelevantServices as the nRequiredServices value requested from filtering seeds.
  20. theuni commented at 4:40 pm on June 8, 2016: member
    Nit: For readability, can we get a constant NODE_SERVICES_NONE or so (i’m at a loss for a good name) rather than passing 0 everywhere?
  21. sipa commented at 5:14 pm on June 8, 2016: member
    For discussion: I’ve instead switched the NODE_* flags to an enum.
  22. theuni commented at 5:34 pm on June 8, 2016: member
    ahhh, much better. Thanks.
  23. laanwj commented at 5:44 am on June 9, 2016: member

    For discussion: I’ve instead switched the NODE_* flags to an enum.

    ACK

  24. sipa force-pushed on Jun 12, 2016
  25. sipa commented at 9:51 pm on June 12, 2016: member
    Rebased and addressed @kazcw ’s comment.
  26. in src/main.cpp: in d2acb5164b outdated
    4784@@ -4785,6 +4785,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
    4785         {
    4786             boost::this_thread::interruption_point();
    4787 
    4788+            if (!(addr.nServices & NODE_NETWORK))
    


    laanwj commented at 1:09 pm on June 13, 2016:
    Maybe make the bitmask of required services a constant
  27. in src/net.cpp: in d2acb5164b outdated
    1595@@ -1596,6 +1596,10 @@ void ThreadOpenConnections()
    1596             if (IsLimited(addr))
    1597                 continue;
    1598 
    1599+            // only connect to full nodes
    1600+            if (!(addr.nServices & NODE_NETWORK))
    


    laanwj commented at 1:13 pm on June 13, 2016:
    Or wait, shouldn’t this be nRelevantServices? Though I’m not sure “relevantservices” is a good name if we only consider nodes with those service bits.

    sipa commented at 1:17 pm on June 13, 2016:
    There may be relevant services that are not required, but still preferred. I’ll add a constant for required services.

    sipa commented at 2:01 pm on June 13, 2016:
    Done.
  28. sipa force-pushed on Jun 13, 2016
  29. Keep addrman's nService bits consistent with outbound observations 3764dec36c
  30. Verify that outbound connections have expected services fc83f18153
  31. Only store and connect to NODE_NETWORK nodes 5e7ab16d29
  32. Don't require services in -addnode 15bf863219
  33. Introduce enum ServiceFlags for service flags ee06e04369
  34. Introduce REQUIRED_SERVICES constant ecd7fd37c8
  35. sipa force-pushed on Jun 13, 2016
  36. gmaxwell commented at 5:25 pm on June 13, 2016: contributor
    ACK
  37. laanwj commented at 5:29 pm on June 13, 2016: member
    utACK ecd7fd3
  38. laanwj merged this on Jun 13, 2016
  39. laanwj closed this on Jun 13, 2016

  40. laanwj referenced this in commit be9711e597 on Jun 13, 2016
  41. in src/main.cpp: in ecd7fd37c8
    4617+        pfrom->nServices = ServiceFlags(nServiceInt);
    4618+        if (!pfrom->fInbound)
    4619+        {
    4620+            addrman.SetServices(pfrom->addr, pfrom->nServices);
    4621+        }
    4622+        if (pfrom->nServicesExpected & ~pfrom->nServices)
    


    rebroad commented at 6:43 am on August 24, 2016:
    Is disconnection really the right solution here? For example, let’s say we were expecting NODE_NETWORK yet we connect and now find the node is a pruned node. This wouldn’t be an issue if we’re already caught up with the blockchain, would it?

    rebroad commented at 7:43 am on September 1, 2016:

    Ok, I think I have found a problem with this line. Shouldn’t it instead read:-

    if (nRelevantServices & ~pfrom->nServices)

    ?

    i.e. the ExpectedServices are irrelevant (which are ANDed with nRelevantServices anyway). E.g. if the relevant services are NODE_NETWORK (as they usually are) and you connect to a node which HAS NODE_NETWORK but it wasn’t expected to have NODE_NETWORK, then why would you still want it to disconnect? Afterall ServicesExpected is simply an old version of what the node used to advertise. nServices is the up-to-date information so why refer to the out-of-date information when you have the up-to-date information?

  42. in src/net.cpp: in ecd7fd37c8
    1594@@ -1592,6 +1595,10 @@ void ThreadOpenConnections()
    1595             if (IsLimited(addr))
    1596                 continue;
    1597 
    1598+            // only connect to full nodes
    


    rebroad commented at 6:56 am on August 24, 2016:
    Why only connect to full nodes? Surely this is only a requirement when we are more than 550 blocks behind on the blockchain. Also, with this change, it is possible that a node that was previously pruning becomes a full-node, and it will never be rediscovered again as a full-node for as long as it’s IP address remains the same.

    sipa commented at 7:04 am on August 24, 2016:

    Why only connect to full nodes? Surely this is only a requirement when we are more than 550 blocks behind on the blockchain.

    No, we always want this requirement.

    Otherwise we may end up trying to connect to lightweight clients that do not even relay blocks at all.

  43. sipa commented at 7:49 am on September 1, 2016: member

    No, there can be relevant services that a peer does not advertize, and we decide to connect to them anyway. We shouldn’t disconnect them later just because they happen to not have that service listed.

    I’m tired of explaining this over and over again. Relevant does not mean required; it means relevant. You’re welcome to add comments with explanations about the meaning of variables and logic, but please don’t try to change code you don’t understand.

  44. in src/main.cpp: in ecd7fd37c8
    4623+        {
    4624+            LogPrint("net", "peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom->id, pfrom->nServices, pfrom->nServicesExpected);
    4625+            pfrom->PushMessage(NetMsgType::REJECT, strCommand, REJECT_NONSTANDARD,
    4626+                               strprintf("Expected to offer services %08x", pfrom->nServicesExpected));
    4627+            pfrom->fDisconnect = true;
    4628+            return false;
    


    rebroad commented at 1:25 am on October 16, 2016:
    Why return false rather than true? False just causes an extra error message to be displayed in debug.log (saying ProcessMessage failed).
  45. random-zebra referenced this in commit f295ee4e4e on May 13, 2020
  46. DrahtBot locked this on Sep 8, 2021

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-10-04 22:12 UTC

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