Skip to content

Commit

Permalink
Merge #19791: [net processing] Move Misbehaving() to PeerManager
Browse files Browse the repository at this point in the history
9156849 [net processing] Move Misbehaving() to PeerManager (John Newbery)
2583e43 [net_processing] Move SendBlockTransactions into PeerManager (John Newbery)
5d713c4 [net processing] Move MaybePunishPeerForTx to PeerManager (John Newbery)
794321a [net processing] Move ProcessOrphanTx to PeerManager (John Newbery)
cdb1541 [net processing] Move MaybePunishNodeForBlock into PeerManager (John Newbery)
d2d3682 [net processing] Move ProcessHeadersMessage to PeerManager (John Newbery)
2459556 [whitespace] tidy up indentation after scripted diff (John Newbery)
68bf31d scripted-diff: [net processing] Rename PeerLogicValidation to PeerManager (John Newbery)
3be3c35 [net_processing] Pass chainparams to PeerLogicValidation constructor (John Newbery)
8651262 [move only] Collect all private members of PeerLogicValidation together (John Newbery)

Pull request description:

  Continues the work of moving net_processing logic into PeerLogicValidation. See bitcoin/bitcoin#19704 and bitcoin/bitcoin#19607 (comment) for motivation.

  This PR also renames `PeerLogicValidation` to `PeerManager` as suggested in bitcoin/bitcoin#10756 (review).

ACKs for top commit:
  MarcoFalke:
    re-ACK 9156849 only change is rebase due to conflict in struct NodeContext and variable rename 🤸
  hebasto:
    re-ACK 9156849, only rebased, and added renaming `s/peer_logic/peerman/` into scripted-diff since my [previous](bitcoin/bitcoin#19791 (review)) review (verified with `git range-diff`).

Tree-SHA512: a2de4a521688fd25125b401e5575402c52b328a0fa27b3010567008d4f596b960aabbd02b2d81f42658f88f4365443fadb1008150a62fbcea123fb42d85a2c21
  • Loading branch information
MarcoFalke committed Sep 7, 2020
2 parents 3dd7add + 9156849 commit 4bb0ddb
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 123 deletions.
10 changes: 5 additions & 5 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ void Shutdown(NodeContext& node)

// Because these depend on each-other, we make sure that neither can be
// using the other before destroying them.
if (node.peer_logic) UnregisterValidationInterface(node.peer_logic.get());
if (node.peerman) UnregisterValidationInterface(node.peerman.get());
// Follow the lock order requirements:
// * CheckForStaleTipAndEvictPeers locks cs_main before indirectly calling GetExtraOutboundCount
// which locks cs_vNodes.
Expand All @@ -227,7 +227,7 @@ void Shutdown(NodeContext& node)

// After the threads that potentially access these pointers have been stopped,
// destruct and reset all to nullptr.
node.peer_logic.reset();
node.peerman.reset();
node.connman.reset();
node.banman.reset();

Expand Down Expand Up @@ -1376,8 +1376,8 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
node.chainman = &g_chainman;
ChainstateManager& chainman = *Assert(node.chainman);

node.peer_logic.reset(new PeerLogicValidation(*node.connman, node.banman.get(), *node.scheduler, chainman, *node.mempool));
RegisterValidationInterface(node.peer_logic.get());
node.peerman.reset(new PeerManager(chainparams, *node.connman, node.banman.get(), *node.scheduler, chainman, *node.mempool));
RegisterValidationInterface(node.peerman.get());

// sanitize comments per BIP-0014, format user agent and check total size
std::vector<std::string> uacomments;
Expand Down Expand Up @@ -1911,7 +1911,7 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
connOptions.nBestHeight = chain_active_height;
connOptions.uiInterface = &uiInterface;
connOptions.m_banman = node.banman.get();
connOptions.m_msgproc = node.peer_logic.get();
connOptions.m_msgproc = node.peerman.get();
connOptions.nSendBufferMaxSize = 1000 * args.GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER);
connOptions.nReceiveFloodSize = 1000 * args.GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER);
connOptions.m_added_nodes = args.GetArgs("-addnode");
Expand Down
148 changes: 64 additions & 84 deletions src/net_processing.cpp

Large diffs are not rendered by default.

70 changes: 56 additions & 14 deletions src/net_processing.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@
#include <sync.h>
#include <validationinterface.h>

