test/BIP324: functional tests for v2 P2P encryption#24748
test/BIP324: functional tests for v2 P2P encryption#24748achow101 merged 15 commits intobitcoin:masterfrom
Conversation
24f028a to
9880108
Compare
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code CoverageFor detailed information about the code coverage, see the test coverage report. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. ConflictsReviewers, this pull request conflicts with the following ones:
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. |
|
Concept ACK |
|
Concept ACK |
|
converting this PR into a draft. I'll push the updated version which includes the new spec changes in BIP 324 soon. |
Instantiate this object when the connection supports v2 P2P transport protocol. - When a P2PConnection is opened, perform initiate_v2_handshake() if the connection is an initiator. application layer messages are only sent after the initial v2 handshake is over (for both initiator and responder).
Messages are built, encrypted and sent over the socket in v2 connections. If a race condition happens between python's main thread and p2p thread with both of them trying to send a message, it's possible that the messages get encrypted with wrong keystream. Messages are built and sent over the socket in v1 connections. So there's no problem if messages are sent in the wrong order. Co-authored-by: Martin Zumsande <[email protected]> Co-authored-by: theStack <[email protected]>
…te mismatch - When a v2 TestNode makes an outbound connection to a P2PInterface node which doesn't support v2 but is advertised as v2 by some malicious intermediary, the TestNode sends 64 bytes ellswift. The v1 node doesn't understand this and disconnects. Then the v2 TestNode reconnects by sending a v1/version message.
- Add an optional `supports_v2_p2p` parameter to specify if the inbound and outbound connections support v2 P2P protocol. - In the `addconnection_callback` which gets called when creating outbound connections, call the `addconnection` RPC with v2 P2P protocol support enabled.
Also allow P2PConnection::send_message() to send decoy messages for writing tests.
…P 324 - A node initiates a v2 connection by sending 64 bytes ellswift - In BIP 324 "The responder waits until one byte is received which does not match the V1_PREFIX (16 bytes consisting of the network magic followed by "version\x00\x00\x00\x00\x00".)" - It's possible that the 64 bytes ellswift sent by an initiator starts with a prefix of V1_PREFIX - Example form of 64 bytes ellswift could be: 4 bytes network magic + 60 bytes which aren't prefixed with remaining V1_PREFIX - We test this behaviour: - when responder receives 4 byte network magic -> no response received by initiator - when first mismatch happens -> response received by initiator
yes! goal here was to just introduce support for v2 in the test framework. we need more tests after this. |
|
ACK bc9283c |
|
The test fails for me: |
|
hmm weird, looking into it. i also have a WIP branch which uses this test file and adds more v2 tests for sending excess garbage bytes, wrong garbage terminator, incorrect ellswift and non-empty version packet. |
Is this consistently failing for you (or can you at least reproduce it)? I can see it also failing on some of the current open PRs but I can not get my head around why (nor can I reproduce it). This should only happen if To my understanding, the node should not have been able to parse enough data to be replying (with either v1 or v2) 😕 In case you can reproduce it, it may be useful to log what |
see #29352 for a fix (and a way to reproduce it). |
This PR introduces support for v2 P2P encryption(BIP 324) in the existing functional test framework and adds functional tests for the same.
commits overview
introduces a new class
EncryptedP2PStateto store the keys, functions for performing the initial v2 handshake and encryption/decryption.this class is used by
P2PConnectionin inbound/outbound connections to perform the initial v2 handshake before the v1 version handshake. Only after the initial v2 handshake is performed do application layer P2P messages(version, verack etc..) get exchanged. (in a v2 connection)v2_stateis the object of classEncryptedP2PStateinP2PConnectionused to store its keys, session-id etc.supports_v2_p2pinP2PConnectionto denote if it supports v2 P2P.advertises_v2_p2pto denote whetherP2PConnectionwhich mimics peer behaviour advertises V2 P2P support. Default option isFalse.TestNodeP2PConnectionis the initiator [TestNode<---------P2PConnection]TestNodeadvertises/signals v2 P2P support (meansself.nodes[i]set up with"-v2transport=1"), different behaviour will be exhibited based on whether:P2PConnectionsupports v2 P2PP2PConnectiondoes not support v2 P2PP2PConnectionshould support v2 P2P or not. Sosupports_v2_p2pboolean variable is used as an option to enable support for v2 P2P inP2PConnection.TestNodeadvertises v2 P2P support (using "-v2transport=1"), our initiatorP2PConnectionwould send:P2PConnectionsupports v2 P2P) ellswift + garbage bytes to initiate the connectionP2PConnectiondoes not support v2 P2P) version message to initiate the connectionTestNodedoesn't signal v2 P2P support;P2PConnectionbeing the initiator would send version message to initiate a connection.TestNodewould send:P2PConnectionadvertises v2 P2P) ellswift + garbage bytes to initiate the connectionP2PConnectionadvertises v2 P2P) version message to initiate the connectionP2PConnectionadvertises v2 P2P support when it actually doesn't support v2 P2P (false advertisement scenario)TestNodesends ellswift + garbage bytesP2PConnectionreceives but can't process it and disconnects.TestNodethen tries using v1 P2P and sends version messageP2PConnectionreceives/processes this successfully and they communicate on v1 P2Pthe encrypted P2P messages follow a different format - 3 byte length + 1-13 byte message_type + payload + 16 byte MAC
includes support for testing decoy messages and v2 connection downgrade(using false advertisement - when a v2 node makes an outbound connection to a node which doesn't support v2 but is advertised as v2 by some malicious
intermediary)
run the tests
test/functional/p2p_v2_encrypted.pytest/functional/p2p_v2_earlykeyresponse.pyI'm also super grateful to @ dhruv for his really valuable feedback on this branch.
Also written a more elaborate explanation here - https://github.com/stratospher/blogosphere/blob/main/integration_test_bip324.md