18#include <boost/test/unit_test.hpp>
23using namespace std::literals;
31 :
AddrMan( std::vector<bool>(), true, 100)
50 unsigned char nVersion = 1;
52 s << ((
unsigned char)32);
74 ssPeersIn << _addrman;
75 std::string str = ssPeersIn.
str();
76 std::vector<unsigned char> vchData(str.begin(), str.end());
86 std::vector<bool> asmap = std::vector<bool>())
87 :
AddrMan(asmap, makeDeterministic, 100)
95 return m_impl->Find(addr, pnId);
101 return m_impl->Create(addr, addrSource, pnId);
114 int nId =
m_impl->mapAddr[addr];
117 if (nId ==
m_impl->vvNew[bucket][entry]) {
118 return std::pair<int, int>(bucket, entry);
122 return std::pair<int, int>(-1, -1);
128 int64_t nLastSuccess = 1;
130 Good(addr, nLastSuccess);
132 bool count_failure =
false;
134 Attempt(addr, count_failure, nLastTry);
148 BOOST_CHECK_MESSAGE(
Lookup(
ip, serv, port,
false),
strprintf(
"failed to resolve: %s:%i",
ip, port));
154 std::vector<bool> result(vector_size);
155 for (
int byte_i = 0; byte_i < vector_size / 8; ++byte_i) {
156 unsigned char cur_byte =
source[byte_i];
157 for (
int bit_i = 0; bit_i < 8; ++bit_i) {
158 result[byte_i * 8 + bit_i] = (cur_byte >> bit_i) & 1;
169 auto addrman = std::make_unique<AddrManTest>();
175 auto addr_null = addrman->Select().first;
182 auto addr_ret1 = addrman->Select().first;
203 addrman = std::make_unique<AddrManTest>();
204 std::vector<CAddress> vAddr;
227 auto addr_ret2 = addrman.
Select().first;
228 BOOST_CHECK(addr_ret2.ToString() ==
"250.1.1.1:8333" || addr_ret2.ToString() ==
"250.1.1.1:8334");
235 auto addr_ret3 = addrman.
Select(newOnly).first;
252 auto addr_ret1 = addrman.
Select(newOnly).first;
258 auto addr_ret2 = addrman.
Select(newOnly).first;
261 auto addr_ret3 = addrman.
Select().first;
292 std::set<uint16_t> ports;
293 for (
int i = 0; i < 20; ++i) {
294 ports.insert(addrman.
Select().first.GetPort());
305 uint32_t num_addrs{0};
309 while (num_addrs < 22) {
319 uint32_t collisions{1};
334 uint32_t num_addrs{0};
338 while (num_addrs < 64) {
349 uint32_t collisions{1};
377 BOOST_REQUIRE(info1);
382 BOOST_REQUIRE(info2);
387 BOOST_REQUIRE(info3);
438 std::vector<CAddress> vAddr1 = addrman.
GetAddr( 0, 0, std::nullopt);
469 for (
unsigned int i = 1; i < (8 * 256); i++) {
470 int octet1 = i % 256;
471 int octet2 = i >> 8 % 256;
481 std::vector<CAddress> vAddr = addrman.
GetAddr( 2500, 23, std::nullopt);
483 size_t percent23 = (addrman.
size() * 23) / 100;
506 std::vector<bool> asmap;
521 std::set<int> buckets;
522 for (
int i = 0; i < 255; i++) {
527 buckets.insert(bucket);
534 for (
int j = 0; j < 255; j++) {
539 buckets.insert(bucket);
560 std::vector<bool> asmap;
575 std::set<int> buckets;
576 for (
int i = 0; i < 255; i++) {
581 buckets.insert(bucket);
588 for (
int j = 0; j < 4 * 255; j++) {
594 buckets.insert(bucket);
601 for (
int p = 0; p < 255; p++) {
606 buckets.insert(bucket);
654 std::set<int> buckets;
655 for (
int j = 0; j < 255; j++) {
660 buckets.insert(bucket);
667 for (
int j = 0; j < 255; j++) {
672 buckets.insert(bucket);
708 std::set<int> buckets;
709 for (
int i = 0; i < 255; i++) {
714 buckets.insert(bucket);
721 for (
int j = 0; j < 4 * 255; j++) {
727 buckets.insert(bucket);
734 for (
int p = 0; p < 255; p++) {
739 buckets.insert(bucket);
746 for (
int p = 0; p < 255; p++) {
751 buckets.insert(bucket);
763 auto addrman_asmap1 = std::make_unique<AddrManTest>(
true, asmap1);
764 auto addrman_asmap1_dup = std::make_unique<AddrManTest>(
true, asmap1);
765 auto addrman_noasmap = std::make_unique<AddrManTest>();
772 addrman_asmap1->Add({addr}, default_source);
774 stream << *addrman_asmap1;
776 stream >> *addrman_asmap1_dup;
778 std::pair<int, int> bucketAndEntry_asmap1 = addrman_asmap1->GetBucketAndEntry(addr);
779 std::pair<int, int> bucketAndEntry_asmap1_dup = addrman_asmap1_dup->GetBucketAndEntry(addr);
781 BOOST_CHECK(bucketAndEntry_asmap1_dup.second != -1);
783 BOOST_CHECK(bucketAndEntry_asmap1.first == bucketAndEntry_asmap1_dup.first);
784 BOOST_CHECK(bucketAndEntry_asmap1.second == bucketAndEntry_asmap1_dup.second);
787 stream << *addrman_asmap1;
788 stream >> *addrman_noasmap;
789 std::pair<int, int> bucketAndEntry_noasmap = addrman_noasmap->GetBucketAndEntry(addr);
791 BOOST_CHECK(bucketAndEntry_asmap1.first != bucketAndEntry_noasmap.first);
792 BOOST_CHECK(bucketAndEntry_asmap1.second != bucketAndEntry_noasmap.second);
795 addrman_asmap1 = std::make_unique<AddrManTest>(
true, asmap1);
796 addrman_noasmap = std::make_unique<AddrManTest>();
797 addrman_noasmap->Add({addr}, default_source);
798 stream << *addrman_noasmap;
799 stream >> *addrman_asmap1;
800 std::pair<int, int> bucketAndEntry_asmap1_deser = addrman_asmap1->GetBucketAndEntry(addr);
801 BOOST_CHECK(bucketAndEntry_asmap1_deser.second != -1);
802 BOOST_CHECK(bucketAndEntry_asmap1_deser.first != bucketAndEntry_noasmap.first);
803 BOOST_CHECK(bucketAndEntry_asmap1_deser.first == bucketAndEntry_asmap1_dup.first);
804 BOOST_CHECK(bucketAndEntry_asmap1_deser.second == bucketAndEntry_asmap1_dup.second);
807 addrman_asmap1 = std::make_unique<AddrManTest>(
true, asmap1);
808 addrman_noasmap = std::make_unique<AddrManTest>();
811 addrman_noasmap->Add({addr,
addr2}, default_source);
812 std::pair<int, int> bucketAndEntry_noasmap_addr1 = addrman_noasmap->GetBucketAndEntry(
addr1);
813 std::pair<int, int> bucketAndEntry_noasmap_addr2 = addrman_noasmap->GetBucketAndEntry(
addr2);
814 BOOST_CHECK(bucketAndEntry_noasmap_addr1.first != bucketAndEntry_noasmap_addr2.first);
815 BOOST_CHECK(bucketAndEntry_noasmap_addr1.second != bucketAndEntry_noasmap_addr2.second);
816 stream << *addrman_noasmap;
817 stream >> *addrman_asmap1;
818 std::pair<int, int> bucketAndEntry_asmap1_deser_addr1 = addrman_asmap1->GetBucketAndEntry(
addr1);
819 std::pair<int, int> bucketAndEntry_asmap1_deser_addr2 = addrman_asmap1->GetBucketAndEntry(
addr2);
820 BOOST_CHECK(bucketAndEntry_asmap1_deser_addr1.first == bucketAndEntry_asmap1_deser_addr2.first);
821 BOOST_CHECK(bucketAndEntry_asmap1_deser_addr1.second != bucketAndEntry_asmap1_deser_addr2.second);
828 auto addrman = std::make_unique<AddrManTest>();
836 addrman->Add({new1, tried1, new2, tried2},
CNetAddr{});
837 addrman->Good(tried1);
838 addrman->Good(tried2);
839 BOOST_REQUIRE_EQUAL(addrman->size(), 4);
843 const std::string str{stream.
str()};
846 const char new2_raw[]{6, 6, 6, 6};
847 const uint8_t new2_raw_replacement[]{0, 0, 0, 0};
848 pos = str.find(new2_raw, 0,
sizeof(new2_raw));
849 BOOST_REQUIRE(pos != std::string::npos);
850 BOOST_REQUIRE(pos +
sizeof(new2_raw_replacement) <= stream.
size());
851 memcpy(stream.
data() + pos, new2_raw_replacement,
sizeof(new2_raw_replacement));
853 const char tried2_raw[]{8, 8, 8, 8};
854 const uint8_t tried2_raw_replacement[]{255, 255, 255, 255};
855 pos = str.find(tried2_raw, 0,
sizeof(tried2_raw));
856 BOOST_REQUIRE(pos != std::string::npos);
857 BOOST_REQUIRE(pos +
sizeof(tried2_raw_replacement) <= stream.
size());
858 memcpy(stream.
data() + pos, tried2_raw_replacement,
sizeof(tried2_raw_replacement));
860 addrman = std::make_unique<AddrManTest>();
876 for (
unsigned int i = 1; i < 23; i++) {
887 for (
unsigned int i = 1; i < 23; i++) {
903 for (
unsigned int i = 1; i < 36; i++) {
916 addrman.
Good(addr36);
926 for (
unsigned int i = 37; i < 59; i++) {
938 addrman.
Good(addr59);
945 addrman.
Good(addr36);
964 for (
unsigned int i = 1; i < 36; i++) {
999 addrman.
Good(addr19);
1027 bool exceptionThrown =
false;
1028 AddrMan addrman1( std::vector<bool>(),
false, 100);
1032 unsigned char pchMsgTmp[4];
1033 ssPeers1 >> pchMsgTmp;
1034 ssPeers1 >> addrman1;
1035 }
catch (
const std::exception&) {
1036 exceptionThrown =
true;
1045 AddrMan addrman2( std::vector<bool>(),
false, 100);
1058 bool exceptionThrown =
false;
1059 AddrMan addrman1( std::vector<bool>(),
false, 100);
1062 unsigned char pchMsgTmp[4];
1063 ssPeers1 >> pchMsgTmp;
1064 ssPeers1 >> addrman1;
1065 }
catch (
const std::exception&) {
1066 exceptionThrown =
true;
1075 AddrMan addrman2( std::vector<bool>(),
false, 100);
void ReadFromStream(AddrMan &addr, CDataStream &ssPeers)
Only used by tests.
static constexpr int ADDRMAN_BUCKET_SIZE
static constexpr int ADDRMAN_NEW_BUCKET_COUNT
static std::vector< bool > FromBytes(const unsigned char *source, int vector_size)
static CService ResolveService(const std::string &ip, uint16_t port=0)
static CDataStream AddrmanToStream(const AddrManSerializationMock &_addrman)
BOOST_AUTO_TEST_CASE(addrman_simple)
static CNetAddr ResolveIP(const std::string &ip)
static unsigned const char asmap_raw[]
const CChainParams & Params()
Return the currently selected parameters.
Extended statistics about a CAddress.
int GetTriedBucket(const uint256 &nKey, const std::vector< bool > &asmap) const
Calculate in which "tried" bucket this entry belongs.
int GetNewBucket(const uint256 &nKey, const CNetAddr &src, const std::vector< bool > &asmap) const
Calculate in which "new" bucket this entry belongs, given a certain source.
void Serialize(CDataStream &s) const override
Stochastic address manager.
std::pair< CAddress, int64_t > SelectTriedCollision()
Randomly select an address in the tried table that another address is attempting to evict.
const std::unique_ptr< AddrManImpl > m_impl
std::vector< CAddress > GetAddr(size_t max_addresses, size_t max_pct, std::optional< Network > network) const
Return all or many randomly selected addresses, optionally by network.
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, int64_t nTimePenalty=0)
Attempt to add one or more addresses to addrman's new table.
void Good(const CService &addr, int64_t nTime=GetAdjustedTime())
Mark an entry as accessible, possibly moving it from "new" to "tried".
void ResolveCollisions()
See if any to-be-evicted tried table entries have been tested and if so resolve the collisions.
void Attempt(const CService &addr, bool fCountFailure, int64_t nTime=GetAdjustedTime())
Mark an entry as connection attempted to.
void Serialize(Stream &s_) const
size_t size() const
Return the number of (unique) addresses in all tables.
std::pair< CAddress, int64_t > Select(bool newOnly=false) const
Choose an address to connect to.
virtual void Serialize(CDataStream &s) const =0
AddrManSerializationMock()
AddrManTest(bool makeDeterministic=true, std::vector< bool > asmap=std::vector< bool >())
std::pair< int, int > GetBucketAndEntry(const CAddress &addr)
void SimConnFail(const CService &addr)
AddrInfo * Find(const CService &addr, int *pnId=nullptr)
AddrInfo * Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId=nullptr)
void Serialize(CDataStream &s) const override
A CService with information about it as peer.
uint32_t nTime
Always included in serialization.
const CMessageHeader::MessageStartChars & MessageStart() const
Double ended buffer combining vector and stream-like interfaces.
A writer stream (for serialization) that computes a 256-bit hash.
A combination of a network address (CNetAddr) and a (TCP) port.
std::string ToString() const
std::vector< unsigned char > GetKey() const
static const int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
BOOST_AUTO_TEST_SUITE_END()
static CService ip(uint32_t i)
static const std::string addr1
static const std::string addr2
bool Lookup(const std::string &name, std::vector< CService > &vAddr, uint16_t portDefault, bool fAllowLookup, unsigned int nMaxSolutions, DNSLookupFn dns_lookup_function)
Resolve a service string to its corresponding service.
bool LookupHost(const std::string &name, std::vector< CNetAddr > &vIP, unsigned int nMaxSolutions, bool fAllowLookup, DNSLookupFn dns_lookup_function)
Resolve a host string to its corresponding network addresses.
#define BOOST_CHECK_THROW(stmt, excMatch)
#define BOOST_FIXTURE_TEST_SUITE(a, b)
#define BOOST_CHECK_EQUAL(v1, v2)
#define BOOST_CHECK(expr)
std::string ToString(const T &t)
Locale-independent version of std::to_string.
int64_t GetAdjustedTime()
static const int PROTOCOL_VERSION
network protocol versioning