class BlockTransactionsRequest;
class BlockValidationState;
class CBlockHeader;
class CChainParams;
class CTxMemPool;
class ChainstateManager;
class TxValidationState;

extern RecursiveMutex cs_main;
extern RecursiveMutex g_cs_orphans;
Expand All @@ -27,18 +31,10 @@ static const bool DEFAULT_PEERBLOCKFILTERS = false;
/** Threshold for marking a node to be discouraged, e.g. disconnected and added to the discouragement filter. */
static const int DISCOURAGEMENT_THRESHOLD{100};

class PeerLogicValidation final : public CValidationInterface, public NetEventsInterface {
private:
CConnman& m_connman;
/** Pointer to this node's banman. May be nullptr - check existence before dereferencing. */
BanMan* const m_banman;
ChainstateManager& m_chainman;
CTxMemPool& m_mempool;

bool MaybeDiscourageAndDisconnect(CNode& pnode);

class PeerManager final : public CValidationInterface, public NetEventsInterface {
public:
PeerLogicValidation(CConnman& connman, BanMan* banman, CScheduler& scheduler, ChainstateManager& chainman, CTxMemPool& pool);
PeerManager(const CChainParams& chainparams, CConnman& connman, BanMan* banman,
CScheduler& scheduler, ChainstateManager& chainman, CTxMemPool& pool);

/**
* Overridden from CValidationInterface.
Expand Down Expand Up @@ -88,12 +84,58 @@ class PeerLogicValidation final : public CValidationInterface, public NetEventsI

/** Process a single message from a peer. Public for fuzz testing */
void ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv,
const std::chrono::microseconds time_received, const CChainParams& chainparams,
const std::atomic<bool>& interruptMsgProc);
const std::chrono::microseconds time_received, const std::atomic<bool>& interruptMsgProc);

/**
* Increment peer's misbehavior score. If the new value >= DISCOURAGEMENT_THRESHOLD, mark the node
* to be discouraged, meaning the peer might be disconnected and added to the discouragement filter.
* Public for unit testing.
*/
void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message);

private:
int64_t m_stale_tip_check_time; //!< Next time to check for stale tip
/**
* Potentially mark a node discouraged based on the contents of a BlockValidationState object
*
* @param[in] via_compact_block this bool is passed in because net_processing should
* punish peers differently depending on whether the data was provided in a compact
* block message or not. If the compact block had a valid header, but contained invalid
* txs, the peer should not be punished. See BIP 152.
*
* @return Returns true if the peer was punished (probably disconnected)
*/
bool MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& state,
bool via_compact_block, const std::string& message = "");

/**
* Potentially disconnect and discourage a node based on the contents of a TxValidationState object
*
* @return Returns true if the peer was punished (probably disconnected)
*/
bool MaybePunishNodeForTx(NodeId nodeid, const TxValidationState& state, const std::string& message = "");

/** Maybe disconnect a peer and discourage future connections from its address.
*
* @param[in] pnode The node to check.
* @return True if the peer was marked for disconnection in this function
*/
bool MaybeDiscourageAndDisconnect(CNode& pnode);

void ProcessOrphanTx(std::set<uint256>& orphan_work_set, std::list<CTransactionRef>& removed_txn)
EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_cs_orphans);
/** Process a single headers message from a peer. */
void ProcessHeadersMessage(CNode& pfrom, const std::vector<CBlockHeader>& headers, bool via_compact_block);

void SendBlockTransactions(CNode& pfrom, const CBlock& block, const BlockTransactionsRequest& req);

const CChainParams& m_chainparams;
CConnman& m_connman;
/** Pointer to this node's banman. May be nullptr - check existence before dereferencing. */
BanMan* const m_banman;
ChainstateManager& m_chainman;
CTxMemPool& m_mempool;

int64_t m_stale_tip_check_time; //!< Next time to check for stale tip
};

