diff --git a/src/addrman.cpp b/src/addrman.cpp index e23a332622603..ffc8a6955f3f6 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -65,9 +65,14 @@ double CAddrInfo::GetChance(int64_t nNow) const return fChance; } -CAddrInfo* CAddrMan::Find(const CNetAddr& addr, int* pnId) +CAddrInfo* CAddrMan::Find(const CService& addr, int* pnId) { - std::map::iterator it = mapAddr.find(addr); + CService addr2 = addr; + if (!discriminatePorts) { + addr2.SetPort(0); + } + + std::map::iterator it = mapAddr.find(addr2); if (it == mapAddr.end()) return NULL; if (pnId) @@ -80,9 +85,14 @@ CAddrInfo* CAddrMan::Find(const CNetAddr& addr, int* pnId) CAddrInfo* CAddrMan::Create(const CAddress& addr, const CNetAddr& addrSource, int* pnId) { + CService addr2 = addr; + if (!discriminatePorts) { + addr2.SetPort(0); + } + int nId = nIdCount++; mapInfo[nId] = CAddrInfo(addr, addrSource); - mapAddr[addr] = nId; + mapAddr[addr2] = nId; mapInfo[nId].nRandomPos = vRandom.size(); vRandom.push_back(nId); if (pnId) @@ -117,9 +127,14 @@ void CAddrMan::Delete(int nId) assert(!info.fInTried); assert(info.nRefCount == 0); + CService addr = info; + if (!discriminatePorts) { + addr.SetPort(0); + } + SwapRandom(info.nRandomPos, vRandom.size() - 1); vRandom.pop_back(); - mapAddr.erase(info); + mapAddr.erase(addr); mapInfo.erase(nId); nNew--; } diff --git a/src/addrman.h b/src/addrman.h index 76e7b210f7c34..cdb4a65a65cef 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -187,7 +187,7 @@ class CAddrMan std::map mapInfo; //! find an nId based on its network address - std::map mapAddr; + std::map mapAddr; //! randomly-ordered vector of all nIds std::vector vRandom; @@ -207,6 +207,9 @@ class CAddrMan //! last time Good was called (memory only) int64_t nLastGood; + // discriminate entries based on port. Should be false on mainnet/testnet and can be true on devnet/regtest + bool discriminatePorts; + protected: //! secret key to randomize bucket select with uint256 nKey; @@ -215,7 +218,7 @@ class CAddrMan FastRandomContext insecure_rand; //! Find an entry. - CAddrInfo* Find(const CNetAddr& addr, int *pnId = NULL); + CAddrInfo* Find(const CService& addr, int *pnId = NULL); //! find an entry, creating it if necessary. //! nTime and nServices of the found node are updated, if necessary. @@ -469,7 +472,8 @@ class CAddrMan nLastGood = 1; //Initially at 1 so that "never" is strictly worse. } - CAddrMan() + CAddrMan(bool _discriminatePorts = false) : + discriminatePorts(_discriminatePorts) { Clear(); } diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 1060d0d13e55a..e01c9c8c09d21 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -366,8 +366,6 @@ class CTestNetParams : public CChainParams { // Testnet Dash BIP44 coin type is '1' (All coin's testnet default) nExtCoinType = 1; - vFixedSeeds = std::vector(pnSeed6_test, pnSeed6_test + ARRAYLEN(pnSeed6_test)); - fMiningRequiresPeers = true; fDefaultConsistencyChecks = false; fRequireStandard = false; @@ -503,7 +501,7 @@ class CDevNetParams : public CChainParams { fRequireStandard = false; fMineBlocksOnDemand = false; fAllowMultipleAddressesFromGroup = true; - fAllowMultiplePorts = false; + fAllowMultiplePorts = true; nPoolMaxTransactions = 3; nFulfilledRequestExpireTime = 5*60; // fulfilled requests expire in 5 minutes diff --git a/src/net.cpp b/src/net.cpp index b1087939b17a8..f0bd58abbe5a1 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -348,8 +348,10 @@ bool CConnman::CheckIncomingNonce(uint64_t nonce) CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure) { if (pszDest == NULL) { - if (IsLocal(addrConnect)) + bool fAllowLocal = Params().AllowMultiplePorts() && addrConnect.GetPort() != GetListenPort(); + if (!fAllowLocal && IsLocal(addrConnect)) { return NULL; + } // Look for an existing connection CNode* pnode = FindNode((CService)addrConnect); @@ -1786,7 +1788,12 @@ void CConnman::ThreadOpenConnections() CAddrInfo addr = addrman.Select(fFeeler); // if we selected an invalid address, restart - if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr)) + if (!addr.IsValid() || setConnected.count(addr.GetGroup())) + break; + + // if we selected a local address, restart (local addresses are allowed in regtest and devnet) + bool fAllowLocal = Params().AllowMultiplePorts() && addrConnect.GetPort() != GetListenPort(); + if (!fAllowLocal && IsLocal(addrConnect)) break; // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman, @@ -1818,7 +1825,7 @@ void CConnman::ThreadOpenConnections() } // do not allow non-default ports, unless after 50 invalid addresses selected already - if (addr.GetPort() != Params().GetDefaultPort() && nTries < 50) + if (addr.GetPort() != Params().GetDefaultPort() && addr.GetPort() != GetListenPort() && nTries < 50) continue; addrConnect = addr; @@ -1990,9 +1997,16 @@ bool CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai return false; } if (!pszDest) { - if (IsLocal(addrConnect) || - FindNode((CNetAddr)addrConnect) || IsBanned(addrConnect) || - FindNode(addrConnect.ToStringIPPort())) + // banned or exact match? + if (IsBanned(addrConnect) || FindNode(addrConnect.ToStringIPPort())) + return false; + // local and not a connection to itself? + bool fAllowLocal = Params().AllowMultiplePorts() && addrConnect.GetPort() != GetListenPort(); + if (!fAllowLocal && IsLocal(addrConnect)) + return false; + // if multiple ports for same IP are allowed, search for IP:PORT match, otherwise search for IP-only match + if ((!Params().AllowMultiplePorts() && FindNode((CNetAddr)addrConnect)) || + (Params().AllowMultiplePorts() && FindNode((CService)addrConnect))) return false; } else if (FindNode(std::string(pszDest))) return false; @@ -2238,7 +2252,9 @@ void CConnman::SetNetworkActive(bool active) uiInterface.NotifyNetworkActiveChanged(fNetworkActive); } -CConnman::CConnman(uint64_t nSeed0In, uint64_t nSeed1In) : nSeed0(nSeed0In), nSeed1(nSeed1In) +CConnman::CConnman(uint64_t nSeed0In, uint64_t nSeed1In) : + nSeed0(nSeed0In), nSeed1(nSeed1In), + addrman(Params().AllowMultiplePorts()) { fNetworkActive = true; setBannedIsDirty = false; diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index 535faa2b161a3..7a35ff6da1277 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -33,7 +33,7 @@ class CAddrManTest : public CAddrMan return (unsigned int)(state % nMax); } - CAddrInfo* Find(const CNetAddr& addr, int* pnId = NULL) + CAddrInfo* Find(const CService& addr, int* pnId = NULL) { return CAddrMan::Find(addr, pnId); }