mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-30 13:07:32 -03:00
35fbc97208
c9d548c91f
net: remove CService::ToStringPort() (Vasil Dimov)fd4f0f41e9
gui: simplify OptionsDialog::updateDefaultProxyNets() (Vasil Dimov)96c791dd20
net: remove CService::ToString() use ToStringAddrPort() instead (Vasil Dimov)944a9de08a
net: remove CNetAddr::ToString() and use ToStringAddr() instead (Vasil Dimov)043b9de59a
scripted-diff: rename ToStringIP[Port]() to ToStringAddr[Port]() (Vasil Dimov) Pull request description: Before this PR we had the somewhat confusing combination of methods: `CNetAddr::ToStringIP()` `CNetAddr::ToString()` (duplicate of the above) `CService::ToStringIPPort()` `CService::ToString()` (duplicate of the above, overrides a non-virtual method from `CNetAddr`) `CService::ToStringPort()` Avoid [overriding non-virtual methods](https://github.com/bitcoin/bitcoin/pull/25349/#issuecomment-1185226396). "IP" stands for "Internet Protocol" and while sometimes "IP addresses" are called just "IPs", it is incorrect to call Tor or I2P addresses "IPs". Thus use "Addr" instead of "IP". Change the above to: `CNetAddr::ToStringAddr()` `CService::ToStringAddrPort()` The changes touch a lot of files, but are mostly mechanical. ACKs for top commit: sipa: utACKc9d548c91f
achow101: ACKc9d548c91f
jonatack: re-ACKc9d548c91f
only change since my previous reviews is rebase, but as a sanity check rebased to current master and at each commit quickly re-reviewed and re-verified clean build and green unit tests LarryRuane: ACKc9d548c91f
Tree-SHA512: 633fb044bdecf9f551b5e3314c385bf10e2b78e8027dc51ec324b66b018da35e5b01f3fbe6295bbc455ea1bcd1a3629de1918d28de510693afaf6a52693f2157
908 lines
36 KiB
C++
908 lines
36 KiB
C++
// Copyright (c) 2012-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.
|
|
|
|
#include <chainparams.h>
|
|
#include <clientversion.h>
|
|
#include <compat/compat.h>
|
|
#include <cstdint>
|
|
#include <net.h>
|
|
#include <net_processing.h>
|
|
#include <netaddress.h>
|
|
#include <netbase.h>
|
|
#include <netmessagemaker.h>
|
|
#include <serialize.h>
|
|
#include <span.h>
|
|
#include <streams.h>
|
|
#include <test/util/setup_common.h>
|
|
#include <test/util/validation.h>
|
|
#include <timedata.h>
|
|
#include <util/strencodings.h>
|
|
#include <util/string.h>
|
|
#include <util/system.h>
|
|
#include <validation.h>
|
|
#include <version.h>
|
|
|
|
#include <boost/test/unit_test.hpp>
|
|
|
|
#include <algorithm>
|
|
#include <ios>
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <string>
|
|
|
|
using namespace std::literals;
|
|
|
|
BOOST_FIXTURE_TEST_SUITE(net_tests, RegTestingSetup)
|
|
|
|
BOOST_AUTO_TEST_CASE(cnode_listen_port)
|
|
{
|
|
// test default
|
|
uint16_t port{GetListenPort()};
|
|
BOOST_CHECK(port == Params().GetDefaultPort());
|
|
// test set port
|
|
uint16_t altPort = 12345;
|
|
BOOST_CHECK(gArgs.SoftSetArg("-port", ToString(altPort)));
|
|
port = GetListenPort();
|
|
BOOST_CHECK(port == altPort);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(cnode_simple_test)
|
|
{
|
|
NodeId id = 0;
|
|
|
|
in_addr ipv4Addr;
|
|
ipv4Addr.s_addr = 0xa0b0c001;
|
|
|
|
CAddress addr = CAddress(CService(ipv4Addr, 7777), NODE_NETWORK);
|
|
std::string pszDest;
|
|
|
|
std::unique_ptr<CNode> pnode1 = std::make_unique<CNode>(id++,
|
|
/*sock=*/nullptr,
|
|
addr,
|
|
/*nKeyedNetGroupIn=*/0,
|
|
/*nLocalHostNonceIn=*/0,
|
|
CAddress(),
|
|
pszDest,
|
|
ConnectionType::OUTBOUND_FULL_RELAY,
|
|
/*inbound_onion=*/false);
|
|
BOOST_CHECK(pnode1->IsFullOutboundConn() == true);
|
|
BOOST_CHECK(pnode1->IsManualConn() == false);
|
|
BOOST_CHECK(pnode1->IsBlockOnlyConn() == false);
|
|
BOOST_CHECK(pnode1->IsFeelerConn() == false);
|
|
BOOST_CHECK(pnode1->IsAddrFetchConn() == false);
|
|
BOOST_CHECK(pnode1->IsInboundConn() == false);
|
|
BOOST_CHECK(pnode1->m_inbound_onion == false);
|
|
BOOST_CHECK_EQUAL(pnode1->ConnectedThroughNetwork(), Network::NET_IPV4);
|
|
|
|
std::unique_ptr<CNode> pnode2 = std::make_unique<CNode>(id++,
|
|
/*sock=*/nullptr,
|
|
addr,
|
|
/*nKeyedNetGroupIn=*/1,
|
|
/*nLocalHostNonceIn=*/1,
|
|
CAddress(),
|
|
pszDest,
|
|
ConnectionType::INBOUND,
|
|
/*inbound_onion=*/false);
|
|
BOOST_CHECK(pnode2->IsFullOutboundConn() == false);
|
|
BOOST_CHECK(pnode2->IsManualConn() == false);
|
|
BOOST_CHECK(pnode2->IsBlockOnlyConn() == false);
|
|
BOOST_CHECK(pnode2->IsFeelerConn() == false);
|
|
BOOST_CHECK(pnode2->IsAddrFetchConn() == false);
|
|
BOOST_CHECK(pnode2->IsInboundConn() == true);
|
|
BOOST_CHECK(pnode2->m_inbound_onion == false);
|
|
BOOST_CHECK_EQUAL(pnode2->ConnectedThroughNetwork(), Network::NET_IPV4);
|
|
|
|
std::unique_ptr<CNode> pnode3 = std::make_unique<CNode>(id++,
|
|
/*sock=*/nullptr,
|
|
addr,
|
|
/*nKeyedNetGroupIn=*/0,
|
|
/*nLocalHostNonceIn=*/0,
|
|
CAddress(),
|
|
pszDest,
|
|
ConnectionType::OUTBOUND_FULL_RELAY,
|
|
/*inbound_onion=*/false);
|
|
BOOST_CHECK(pnode3->IsFullOutboundConn() == true);
|
|
BOOST_CHECK(pnode3->IsManualConn() == false);
|
|
BOOST_CHECK(pnode3->IsBlockOnlyConn() == false);
|
|
BOOST_CHECK(pnode3->IsFeelerConn() == false);
|
|
BOOST_CHECK(pnode3->IsAddrFetchConn() == false);
|
|
BOOST_CHECK(pnode3->IsInboundConn() == false);
|
|
BOOST_CHECK(pnode3->m_inbound_onion == false);
|
|
BOOST_CHECK_EQUAL(pnode3->ConnectedThroughNetwork(), Network::NET_IPV4);
|
|
|
|
std::unique_ptr<CNode> pnode4 = std::make_unique<CNode>(id++,
|
|
/*sock=*/nullptr,
|
|
addr,
|
|
/*nKeyedNetGroupIn=*/1,
|
|
/*nLocalHostNonceIn=*/1,
|
|
CAddress(),
|
|
pszDest,
|
|
ConnectionType::INBOUND,
|
|
/*inbound_onion=*/true);
|
|
BOOST_CHECK(pnode4->IsFullOutboundConn() == false);
|
|
BOOST_CHECK(pnode4->IsManualConn() == false);
|
|
BOOST_CHECK(pnode4->IsBlockOnlyConn() == false);
|
|
BOOST_CHECK(pnode4->IsFeelerConn() == false);
|
|
BOOST_CHECK(pnode4->IsAddrFetchConn() == false);
|
|
BOOST_CHECK(pnode4->IsInboundConn() == true);
|
|
BOOST_CHECK(pnode4->m_inbound_onion == true);
|
|
BOOST_CHECK_EQUAL(pnode4->ConnectedThroughNetwork(), Network::NET_ONION);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(cnetaddr_basic)
|
|
{
|
|
CNetAddr addr;
|
|
|
|
// IPv4, INADDR_ANY
|
|
BOOST_REQUIRE(LookupHost("0.0.0.0", addr, false));
|
|
BOOST_REQUIRE(!addr.IsValid());
|
|
BOOST_REQUIRE(addr.IsIPv4());
|
|
|
|
BOOST_CHECK(addr.IsBindAny());
|
|
BOOST_CHECK(addr.IsAddrV1Compatible());
|
|
BOOST_CHECK_EQUAL(addr.ToStringAddr(), "0.0.0.0");
|
|
|
|
// IPv4, INADDR_NONE
|
|
BOOST_REQUIRE(LookupHost("255.255.255.255", addr, false));
|
|
BOOST_REQUIRE(!addr.IsValid());
|
|
BOOST_REQUIRE(addr.IsIPv4());
|
|
|
|
BOOST_CHECK(!addr.IsBindAny());
|
|
BOOST_CHECK(addr.IsAddrV1Compatible());
|
|
BOOST_CHECK_EQUAL(addr.ToStringAddr(), "255.255.255.255");
|
|
|
|
// IPv4, casual
|
|
BOOST_REQUIRE(LookupHost("12.34.56.78", addr, false));
|
|
BOOST_REQUIRE(addr.IsValid());
|
|
BOOST_REQUIRE(addr.IsIPv4());
|
|
|
|
BOOST_CHECK(!addr.IsBindAny());
|
|
BOOST_CHECK(addr.IsAddrV1Compatible());
|
|
BOOST_CHECK_EQUAL(addr.ToStringAddr(), "12.34.56.78");
|
|
|
|
// IPv6, in6addr_any
|
|
BOOST_REQUIRE(LookupHost("::", addr, false));
|
|
BOOST_REQUIRE(!addr.IsValid());
|
|
BOOST_REQUIRE(addr.IsIPv6());
|
|
|
|
BOOST_CHECK(addr.IsBindAny());
|
|
BOOST_CHECK(addr.IsAddrV1Compatible());
|
|
BOOST_CHECK_EQUAL(addr.ToStringAddr(), "::");
|
|
|
|
// IPv6, casual
|
|
BOOST_REQUIRE(LookupHost("1122:3344:5566:7788:9900:aabb:ccdd:eeff", addr, false));
|
|
BOOST_REQUIRE(addr.IsValid());
|
|
BOOST_REQUIRE(addr.IsIPv6());
|
|
|
|
BOOST_CHECK(!addr.IsBindAny());
|
|
BOOST_CHECK(addr.IsAddrV1Compatible());
|
|
BOOST_CHECK_EQUAL(addr.ToStringAddr(), "1122:3344:5566:7788:9900:aabb:ccdd:eeff");
|
|
|
|
// IPv6, scoped/link-local. See https://tools.ietf.org/html/rfc4007
|
|
// We support non-negative decimal integers (uint32_t) as zone id indices.
|
|
// Normal link-local scoped address functionality is to append "%" plus the
|
|
// zone id, for example, given a link-local address of "fe80::1" and a zone
|
|
// id of "32", return the address as "fe80::1%32".
|
|
const std::string link_local{"fe80::1"};
|
|
const std::string scoped_addr{link_local + "%32"};
|
|
BOOST_REQUIRE(LookupHost(scoped_addr, addr, false));
|
|
BOOST_REQUIRE(addr.IsValid());
|
|
BOOST_REQUIRE(addr.IsIPv6());
|
|
BOOST_CHECK(!addr.IsBindAny());
|
|
BOOST_CHECK_EQUAL(addr.ToStringAddr(), scoped_addr);
|
|
|
|
// Test that the delimiter "%" and default zone id of 0 can be omitted for the default scope.
|
|
BOOST_REQUIRE(LookupHost(link_local + "%0", addr, false));
|
|
BOOST_REQUIRE(addr.IsValid());
|
|
BOOST_REQUIRE(addr.IsIPv6());
|
|
BOOST_CHECK(!addr.IsBindAny());
|
|
BOOST_CHECK_EQUAL(addr.ToStringAddr(), link_local);
|
|
|
|
// TORv2, no longer supported
|
|
BOOST_CHECK(!addr.SetSpecial("6hzph5hv6337r6p2.onion"));
|
|
|
|
// TORv3
|
|
const char* torv3_addr = "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion";
|
|
BOOST_REQUIRE(addr.SetSpecial(torv3_addr));
|
|
BOOST_REQUIRE(addr.IsValid());
|
|
BOOST_REQUIRE(addr.IsTor());
|
|
|
|
BOOST_CHECK(!addr.IsI2P());
|
|
BOOST_CHECK(!addr.IsBindAny());
|
|
BOOST_CHECK(!addr.IsAddrV1Compatible());
|
|
BOOST_CHECK_EQUAL(addr.ToStringAddr(), torv3_addr);
|
|
|
|
// TORv3, broken, with wrong checksum
|
|
BOOST_CHECK(!addr.SetSpecial("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscsad.onion"));
|
|
|
|
// TORv3, broken, with wrong version
|
|
BOOST_CHECK(!addr.SetSpecial("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscrye.onion"));
|
|
|
|
// TORv3, malicious
|
|
BOOST_CHECK(!addr.SetSpecial(std::string{
|
|
"pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd\0wtf.onion", 66}));
|
|
|
|
// TOR, bogus length
|
|
BOOST_CHECK(!addr.SetSpecial(std::string{"mfrggzak.onion"}));
|
|
|
|
// TOR, invalid base32
|
|
BOOST_CHECK(!addr.SetSpecial(std::string{"mf*g zak.onion"}));
|
|
|
|
// I2P
|
|
const char* i2p_addr = "UDHDrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.I2P";
|
|
BOOST_REQUIRE(addr.SetSpecial(i2p_addr));
|
|
BOOST_REQUIRE(addr.IsValid());
|
|
BOOST_REQUIRE(addr.IsI2P());
|
|
|
|
BOOST_CHECK(!addr.IsTor());
|
|
BOOST_CHECK(!addr.IsBindAny());
|
|
BOOST_CHECK(!addr.IsAddrV1Compatible());
|
|
BOOST_CHECK_EQUAL(addr.ToStringAddr(), ToLower(i2p_addr));
|
|
|
|
// I2P, correct length, but decodes to less than the expected number of bytes.
|
|
BOOST_CHECK(!addr.SetSpecial("udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jn=.b32.i2p"));
|
|
|
|
// I2P, extra unnecessary padding
|
|
BOOST_CHECK(!addr.SetSpecial("udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna=.b32.i2p"));
|
|
|
|
// I2P, malicious
|
|
BOOST_CHECK(!addr.SetSpecial("udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v\0wtf.b32.i2p"s));
|
|
|
|
// I2P, valid but unsupported (56 Base32 characters)
|
|
// See "Encrypted LS with Base 32 Addresses" in
|
|
// https://geti2p.net/spec/encryptedleaseset.txt
|
|
BOOST_CHECK(
|
|
!addr.SetSpecial("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscsad.b32.i2p"));
|
|
|
|
// I2P, invalid base32
|
|
BOOST_CHECK(!addr.SetSpecial(std::string{"tp*szydbh4dp.b32.i2p"}));
|
|
|
|
// Internal
|
|
addr.SetInternal("esffpp");
|
|
BOOST_REQUIRE(!addr.IsValid()); // "internal" is considered invalid
|
|
BOOST_REQUIRE(addr.IsInternal());
|
|
|
|
BOOST_CHECK(!addr.IsBindAny());
|
|
BOOST_CHECK(addr.IsAddrV1Compatible());
|
|
BOOST_CHECK_EQUAL(addr.ToStringAddr(), "esffpvrt3wpeaygy.internal");
|
|
|
|
// Totally bogus
|
|
BOOST_CHECK(!addr.SetSpecial("totally bogus"));
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(cnetaddr_tostring_canonical_ipv6)
|
|
{
|
|
// Test that CNetAddr::ToString formats IPv6 addresses with zero compression as described in
|
|
// RFC 5952 ("A Recommendation for IPv6 Address Text Representation").
|
|
const std::map<std::string, std::string> canonical_representations_ipv6{
|
|
{"0000:0000:0000:0000:0000:0000:0000:0000", "::"},
|
|
{"000:0000:000:00:0:00:000:0000", "::"},
|
|
{"000:000:000:000:000:000:000:000", "::"},
|
|
{"00:00:00:00:00:00:00:00", "::"},
|
|
{"0:0:0:0:0:0:0:0", "::"},
|
|
{"0:0:0:0:0:0:0:1", "::1"},
|
|
{"2001:0:0:1:0:0:0:1", "2001:0:0:1::1"},
|
|
{"2001:0db8:0:0:1:0:0:1", "2001:db8::1:0:0:1"},
|
|
{"2001:0db8:85a3:0000:0000:8a2e:0370:7334", "2001:db8:85a3::8a2e:370:7334"},
|
|
{"2001:0db8::0001", "2001:db8::1"},
|
|
{"2001:0db8::0001:0000", "2001:db8::1:0"},
|
|
{"2001:0db8::1:0:0:1", "2001:db8::1:0:0:1"},
|
|
{"2001:db8:0000:0:1::1", "2001:db8::1:0:0:1"},
|
|
{"2001:db8:0000:1:1:1:1:1", "2001:db8:0:1:1:1:1:1"},
|
|
{"2001:db8:0:0:0:0:2:1", "2001:db8::2:1"},
|
|
{"2001:db8:0:0:0::1", "2001:db8::1"},
|
|
{"2001:db8:0:0:1:0:0:1", "2001:db8::1:0:0:1"},
|
|
{"2001:db8:0:0:1::1", "2001:db8::1:0:0:1"},
|
|
{"2001:DB8:0:0:1::1", "2001:db8::1:0:0:1"},
|
|
{"2001:db8:0:0::1", "2001:db8::1"},
|
|
{"2001:db8:0:0:aaaa::1", "2001:db8::aaaa:0:0:1"},
|
|
{"2001:db8:0:1:1:1:1:1", "2001:db8:0:1:1:1:1:1"},
|
|
{"2001:db8:0::1", "2001:db8::1"},
|
|
{"2001:db8:85a3:0:0:8a2e:370:7334", "2001:db8:85a3::8a2e:370:7334"},
|
|
{"2001:db8::0:1", "2001:db8::1"},
|
|
{"2001:db8::0:1:0:0:1", "2001:db8::1:0:0:1"},
|
|
{"2001:DB8::1", "2001:db8::1"},
|
|
{"2001:db8::1", "2001:db8::1"},
|
|
{"2001:db8::1:0:0:1", "2001:db8::1:0:0:1"},
|
|
{"2001:db8::1:1:1:1:1", "2001:db8:0:1:1:1:1:1"},
|
|
{"2001:db8::aaaa:0:0:1", "2001:db8::aaaa:0:0:1"},
|
|
{"2001:db8:aaaa:bbbb:cccc:dddd:0:1", "2001:db8:aaaa:bbbb:cccc:dddd:0:1"},
|
|
{"2001:db8:aaaa:bbbb:cccc:dddd::1", "2001:db8:aaaa:bbbb:cccc:dddd:0:1"},
|
|
{"2001:db8:aaaa:bbbb:cccc:dddd:eeee:0001", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:1"},
|
|
{"2001:db8:aaaa:bbbb:cccc:dddd:eeee:001", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:1"},
|
|
{"2001:db8:aaaa:bbbb:cccc:dddd:eeee:01", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:1"},
|
|
{"2001:db8:aaaa:bbbb:cccc:dddd:eeee:1", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:1"},
|
|
{"2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa"},
|
|
{"2001:db8:aaaa:bbbb:cccc:dddd:eeee:AAAA", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa"},
|
|
{"2001:db8:aaaa:bbbb:cccc:dddd:eeee:AaAa", "2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa"},
|
|
};
|
|
for (const auto& [input_address, expected_canonical_representation_output] : canonical_representations_ipv6) {
|
|
CNetAddr net_addr;
|
|
BOOST_REQUIRE(LookupHost(input_address, net_addr, false));
|
|
BOOST_REQUIRE(net_addr.IsIPv6());
|
|
BOOST_CHECK_EQUAL(net_addr.ToStringAddr(), expected_canonical_representation_output);
|
|
}
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(cnetaddr_serialize_v1)
|
|
{
|
|
CNetAddr addr;
|
|
CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
|
|
|
|
s << addr;
|
|
BOOST_CHECK_EQUAL(HexStr(s), "00000000000000000000000000000000");
|
|
s.clear();
|
|
|
|
BOOST_REQUIRE(LookupHost("1.2.3.4", addr, false));
|
|
s << addr;
|
|
BOOST_CHECK_EQUAL(HexStr(s), "00000000000000000000ffff01020304");
|
|
s.clear();
|
|
|
|
BOOST_REQUIRE(LookupHost("1a1b:2a2b:3a3b:4a4b:5a5b:6a6b:7a7b:8a8b", addr, false));
|
|
s << addr;
|
|
BOOST_CHECK_EQUAL(HexStr(s), "1a1b2a2b3a3b4a4b5a5b6a6b7a7b8a8b");
|
|
s.clear();
|
|
|
|
// TORv2, no longer supported
|
|
BOOST_CHECK(!addr.SetSpecial("6hzph5hv6337r6p2.onion"));
|
|
|
|
BOOST_REQUIRE(addr.SetSpecial("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion"));
|
|
s << addr;
|
|
BOOST_CHECK_EQUAL(HexStr(s), "00000000000000000000000000000000");
|
|
s.clear();
|
|
|
|
addr.SetInternal("a");
|
|
s << addr;
|
|
BOOST_CHECK_EQUAL(HexStr(s), "fd6b88c08724ca978112ca1bbdcafac2");
|
|
s.clear();
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(cnetaddr_serialize_v2)
|
|
{
|
|
CNetAddr addr;
|
|
CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
|
|
// Add ADDRV2_FORMAT to the version so that the CNetAddr
|
|
// serialize method produces an address in v2 format.
|
|
s.SetVersion(s.GetVersion() | ADDRV2_FORMAT);
|
|
|
|
s << addr;
|
|
BOOST_CHECK_EQUAL(HexStr(s), "021000000000000000000000000000000000");
|
|
s.clear();
|
|
|
|
BOOST_REQUIRE(LookupHost("1.2.3.4", addr, false));
|
|
s << addr;
|
|
BOOST_CHECK_EQUAL(HexStr(s), "010401020304");
|
|
s.clear();
|
|
|
|
BOOST_REQUIRE(LookupHost("1a1b:2a2b:3a3b:4a4b:5a5b:6a6b:7a7b:8a8b", addr, false));
|
|
s << addr;
|
|
BOOST_CHECK_EQUAL(HexStr(s), "02101a1b2a2b3a3b4a4b5a5b6a6b7a7b8a8b");
|
|
s.clear();
|
|
|
|
// TORv2, no longer supported
|
|
BOOST_CHECK(!addr.SetSpecial("6hzph5hv6337r6p2.onion"));
|
|
|
|
BOOST_REQUIRE(addr.SetSpecial("kpgvmscirrdqpekbqjsvw5teanhatztpp2gl6eee4zkowvwfxwenqaid.onion"));
|
|
s << addr;
|
|
BOOST_CHECK_EQUAL(HexStr(s), "042053cd5648488c4707914182655b7664034e09e66f7e8cbf1084e654eb56c5bd88");
|
|
s.clear();
|
|
|
|
BOOST_REQUIRE(addr.SetInternal("a"));
|
|
s << addr;
|
|
BOOST_CHECK_EQUAL(HexStr(s), "0210fd6b88c08724ca978112ca1bbdcafac2");
|
|
s.clear();
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(cnetaddr_unserialize_v2)
|
|
{
|
|
CNetAddr addr;
|
|
CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
|
|
// Add ADDRV2_FORMAT to the version so that the CNetAddr
|
|
// unserialize method expects an address in v2 format.
|
|
s.SetVersion(s.GetVersion() | ADDRV2_FORMAT);
|
|
|
|
// Valid IPv4.
|
|
s << Span{ParseHex("01" // network type (IPv4)
|
|
"04" // address length
|
|
"01020304")}; // address
|
|
s >> addr;
|
|
BOOST_CHECK(addr.IsValid());
|
|
BOOST_CHECK(addr.IsIPv4());
|
|
BOOST_CHECK(addr.IsAddrV1Compatible());
|
|
BOOST_CHECK_EQUAL(addr.ToStringAddr(), "1.2.3.4");
|
|
BOOST_REQUIRE(s.empty());
|
|
|
|
// Invalid IPv4, valid length but address itself is shorter.
|
|
s << Span{ParseHex("01" // network type (IPv4)
|
|
"04" // address length
|
|
"0102")}; // address
|
|
BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure, HasReason("end of data"));
|
|
BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
|
|
s.clear();
|
|
|
|
// Invalid IPv4, with bogus length.
|
|
s << Span{ParseHex("01" // network type (IPv4)
|
|
"05" // address length
|
|
"01020304")}; // address
|
|
BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
|
|
HasReason("BIP155 IPv4 address with length 5 (should be 4)"));
|
|
BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
|
|
s.clear();
|
|
|
|
// Invalid IPv4, with extreme length.
|
|
s << Span{ParseHex("01" // network type (IPv4)
|
|
"fd0102" // address length (513 as CompactSize)
|
|
"01020304")}; // address
|
|
BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
|
|
HasReason("Address too long: 513 > 512"));
|
|
BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
|
|
s.clear();
|
|
|
|
// Valid IPv6.
|
|
s << Span{ParseHex("02" // network type (IPv6)
|
|
"10" // address length
|
|
"0102030405060708090a0b0c0d0e0f10")}; // address
|
|
s >> addr;
|
|
BOOST_CHECK(addr.IsValid());
|
|
BOOST_CHECK(addr.IsIPv6());
|
|
BOOST_CHECK(addr.IsAddrV1Compatible());
|
|
BOOST_CHECK_EQUAL(addr.ToStringAddr(), "102:304:506:708:90a:b0c:d0e:f10");
|
|
BOOST_REQUIRE(s.empty());
|
|
|
|
// Valid IPv6, contains embedded "internal".
|
|
s << Span{ParseHex(
|
|
"02" // network type (IPv6)
|
|
"10" // address length
|
|
"fd6b88c08724ca978112ca1bbdcafac2")}; // address: 0xfd + sha256("bitcoin")[0:5] +
|
|
// sha256(name)[0:10]
|
|
s >> addr;
|
|
BOOST_CHECK(addr.IsInternal());
|
|
BOOST_CHECK(addr.IsAddrV1Compatible());
|
|
BOOST_CHECK_EQUAL(addr.ToStringAddr(), "zklycewkdo64v6wc.internal");
|
|
BOOST_REQUIRE(s.empty());
|
|
|
|
// Invalid IPv6, with bogus length.
|
|
s << Span{ParseHex("02" // network type (IPv6)
|
|
"04" // address length
|
|
"00")}; // address
|
|
BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
|
|
HasReason("BIP155 IPv6 address with length 4 (should be 16)"));
|
|
BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
|
|
s.clear();
|
|
|
|
// Invalid IPv6, contains embedded IPv4.
|
|
s << Span{ParseHex("02" // network type (IPv6)
|
|
"10" // address length
|
|
"00000000000000000000ffff01020304")}; // address
|
|
s >> addr;
|
|
BOOST_CHECK(!addr.IsValid());
|
|
BOOST_REQUIRE(s.empty());
|
|
|
|
// Invalid IPv6, contains embedded TORv2.
|
|
s << Span{ParseHex("02" // network type (IPv6)
|
|
"10" // address length
|
|
"fd87d87eeb430102030405060708090a")}; // address
|
|
s >> addr;
|
|
BOOST_CHECK(!addr.IsValid());
|
|
BOOST_REQUIRE(s.empty());
|
|
|
|
// TORv2, no longer supported.
|
|
s << Span{ParseHex("03" // network type (TORv2)
|
|
"0a" // address length
|
|
"f1f2f3f4f5f6f7f8f9fa")}; // address
|
|
s >> addr;
|
|
BOOST_CHECK(!addr.IsValid());
|
|
BOOST_REQUIRE(s.empty());
|
|
|
|
// Valid TORv3.
|
|
s << Span{ParseHex("04" // network type (TORv3)
|
|
"20" // address length
|
|
"79bcc625184b05194975c28b66b66b04" // address
|
|
"69f7f6556fb1ac3189a79b40dda32f1f"
|
|
)};
|
|
s >> addr;
|
|
BOOST_CHECK(addr.IsValid());
|
|
BOOST_CHECK(addr.IsTor());
|
|
BOOST_CHECK(!addr.IsAddrV1Compatible());
|
|
BOOST_CHECK_EQUAL(addr.ToStringAddr(),
|
|
"pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion");
|
|
BOOST_REQUIRE(s.empty());
|
|
|
|
// Invalid TORv3, with bogus length.
|
|
s << Span{ParseHex("04" // network type (TORv3)
|
|
"00" // address length
|
|
"00" // address
|
|
)};
|
|
BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
|
|
HasReason("BIP155 TORv3 address with length 0 (should be 32)"));
|
|
BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
|
|
s.clear();
|
|
|
|
// Valid I2P.
|
|
s << Span{ParseHex("05" // network type (I2P)
|
|
"20" // address length
|
|
"a2894dabaec08c0051a481a6dac88b64" // address
|
|
"f98232ae42d4b6fd2fa81952dfe36a87")};
|
|
s >> addr;
|
|
BOOST_CHECK(addr.IsValid());
|
|
BOOST_CHECK(addr.IsI2P());
|
|
BOOST_CHECK(!addr.IsAddrV1Compatible());
|
|
BOOST_CHECK_EQUAL(addr.ToStringAddr(),
|
|
"ukeu3k5oycgaauneqgtnvselmt4yemvoilkln7jpvamvfx7dnkdq.b32.i2p");
|
|
BOOST_REQUIRE(s.empty());
|
|
|
|
// Invalid I2P, with bogus length.
|
|
s << Span{ParseHex("05" // network type (I2P)
|
|
"03" // address length
|
|
"00" // address
|
|
)};
|
|
BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
|
|
HasReason("BIP155 I2P address with length 3 (should be 32)"));
|
|
BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
|
|
s.clear();
|
|
|
|
// Valid CJDNS.
|
|
s << Span{ParseHex("06" // network type (CJDNS)
|
|
"10" // address length
|
|
"fc000001000200030004000500060007" // address
|
|
)};
|
|
s >> addr;
|
|
BOOST_CHECK(addr.IsValid());
|
|
BOOST_CHECK(addr.IsCJDNS());
|
|
BOOST_CHECK(!addr.IsAddrV1Compatible());
|
|
BOOST_CHECK_EQUAL(addr.ToStringAddr(), "fc00:1:2:3:4:5:6:7");
|
|
BOOST_REQUIRE(s.empty());
|
|
|
|
// Invalid CJDNS, wrong prefix.
|
|
s << Span{ParseHex("06" // network type (CJDNS)
|
|
"10" // address length
|
|
"aa000001000200030004000500060007" // address
|
|
)};
|
|
s >> addr;
|
|
BOOST_CHECK(addr.IsCJDNS());
|
|
BOOST_CHECK(!addr.IsValid());
|
|
BOOST_REQUIRE(s.empty());
|
|
|
|
// Invalid CJDNS, with bogus length.
|
|
s << Span{ParseHex("06" // network type (CJDNS)
|
|
"01" // address length
|
|
"00" // address
|
|
)};
|
|
BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
|
|
HasReason("BIP155 CJDNS address with length 1 (should be 16)"));
|
|
BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
|
|
s.clear();
|
|
|
|
// Unknown, with extreme length.
|
|
s << Span{ParseHex("aa" // network type (unknown)
|
|
"fe00000002" // address length (CompactSize's MAX_SIZE)
|
|
"01020304050607" // address
|
|
)};
|
|
BOOST_CHECK_EXCEPTION(s >> addr, std::ios_base::failure,
|
|
HasReason("Address too long: 33554432 > 512"));
|
|
BOOST_REQUIRE(!s.empty()); // The stream is not consumed on invalid input.
|
|
s.clear();
|
|
|
|
// Unknown, with reasonable length.
|
|
s << Span{ParseHex("aa" // network type (unknown)
|
|
"04" // address length
|
|
"01020304" // address
|
|
)};
|
|
s >> addr;
|
|
BOOST_CHECK(!addr.IsValid());
|
|
BOOST_REQUIRE(s.empty());
|
|
|
|
// Unknown, with zero length.
|
|
s << Span{ParseHex("aa" // network type (unknown)
|
|
"00" // address length
|
|
"" // address
|
|
)};
|
|
s >> addr;
|
|
BOOST_CHECK(!addr.IsValid());
|
|
BOOST_REQUIRE(s.empty());
|
|
}
|
|
|
|
// prior to PR #14728, this test triggers an undefined behavior
|
|
BOOST_AUTO_TEST_CASE(ipv4_peer_with_ipv6_addrMe_test)
|
|
{
|
|
// set up local addresses; all that's necessary to reproduce the bug is
|
|
// that a normal IPv4 address is among the entries, but if this address is
|
|
// !IsRoutable the undefined behavior is easier to trigger deterministically
|
|
in_addr raw_addr;
|
|
raw_addr.s_addr = htonl(0x7f000001);
|
|
const CNetAddr mapLocalHost_entry = CNetAddr(raw_addr);
|
|
{
|
|
LOCK(g_maplocalhost_mutex);
|
|
LocalServiceInfo lsi;
|
|
lsi.nScore = 23;
|
|
lsi.nPort = 42;
|
|
mapLocalHost[mapLocalHost_entry] = lsi;
|
|
}
|
|
|
|
// create a peer with an IPv4 address
|
|
in_addr ipv4AddrPeer;
|
|
ipv4AddrPeer.s_addr = 0xa0b0c001;
|
|
CAddress addr = CAddress(CService(ipv4AddrPeer, 7777), NODE_NETWORK);
|
|
std::unique_ptr<CNode> pnode = std::make_unique<CNode>(/*id=*/0,
|
|
/*sock=*/nullptr,
|
|
addr,
|
|
/*nKeyedNetGroupIn=*/0,
|
|
/*nLocalHostNonceIn=*/0,
|
|
CAddress{},
|
|
/*pszDest=*/std::string{},
|
|
ConnectionType::OUTBOUND_FULL_RELAY,
|
|
/*inbound_onion=*/false);
|
|
pnode->fSuccessfullyConnected.store(true);
|
|
|
|
// the peer claims to be reaching us via IPv6
|
|
in6_addr ipv6AddrLocal;
|
|
memset(ipv6AddrLocal.s6_addr, 0, 16);
|
|
ipv6AddrLocal.s6_addr[0] = 0xcc;
|
|
CAddress addrLocal = CAddress(CService(ipv6AddrLocal, 7777), NODE_NETWORK);
|
|
pnode->SetAddrLocal(addrLocal);
|
|
|
|
// before patch, this causes undefined behavior detectable with clang's -fsanitize=memory
|
|
GetLocalAddrForPeer(*pnode);
|
|
|
|
// suppress no-checks-run warning; if this test fails, it's by triggering a sanitizer
|
|
BOOST_CHECK(1);
|
|
|
|
// Cleanup, so that we don't confuse other tests.
|
|
{
|
|
LOCK(g_maplocalhost_mutex);
|
|
mapLocalHost.erase(mapLocalHost_entry);
|
|
}
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(get_local_addr_for_peer_port)
|
|
{
|
|
// Test that GetLocalAddrForPeer() properly selects the address to self-advertise:
|
|
//
|
|
// 1. GetLocalAddrForPeer() calls GetLocalAddress() which returns an address that is
|
|
// not routable.
|
|
// 2. GetLocalAddrForPeer() overrides the address with whatever the peer has told us
|
|
// he sees us as.
|
|
// 2.1. For inbound connections we must override both the address and the port.
|
|
// 2.2. For outbound connections we must override only the address.
|
|
|
|
// Pretend that we bound to this port.
|
|
const uint16_t bind_port = 20001;
|
|
m_node.args->ForceSetArg("-bind", strprintf("3.4.5.6:%u", bind_port));
|
|
|
|
// Our address:port as seen from the peer, completely different from the above.
|
|
in_addr peer_us_addr;
|
|
peer_us_addr.s_addr = htonl(0x02030405);
|
|
const CService peer_us{peer_us_addr, 20002};
|
|
|
|
// Create a peer with a routable IPv4 address (outbound).
|
|
in_addr peer_out_in_addr;
|
|
peer_out_in_addr.s_addr = htonl(0x01020304);
|
|
CNode peer_out{/*id=*/0,
|
|
/*sock=*/nullptr,
|
|
/*addrIn=*/CAddress{CService{peer_out_in_addr, 8333}, NODE_NETWORK},
|
|
/*nKeyedNetGroupIn=*/0,
|
|
/*nLocalHostNonceIn=*/0,
|
|
/*addrBindIn=*/CAddress{},
|
|
/*addrNameIn=*/std::string{},
|
|
/*conn_type_in=*/ConnectionType::OUTBOUND_FULL_RELAY,
|
|
/*inbound_onion=*/false};
|
|
peer_out.fSuccessfullyConnected = true;
|
|
peer_out.SetAddrLocal(peer_us);
|
|
|
|
// Without the fix peer_us:8333 is chosen instead of the proper peer_us:bind_port.
|
|
auto chosen_local_addr = GetLocalAddrForPeer(peer_out);
|
|
BOOST_REQUIRE(chosen_local_addr);
|
|
const CService expected{peer_us_addr, bind_port};
|
|
BOOST_CHECK(*chosen_local_addr == expected);
|
|
|
|
// Create a peer with a routable IPv4 address (inbound).
|
|
in_addr peer_in_in_addr;
|
|
peer_in_in_addr.s_addr = htonl(0x05060708);
|
|
CNode peer_in{/*id=*/0,
|
|
/*sock=*/nullptr,
|
|
/*addrIn=*/CAddress{CService{peer_in_in_addr, 8333}, NODE_NETWORK},
|
|
/*nKeyedNetGroupIn=*/0,
|
|
/*nLocalHostNonceIn=*/0,
|
|
/*addrBindIn=*/CAddress{},
|
|
/*addrNameIn=*/std::string{},
|
|
/*conn_type_in=*/ConnectionType::INBOUND,
|
|
/*inbound_onion=*/false};
|
|
peer_in.fSuccessfullyConnected = true;
|
|
peer_in.SetAddrLocal(peer_us);
|
|
|
|
// Without the fix peer_us:8333 is chosen instead of the proper peer_us:peer_us.GetPort().
|
|
chosen_local_addr = GetLocalAddrForPeer(peer_in);
|
|
BOOST_REQUIRE(chosen_local_addr);
|
|
BOOST_CHECK(*chosen_local_addr == peer_us);
|
|
|
|
m_node.args->ForceSetArg("-bind", "");
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(LimitedAndReachable_Network)
|
|
{
|
|
BOOST_CHECK(IsReachable(NET_IPV4));
|
|
BOOST_CHECK(IsReachable(NET_IPV6));
|
|
BOOST_CHECK(IsReachable(NET_ONION));
|
|
BOOST_CHECK(IsReachable(NET_I2P));
|
|
BOOST_CHECK(IsReachable(NET_CJDNS));
|
|
|
|
SetReachable(NET_IPV4, false);
|
|
SetReachable(NET_IPV6, false);
|
|
SetReachable(NET_ONION, false);
|
|
SetReachable(NET_I2P, false);
|
|
SetReachable(NET_CJDNS, false);
|
|
|
|
BOOST_CHECK(!IsReachable(NET_IPV4));
|
|
BOOST_CHECK(!IsReachable(NET_IPV6));
|
|
BOOST_CHECK(!IsReachable(NET_ONION));
|
|
BOOST_CHECK(!IsReachable(NET_I2P));
|
|
BOOST_CHECK(!IsReachable(NET_CJDNS));
|
|
|
|
SetReachable(NET_IPV4, true);
|
|
SetReachable(NET_IPV6, true);
|
|
SetReachable(NET_ONION, true);
|
|
SetReachable(NET_I2P, true);
|
|
SetReachable(NET_CJDNS, true);
|
|
|
|
BOOST_CHECK(IsReachable(NET_IPV4));
|
|
BOOST_CHECK(IsReachable(NET_IPV6));
|
|
BOOST_CHECK(IsReachable(NET_ONION));
|
|
BOOST_CHECK(IsReachable(NET_I2P));
|
|
BOOST_CHECK(IsReachable(NET_CJDNS));
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(LimitedAndReachable_NetworkCaseUnroutableAndInternal)
|
|
{
|
|
BOOST_CHECK(IsReachable(NET_UNROUTABLE));
|
|
BOOST_CHECK(IsReachable(NET_INTERNAL));
|
|
|
|
SetReachable(NET_UNROUTABLE, false);
|
|
SetReachable(NET_INTERNAL, false);
|
|
|
|
BOOST_CHECK(IsReachable(NET_UNROUTABLE)); // Ignored for both networks
|
|
BOOST_CHECK(IsReachable(NET_INTERNAL));
|
|
}
|
|
|
|
CNetAddr UtilBuildAddress(unsigned char p1, unsigned char p2, unsigned char p3, unsigned char p4)
|
|
{
|
|
unsigned char ip[] = {p1, p2, p3, p4};
|
|
|
|
struct sockaddr_in sa;
|
|
memset(&sa, 0, sizeof(sockaddr_in)); // initialize the memory block
|
|
memcpy(&(sa.sin_addr), &ip, sizeof(ip));
|
|
return CNetAddr(sa.sin_addr);
|
|
}
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(LimitedAndReachable_CNetAddr)
|
|
{
|
|
CNetAddr addr = UtilBuildAddress(0x001, 0x001, 0x001, 0x001); // 1.1.1.1
|
|
|
|
SetReachable(NET_IPV4, true);
|
|
BOOST_CHECK(IsReachable(addr));
|
|
|
|
SetReachable(NET_IPV4, false);
|
|
BOOST_CHECK(!IsReachable(addr));
|
|
|
|
SetReachable(NET_IPV4, true); // have to reset this, because this is stateful.
|
|
}
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(LocalAddress_BasicLifecycle)
|
|
{
|
|
CService addr = CService(UtilBuildAddress(0x002, 0x001, 0x001, 0x001), 1000); // 2.1.1.1:1000
|
|
|
|
SetReachable(NET_IPV4, true);
|
|
|
|
BOOST_CHECK(!IsLocal(addr));
|
|
BOOST_CHECK(AddLocal(addr, 1000));
|
|
BOOST_CHECK(IsLocal(addr));
|
|
|
|
RemoveLocal(addr);
|
|
BOOST_CHECK(!IsLocal(addr));
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(initial_advertise_from_version_message)
|
|
{
|
|
LOCK(NetEventsInterface::g_msgproc_mutex);
|
|
|
|
// Tests the following scenario:
|
|
// * -bind=3.4.5.6:20001 is specified
|
|
// * we make an outbound connection to a peer
|
|
// * the peer reports he sees us as 2.3.4.5:20002 in the version message
|
|
// (20002 is a random port assigned by our OS for the outgoing TCP connection,
|
|
// we cannot accept connections to it)
|
|
// * we should self-advertise to that peer as 2.3.4.5:20001
|
|
|
|
// Pretend that we bound to this port.
|
|
const uint16_t bind_port = 20001;
|
|
m_node.args->ForceSetArg("-bind", strprintf("3.4.5.6:%u", bind_port));
|
|
m_node.args->ForceSetArg("-capturemessages", "1");
|
|
|
|
// Our address:port as seen from the peer - 2.3.4.5:20002 (different from the above).
|
|
in_addr peer_us_addr;
|
|
peer_us_addr.s_addr = htonl(0x02030405);
|
|
const CService peer_us{peer_us_addr, 20002};
|
|
|
|
// Create a peer with a routable IPv4 address.
|
|
in_addr peer_in_addr;
|
|
peer_in_addr.s_addr = htonl(0x01020304);
|
|
CNode peer{/*id=*/0,
|
|
/*sock=*/nullptr,
|
|
/*addrIn=*/CAddress{CService{peer_in_addr, 8333}, NODE_NETWORK},
|
|
/*nKeyedNetGroupIn=*/0,
|
|
/*nLocalHostNonceIn=*/0,
|
|
/*addrBindIn=*/CAddress{},
|
|
/*addrNameIn=*/std::string{},
|
|
/*conn_type_in=*/ConnectionType::OUTBOUND_FULL_RELAY,
|
|
/*inbound_onion=*/false};
|
|
|
|
const uint64_t services{NODE_NETWORK | NODE_WITNESS};
|
|
const int64_t time{0};
|
|
const CNetMsgMaker msg_maker{PROTOCOL_VERSION};
|
|
|
|
// Force Chainstate::IsInitialBlockDownload() to return false.
|
|
// Otherwise PushAddress() isn't called by PeerManager::ProcessMessage().
|
|
TestChainState& chainstate =
|
|
*static_cast<TestChainState*>(&m_node.chainman->ActiveChainstate());
|
|
chainstate.JumpOutOfIbd();
|
|
|
|
m_node.peerman->InitializeNode(peer, NODE_NETWORK);
|
|
|
|
std::atomic<bool> interrupt_dummy{false};
|
|
std::chrono::microseconds time_received_dummy{0};
|
|
|
|
const auto msg_version =
|
|
msg_maker.Make(NetMsgType::VERSION, PROTOCOL_VERSION, services, time, services, peer_us);
|
|
CDataStream msg_version_stream{msg_version.data, SER_NETWORK, PROTOCOL_VERSION};
|
|
|
|
m_node.peerman->ProcessMessage(
|
|
peer, NetMsgType::VERSION, msg_version_stream, time_received_dummy, interrupt_dummy);
|
|
|
|
const auto msg_verack = msg_maker.Make(NetMsgType::VERACK);
|
|
CDataStream msg_verack_stream{msg_verack.data, SER_NETWORK, PROTOCOL_VERSION};
|
|
|
|
// Will set peer.fSuccessfullyConnected to true (necessary in SendMessages()).
|
|
m_node.peerman->ProcessMessage(
|
|
peer, NetMsgType::VERACK, msg_verack_stream, time_received_dummy, interrupt_dummy);
|
|
|
|
// Ensure that peer_us_addr:bind_port is sent to the peer.
|
|
const CService expected{peer_us_addr, bind_port};
|
|
bool sent{false};
|
|
|
|
const auto CaptureMessageOrig = CaptureMessage;
|
|
CaptureMessage = [&sent, &expected](const CAddress& addr,
|
|
const std::string& msg_type,
|
|
Span<const unsigned char> data,
|
|
bool is_incoming) -> void {
|
|
if (!is_incoming && msg_type == "addr") {
|
|
CDataStream s(data, SER_NETWORK, PROTOCOL_VERSION);
|
|
std::vector<CAddress> addresses;
|
|
|
|
s >> addresses;
|
|
|
|
for (const auto& addr : addresses) {
|
|
if (addr == expected) {
|
|
sent = true;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
m_node.peerman->SendMessages(&peer);
|
|
|
|
BOOST_CHECK(sent);
|
|
|
|
CaptureMessage = CaptureMessageOrig;
|
|
chainstate.ResetIbd();
|
|
m_node.args->ForceSetArg("-capturemessages", "0");
|
|
m_node.args->ForceSetArg("-bind", "");
|
|
// PeerManager::ProcessMessage() calls AddTimeData() which changes the internal state
|
|
// in timedata.cpp and later confuses the test "timedata_tests/addtimedata". Thus reset
|
|
// that state as it was before our test was run.
|
|
TestOnlyResetTimeData();
|
|
}
|
|
|
|
BOOST_AUTO_TEST_SUITE_END()
|