LCOV - code coverage report
Current view: top level - src - addrman_impl.h (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 11 11 100.0 %
Date: 2022-04-21 14:51:19 Functions: 10 11 90.9 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 0 0 -

           Branch data     Line data    Source code
#       1                 :            : // Copyright (c) 2021 The Bitcoin Core 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                 :            : #ifndef BITCOIN_ADDRMAN_IMPL_H
#       6                 :            : #define BITCOIN_ADDRMAN_IMPL_H
#       7                 :            : 
#       8                 :            : #include <logging.h>
#       9                 :            : #include <logging/timer.h>
#      10                 :            : #include <netaddress.h>
#      11                 :            : #include <protocol.h>
#      12                 :            : #include <serialize.h>
#      13                 :            : #include <sync.h>
#      14                 :            : #include <uint256.h>
#      15                 :            : 
#      16                 :            : #include <cstdint>
#      17                 :            : #include <optional>
#      18                 :            : #include <set>
#      19                 :            : #include <unordered_map>
#      20                 :            : #include <unordered_set>
#      21                 :            : #include <utility>
#      22                 :            : #include <vector>
#      23                 :            : 
#      24                 :            : /** Total number of buckets for tried addresses */
#      25                 :            : static constexpr int32_t ADDRMAN_TRIED_BUCKET_COUNT_LOG2{8};
#      26                 :            : static constexpr int ADDRMAN_TRIED_BUCKET_COUNT{1 << ADDRMAN_TRIED_BUCKET_COUNT_LOG2};
#      27                 :            : /** Total number of buckets for new addresses */
#      28                 :            : static constexpr int32_t ADDRMAN_NEW_BUCKET_COUNT_LOG2{10};
#      29                 :            : static constexpr int ADDRMAN_NEW_BUCKET_COUNT{1 << ADDRMAN_NEW_BUCKET_COUNT_LOG2};
#      30                 :            : /** Maximum allowed number of entries in buckets for new and tried addresses */
#      31                 :            : static constexpr int32_t ADDRMAN_BUCKET_SIZE_LOG2{6};
#      32                 :            : static constexpr int ADDRMAN_BUCKET_SIZE{1 << ADDRMAN_BUCKET_SIZE_LOG2};
#      33                 :            : 
#      34                 :            : /**
#      35                 :            :  * Extended statistics about a CAddress
#      36                 :            :  */
#      37                 :            : class AddrInfo : public CAddress
#      38                 :            : {
#      39                 :            : public:
#      40                 :            :     //! last try whatsoever by us (memory only)
#      41                 :            :     int64_t nLastTry{0};
#      42                 :            : 
#      43                 :            :     //! last counted attempt (memory only)
#      44                 :            :     int64_t nLastCountAttempt{0};
#      45                 :            : 
#      46                 :            :     //! where knowledge about this address first came from
#      47                 :            :     CNetAddr source;
#      48                 :            : 
#      49                 :            :     //! last successful connection by us
#      50                 :            :     int64_t nLastSuccess{0};
#      51                 :            : 
#      52                 :            :     //! connection attempts since last successful attempt
#      53                 :            :     int nAttempts{0};
#      54                 :            : 
#      55                 :            :     //! reference count in new sets (memory only)
#      56                 :            :     int nRefCount{0};
#      57                 :            : 
#      58                 :            :     //! in tried set? (memory only)
#      59                 :            :     bool fInTried{false};
#      60                 :            : 
#      61                 :            :     //! position in vRandom
#      62                 :            :     mutable int nRandomPos{-1};
#      63                 :            : 
#      64                 :            :     SERIALIZE_METHODS(AddrInfo, obj)
#      65                 :      48971 :     {
#      66                 :      48971 :         READWRITEAS(CAddress, obj);
#      67                 :      48971 :         READWRITE(obj.source, obj.nLastSuccess, obj.nAttempts);
#      68                 :      48971 :     }
#      69                 :            : 
#      70                 :            :     AddrInfo(const CAddress &addrIn, const CNetAddr &addrSource) : CAddress(addrIn), source(addrSource)
#      71                 :      35243 :     {
#      72                 :      35243 :     }
#      73                 :            : 
#      74                 :            :     AddrInfo() : CAddress(), source()
#      75                 :      29195 :     {
#      76                 :      29195 :     }
#      77                 :            : 
#      78                 :            :     //! Calculate in which "tried" bucket this entry belongs
#      79                 :            :     int GetTriedBucket(const uint256 &nKey, const std::vector<bool> &asmap) const;
#      80                 :            : 
#      81                 :            :     //! Calculate in which "new" bucket this entry belongs, given a certain source
#      82                 :            :     int GetNewBucket(const uint256 &nKey, const CNetAddr& src, const std::vector<bool> &asmap) const;
#      83                 :            : 
#      84                 :            :     //! Calculate in which "new" bucket this entry belongs, using its default source
#      85                 :            :     int GetNewBucket(const uint256 &nKey, const std::vector<bool> &asmap) const
#      86                 :       7492 :     {
#      87                 :       7492 :         return GetNewBucket(nKey, source, asmap);
#      88                 :       7492 :     }
#      89                 :            : 
#      90                 :            :     //! Calculate in which position of a bucket to store this entry.
#      91                 :            :     int GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) const;
#      92                 :            : 
#      93                 :            :     //! Determine whether the statistics about this entry are bad enough so that it can just be deleted
#      94                 :            :     bool IsTerrible(int64_t nNow = GetAdjustedTime()) const;
#      95                 :            : 
#      96                 :            :     //! Calculate the relative chance this entry should be given when selecting nodes to connect to
#      97                 :            :     double GetChance(int64_t nNow = GetAdjustedTime()) const;
#      98                 :            : };
#      99                 :            : 
#     100                 :            : class AddrManImpl
#     101                 :            : {
#     102                 :            : public:
#     103                 :            :     AddrManImpl(std::vector<bool>&& asmap, bool deterministic, int32_t consistency_check_ratio);
#     104                 :            : 
#     105                 :            :     ~AddrManImpl();
#     106                 :            : 
#     107                 :            :     template <typename Stream>
#     108                 :            :     void Serialize(Stream& s_) const EXCLUSIVE_LOCKS_REQUIRED(!cs);
#     109                 :            : 
#     110                 :            :     template <typename Stream>
#     111                 :            :     void Unserialize(Stream& s_) EXCLUSIVE_LOCKS_REQUIRED(!cs);
#     112                 :            : 
#     113                 :            :     size_t size() const EXCLUSIVE_LOCKS_REQUIRED(!cs);
#     114                 :            : 
#     115                 :            :     bool Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, int64_t nTimePenalty)
#     116                 :            :         EXCLUSIVE_LOCKS_REQUIRED(!cs);
#     117                 :            : 
#     118                 :            :     bool Good(const CService& addr, int64_t nTime)
#     119                 :            :         EXCLUSIVE_LOCKS_REQUIRED(!cs);
#     120                 :            : 
#     121                 :            :     void Attempt(const CService& addr, bool fCountFailure, int64_t nTime)
#     122                 :            :         EXCLUSIVE_LOCKS_REQUIRED(!cs);
#     123                 :            : 
#     124                 :            :     void ResolveCollisions() EXCLUSIVE_LOCKS_REQUIRED(!cs);
#     125                 :            : 
#     126                 :            :     std::pair<CAddress, int64_t> SelectTriedCollision() EXCLUSIVE_LOCKS_REQUIRED(!cs);
#     127                 :            : 
#     128                 :            :     std::pair<CAddress, int64_t> Select(bool newOnly) const
#     129                 :            :         EXCLUSIVE_LOCKS_REQUIRED(!cs);
#     130                 :            : 
#     131                 :            :     std::vector<CAddress> GetAddr(size_t max_addresses, size_t max_pct, std::optional<Network> network) const
#     132                 :            :         EXCLUSIVE_LOCKS_REQUIRED(!cs);
#     133                 :            : 
#     134                 :            :     void Connected(const CService& addr, int64_t nTime)
#     135                 :            :         EXCLUSIVE_LOCKS_REQUIRED(!cs);
#     136                 :            : 
#     137                 :            :     void SetServices(const CService& addr, ServiceFlags nServices)
#     138                 :            :         EXCLUSIVE_LOCKS_REQUIRED(!cs);
#     139                 :            : 
#     140                 :            :     std::optional<AddressPosition> FindAddressEntry(const CAddress& addr)
#     141                 :            :         EXCLUSIVE_LOCKS_REQUIRED(!cs);
#     142                 :            : 
#     143                 :            :     const std::vector<bool>& GetAsmap() const;
#     144                 :            : 
#     145                 :            :     friend class AddrManDeterministic;
#     146                 :            : 
#     147                 :            : private:
#     148                 :            :     //! A mutex to protect the inner data structures.
#     149                 :            :     mutable Mutex cs;
#     150                 :            : 
#     151                 :            :     //! Source of random numbers for randomization in inner loops
#     152                 :            :     mutable FastRandomContext insecure_rand GUARDED_BY(cs);
#     153                 :            : 
#     154                 :            :     //! secret key to randomize bucket select with
#     155                 :            :     uint256 nKey;
#     156                 :            : 
#     157                 :            :     //! Serialization versions.
#     158                 :            :     enum Format : uint8_t {
#     159                 :            :         V0_HISTORICAL = 0,    //!< historic format, before commit e6b343d88
#     160                 :            :         V1_DETERMINISTIC = 1, //!< for pre-asmap files
#     161                 :            :         V2_ASMAP = 2,         //!< for files including asmap version
#     162                 :            :         V3_BIP155 = 3,        //!< same as V2_ASMAP plus addresses are in BIP155 format
#     163                 :            :         V4_MULTIPORT = 4,     //!< adds support for multiple ports per IP
#     164                 :            :     };
#     165                 :            : 
#     166                 :            :     //! The maximum format this software knows it can unserialize. Also, we always serialize
#     167                 :            :     //! in this format.
#     168                 :            :     //! The format (first byte in the serialized stream) can be higher than this and
#     169                 :            :     //! still this software may be able to unserialize the file - if the second byte
#     170                 :            :     //! (see `lowest_compatible` in `Unserialize()`) is less or equal to this.
#     171                 :            :     static constexpr Format FILE_FORMAT = Format::V4_MULTIPORT;
#     172                 :            : 
#     173                 :            :     //! The initial value of a field that is incremented every time an incompatible format
#     174                 :            :     //! change is made (such that old software versions would not be able to parse and
#     175                 :            :     //! understand the new file format). This is 32 because we overtook the "key size"
#     176                 :            :     //! field which was 32 historically.
#     177                 :            :     //! @note Don't increment this. Increment `lowest_compatible` in `Serialize()` instead.
#     178                 :            :     static constexpr uint8_t INCOMPATIBILITY_BASE = 32;
#     179                 :            : 
#     180                 :            :     //! last used nId
#     181                 :            :     int nIdCount GUARDED_BY(cs){0};
#     182                 :            : 
#     183                 :            :     //! table with information about all nIds
#     184                 :            :     std::unordered_map<int, AddrInfo> mapInfo GUARDED_BY(cs);
#     185                 :            : 
#     186                 :            :     //! find an nId based on its network address and port.
#     187                 :            :     std::unordered_map<CService, int, CServiceHash> mapAddr GUARDED_BY(cs);
#     188                 :            : 
#     189                 :            :     //! randomly-ordered vector of all nIds
#     190                 :            :     //! This is mutable because it is unobservable outside the class, so any
#     191                 :            :     //! changes to it (even in const methods) are also unobservable.
#     192                 :            :     mutable std::vector<int> vRandom GUARDED_BY(cs);
#     193                 :            : 
#     194                 :            :     // number of "tried" entries
#     195                 :            :     int nTried GUARDED_BY(cs){0};
#     196                 :            : 
#     197                 :            :     //! list of "tried" buckets
#     198                 :            :     int vvTried[ADDRMAN_TRIED_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs);
#     199                 :            : 
#     200                 :            :     //! number of (unique) "new" entries
#     201                 :            :     int nNew GUARDED_BY(cs){0};
#     202                 :            : 
#     203                 :            :     //! list of "new" buckets
#     204                 :            :     int vvNew[ADDRMAN_NEW_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs);
#     205                 :            : 
#     206                 :            :     //! last time Good was called (memory only). Initially set to 1 so that "never" is strictly worse.
#     207                 :            :     int64_t nLastGood GUARDED_BY(cs){1};
#     208                 :            : 
#     209                 :            :     //! Holds addrs inserted into tried table that collide with existing entries. Test-before-evict discipline used to resolve these collisions.
#     210                 :            :     std::set<int> m_tried_collisions;
#     211                 :            : 
#     212                 :            :     /** Perform consistency checks every m_consistency_check_ratio operations (if non-zero). */
#     213                 :            :     const int32_t m_consistency_check_ratio;
#     214                 :            : 
#     215                 :            :     // Compressed IP->ASN mapping, loaded from a file when a node starts.
#     216                 :            :     // Should be always empty if no file was provided.
#     217                 :            :     // This mapping is then used for bucketing nodes in Addrman.
#     218                 :            :     //
#     219                 :            :     // If asmap is provided, nodes will be bucketed by
#     220                 :            :     // AS they belong to, in order to make impossible for a node
#     221                 :            :     // to connect to several nodes hosted in a single AS.
#     222                 :            :     // This is done in response to Erebus attack, but also to generally
#     223                 :            :     // diversify the connections every node creates,
#     224                 :            :     // especially useful when a large fraction of nodes
#     225                 :            :     // operate under a couple of cloud providers.
#     226                 :            :     //
#     227                 :            :     // If a new asmap was provided, the existing records
#     228                 :            :     // would be re-bucketed accordingly.
#     229                 :            :     const std::vector<bool> m_asmap;
#     230                 :            : 
#     231                 :            :     //! Find an entry.
#     232                 :            :     AddrInfo* Find(const CService& addr, int* pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);
#     233                 :            : 
#     234                 :            :     //! Create a new entry and add it to the internal data structures mapInfo, mapAddr and vRandom.
#     235                 :            :     AddrInfo* Create(const CAddress& addr, const CNetAddr& addrSource, int* pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);
#     236                 :            : 
#     237                 :            :     //! Swap two elements in vRandom.
#     238                 :            :     void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2) const EXCLUSIVE_LOCKS_REQUIRED(cs);
#     239                 :            : 
#     240                 :            :     //! Delete an entry. It must not be in tried, and have refcount 0.
#     241                 :            :     void Delete(int nId) EXCLUSIVE_LOCKS_REQUIRED(cs);
#     242                 :            : 
#     243                 :            :     //! Clear a position in a "new" table. This is the only place where entries are actually deleted.
#     244                 :            :     void ClearNew(int nUBucket, int nUBucketPos) EXCLUSIVE_LOCKS_REQUIRED(cs);
#     245                 :            : 
#     246                 :            :     //! Move an entry from the "new" table(s) to the "tried" table
#     247                 :            :     void MakeTried(AddrInfo& info, int nId) EXCLUSIVE_LOCKS_REQUIRED(cs);
#     248                 :            : 
#     249                 :            :     /** Attempt to add a single address to addrman's new table.
#     250                 :            :      *  @see AddrMan::Add() for parameters. */
#     251                 :            :     bool AddSingle(const CAddress& addr, const CNetAddr& source, int64_t nTimePenalty) EXCLUSIVE_LOCKS_REQUIRED(cs);
#     252                 :            : 
#     253                 :            :     bool Good_(const CService& addr, bool test_before_evict, int64_t time) EXCLUSIVE_LOCKS_REQUIRED(cs);
#     254                 :            : 
#     255                 :            :     bool Add_(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64_t nTimePenalty) EXCLUSIVE_LOCKS_REQUIRED(cs);
#     256                 :            : 
#     257                 :            :     void Attempt_(const CService& addr, bool fCountFailure, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);
#     258                 :            : 
#     259                 :            :     std::pair<CAddress, int64_t> Select_(bool newOnly) const EXCLUSIVE_LOCKS_REQUIRED(cs);
#     260                 :            : 
#     261                 :            :     std::vector<CAddress> GetAddr_(size_t max_addresses, size_t max_pct, std::optional<Network> network) const EXCLUSIVE_LOCKS_REQUIRED(cs);
#     262                 :            : 
#     263                 :            :     void Connected_(const CService& addr, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);
#     264                 :            : 
#     265                 :            :     void SetServices_(const CService& addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(cs);
#     266                 :            : 
#     267                 :            :     void ResolveCollisions_() EXCLUSIVE_LOCKS_REQUIRED(cs);
#     268                 :            : 
#     269                 :            :     std::pair<CAddress, int64_t> SelectTriedCollision_() EXCLUSIVE_LOCKS_REQUIRED(cs);
#     270                 :            : 
#     271                 :            :     std::optional<AddressPosition> FindAddressEntry_(const CAddress& addr) EXCLUSIVE_LOCKS_REQUIRED(cs);
#     272                 :            : 
#     273                 :            :     //! Consistency check, taking into account m_consistency_check_ratio.
#     274                 :            :     //! Will std::abort if an inconsistency is detected.
#     275                 :            :     void Check() const EXCLUSIVE_LOCKS_REQUIRED(cs);
#     276                 :            : 
#     277                 :            :     //! Perform consistency check, regardless of m_consistency_check_ratio.
#     278                 :            :     //! @returns an error code or zero.
#     279                 :            :     int CheckAddrman() const EXCLUSIVE_LOCKS_REQUIRED(cs);
#     280                 :            : };
#     281                 :            : 
#     282                 :            : #endif // BITCOIN_ADDRMAN_IMPL_H

Generated by: LCOV version 0-eol-96201-ge66f56f4af6a