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 <hash.h> | |||||
#include <netbase.h> | |||||
#include <protocol.h> | |||||
#include <seeder/bitcoin.h> | |||||
#include <seeder/db.h> | |||||
#include <seeder/dns.h> | #include <seeder/dns.h> | ||||
#include <serialize.h> | |||||
#include <streams.h> | |||||
#include <uint256.h> | |||||
#include <util/system.h> | |||||
#include <version.h> | |||||
#include <boost/test/unit_test.hpp> | #include <boost/test/unit_test.hpp> | ||||
#include <array> | #include <array> | ||||
#include <functional> | |||||
#include <iomanip> | #include <iomanip> | ||||
#include <iostream> | #include <iostream> | ||||
#include <sstream> | #include <sstream> | ||||
#include <string> | #include <string> | ||||
#include <vector> | |||||
const std::function<std::string(const char *)> G_TRANSLATION_FUN = nullptr; | |||||
BOOST_AUTO_TEST_SUITE(seeder) | BOOST_AUTO_TEST_SUITE(seeder) | ||||
const int BUFFER_LENGTH = 512; | const int BUFFER_LENGTH = 512; | ||||
const int QNAME_BUFFER_LENGTH = 256; | const int QNAME_BUFFER_LENGTH = 256; | ||||
const int SIZE_OF_QTYPE = 2; | const int SIZE_OF_QTYPE = 2; | ||||
const int SIZE_OF_QCLASS = 2; | const int SIZE_OF_QCLASS = 2; | ||||
const unsigned short MAINNET_PORT = 8333; | |||||
const std::string VERACK_COMMAND = "verack"; | |||||
const std::string VERSION_COMMAND = "version"; | |||||
const std::string ADDR_COMMAND = "addr"; | |||||
const std::string SEED = "seed.bitcoinabc.org"; | |||||
// Builds dummy DNS query message | // Builds dummy DNS query message | ||||
std::array<uint8_t, BUFFER_LENGTH> CreateDNSQuestion(const std::string &qname) { | std::array<uint8_t, BUFFER_LENGTH> CreateDNSQuestion(const std::string &qname) { | ||||
std::stringstream querryhex; | std::stringstream querryhex; | ||||
querryhex.clear(); | querryhex.clear(); | ||||
querryhex << std::hex << std::setfill('0'); | querryhex << std::hex << std::setfill('0'); | ||||
// Build the DNS message question section | // Build the DNS message question section | ||||
Show All 24 Lines | std::array<uint8_t, BUFFER_LENGTH> CreateDNSQuestion(const std::string &qname) { | ||||
querryhex << std::setw(2) << static_cast<uint8_t>(1); | querryhex << std::setw(2) << static_cast<uint8_t>(1); | ||||
std::array<uint8_t, BUFFER_LENGTH> messageBuffer; | std::array<uint8_t, BUFFER_LENGTH> messageBuffer; | ||||
messageBuffer.fill(0); | messageBuffer.fill(0); | ||||
querryhex >> std::hex >> messageBuffer.data(); | querryhex >> std::hex >> messageBuffer.data(); | ||||
return messageBuffer; | return messageBuffer; | ||||
} | } | ||||
class TestCSeederNode : public CSeederNode { | |||||
public: | |||||
TestCSeederNode(const CService &service, std::vector<CAddress> &vAddrIn) | |||||
: CSeederNode(service, &vAddr), vAddr(vAddrIn), | |||||
nVersion(INIT_PROTO_VERSION), message(SER_NETWORK, 0), | |||||
header(netMagic, ADDR_COMMAND.c_str(), 0) {} | |||||
bool TestProcessMessage(const std::string &strCommand) { | |||||
if (strCommand == VERSION_COMMAND) { | |||||
CreateVersionMessage(); | |||||
return CSeederNode::ProcessMessage(VERSION_COMMAND, message); | |||||
} else if (strCommand == VERACK_COMMAND) { | |||||
CreateVerackMessage(); | |||||
return CSeederNode::ProcessMessage(VERACK_COMMAND, message); | |||||
} else { | |||||
// strCommand == ADDR_COMMAND | |||||
CreateAddrMessage(); | |||||
return CSeederNode::ProcessMessage(ADDR_COMMAND, message); | |||||
} | |||||
} | |||||
void setVersion(int32_t version) { nVersion = version; } | |||||
size_t getAddrListSize() { return vAddr.size(); } | |||||
private: | |||||
void CreateVersionMessage() { | |||||
CDataStream payload(SER_NETWORK, 0); | |||||
payload.SetVersion(nVersion); | |||||
ServiceFlags service = ServiceFlags(NODE_NETWORK); | |||||
int64_t now = time(nullptr); | |||||
uint64_t nonce = 0; | |||||
uint16_t user_agent = 0; | |||||
CAddress addrTo = vAddr[0]; | |||||
CService serviceFrom; | |||||
CAddress addrFrom(serviceFrom, | |||||
ServiceFlags(NODE_NETWORK | NODE_BITCOIN_CASH)); | |||||
int32_t start_height = GetRequireHeight(false); | |||||
payload << nVersion << static_cast<uint64_t>(service) << now << addrTo | |||||
<< addrFrom << nonce << user_agent << start_height; | |||||
message.erase(message.begin(), message.end()); | |||||
message.SetVersion(nVersion); | |||||
message += payload; | |||||
header.nMessageSize = payload.size(); | |||||
uint256 hash = Hash(payload.begin(), payload.end()); | |||||
memcpy(header.pchChecksum, &hash, header.CHECKSUM_SIZE); | |||||
} | |||||
// Verack message consists of only the header with VERACK_COMMAND as the | |||||
// command string. | |||||
void CreateVerackMessage() { | |||||
header.nMessageSize = 0; | |||||
CDataStream payload(SER_NETWORK, 0); | |||||
payload.SetVersion(nVersion); | |||||
payload << static_cast<uint32_t>(0); | |||||
uint256 hash = Hash(payload.begin(), payload.end()); | |||||
memcpy(header.pchChecksum, &hash, header.CHECKSUM_SIZE); | |||||
message.erase(message.begin(), message.end()); | |||||
message.SetVersion(nVersion); | |||||
message << header.pchMessageStart << header.GetCommand() | |||||
<< header.nMessageSize << header.pchChecksum; | |||||
} | |||||
void CreateAddrMessage() { | |||||
CDataStream payload(SER_NETWORK, 0); | |||||
payload.SetVersion(nVersion); | |||||
payload << static_cast<uint8_t>(1); | |||||
payload << vAddr[0]; | |||||
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; | |||||
int32_t nVersion; | |||||
CDataStream message; | |||||
CMessageHeader header; | |||||
}; | |||||
BOOST_AUTO_TEST_CASE(parse_name_simple) { | BOOST_AUTO_TEST_CASE(parse_name_simple) { | ||||
const std::string messageQName = "www.mydomain.com"; | const std::string messageQName = "www.mydomain.com"; | ||||
std::array<uint8_t, BUFFER_LENGTH> dnsMessage; | std::array<uint8_t, BUFFER_LENGTH> dnsMessage; | ||||
dnsMessage.fill(0); | dnsMessage.fill(0); | ||||
dnsMessage = CreateDNSQuestion(messageQName); | dnsMessage = CreateDNSQuestion(messageQName); | ||||
std::array<char, QNAME_BUFFER_LENGTH> qname; | std::array<char, QNAME_BUFFER_LENGTH> qname; | ||||
qname.fill(0); | qname.fill(0); | ||||
size_t writeBufferSize = QNAME_BUFFER_LENGTH; | size_t writeBufferSize = QNAME_BUFFER_LENGTH; | ||||
Show All 39 Lines | BOOST_AUTO_TEST_CASE(parse_name_simple) { | ||||
messageBegin = dnsMessage.data(); | messageBegin = dnsMessage.data(); | ||||
messageEnd = dnsMessage.data() + tooLongQName.size() + 1 + SIZE_OF_QTYPE + | messageEnd = dnsMessage.data() + tooLongQName.size() + 1 + SIZE_OF_QTYPE + | ||||
SIZE_OF_QCLASS; | SIZE_OF_QCLASS; | ||||
ret = parse_name(&messageBegin, messageEnd, dnsMessage.data(), qname.data(), | ret = parse_name(&messageBegin, messageEnd, dnsMessage.data(), qname.data(), | ||||
writeBufferSize); | writeBufferSize); | ||||
BOOST_CHECK_EQUAL(ret, -1); | BOOST_CHECK_EQUAL(ret, -1); | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(seeder_node_tests) { | |||||
CNetAddr ip; | |||||
LookupHost(SEED.c_str(), ip, true); | |||||
const CService service(ip, MAINNET_PORT); | |||||
CAddress addr(service, ServiceFlags()); | |||||
fprintf(stderr, "addr time: %d", addr.nTime); | |||||
std::vector<CAddress> vAddr(999, addr); | |||||
TestCSeederNode testNode(service, vAddr); | |||||
bool ret = testNode.TestProcessMessage(VERSION_COMMAND); | |||||
BOOST_CHECK_EQUAL(ret, false); | |||||
ret = testNode.TestProcessMessage(VERACK_COMMAND); | |||||
BOOST_CHECK_EQUAL(ret, false); | |||||
// vAddr adds new addresses up to the 1000th | |||||
ret = testNode.TestProcessMessage(ADDR_COMMAND); | |||||
BOOST_CHECK_EQUAL(ret, false); | |||||
BOOST_CHECK_EQUAL(1000, testNode.getAddrListSize()); | |||||
// After the 1000th, only one is added and the rest are ignored | |||||
ret = testNode.TestProcessMessage(ADDR_COMMAND); | |||||
BOOST_CHECK_EQUAL(ret, true); | |||||
BOOST_CHECK_EQUAL(1001, testNode.getAddrListSize()); | |||||
testNode.setVersion(10300); | |||||
ret = testNode.TestProcessMessage(VERSION_COMMAND); | |||||
BOOST_CHECK_EQUAL(ret, false); | |||||
testNode.setVersion(106); | |||||
ret = testNode.TestProcessMessage(VERSION_COMMAND); | |||||
BOOST_CHECK_EQUAL(ret, false); | |||||
} | |||||
BOOST_AUTO_TEST_SUITE_END() | BOOST_AUTO_TEST_SUITE_END() |