Closed stratospher closed 7 months ago
test/functional/*
BitcoinTestFramework
(base class for all functional tests), writing test parameters in set_test_params()
and writing the test in run_test()
#!/usr/bin/env python3
# Copyright (c) 2021-2022 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
from test_framework.p2p import P2PInterface
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_greater_than
class FunInterface(P2PInterface):
def on_version(self, message):
super().on_version(message)
print(message)
class FunTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
def setup_network(self):
self.setup_nodes()
# Don't connect the nodes
def run_test(self):
# info1 = self.nodes[0].getpeerinfo()
# print(info1)
# self.connect_nodes(0, 1)
# print("does anything change")
# info2 = self.nodes[0].getpeerinfo()
# for keys in info2[0]:
# print(keys, info2[0][keys])
peer_0 = self.nodes[0].add_p2p_connection(FunInterface())
info1 = self.nodes[0].getpeerinfo()
assert_greater_than(info1[0]['bytesrecv_per_msg']['version'], 0)
# assert False
if __name__ == "__main__":
FunTest().main()
TestNode
and P2PInterface
:
TestNode
=> class which manages the bitcoind process(start/stop node, manages node's data directory, log file)P2PInterface
=> Python class which can speak the bitcoin protocol so that we can mock the behaviour of a peer. It's not an actual node but a dummy implementation of how a node's peer would behave.BIP 324 was recently merged and nodes can now send encrypted P2P messages to each other if they run the latest client. This PR adds support for BIP 324 to the dummy implementation of peer in python so that the python code can also talk to bitcoind using the encrypted protocol. We need this to test BIP 324 code (things like whether we're communicating on encrypted/unencrypted protocol, backward compatible with unencrypted protocol etc..) and also to confirm that existing tests work fine and behave as expected.
TestNode::add_p2p_connection
makes a call to peer_connect
TestNode::add_p2p_connection
makes a call to P2PInterface::peer_connect()
which makes a call to P2PConnection::peer_connect()
loop.create_connection
is a coroutine that returns as soon as it has created a transport/protocol pair. P2PInterface
can just open a TCP connection to it. In outbound connection, we need to have a running P2PInterface process
, so that bitcoind had something to connect to. That's why the mechanisms differ.P2PConnection
implements low-level network operations, such as opening and closing the TCP connection to the node and reading bytes from and writing bytes to the socket.version handshake: after the node has identified a peer it wants to connect to, it sends a version message to the peer and waits for the peer to send a version message and a verack message back to it. It then sends a verack back to the peer to establish the connection.
significance:
Tools to observe different messages - stats from getpeerinfo
(bytesrecv_per_msg
), test/functional/combine_logs.py
suppose node1(initiator) wants to connect to node2(responder)
In v1 protocol, node1 starts the connection by sending a version message and performing the version handshake described above.
In v2 protocol, we want even these version messages to be encrypted
so both node1 and node2 need to have the same keys which nobody else knows about so that they can encrypt/decrypt the P2P messages
In v2 protocol, a more advanced form of Diffie-Hellman handshake takes place so that the initiator and responder arrive at the same key stream. Then both of them can use this keystream to encrypt/decrypt P2P messages.
Session Details
p2p
test
python
Learning
This is the introductory session for a 2-part review club. The review club will focus on how the functional test framework works on current master and will not cover the changes in PR #24748. If this is your first exposure to the test framework, it is recommended to understand the basics discussed in this review club. It's a definite prerequisite to understanding PR #24748.
P2P network
Summary
TestNode
.P2PInterface
class serves this purpose and mocks the behaviour of a peer. It can be easily customised.TestNode <--> TestNode
) usingconnect_nodes
which invokes theaddnode
RPC.P2PInterface
allows custom interaction. You can create inbound/outbound connections to theTestNode
from your mockable peer.TestNode
are made usingadd_p2p_connection()
TestNode <---------- P2PInterface
P2PInterface
is the initiator of the connectionTestNode
are made usingadd_outbound_p2p_connection()
TestNode ----------> P2PInterface
TestNode
is the initiator of the connectionQuestions
TestNode::add_p2p_connection
makes a call topeer_connect
TestNode::add_outbound_p2p_connection
makes a call topeer_accept_connection
data_received()
andsend_message()
Extra reading