diff --git a/src/init.cpp b/src/init.cpp --- a/src/init.cpp +++ b/src/init.cpp @@ -69,8 +69,12 @@ static const bool DEFAULT_REST_ENABLE = false; static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false; +// Dump addresses to banlist.dat every 15 minutes (900s) +static constexpr int DUMP_BANS_INTERVAL = 60 * 15; + std::unique_ptr g_connman; std::unique_ptr peerLogic; +std::unique_ptr g_banman; #if !(ENABLE_WALLET) class DummyWalletInit : public WalletInitInterface { @@ -230,6 +234,7 @@ // stopped, destruct and reset all to nullptr. peerLogic.reset(); g_connman.reset(); + g_banman.reset(); g_txindex.reset(); if (g_is_mempool_loaded && @@ -1938,14 +1943,15 @@ // is not yet setup and may end up being set up twice if we // need to reindex later. + assert(!g_banman); + g_banman = std::make_unique(config.GetChainParams(), &uiInterface); assert(!g_connman); g_connman = std::make_unique( config, GetRand(std::numeric_limits::max()), GetRand(std::numeric_limits::max())); - CConnman &connman = *g_connman; peerLogic.reset(new PeerLogicValidation( - &connman, scheduler, + g_connman.get(), g_banman.get(), scheduler, gArgs.GetBoolArg("-enablebip61", DEFAULT_ENABLE_BIP61))); RegisterValidationInterface(peerLogic.get()); @@ -2431,6 +2437,7 @@ connOptions.nMaxFeeler = 1; connOptions.nBestHeight = chain_active_height; connOptions.uiInterface = &uiInterface; + connOptions.m_banman = g_banman.get(); connOptions.m_msgproc = peerLogic.get(); connOptions.nSendBufferMaxSize = 1000 * gArgs.GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER); @@ -2481,7 +2488,7 @@ connOptions.m_specified_outgoing = connect; } } - if (!connman.Start(scheduler, connOptions)) { + if (!g_connman->Start(scheduler, connOptions)) { return false; } @@ -2492,5 +2499,12 @@ g_wallet_init_interface.Start(scheduler); + scheduler.scheduleEvery( + [] { + g_banman->DumpBanlist(); + return true; + }, + DUMP_BANS_INTERVAL * 1000); + return true; } diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp --- a/src/interfaces/node.cpp +++ b/src/interfaces/node.cpp @@ -131,23 +131,23 @@ return false; } bool getBanned(banmap_t &banmap) override { - if (g_connman) { - g_connman->GetBanned(banmap); + if (g_banman) { + g_banman->GetBanned(banmap); return true; } return false; } bool ban(const CNetAddr &net_addr, BanReason reason, int64_t ban_time_offset) override { - if (g_connman) { - g_connman->Ban(net_addr, reason, ban_time_offset); + if (g_banman) { + g_banman->Ban(net_addr, reason, ban_time_offset); return true; } return false; } bool unban(const CSubNet &ip) override { - if (g_connman) { - g_connman->Unban(ip); + if (g_banman) { + g_banman->Unban(ip); return true; } return false; diff --git a/src/net.h b/src/net.h --- a/src/net.h +++ b/src/net.h @@ -92,7 +92,7 @@ // Default 24-hour ban. // NOTE: When adjusting this, update rpcnet:setban's help ("24h") -static const unsigned int DEFAULT_MISBEHAVING_BANTIME = 60 * 60 * 24; +static constexpr unsigned int DEFAULT_MISBEHAVING_BANTIME = 60 * 60 * 24; typedef int64_t NodeId; @@ -118,6 +118,53 @@ std::string command; }; +class BanMan { +public: + // Denial-of-service detection/prevention + // The idea is to detect peers that are behaving + // badly and disconnect/ban them, but do it in a + // one-coding-mistake-won't-shatter-the-entire-network + // way. + // IMPORTANT: There should be nothing I can give a + // node that it will forward on that will make that + // node's peers drop it. If there is, an attacker + // can isolate a node and/or try to split the network. + // Dropping a node for sending stuff that is invalid + // now but might be valid in a later version is also + // dangerous, because it can cause a network split + // between nodes running old code and nodes running + // new code. + ~BanMan(); + BanMan(const CChainParams &_params, CClientUIInterface *client_interface); + void Ban(const CNetAddr &netAddr, const BanReason &reason, + int64_t bantimeoffset = 0, bool sinceUnixEpoch = false); + void Ban(const CSubNet &subNet, const BanReason &reason, + int64_t bantimeoffset = 0, bool sinceUnixEpoch = false); + // needed for unit testing + void ClearBanned(); + bool IsBanned(CNetAddr ip); + bool IsBanned(CSubNet subnet); + bool Unban(const CNetAddr &ip); + bool Unban(const CSubNet &ip); + void GetBanned(banmap_t &banmap); + void DumpBanlist(); + +private: + void SetBanned(const banmap_t &banmap); + bool BannedSetIsDirty(); + //! set the "dirty" flag for the banlist + void SetBannedSetDirty(bool dirty = true); + //! clean unused entries (if bantime has expired) + void SweepBanned(); + + banmap_t setBanned; + CCriticalSection cs_setBanned; + bool setBannedIsDirty; + CClientUIInterface *clientInterface = nullptr; + + const CChainParams ¶ms; +}; + class NetEventsInterface; class CConnman { public: @@ -137,6 +184,7 @@ int nBestHeight = 0; CClientUIInterface *uiInterface = nullptr; NetEventsInterface *m_msgproc = nullptr; + BanMan *m_banman = nullptr; unsigned int nSendBufferMaxSize = 0; unsigned int nReceiveFloodSize = 0; uint64_t nMaxOutboundTimeframe = 0; @@ -158,6 +206,7 @@ nMaxFeeler = connOptions.nMaxFeeler; nBestHeight = connOptions.nBestHeight; clientInterface = connOptions.uiInterface; + m_banman = connOptions.m_banman; m_msgproc = connOptions.m_msgproc; nSendBufferMaxSize = connOptions.nSendBufferMaxSize; nReceiveFloodSize = connOptions.nReceiveFloodSize; @@ -240,28 +289,6 @@ const CAddress &addrFrom, int64_t nTimePenalty = 0); std::vector GetAddresses(); - // Denial-of-service detection/prevention. The idea is to detect peers that - // are behaving badly and disconnect/ban them, but do it in a - // one-coding-mistake-won't-shatter-the-entire-network way. - // IMPORTANT: There should be nothing I can give a node that it will forward - // on that will make that node's peers drop it. If there is, an attacker can - // isolate a node and/or try to split the network. Dropping a node for - // sending stuff that is invalid now but might be valid in a later version - // is also dangerous, because it can cause a network split between nodes - // running old code and nodes running new code. - void Ban(const CNetAddr &netAddr, const BanReason &reason, - int64_t bantimeoffset = 0, bool sinceUnixEpoch = false); - void Ban(const CSubNet &subNet, const BanReason &reason, - int64_t bantimeoffset = 0, bool sinceUnixEpoch = false); - // Needed for unit testing. - void ClearBanned(); - bool IsBanned(CNetAddr ip); - bool IsBanned(CSubNet subnet); - bool Unban(const CNetAddr &ip); - bool Unban(const CSubNet &ip); - void GetBanned(banmap_t &banmap); - void SetBanned(const banmap_t &banmap); - // This allows temporarily exceeding nMaxOutbound, with the goal of finding // a peer that is better than all our current peers. void SetTryNewOutboundPeer(bool flag); @@ -367,15 +394,7 @@ NodeId GetNewNodeId(); size_t SocketSendData(CNode *pnode) const; - //! check is the banlist has unwritten changes - bool BannedSetIsDirty(); - //! set the "dirty" flag for the banlist - void SetBannedSetDirty(bool dirty = true); - //! clean unused entries (if bantime has expired) - void SweepBanned(); void DumpAddresses(); - void DumpData(); - void DumpBanlist(); // Network stats void RecordBytesRecv(uint64_t bytes); @@ -407,9 +426,6 @@ std::vector vhListenSocket; std::atomic fNetworkActive{true}; - banmap_t setBanned GUARDED_BY(cs_setBanned); - CCriticalSection cs_setBanned; - bool setBannedIsDirty GUARDED_BY(cs_setBanned){false}; bool fAddressesInitialized{false}; CAddrMan addrman; std::deque vOneShots GUARDED_BY(cs_vOneShots); @@ -434,6 +450,7 @@ std::atomic nBestHeight; CClientUIInterface *clientInterface; NetEventsInterface *m_msgproc; + BanMan *m_banman; /** SipHasher seeds for deterministic randomness */ const uint64_t nSeed0, nSeed1; @@ -464,6 +481,7 @@ }; extern std::unique_ptr g_connman; +extern std::unique_ptr g_banman; void Discover(); void StartMapPort(); void InterruptMapPort(); diff --git a/src/net.cpp b/src/net.cpp --- a/src/net.cpp +++ b/src/net.cpp @@ -41,9 +41,6 @@ // Dump addresses to peers.dat every 15 minutes (900s) static constexpr int DUMP_PEERS_INTERVAL = 15 * 60; -// Dump addresses to banlist.dat every 15 minutes (900s) -static constexpr int DUMP_BANS_INTERVAL = 60 * 15; - // We add a random period time (0 to 1 seconds) to feeler connections to prevent // synchronization. #define FEELER_SLEEP_WINDOW 1 @@ -475,7 +472,7 @@ return pnode; } -void CConnman::DumpBanlist() { +void BanMan::DumpBanlist() { // Clean unused entries (if bantime has expired) SweepBanned(); @@ -484,8 +481,7 @@ } int64_t nStart = GetTimeMillis(); - - CBanDB bandb(config->GetChainParams()); + CBanDB bandb(params); banmap_t banmap; GetBanned(banmap); if (bandb.Write(banmap)) { @@ -506,7 +502,7 @@ } } -void CConnman::ClearBanned() { +void BanMan::ClearBanned() { { LOCK(cs_setBanned); setBanned.clear(); @@ -520,7 +516,7 @@ } } -bool CConnman::IsBanned(CNetAddr ip) { +bool BanMan::IsBanned(CNetAddr ip) { LOCK(cs_setBanned); for (const auto &it : setBanned) { CSubNet subNet = it.first; @@ -534,7 +530,7 @@ return false; } -bool CConnman::IsBanned(CSubNet subnet) { +bool BanMan::IsBanned(CSubNet subnet) { LOCK(cs_setBanned); banmap_t::iterator i = setBanned.find(subnet); @@ -548,14 +544,14 @@ return false; } -void CConnman::Ban(const CNetAddr &addr, const BanReason &banReason, - int64_t bantimeoffset, bool sinceUnixEpoch) { +void BanMan::Ban(const CNetAddr &addr, const BanReason &banReason, + int64_t bantimeoffset, bool sinceUnixEpoch) { CSubNet subNet(addr); Ban(subNet, banReason, bantimeoffset, sinceUnixEpoch); } -void CConnman::Ban(const CSubNet &subNet, const BanReason &banReason, - int64_t bantimeoffset, bool sinceUnixEpoch) { +void BanMan::Ban(const CSubNet &subNet, const BanReason &banReason, + int64_t bantimeoffset, bool sinceUnixEpoch) { CBanEntry banEntry(GetTime()); banEntry.banReason = banReason; if (bantimeoffset <= 0) { @@ -584,12 +580,12 @@ } } -bool CConnman::Unban(const CNetAddr &addr) { +bool BanMan::Unban(const CNetAddr &addr) { CSubNet subNet(addr); return Unban(subNet); } -bool CConnman::Unban(const CSubNet &subNet) { +bool BanMan::Unban(const CSubNet &subNet) { { LOCK(cs_setBanned); if (!setBanned.erase(subNet)) { @@ -607,7 +603,7 @@ return true; } -void CConnman::GetBanned(banmap_t &banMap) { +void BanMan::GetBanned(banmap_t &banMap) { LOCK(cs_setBanned); // Sweep the banlist so expired bans are not returned SweepBanned(); @@ -615,13 +611,13 @@ banMap = setBanned; } -void CConnman::SetBanned(const banmap_t &banMap) { +void BanMan::SetBanned(const banmap_t &banMap) { LOCK(cs_setBanned); setBanned = banMap; setBannedIsDirty = true; } -void CConnman::SweepBanned() { +void BanMan::SweepBanned() { int64_t now = GetTime(); bool notifyUI = false; { @@ -650,12 +646,12 @@ } } -bool CConnman::BannedSetIsDirty() { +bool BanMan::BannedSetIsDirty() { LOCK(cs_setBanned); return setBannedIsDirty; } -void CConnman::SetBannedSetDirty(bool dirty) { +void BanMan::SetBannedSetDirty(bool dirty) { // Reuse setBanned lock for the isDirty flag. LOCK(cs_setBanned); setBannedIsDirty = dirty; @@ -1195,7 +1191,7 @@ // sockets on all platforms. Set it again here just to be sure. SetSocketNoDelay(hSocket); - if (IsBanned(addr) && !whitelisted) { + if (m_banman && m_banman->IsBanned(addr) && !whitelisted) { LogPrint(BCLog::NET, "connection from %s dropped (banned)\n", addr.ToString()); CloseSocket(hSocket); @@ -2111,7 +2107,8 @@ if (!pszDest) { if (IsLocal(addrConnect) || FindNode(static_cast(addrConnect)) || - IsBanned(addrConnect) || FindNode(addrConnect.ToStringIPPort())) { + (m_banman && m_banman->IsBanned(addrConnect)) || + FindNode(addrConnect.ToStringIPPort())) { return; } } else if (FindNode(std::string(pszDest))) { @@ -2437,30 +2434,6 @@ DumpAddresses(); } } - if (clientInterface) { - clientInterface->InitMessage(_("Loading banlist...")); - } - // Load addresses from banlist.dat - nStart = GetTimeMillis(); - CBanDB bandb(config->GetChainParams()); - banmap_t banmap; - if (bandb.Read(banmap)) { - // thread save setter - SetBanned(banmap); - // no need to write down, just read data - SetBannedSetDirty(false); - // sweep out unused entries - SweepBanned(); - - LogPrint(BCLog::NET, - "Loaded %d banned node ips/subnets from banlist.dat %dms\n", - banmap.size(), GetTimeMillis() - nStart); - } else { - LogPrintf("Invalid or missing banlist.dat; recreating\n"); - // force write - SetBannedSetDirty(true); - DumpBanlist(); - } uiInterface.InitMessage(_("Starting network threads...")); @@ -2542,16 +2515,44 @@ }, DUMP_PEERS_INTERVAL * 1000); - scheduler.scheduleEvery( - [this]() { - this->DumpBanlist(); - return true; - }, - DUMP_BANS_INTERVAL * 1000); - return true; } +BanMan::BanMan(const CChainParams &_params, + CClientUIInterface *client_interface) + : clientInterface(client_interface), params(_params) { + if (clientInterface) { + clientInterface->InitMessage(_("Loading banlist...")); + } + + // Load addresses from banlist.dat + int64_t nStart = GetTimeMillis(); + setBannedIsDirty = false; + CBanDB bandb(params); + banmap_t banmap; + if (bandb.Read(banmap)) { + // thread save setter + SetBanned(banmap); + // no need to write down, just read data + SetBannedSetDirty(false); + // sweep out unused entries + SweepBanned(); + + LogPrint(BCLog::NET, + "Loaded %d banned node ips/subnets from banlist.dat %dms\n", + banmap.size(), GetTimeMillis() - nStart); + } else { + LogPrintf("Invalid or missing banlist.dat; recreating\n"); + // force write + SetBannedSetDirty(true); + DumpBanlist(); + } +} + +BanMan::~BanMan() { + DumpBanlist(); +} + class CNetCleanup { public: CNetCleanup() {} @@ -2606,7 +2607,6 @@ if (fAddressesInitialized) { DumpAddresses(); - DumpBanlist(); fAddressesInitialized = false; } diff --git a/src/net_processing.h b/src/net_processing.h --- a/src/net_processing.h +++ b/src/net_processing.h @@ -30,10 +30,14 @@ public NetEventsInterface { private: CConnman *const connman; + BanMan *const m_banman; + + bool SendRejectsAndCheckIfBanned(CNode *pnode, bool enable_bip61) + EXCLUSIVE_LOCKS_REQUIRED(cs_main); public: - explicit PeerLogicValidation(CConnman *connman, CScheduler &scheduler, - bool enable_bip61); + PeerLogicValidation(CConnman *connman, BanMan *banman, + CScheduler &scheduler, bool enable_bip61); /** * Overridden from CValidationInterface. diff --git a/src/net_processing.cpp b/src/net_processing.cpp --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -992,12 +992,11 @@ STALE_RELAY_AGE_LIMIT); } -PeerLogicValidation::PeerLogicValidation(CConnman *connmanIn, +PeerLogicValidation::PeerLogicValidation(CConnman *connmanIn, BanMan *banman, CScheduler &scheduler, bool enable_bip61) - : connman(connmanIn), m_stale_tip_check_time(0), + : connman(connmanIn), m_banman(banman), m_stale_tip_check_time(0), m_enable_bip61(enable_bip61) { - // Initialize global variables that cannot be constructed at startup. recentRejects.reset(new CRollingBloomFilter(120000, 0.000001)); @@ -3380,8 +3379,8 @@ return true; } -static bool SendRejectsAndCheckIfBanned(CNode *pnode, CConnman *connman, - bool enable_bip61) +bool PeerLogicValidation::SendRejectsAndCheckIfBanned(CNode *pnode, + bool enable_bip61) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { AssertLockHeld(cs_main); CNodeState &state = *State(pnode->GetId()); @@ -3413,7 +3412,9 @@ pnode->fDisconnect = true; } else { // Disconnect and ban all nodes sharing the address - connman->Ban(pnode->addr, BanReasonNodeMisbehaving); + if (m_banman) { + m_banman->Ban(pnode->addr, BanReasonNodeMisbehaving); + } connman->DisconnectNode(pnode->addr); } return true; @@ -3480,7 +3481,9 @@ SanitizeString(msg.hdr.GetCommand()), pfrom->GetId()); // Make sure we ban where that come from for some time. - connman->Ban(pfrom->addr, BanReasonNodeMisbehaving); + if (m_banman) { + m_banman->Ban(pfrom->addr, BanReasonNodeMisbehaving); + } connman->DisconnectNode(pfrom->addr); pfrom->fDisconnect = true; @@ -3513,7 +3516,9 @@ HexStr(hdr.pchChecksum, hdr.pchChecksum + CMessageHeader::CHECKSUM_SIZE), pfrom->GetId()); - connman->Ban(pfrom->addr, BanReasonNodeMisbehaving); + if (m_banman) { + m_banman->Ban(pfrom->addr, BanReasonNodeMisbehaving); + } connman->DisconnectNode(pfrom->addr); return fMoreWork; } @@ -3570,7 +3575,7 @@ } LOCK(cs_main); - SendRejectsAndCheckIfBanned(pfrom, connman, m_enable_bip61); + SendRejectsAndCheckIfBanned(pfrom, m_enable_bip61); return fMoreWork; } @@ -3835,7 +3840,7 @@ return true; } - if (SendRejectsAndCheckIfBanned(pto, connman, m_enable_bip61)) { + if (SendRejectsAndCheckIfBanned(pto, m_enable_bip61)) { return true; } CNodeState &state = *State(pto->GetId()); diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -643,10 +643,9 @@ HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400")); } - if (!g_connman) { - throw JSONRPCError( - RPC_CLIENT_P2P_DISABLED, - "Error: Peer-to-peer functionality missing or disabled"); + if (!g_banman) { + throw JSONRPCError(RPC_DATABASE_ERROR, + "Error: Ban database not loaded"); } CSubNet subNet; @@ -671,8 +670,8 @@ } if (strCommand == "add") { - if (isSubnet ? g_connman->IsBanned(subNet) - : g_connman->IsBanned(netAddr)) { + if (isSubnet ? g_banman->IsBanned(subNet) + : g_banman->IsBanned(netAddr)) { throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned"); } @@ -689,15 +688,18 @@ } if (isSubnet) { - g_connman->Ban(subNet, BanReasonManuallyAdded, banTime, absolute); - g_connman->DisconnectNode(subNet); + g_banman->Ban(subNet, BanReasonManuallyAdded, banTime, absolute); + if (g_connman) { + g_connman->DisconnectNode(subNet); + } } else { - g_connman->Ban(netAddr, BanReasonManuallyAdded, banTime, absolute); - g_connman->DisconnectNode(netAddr); + g_banman->Ban(netAddr, BanReasonManuallyAdded, banTime, absolute); + if (g_connman) { + g_connman->DisconnectNode(netAddr); + } } } else if (strCommand == "remove") { - if (!(isSubnet ? g_connman->Unban(subNet) - : g_connman->Unban(netAddr))) { + if (!(isSubnet ? g_banman->Unban(subNet) : g_banman->Unban(netAddr))) { throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Unban failed. Requested address/subnet " "was not previously banned."); @@ -716,14 +718,13 @@ HelpExampleRpc("listbanned", "")); } - if (!g_connman) { - throw JSONRPCError( - RPC_CLIENT_P2P_DISABLED, - "Error: Peer-to-peer functionality missing or disabled"); + if (!g_banman) { + throw JSONRPCError(RPC_DATABASE_ERROR, + "Error: Ban database not loaded"); } banmap_t banMap; - g_connman->GetBanned(banMap); + g_banman->GetBanned(banMap); UniValue bannedAddresses(UniValue::VARR); for (const auto &entry : banMap) { @@ -750,13 +751,13 @@ HelpExampleRpc("clearbanned", "")); } - if (!g_connman) { + if (!g_banman) { throw JSONRPCError( RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); } - g_connman->ClearBanned(); + g_banman->ClearBanned(); return NullUniValue; } diff --git a/src/test/avalanche_tests.cpp b/src/test/avalanche_tests.cpp --- a/src/test/avalanche_tests.cpp +++ b/src/test/avalanche_tests.cpp @@ -213,8 +213,8 @@ const Config &config = GetConfig(); auto connman = std::make_unique(config, 0x1337, 0x1337); - auto peerLogic = - std::make_unique(connman.get(), scheduler, false); + auto peerLogic = std::make_unique( + connman.get(), nullptr, scheduler, false); AvalancheProcessor p(connman.get()); std::vector updates; @@ -377,8 +377,8 @@ const Config &config = GetConfig(); auto connman = std::make_unique(config, 0x1337, 0x1337); - auto peerLogic = - std::make_unique(connman.get(), scheduler, false); + auto peerLogic = std::make_unique( + connman.get(), nullptr, scheduler, false); AvalancheProcessor p(connman.get()); CBlockIndex indexA, indexB; @@ -489,8 +489,8 @@ const Config &config = GetConfig(); auto connman = std::make_unique(config, 0x1337, 0x1337); - auto peerLogic = - std::make_unique(connman.get(), scheduler, false); + auto peerLogic = std::make_unique( + connman.get(), nullptr, scheduler, false); AvalancheProcessor p(connman.get()); @@ -636,8 +636,8 @@ const Config &config = GetConfig(); auto connman = std::make_unique(config, 0x1337, 0x1337); - auto peerLogic = - std::make_unique(connman.get(), scheduler, false); + auto peerLogic = std::make_unique( + connman.get(), nullptr, scheduler, false); AvalancheProcessor p(connman.get()); @@ -700,8 +700,8 @@ const Config &config = GetConfig(); auto connman = std::make_unique(config, 0x1337, 0x1337); - auto peerLogic = - std::make_unique(connman.get(), scheduler, false); + auto peerLogic = std::make_unique( + connman.get(), nullptr, scheduler, false); AvalancheProcessor p(connman.get()); @@ -759,8 +759,8 @@ const Config &config = GetConfig(); auto connman = std::make_unique(config, 0x1337, 0x1337); - auto peerLogic = - std::make_unique(connman.get(), scheduler, false); + auto peerLogic = std::make_unique( + connman.get(), nullptr, scheduler, false); AvalancheProcessor p(connman.get()); std::vector updates; @@ -831,8 +831,8 @@ const Config &config = GetConfig(); auto connman = std::make_unique(config, 0x1337, 0x1337); - auto peerLogic = - std::make_unique(connman.get(), scheduler, false); + auto peerLogic = std::make_unique( + connman.get(), nullptr, scheduler, false); AvalancheProcessor p(connman.get()); CScheduler s; diff --git a/src/test/denialofservice_tests.cpp b/src/test/denialofservice_tests.cpp --- a/src/test/denialofservice_tests.cpp +++ b/src/test/denialofservice_tests.cpp @@ -73,8 +73,8 @@ std::atomic interruptDummy(false); auto connman = std::make_unique(config, 0x1337, 0x1337); - auto peerLogic = - std::make_unique(connman.get(), scheduler, false); + auto peerLogic = std::make_unique( + connman.get(), nullptr, scheduler, false); // Mock an outbound peer CAddress addr1(ip(0xa0b0c001), NODE_NONE); @@ -154,8 +154,8 @@ const Config &config = GetConfig(); auto connman = std::make_unique(config, 0x1337, 0x1337); - auto peerLogic = - std::make_unique(connman.get(), scheduler, false); + auto peerLogic = std::make_unique( + connman.get(), nullptr, scheduler, false); const Consensus::Params &consensusParams = config.GetChainParams().GetConsensus(); @@ -229,11 +229,12 @@ const Config &config = GetConfig(); std::atomic interruptDummy(false); + auto banman = std::make_unique(config.GetChainParams(), nullptr); auto connman = std::make_unique(config, 0x1337, 0x1337); - auto peerLogic = - std::make_unique(connman.get(), scheduler, false); + auto peerLogic = std::make_unique( + connman.get(), banman.get(), scheduler, false); - connman->ClearBanned(); + banman->ClearBanned(); CAddress addr1(ip(0xa0b0c001), NODE_NONE); CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 0, 0, CAddress(), "", true); @@ -250,9 +251,9 @@ LOCK2(cs_main, dummyNode1.cs_sendProcessing); peerLogic->SendMessages(config, &dummyNode1, interruptDummy); } - BOOST_CHECK(connman->IsBanned(addr1)); + BOOST_CHECK(banman->IsBanned(addr1)); // Different IP, not banned. - BOOST_CHECK(!connman->IsBanned(ip(0xa0b0c001 | 0x0000ff00))); + BOOST_CHECK(!banman->IsBanned(ip(0xa0b0c001 | 0x0000ff00))); CAddress addr2(ip(0xa0b0c002), NODE_NONE); CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, 1, 1, @@ -270,9 +271,9 @@ peerLogic->SendMessages(config, &dummyNode2, interruptDummy); } // 2 not banned yet... - BOOST_CHECK(!connman->IsBanned(addr2)); + BOOST_CHECK(!banman->IsBanned(addr2)); // ... but 1 still should be. - BOOST_CHECK(connman->IsBanned(addr1)); + BOOST_CHECK(banman->IsBanned(addr1)); { LOCK(cs_main); Misbehaving(dummyNode2.GetId(), 50, ""); @@ -281,7 +282,7 @@ LOCK2(cs_main, dummyNode2.cs_sendProcessing); peerLogic->SendMessages(config, &dummyNode2, interruptDummy); } - BOOST_CHECK(connman->IsBanned(addr2)); + BOOST_CHECK(banman->IsBanned(addr2)); bool dummy; peerLogic->FinalizeNode(config, dummyNode1.GetId(), dummy); @@ -292,11 +293,12 @@ const Config &config = GetConfig(); std::atomic interruptDummy(false); + auto banman = std::make_unique(config.GetChainParams(), nullptr); auto connman = std::make_unique(config, 0x1337, 0x1337); - auto peerLogic = - std::make_unique(connman.get(), scheduler, false); + auto peerLogic = std::make_unique( + connman.get(), banman.get(), scheduler, false); - connman->ClearBanned(); + banman->ClearBanned(); // because 11 is my favorite number. gArgs.ForceSetArg("-banscore", "111"); CAddress addr1(ip(0xa0b0c001), NODE_NONE); @@ -314,7 +316,7 @@ LOCK2(cs_main, dummyNode1.cs_sendProcessing); peerLogic->SendMessages(config, &dummyNode1, interruptDummy); } - BOOST_CHECK(!connman->IsBanned(addr1)); + BOOST_CHECK(!banman->IsBanned(addr1)); { LOCK(cs_main); Misbehaving(dummyNode1.GetId(), 10, ""); @@ -323,7 +325,7 @@ LOCK2(cs_main, dummyNode1.cs_sendProcessing); peerLogic->SendMessages(config, &dummyNode1, interruptDummy); } - BOOST_CHECK(!connman->IsBanned(addr1)); + BOOST_CHECK(!banman->IsBanned(addr1)); { LOCK(cs_main); Misbehaving(dummyNode1.GetId(), 1, ""); @@ -332,7 +334,7 @@ LOCK2(cs_main, dummyNode1.cs_sendProcessing); peerLogic->SendMessages(config, &dummyNode1, interruptDummy); } - BOOST_CHECK(connman->IsBanned(addr1)); + BOOST_CHECK(banman->IsBanned(addr1)); gArgs.ForceSetArg("-banscore", std::to_string(DEFAULT_BANSCORE_THRESHOLD)); bool dummy; @@ -343,11 +345,12 @@ const Config &config = GetConfig(); std::atomic interruptDummy(false); + auto banman = std::make_unique(config.GetChainParams(), nullptr); auto connman = std::make_unique(config, 0x1337, 0x1337); - auto peerLogic = - std::make_unique(connman.get(), scheduler, false); + auto peerLogic = std::make_unique( + connman.get(), banman.get(), scheduler, false); - connman->ClearBanned(); + banman->ClearBanned(); int64_t nStartTime = GetTime(); // Overrides future calls to GetTime() SetMockTime(nStartTime); @@ -368,13 +371,13 @@ LOCK2(cs_main, dummyNode.cs_sendProcessing); peerLogic->SendMessages(config, &dummyNode, interruptDummy); } - BOOST_CHECK(connman->IsBanned(addr)); + BOOST_CHECK(banman->IsBanned(addr)); SetMockTime(nStartTime + 60 * 60); - BOOST_CHECK(connman->IsBanned(addr)); + BOOST_CHECK(banman->IsBanned(addr)); SetMockTime(nStartTime + 60 * 60 * 24 + 1); - BOOST_CHECK(!connman->IsBanned(addr)); + BOOST_CHECK(!banman->IsBanned(addr)); bool dummy; peerLogic->FinalizeNode(config, dummyNode.GetId(), dummy); diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -116,6 +116,8 @@ for (int i = 0; i < nScriptCheckThreads - 1; i++) { threadGroup.create_thread(&ThreadScriptCheck); } + + g_banman = std::make_unique(chainparams, nullptr); // Deterministic randomness for tests. g_connman = std::make_unique(config, 0x1337, 0x1337); } @@ -126,6 +128,7 @@ GetMainSignals().FlushBackgroundCallbacks(); GetMainSignals().UnregisterBackgroundSignalScheduler(); g_connman.reset(); + g_banman.reset(); UnloadBlockIndex(); pcoinsTip.reset(); pcoinsdbview.reset(); diff --git a/src/test/test_bitcoin_main.cpp b/src/test/test_bitcoin_main.cpp --- a/src/test/test_bitcoin_main.cpp +++ b/src/test/test_bitcoin_main.cpp @@ -9,6 +9,7 @@ #include std::unique_ptr g_connman; +std::unique_ptr g_banman; [[noreturn]] void Shutdown(void *parg) { std::exit(EXIT_SUCCESS);