struct CNodeStateStats {
Expand Down
4 changes: 2 additions & 2 deletions src/node/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class CConnman;
class CScheduler;
class CTxMemPool;
class ChainstateManager;
class PeerLogicValidation;
class PeerManager;
namespace interfaces {
class Chain;
class ChainClient;
Expand All @@ -36,7 +36,7 @@ class WalletClient;
struct NodeContext {
std::unique_ptr<CConnman> connman;
std::unique_ptr<CTxMemPool> mempool;
std::unique_ptr<PeerLogicValidation> peer_logic;
std::unique_ptr<PeerManager> peerman;
ChainstateManager* chainman{nullptr}; // Currently a raw pointer because the memory is not managed by this struct
std::unique_ptr<BanMan> banman;
ArgsManager* args{nullptr}; // Currently a raw pointer because the memory is not managed by this struct
Expand Down
23 changes: 13 additions & 10 deletions src/test/denialofservice_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ struct CConnmanTest : public CConnman {
extern bool AddOrphanTx(const CTransactionRef& tx, NodeId peer);
extern void EraseOrphansFor(NodeId peer);
extern unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans);
extern void Misbehaving(NodeId nodeid, int howmuch, const std::string& message="");

struct COrphanTx {
CTransactionRef tx;
Expand Down Expand Up @@ -79,8 +78,9 @@ BOOST_FIXTURE_TEST_SUITE(denialofservice_tests, TestingSetup)
// work.
BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
{
const CChainParams& chainparams = Params();
auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
auto peerLogic = MakeUnique<PeerLogicValidation>(*connman, nullptr, *m_node.scheduler, *m_node.chainman, *m_node.mempool);
auto peerLogic = MakeUnique<PeerManager>(chainparams, *connman, nullptr, *m_node.scheduler, *m_node.chainman, *m_node.mempool);

// Mock an outbound peer
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
Expand Down Expand Up @@ -133,7 +133,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
peerLogic->FinalizeNode(dummyNode1.GetId(), dummy);
}

static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerLogicValidation &peerLogic, CConnmanTest* connman)
static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerManager &peerLogic, CConnmanTest* connman)
{
CAddress addr(ip(g_insecure_rand_ctx.randbits(32)), NODE_NONE);
vNodes.emplace_back(new CNode(id++, ServiceFlags(NODE_NETWORK | NODE_WITNESS), 0, INVALID_SOCKET, addr, 0, 0, CAddress(), "", ConnectionType::OUTBOUND_FULL_RELAY));
Expand All @@ -149,8 +149,9 @@ static void AddRandomOutboundPeer(std::vector<CNode *> &vNodes, PeerLogicValidat

BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
{
const CChainParams& chainparams = Params();
auto connman = MakeUnique<CConnmanTest>(0x1337, 0x1337);
auto peerLogic = MakeUnique<PeerLogicValidation>(*connman, nullptr, *m_node.scheduler, *m_node.chainman, *m_node.mempool);
auto peerLogic = MakeUnique<PeerManager>(chainparams, *connman, nullptr, *m_node.scheduler, *m_node.chainman, *m_node.mempool);

const Consensus::Params& consensusParams = Params().GetConsensus();
constexpr int max_outbound_full_relay = MAX_OUTBOUND_FULL_RELAY_CONNECTIONS;
Expand Down Expand Up @@ -221,9 +222,10 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)

BOOST_AUTO_TEST_CASE(peer_discouragement)
{
const CChainParams& chainparams = Params();
auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
auto peerLogic = MakeUnique<PeerLogicValidation>(*connman, banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool);
auto peerLogic = MakeUnique<PeerManager>(chainparams, *connman, banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool);

banman->ClearBanned();
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
Expand All @@ -232,7 +234,7 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
peerLogic->InitializeNode(&dummyNode1);
dummyNode1.nVersion = 1;
dummyNode1.fSuccessfullyConnected = true;
Misbehaving(dummyNode1.GetId(), DISCOURAGEMENT_THRESHOLD); // Should be discouraged
peerLogic->Misbehaving(dummyNode1.GetId(), DISCOURAGEMENT_THRESHOLD, /* message */ ""); // Should be discouraged
{
LOCK(dummyNode1.cs_sendProcessing);
BOOST_CHECK(peerLogic->SendMessages(&dummyNode1));
Expand All @@ -246,14 +248,14 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
peerLogic->InitializeNode(&dummyNode2);
dummyNode2.nVersion = 1;
dummyNode2.fSuccessfullyConnected = true;
Misbehaving(dummyNode2.GetId(), DISCOURAGEMENT_THRESHOLD - 1);
peerLogic->Misbehaving(dummyNode2.GetId(), DISCOURAGEMENT_THRESHOLD - 1, /* message */ "");
{
LOCK(dummyNode2.cs_sendProcessing);
BOOST_CHECK(peerLogic->SendMessages(&dummyNode2));
}
BOOST_CHECK(!banman->IsDiscouraged(addr2)); // 2 not discouraged yet...
BOOST_CHECK(banman->IsDiscouraged(addr1)); // ... but 1 still should be
Misbehaving(dummyNode2.GetId(), 1); // 2 reaches discouragement threshold
peerLogic->Misbehaving(dummyNode2.GetId(), 1, /* message */ ""); // 2 reaches discouragement threshold
{
LOCK(dummyNode2.cs_sendProcessing);
BOOST_CHECK(peerLogic->SendMessages(&dummyNode2));
Expand All @@ -268,9 +270,10 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)

BOOST_AUTO_TEST_CASE(DoS_bantime)
{
const CChainParams& chainparams = Params();
auto banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
auto connman = MakeUnique<CConnman>(0x1337, 0x1337);
auto peerLogic = MakeUnique<PeerLogicValidation>(*connman, banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool);
auto peerLogic = MakeUnique<PeerManager>(chainparams, *connman, banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool);

banman->ClearBanned();
int64_t nStartTime = GetTime();
Expand All @@ -283,7 +286,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
dummyNode.nVersion = 1;
dummyNode.fSuccessfullyConnected = true;

Misbehaving(dummyNode.GetId(), DISCOURAGEMENT_THRESHOLD);
peerLogic->Misbehaving(dummyNode.GetId(), DISCOURAGEMENT_THRESHOLD, /* message */ "");
{
LOCK(dummyNode.cs_sendProcessing);
BOOST_CHECK(peerLogic->SendMessages(&dummyNode));
Expand Down
7 changes: 3 additions & 4 deletions src/test/fuzz/process_message.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,10 @@ void test_one_input(const std::vector<uint8_t>& buffer)
p2p_node.nVersion = PROTOCOL_VERSION;
p2p_node.SetSendVersion(PROTOCOL_VERSION);
connman.AddTestNode(p2p_node);
g_setup->m_node.peer_logic->InitializeNode(&p2p_node);
g_setup->m_node.peerman->InitializeNode(&p2p_node);
try {
g_setup->m_node.peer_logic->ProcessMessage(p2p_node, random_message_type, random_bytes_data_stream,
GetTime<std::chrono::microseconds>(), Params(),
std::atomic<bool>{false});
g_setup->m_node.peerman->ProcessMessage(p2p_node, random_message_type, random_bytes_data_stream,
GetTime<std::chrono::microseconds>(), std::atomic<bool>{false});
} catch (const std::ios_base::failure&) {
}
SyncWithValidationInterfaceQueue();
Expand Down
2 changes: 1 addition & 1 deletion src/test/fuzz/process_messages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
p2p_node.fPauseSend = false;
p2p_node.nVersion = PROTOCOL_VERSION;
p2p_node.SetSendVersion(PROTOCOL_VERSION);
g_setup->m_node.peer_logic->InitializeNode(&p2p_node);
g_setup->m_node.peerman->InitializeNode(&p2p_node);

connman.AddTestNode(p2p_node);
}
Expand Down
4 changes: 2 additions & 2 deletions src/test/util/setup_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,10 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const

m_node.banman = MakeUnique<BanMan>(GetDataDir() / "banlist.dat", nullptr, DEFAULT_MISBEHAVING_BANTIME);
m_node.connman = MakeUnique<CConnman>(0x1337, 0x1337); // Deterministic randomness for tests.
m_node.peer_logic = MakeUnique<PeerLogicValidation>(*m_node.connman, m_node.banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool);
m_node.peerman = MakeUnique<PeerManager>(chainparams, *m_node.connman, m_node.banman.get(), *m_node.scheduler, *m_node.chainman, *m_node.mempool);
{
CConnman::Options options;
options.m_msgproc = m_node.peer_logic.get();
options.m_msgproc = m_node.peerman.get();
m_node.connman->Init(options);
}
}
Expand Down
2 changes: 1 addition & 1 deletion test/sanitizer_suppressions/tsan
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ mutex:CConnman::ThreadOpenConnections
mutex:CConnman::ThreadOpenAddedConnections
mutex:CConnman::SocketHandler
mutex:UpdateTip
mutex:PeerLogicValidation::UpdatedBlockTip
mutex:PeerManager::UpdatedBlockTip
mutex:g_best_block_mutex
# race (TODO fix)
race:CConnman::WakeMessageHandler
Expand Down

0 comments on commit 4bb0ddb

Please sign in to comment.