Here's a writeup of the implementation details used in the test framework. (Note: v2 P2P refers to the encrypted P2P transport protocol proposed in BIP 324)
We need a way in the functional test framework to make sure that v2 P2P enabled bitcoind process exhibits behaviour intended in BIP 324. Example:
- actually communicates on V2 P2P protocol (depending on whether the node you're connected to supports v2 P2P or not)
- whether v2 P2P protocol is backward compatible with nodes communicating on v1 P2P protocol
- whether traffic shaping during initial v2 handshake works
- whether initial v2 handshake works as intended - one such example, if both our nodes run BIP 324 and i send you ellswift bytes, you should respond back only when mismatch from V1_PREFIX occurs.
- whether we can send decoy messages
- behaviour during false advertisement of v2 P2P support etc.
These require a way to pause and examine whether bitcoind process has sent/received correct responses, and so we need to extend BIP 324 support to P2PConnection
.
TestNode
vsP2PConnection
-TestNode
runs an actual bitcoind process andP2PConnection
is a class to make inbound/outbound connections to/from theTestNode
which would mimic the behaviour of a peer and allow us to pause/examine responses.- Inbound connections to the
TestNode
are made usingadd_p2p_connection()
TestNode
<----------P2PConnection
- Here,
P2PConnection
is the initiator of the connection
- Outbound connections from the
TestNode
are made usingadd_outbound_p2p_connection()
TestNode
---------->P2PConnection
- Here,
TestNode
is the initiator of the connection
- A node advertising support for v2 P2P(using
NODE_P2P_V2
service flag) is different from a node actually supporting v2 P2P.- since this branch is built on top of #24545,
TestNode
(a bitcoind process) supports v2 P2P. - we'd need additional options in
P2PConnection
so that we know if it supports v2 P2P or not.
- the node could be falsely advertised to support encrypted P2P transport when it actually doesn't support encrypted v2 P2P.
- in the real world, the only way to know for sure if the other node supports BIP 324 is by sending it ellswift + garbage bytes and initiating v2 handshake to see if it actually responds. We initiate this v2 handshake based on the service flags this responder node advertises. But we can't know for sure until we actually establish a connection.
- supposing it was falsely advertised to support v2 P2P by some intermediary, the responder node would terminate the connection. the initiator node would then have to reconnect using v1 P2P protocol. (See BIP)
- In the test framework, we cannot test this false advertisement behaviour when the responder node is the actual bitcoind process(an inbound connection to the
TestNode
<----------P2PConnection
) since service advertisement is done using the CLI arg"-v2transport=1"
and there's no false advertisement possible(in the test framework). - This false advertisement and reconnection property is however very important to ensure that no network partition happens and existing v1 P2P is always preserved for BIP 324 enabled nodes in the future.
- by adding options in
P2PConnection
to falsely advertise v2 P2P support, it is possible to ensure the above-mentioned behaviour when the responder node is aP2PConnection
(an Outbound connection from theTestNode
). And since it's a transport protocol behaviour which has to be tested, we introduce a separate variable for this.
- since this branch is built on top of #24545,
- Ports
- TODO
EncryptedP2PState
- we need a class which stores keys, session-id, functions to perform initial v2 handshake, encryption/decryption etc.v2_state
-P2PConnection
needs an object of classEncryptedP2PState
to store its keys, session-id etc.supports_v2_p2p
- boolean variable used byP2PConnection
to denote if it supports v2 P2P.- CLI arg
"-v2transport=1"
- whether theTestNode
running the actual bitcoind process signals/advertises V2 P2P support.- see commit.
- Default option is
False
.
advertises_v2_p2p
- whetherP2PConnection
which mimics peer behaviour advertises V2 P2P support. Default option isFalse
.- In the test framework, you can create Inbound and Outbound connections to
TestNode
- During Inbound Connections,
P2PConnection
is the initiator [TestNode
<---------P2PConnection
]- if the
TestNode
advertises/signals v2 P2P support (meansself.nodes[i]
set up with"-v2transport=1"
), different behaviour will be exhibited based on whether:P2PConnection
supports v2 P2PP2PConnection
does not support v2 P2P
- In a real world scenario, the initiator node would intrinsically know if they support v2 P2P based on whatever code they choose to run.
- However, in the test scenario where we mimic peer behaviour, we have no way of knowing if
P2PConnection
should support v2 P2P or not. - we need an option to enable support for v2 P2P - this is done using the variable
supports_v2_p2p
- Since the
TestNode
advertises v2 P2P support (using"-v2transport=1"
), our initiatorP2PConnection
would send:- (if the
P2PConnection
supports v2 P2P) ellswift + garbage bytes to initiate the connection - (if the
P2PConnection
does not support v2 P2P) version message to initiate the connection
- (if the
- if the
TestNode
doesn't signal v2 P2P support;P2PConnection
being the initiator would send version message to initiate a connection.
- if the
- During Outbound Connections [
TestNode
-------->P2PConnection
]- initiator
TestNode
would send:- (if the
P2PConnection
advertises v2 P2P) ellswift + garbage bytes to initiate the connection - (if the
P2PConnection
advertises v2 P2P) version message to initiate the connection
- (if the
- Suppose
P2PConnection
advertises v2 P2P support when it actually doesn't support v2 P2P (false advertisement scenario)TestNode
sends ellswift + garbage bytesP2PConnection
receives but can't process it and disconnects.TestNode
then tries using v1 P2P and sends version messageP2PConnection
receives/processes this successfully and they communicate on v1 P2P
- initiator
- During Inbound Connections,