Bitcoin ABC  0.22.12
P2P Digital Currency
p2p_messaging_tests.cpp
Go to the documentation of this file.
1 // Copyright (c) 2019 The Bitcoin developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <chainparams.h>
6 #include <protocol.h>
7 #include <seeder/bitcoin.h>
8 #include <seeder/db.h>
9 #include <seeder/test/util.h>
10 #include <serialize.h>
11 #include <streams.h>
12 #include <util/system.h>
13 #include <version.h>
14 
15 #include <boost/test/unit_test.hpp>
16 
17 #include <memory>
18 #include <ostream>
19 #include <string>
20 #include <vector>
21 
22 std::ostream &operator<<(std::ostream &os, const PeerMessagingState &state) {
23  os << to_integral(state);
24  return os;
25 }
26 
27 namespace {
28 class CSeederNodeTest : public CSeederNode {
29 public:
30  CSeederNodeTest(const CService &service, std::vector<CAddress> *vAddrIn)
31  : CSeederNode(service, vAddrIn) {}
32 
33  void TestProcessMessage(const std::string &strCommand, CDataStream &message,
34  PeerMessagingState expectedState) {
35  PeerMessagingState ret = ProcessMessage(strCommand, message);
36  BOOST_CHECK_EQUAL(ret, expectedState);
37  }
38 
39  CDataStream getSendBuffer() { return vSend; }
40 };
41 } // namespace
42 
43 static const unsigned short SERVICE_PORT = 18444;
44 
48  CNetAddr ip;
49  ip.SetInternal("bitcoin.test");
50  CService service = {ip, SERVICE_PORT};
51  vAddr.emplace_back(service, ServiceFlags());
52  testNode = std::make_unique<CSeederNodeTest>(service, &vAddr);
53  }
54 
55  std::vector<CAddress> vAddr;
56  std::unique_ptr<CSeederNodeTest> testNode;
57 };
58 
59 BOOST_FIXTURE_TEST_SUITE(p2p_messaging_tests, SeederTestingSetup)
60 
61 static CDataStream
62 CreateVersionMessage(int64_t now, CAddress addrTo, CAddress addrFrom,
63  int32_t start_height, uint32_t nVersion,
64  uint64_t nonce = 0,
65  std::string user_agent = "/bitcoin-cash-seeder:0.15/") {
66  CDataStream payload(SER_NETWORK, 0);
67  payload.SetVersion(nVersion);
68  ServiceFlags serviceflags = ServiceFlags(NODE_NETWORK);
69  payload << nVersion << uint64_t(serviceflags) << now << addrTo << addrFrom
70  << nonce << user_agent << start_height;
71  return payload;
72 }
73 
74 static const int SEEDER_INIT_VERSION = 0;
75 
76 BOOST_AUTO_TEST_CASE(process_version_msg) {
77  CService serviceFrom;
78  CAddress addrFrom(serviceFrom, ServiceFlags(NODE_NETWORK));
79 
80  CDataStream versionMessage = CreateVersionMessage(
81  GetTime(), vAddr[0], addrFrom, GetRequireHeight(), INIT_PROTO_VERSION);
82 
83  // Verify the version is set as the initial value
84  BOOST_CHECK_EQUAL(testNode->CSeederNode::GetClientVersion(),
86  testNode->TestProcessMessage(NetMsgType::VERSION, versionMessage,
88  // Verify the version has been updated
89  BOOST_CHECK_EQUAL(testNode->CSeederNode::GetClientVersion(),
90  versionMessage.GetVersion());
91 }
92 
93 BOOST_AUTO_TEST_CASE(process_verack_msg) {
94  CDataStream verackMessage(SER_NETWORK, 0);
95  verackMessage.SetVersion(INIT_PROTO_VERSION);
96  testNode->TestProcessMessage(NetMsgType::VERACK, verackMessage,
98 
99  // Seeder should respond with an ADDR message
100  const CMessageHeader::MessageMagic netMagic = Params().NetMagic();
101  CMessageHeader header(netMagic);
102  CDataStream sendBuffer = testNode->getSendBuffer();
103  sendBuffer >> header;
104  BOOST_CHECK(header.IsValidWithoutConfig(netMagic));
105  BOOST_CHECK_EQUAL(header.GetCommand(), NetMsgType::GETADDR);
106 
107  // Next message should be GETHEADERS
108  sendBuffer >> header;
109  BOOST_CHECK(header.IsValidWithoutConfig(netMagic));
110  BOOST_CHECK_EQUAL(header.GetCommand(), NetMsgType::GETHEADERS);
111 
112  CBlockLocator locator;
113  uint256 hashStop;
114  sendBuffer >> locator >> hashStop;
115  std::vector<BlockHash> expectedLocator = {
116  Params().Checkpoints().mapCheckpoints.rbegin()->second};
117  BOOST_CHECK(locator.vHave == expectedLocator);
118  BOOST_CHECK(hashStop == uint256());
119 }
120 
121 static CDataStream CreateAddrMessage(std::vector<CAddress> sendAddrs,
122  uint32_t nVersion = INIT_PROTO_VERSION) {
123  CDataStream payload(SER_NETWORK, 0);
124  payload.SetVersion(nVersion);
125  payload << sendAddrs;
126  return payload;
127 }
128 
129 BOOST_AUTO_TEST_CASE(process_addr_msg) {
130  // vAddrs starts with 1 entry.
131  std::vector<CAddress> sendAddrs(ADDR_SOFT_CAP - 1, vAddr[0]);
132 
133  // Happy path
134  // addrs are added normally to vAddr until ADDR_SOFT_CAP is reached.
135  // Add addrs up to the soft cap.
136  CDataStream addrMessage = CreateAddrMessage(sendAddrs);
137  BOOST_CHECK_EQUAL(1, vAddr.size());
138  testNode->TestProcessMessage(NetMsgType::ADDR, addrMessage,
140  BOOST_CHECK_EQUAL(ADDR_SOFT_CAP, vAddr.size());
141 
142  // ADDR_SOFT_CAP is exceeded
143  sendAddrs.resize(1);
144  addrMessage = CreateAddrMessage(sendAddrs);
145  testNode->TestProcessMessage(NetMsgType::ADDR, addrMessage,
147  BOOST_CHECK_EQUAL(ADDR_SOFT_CAP + 1, vAddr.size());
148 
149  // Test the seeder's behavior after ADDR_SOFT_CAP addrs
150  // Only one addr per ADDR message will be added, the rest are ignored
151  size_t expectedSize = vAddr.size() + 1;
152  for (size_t i = 1; i < 10; i++) {
153  sendAddrs.resize(i, sendAddrs[0]);
154  addrMessage = CreateAddrMessage(sendAddrs);
155  testNode->TestProcessMessage(NetMsgType::ADDR, addrMessage,
157  BOOST_CHECK_EQUAL(expectedSize, vAddr.size());
158  ++expectedSize;
159  }
160 }
161 
ServiceFlags
nServices flags.
Definition: protocol.h:320
Describes a place in the block chain to another node such that if the other node doesn&#39;t have the sam...
Definition: block.h:110
int GetVersion() const
Definition: streams.h:386
static const std::string REGTEST
const char * GETADDR
The getaddr message requests an addr message from the receiving node, preferably one with lots of IP ...
Definition: protocol.cpp:32
static CDataStream CreateVersionMessage(int64_t now, CAddress addrTo, CAddress addrFrom, int32_t start_height, uint32_t nVersion, uint64_t nonce=0, std::string user_agent="/bitcoin-cash-seeder:0.15/")
static const int SEEDER_INIT_VERSION
static NodeContext testNode
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:196
const CCheckpointData & Checkpoints() const
Definition: chainparams.h:94
std::vector< CAddress > vAddr
std::ostream & operator<<(std::ostream &os, const PeerMessagingState &state)
CSeederNode(const CService &ip, std::vector< CAddress > *vAddrIn)
Definition: bitcoin.cpp:175
static const unsigned short SERVICE_PORT
CDataStream vSend
Definition: bitcoin.h:37
const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
Definition: protocol.cpp:28
PeerMessagingState ProcessMessage(std::string strCommand, CDataStream &recv)
Definition: bitcoin.cpp:37
void SelectParams(const std::string &network)
Sets the params returned by Params() to those for the given BIP70 chain name.
static const int INIT_PROTO_VERSION
initial proto version, to be increased after version/verack negotiation
Definition: version.h:14
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:179
A CService with information about it as peer.
Definition: protocol.h:427
static int GetRequireHeight()
Definition: db.h:28
const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
Definition: protocol.cpp:23
static const unsigned int ADDR_SOFT_CAP
Definition: bitcoin.h:21
std::unique_ptr< CSeederNodeTest > testNode
const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
Definition: protocol.cpp:22
IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96))
Definition: netaddress.h:30
256-bit opaque blob.
Definition: uint256.h:120
static CDataStream CreateAddrMessage(std::vector< CAddress > sendAddrs, uint32_t nVersion=INIT_PROTO_VERSION)
MapCheckpoints mapCheckpoints
Definition: chainparams.h:25
#define BOOST_FIXTURE_TEST_SUITE(a, b)
Definition: object.cpp:14
std::array< uint8_t, MESSAGE_START_SIZE > MessageMagic
Definition: protocol.h:49
const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
Definition: protocol.cpp:21
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:18
const CChainParams & Params()
Return the currently selected parameters.
PeerMessagingState
Definition: bitcoin.h:23
#define BOOST_AUTO_TEST_SUITE_END()
Definition: object.cpp:16
bool SetInternal(const std::string &name)
Try to make this a dummy address that maps the specified name into IPv6 like so: (0xFD + sha256("bitc...
Definition: netaddress.cpp:60
void SetVersion(int n)
Definition: streams.h:385
int64_t GetTime()
Return system time (or mocked time, if set)
Definition: time.cpp:27
BOOST_AUTO_TEST_CASE(process_version_msg)
constexpr std::underlying_type< E >::type to_integral(E e)
Definition: util.h:11
const CMessageHeader::MessageMagic & NetMagic() const
Definition: chainparams.h:61
#define BOOST_CHECK(expr)
Definition: object.cpp:17
Message header.
Definition: protocol.h:37