Changeset View
Changeset View
Standalone View
Standalone View
src/seeder/test/seeder_tests.cpp
// Copyright (c) 2019 The Bitcoin developers | // Copyright (c) 2019 The Bitcoin developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#define BOOST_TEST_MODULE Bitcoin Seeder Test Suite | #define BOOST_TEST_MODULE Bitcoin Seeder Test Suite | ||||
#include <chainparamsconstants.h> | |||||
#include <hash.h> | #include <hash.h> | ||||
#include <netbase.h> | #include <netbase.h> | ||||
#include <protocol.h> | #include <protocol.h> | ||||
#include <seeder/bitcoin.h> | #include <seeder/bitcoin.h> | ||||
#include <seeder/db.h> | #include <seeder/db.h> | ||||
#include <seeder/dns.h> | #include <seeder/dns.h> | ||||
#include <serialize.h> | #include <serialize.h> | ||||
#include <streams.h> | #include <streams.h> | ||||
Show All 22 Lines | |||||
static const uint16_t QUESTION_CLASS = 1; | static const uint16_t QUESTION_CLASS = 1; | ||||
static const uint16_t QUESTION_TYPE = 1; | static const uint16_t QUESTION_TYPE = 1; | ||||
static const uint8_t END_OF_NAME_FIELD = 0; | static const uint8_t END_OF_NAME_FIELD = 0; | ||||
static const size_t MAX_LABEL_LENGTH = 63; | static const size_t MAX_LABEL_LENGTH = 63; | ||||
static const unsigned short MAINNET_PORT = 8333; | static const unsigned short MAINNET_PORT = 8333; | ||||
static const std::string VERACK_COMMAND = "verack"; | static const std::string VERACK_COMMAND = "verack"; | ||||
static const std::string VERSION_COMMAND = "version"; | static const std::string VERSION_COMMAND = "version"; | ||||
static const std::string ADDR_COMMAND = "addr"; | static const std::string ADDR_COMMAND = "addr"; | ||||
static const std::string SENDHEADERS_COMMAND = "sendheaders"; | |||||
static const std::string HEADERS_COMMAND = "headers"; | |||||
static const std::string EMPTY_HEADERS_COMMAND = "emptyheaders"; | |||||
static const uint8_t HEADERS_TXN_COUNT = 0; | |||||
static const std::string SEED = "seed.bitcoinabc.org"; | static const std::string SEED = "seed.bitcoinabc.org"; | ||||
static const uint32_t VERACK_PAYLOAD = 0; | static const uint32_t VERACK_PAYLOAD = 0; | ||||
// Builds dummy DNS query message | // Builds dummy DNS query message | ||||
std::array<uint8_t, BUFFER_LENGTH> | std::array<uint8_t, BUFFER_LENGTH> | ||||
CreateDNSQuestion(const std::string &qualifierName) { | CreateDNSQuestion(const std::string &qualifierName) { | ||||
std::stringstream querryhex; | std::stringstream querryhex; | ||||
querryhex.clear(); | querryhex.clear(); | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | public: | ||||
bool TestProcessMessage(const std::string &strCommand) { | bool TestProcessMessage(const std::string &strCommand) { | ||||
if (strCommand == VERSION_COMMAND) { | if (strCommand == VERSION_COMMAND) { | ||||
CreateVersionMessage(); | CreateVersionMessage(); | ||||
return CSeederNode::ProcessMessage(VERSION_COMMAND, message); | return CSeederNode::ProcessMessage(VERSION_COMMAND, message); | ||||
} else if (strCommand == VERACK_COMMAND) { | } else if (strCommand == VERACK_COMMAND) { | ||||
CreateVerackMessage(); | CreateVerackMessage(); | ||||
return CSeederNode::ProcessMessage(VERACK_COMMAND, message); | return CSeederNode::ProcessMessage(VERACK_COMMAND, message); | ||||
} else { | } else if (strCommand == ADDR_COMMAND) { | ||||
// strCommand == ADDR_COMMAND | |||||
CreateAddrMessage(); | CreateAddrMessage(); | ||||
return CSeederNode::ProcessMessage(ADDR_COMMAND, message); | return CSeederNode::ProcessMessage(ADDR_COMMAND, message); | ||||
} else if (strCommand == EMPTY_HEADERS_COMMAND) { | |||||
CreateHeadersMessage(true); | |||||
// Calls ProcessMessage() on an empty headers message, but the | |||||
// message is still a headers message with a headers command | |||||
return CSeederNode::ProcessMessage(HEADERS_COMMAND, message); | |||||
} else { | |||||
// strCommand == HEADERS_COMMAND | |||||
CreateHeadersMessage(false); | |||||
return CSeederNode::ProcessMessage(HEADERS_COMMAND, message); | |||||
} | } | ||||
} | } | ||||
void setVersion(int32_t version) { nVersion = version; } | void setVersion(int32_t version) { nVersion = version; } | ||||
size_t getAddrListSize() { return vAddr.size(); } | size_t getAddrListSize() { return vAddr.size(); } | ||||
private: | private: | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | void CreateAddrMessage() { | ||||
message.erase(message.begin(), message.end()); | message.erase(message.begin(), message.end()); | ||||
message += payload; | message += payload; | ||||
header.nMessageSize = payload.size(); | header.nMessageSize = payload.size(); | ||||
uint256 hash = Hash(payload.begin(), payload.end()); | uint256 hash = Hash(payload.begin(), payload.end()); | ||||
memcpy(header.pchChecksum, &hash, header.CHECKSUM_SIZE); | memcpy(header.pchChecksum, &hash, header.CHECKSUM_SIZE); | ||||
} | } | ||||
void CreateHeadersMessage(bool emptyMessage) { | |||||
CDataStream payload(SER_NETWORK, 0); | |||||
payload.SetVersion(nVersion); | |||||
uint8_t messageSize = emptyMessage ? 0 : 1; | |||||
payload << messageSize; | |||||
// The actual headers can be garbage data, Seeder only cares that it got | |||||
// a specific type of message and the size. | |||||
uint256 garbageHash = Hash(payload.begin(), payload.end()); | |||||
uint32_t garbageTimeStamp = 0; | |||||
uint32_t garbageBits = 0; | |||||
uint32_t garbageNonce = 0; | |||||
payload << nVersion; | |||||
// prev_block | |||||
payload << garbageHash; | |||||
// merkle_root | |||||
payload << garbageHash; | |||||
// timestamp | |||||
payload << garbageTimeStamp; | |||||
// bits | |||||
payload << garbageBits; | |||||
// nonce | |||||
payload << garbageNonce; | |||||
// txn_count | |||||
payload << HEADERS_TXN_COUNT; | |||||
message.erase(message.begin(), message.end()); | |||||
message += payload; | |||||
header.nMessageSize = payload.size(); | |||||
uint256 hash = Hash(payload.begin(), payload.end()); | |||||
memcpy(header.pchChecksum, &hash, header.CHECKSUM_SIZE); | |||||
} | |||||
std::vector<CAddress> vAddr; | std::vector<CAddress> vAddr; | ||||
int32_t nVersion; | int32_t nVersion; | ||||
CDataStream message; | CDataStream message; | ||||
CMessageHeader header; | CMessageHeader header; | ||||
}; | }; | ||||
BOOST_AUTO_TEST_CASE(parse_name_happy_path) { | BOOST_AUTO_TEST_CASE(parse_name_happy_path) { | ||||
const std::string messageQualifierName = "www.mydomain.com"; | const std::string messageQualifierName = "www.mydomain.com"; | ||||
▲ Show 20 Lines • Show All 160 Lines • ▼ Show 20 Lines | BOOST_AUTO_TEST_CASE(seeder_node_addr_test_full_vaddr) { | ||||
TestCSeederNode testNode(service, vAddr); | TestCSeederNode testNode(service, vAddr); | ||||
// After the 1000th, only one is added and the rest are ignored | // After the 1000th, only one is added and the rest are ignored | ||||
bool ret = testNode.TestProcessMessage(ADDR_COMMAND); | bool ret = testNode.TestProcessMessage(ADDR_COMMAND); | ||||
BOOST_CHECK_EQUAL(ret, true); | BOOST_CHECK_EQUAL(ret, true); | ||||
BOOST_CHECK_EQUAL(1001, testNode.getAddrListSize()); | BOOST_CHECK_EQUAL(1001, testNode.getAddrListSize()); | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(seeder_node_headers_test_happy_path) { | |||||
CNetAddr ip; | |||||
LookupHost(SEED.c_str(), ip, true); | |||||
const CService service(ip, MAINNET_PORT); | |||||
CAddress addr(service, ServiceFlags()); | |||||
std::vector<CAddress> vAddr(1, addr); | |||||
TestCSeederNode testNode(service, vAddr); | |||||
bool ret = testNode.TestProcessMessage(HEADERS_COMMAND); | |||||
BOOST_CHECK_EQUAL(ret, false); | |||||
} | |||||
BOOST_AUTO_TEST_CASE(seeder_node_empty_headers_test) { | |||||
CNetAddr ip; | |||||
LookupHost(SEED.c_str(), ip, true); | |||||
const CService service(ip, MAINNET_PORT); | |||||
CAddress addr(service, ServiceFlags()); | |||||
std::vector<CAddress> vAddr(1, addr); | |||||
TestCSeederNode testNode(service, vAddr); | |||||
bool ret = testNode.TestProcessMessage(EMPTY_HEADERS_COMMAND); | |||||
BOOST_CHECK_EQUAL(ret, false); | |||||
} | |||||
BOOST_AUTO_TEST_SUITE_END() | BOOST_AUTO_TEST_SUITE_END() |