Skip to content
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

test: p2p: check disconnect due to lack of desirable service flags #29279

Conversation

theStack
Copy link
Contributor

This PR adds missing test coverage for disconnecting peers which don't offer the desirable service flags in their VERSION message:

bitcoin/src/net_processing.cpp

Lines 3384 to 3389 in 5f3a057

if (pfrom.ExpectServicesFromConn() && !HasAllDesirableServiceFlags(nServices))
{
LogPrint(BCLog::NET, "peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom.GetId(), nServices, GetDesirableServiceFlags(nServices));
pfrom.fDisconnect = true;
return;
}

This check is relevant for the connection types "outbound-full-relay", "block-relay-only" and "addr-fetch" (see CNode::ExpectServicesFromConn(...)). Feeler connections always disconnect, which is also tested here.

In lack of finding a proper file where this test would fit in, I created a new one. Happy to take suggestions there.

@DrahtBot
Copy link
Contributor

DrahtBot commented Jan 19, 2024

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

Code Coverage

For detailed information about the code coverage, see the test coverage report.

Reviews

See the guideline for information on the review process.

Type Reviewers
ACK davidgumberg, fjahr, cbergqvist, stratospher, itornaza
Concept ACK furszy, BrandonOdiwuor
Stale ACK delta1, epiccurious, marcofleon, mzumsande

If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

Conflicts

No conflicts as of last run.

@DrahtBot DrahtBot added the Tests label Jan 19, 2024
@theStack theStack force-pushed the 202401-test-check_disconnect_lack_desirable_flags branch from 0f7b25f to 358561e Compare January 19, 2024 02:42
Copy link

@delta1 delta1 left a comment

Choose a reason for hiding this comment

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

Code Review ACK 358561e

Adds a new test, increases code coverage.

Copy link
Member

@furszy furszy left a comment

Choose a reason for hiding this comment

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

See #28170. Obvious concept ACK.
We do have a post-IBD bug on this process.

Copy link
Contributor

@BrandonOdiwuor BrandonOdiwuor left a comment

Choose a reason for hiding this comment

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

Concept ACK 358561e

Increasing code coverage

Copy link
Contributor

@stratospher stratospher left a comment

Choose a reason for hiding this comment

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

Concept ACK! i think flaky tests are possible because disconnection could happen before p2p_conn.wait_for_connect() in add_outbound_connection()?

test/functional/p2p_handshake.py Outdated Show resolved Hide resolved
@theStack
Copy link
Contributor Author

Concept ACK! i think flaky tests are possible because disconnection could happen before p2p_conn.wait_for_connect() in add_outbound_connection()?

True, good catch. The flaky case can be reproduced by adding an artificial delay before the wait_for_connect() call, e.g.:

diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py
index 77f6e69e98..4aa54fa64a 100755
--- a/test/functional/test_framework/test_node.py
+++ b/test/functional/test_framework/test_node.py
@@ -725,6 +725,7 @@ class TestNode():
             p2p_conn.wait_until(lambda: p2p_conn.message_count["version"] == 1, check_connected=False)
             p2p_conn.wait_until(lambda: not p2p_conn.is_connected, check_connected=False)
         else:
+            time.sleep(1)
             p2p_conn.wait_for_connect()
             self.p2ps.append(p2p_conn)

I guess one solution could be to add a send_version parameter to add_outbound_p2p_connection (like add_p2p_connection already has) to prevent the immediate sending of the version message. We could set that to false in the test and send the version message triggering the disconnect manually. Will set the PR to draft state until I have something working.

@theStack theStack marked this pull request as draft January 25, 2024 17:52
@theStack theStack force-pushed the 202401-test-check_disconnect_lack_desirable_flags branch from 358561e to ff5f994 Compare January 26, 2024 02:37
@theStack
Copy link
Contributor Author

Solved the flaky test issue by introducing a wait_for_disconnect parameter to add_p2p_outbound_connection, which hits the same code path as for feeler connections if set (i.e. waiting for immediate disconnect).

@theStack theStack marked this pull request as ready for review January 26, 2024 02:53
Copy link
Contributor

@stratospher stratospher left a comment

Choose a reason for hiding this comment

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

tested ACK ff5f994.

test/functional/p2p_handshake.py Outdated Show resolved Hide resolved
@DrahtBot DrahtBot requested review from BrandonOdiwuor, furszy and delta1 and removed request for delta1 and BrandonOdiwuor January 29, 2024 07:57
@theStack theStack force-pushed the 202401-test-check_disconnect_lack_desirable_flags branch from ff5f994 to d82eafb Compare January 29, 2024 22:46
@theStack
Copy link
Contributor Author

Rebased on master (after the merge of #24748 🎉 ), and tackled #29279 (comment). Note that I tried enabling v2 transport for this test, but it seems that it is non-trivial and needs some deeper changes in the test framework regarding the order of version messages sent (see slightly related comment https://mirror.b10c.me/bitcoin-bitcoin/24748/#discussion_r1465420112). Will tackle that in a follow-up.

@stratospher
Copy link
Contributor

ACK d82eafb.

Adds a new boolean parameter `wait_for_disconnect` to the
`add_outbound_p2p_connection` method. If set, the node under
test is checked to disconnect immediately after receiving the
version message (same logic as for feeler connections).
…depth)

This adds coverage for the logic introduced in PR bitcoin#28170
("p2p: adaptive connections services flags").
@theStack theStack force-pushed the 202401-test-check_disconnect_lack_desirable_flags branch from 49fbd57 to 2f23987 Compare March 11, 2024 14:31
@theStack
Copy link
Contributor Author

Force-pushed with rebase on master and tackled comment #29279 (comment).

I reworked the test_desirable_service_flags method in the last commit by introducing a new desirable_service_flags parameter that has to be passed. Also, there are now two constants DESIRABLE_SERVICE_FLAGS_FULL and DESIRABLE_SERVICE_FLAGS_PRUNED with a comment that the latter is dynamic. Hope that this all is not considered too confusing. Re-review would be much appreciated!

@davidgumberg
Copy link
Contributor

reACK 2f23987

Looks good, retested by modifying HasAllDesirableServiceFlags and ExpectServicesFromConn

Copy link
Contributor

@fjahr fjahr left a comment

Choose a reason for hiding this comment

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

re-utACK 2f23987

(CI failure can be ignored)

self.test_desirable_service_flags(node, [NODE_NETWORK_LIMITED | NODE_WITNESS],
DESIRABLE_SERVICE_FLAGS_FULL, expect_disconnect=True)
node.setmocktime(int(time.time()) + 23 * 3600) # tip inside the 24h window, should succeed
self.test_desirable_service_flags(node, [NODE_NETWORK_LIMITED | NODE_WITNESS],
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: The DESIRABLE_SERVICE_FLAGS_* above are the same as the combinations passed as service_flag_tests so that variable could have been used in both places IMO (with a slight rename maybe). But this isn't critical.

Copy link
Contributor

@cbergqvist cbergqvist left a comment

Choose a reason for hiding this comment

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

re ACK 2f23987

Built & re-ran test/functional/test_runner.py --cachedir=/mnt/tmp/cache --tmpdir=/mnt/tmp.

Copy link
Contributor

@stratospher stratospher left a comment

Choose a reason for hiding this comment

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

tested ACK 2f23987. 🚀

@itornaza
Copy link

itornaza commented Mar 18, 2024

tested ACK 2f23987

  • Configured with --with-incompatible-bdb and --enable-suppress-external-warnings
  • Run unit tests with make check and all tests pass
  • Run all functional tests with no extra flags and all tests pass
  • Run all functional tests with --extended and all tests pass

Notes:

  • First time I run the tests for a PR so I am verbose to avoid any pitfalls
  • Tests run on macOS 14.3.1 (23D60)

@glozow glozow merged commit 3d216ba into bitcoin:master Mar 19, 2024
15 of 16 checks passed
@theStack theStack deleted the 202401-test-check_disconnect_lack_desirable_flags branch March 19, 2024 17:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet