-
Notifications
You must be signed in to change notification settings - Fork 38.7k
Enforce expected outbound services #7749
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
Conversation
|
Travis fail was unrelated (#7463), retriggering. |
|
utACK |
|
utACK d4b854d |
|
ACK d4b854d
Minor nit: remove 'the' before 'expected services' (I'm not native English speaker though)? |
|
utACK. @paveljanik "the" is appropriate there. |
| LogPrint("net", "peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom->id, pfrom->nServices, pfrom->nServicesExpected); | ||
| pfrom->PushMessage(NetMsgType::REJECT, strCommand, REJECT_NONSTANDARD, | ||
| strprintf("Expected to offer services %08x", pfrom->nServicesExpected)); | ||
| pfrom->fDisconnect = true; |
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.
return here?
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.
Fixed.
|
Is the behavior that @paveljanik observed with his test the intended behavior? I would have guessed that we'd want |
|
Mental note: we should do an exact assignment (rather than or'ing) when directly connected to a peer and it tells us its nVersion. |
|
Rebased, and fixed the behaviour @paveljanik saw. |
src/protocol.h
Outdated
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.
@sipa Have you made sure the test are not using the default?
I get a failure in test/addrman_tests.cpp:71
test/addrman_tests.cpp: In member function ‘void addrman_tests::addrman_simple::test_method()’:
test/addrman_tests.cpp:71:31: error: no matching function for call to ‘CAddress::CAddress(CService&)’
addrman.Add(CAddress(addr1), source);
^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.
Fixed!
0984386 to
c1d79e6
Compare
|
Rebased. |
|
Rebased on top of #8083, and making it use this PR's nRelevantServices as the nRequiredServices value requested from filtering seeds. |
|
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? |
|
For discussion: I've instead switched the NODE_* flags to an enum. |
|
ahhh, much better. Thanks. |
ACK |
|
Rebased and addressed @kazcw 's comment. |
src/main.cpp
Outdated
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.
Maybe make the bitmask of required services a constant
|
ACK |
|
utACK ecd7fd3 |
ecd7fd3 Introduce REQUIRED_SERVICES constant (Pieter Wuille) ee06e04 Introduce enum ServiceFlags for service flags (Pieter Wuille) 15bf863 Don't require services in -addnode (Pieter Wuille) 5e7ab16 Only store and connect to NODE_NETWORK nodes (Pieter Wuille) fc83f18 Verify that outbound connections have expected services (Pieter Wuille) 3764dec Keep addrman's nService bits consistent with outbound observations (Pieter Wuille)
| { | ||
| addrman.SetServices(pfrom->addr, pfrom->nServices); | ||
| } | ||
| if (pfrom->nServicesExpected & ~pfrom->nServices) |
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.
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?
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.
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?
| if (IsLimited(addr)) | ||
| continue; | ||
|
|
||
| // only connect to full nodes |
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.
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.
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.
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.
|
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. |
| pfrom->PushMessage(NetMsgType::REJECT, strCommand, REJECT_NONSTANDARD, | ||
| strprintf("Expected to offer services %08x", pfrom->nServicesExpected)); | ||
| pfrom->fDisconnect = true; | ||
| return false; |
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.
Why return false rather than true? False just causes an extra error message to be displayed in debug.log (saying ProcessMessage failed).
a48639f Introduce REQUIRED_SERVICES constant (Pieter Wuille) d1391e3 Introduce enum ServiceFlags for service flags (Pieter Wuille) b6a0455 Don't require services in -addnode (Pieter Wuille) 6dba254 Only store and connect to NODE_NETWORK nodes (Pieter Wuille) 1905a6a Verify that outbound connections have expected services (Pieter Wuille) 0c23c01 Keep addrman's nService bits consistent with outbound observations (Pieter Wuille) Pull request description: Backport of bitcoin#7749. This is next in line for #1374. Original description: > 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. ACKs for top commit: furszy: one-one with 7749 with the only exception of the tier two area, looks good, utACK a48639f random-zebra: All good. ACK a48639f and merging... Tree-SHA512: 82f99df4244504cfe6fbc490126485da40d912b9b06390cb91a924426bded550bb939d352a17ba2c5142b4dae4099699b8e5777b7cb49f316342ebea4f9ec71d
At this point, we do not:
Fix this.