mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-19 06:43:45 +01:00
Add main-specific node state
This commit is contained in:
102
src/main.cpp
102
src/main.cpp
@@ -153,17 +153,66 @@ void SyncWithWallets(const uint256 &hash, const CTransaction &tx, const CBlock *
|
||||
// Registration of network node signals.
|
||||
//
|
||||
|
||||
int static GetHeight()
|
||||
namespace {
|
||||
// Maintain validation-specific state about nodes, protected by cs_main, instead
|
||||
// by CNode's own locks. This simplifies asynchronous operation, where
|
||||
// processing of incoming data is done after the ProcessMessage call returns,
|
||||
// and we're no longer holding the node's locks.
|
||||
struct CNodeState {
|
||||
int nMisbehavior;
|
||||
bool fShouldBan;
|
||||
std::string name;
|
||||
|
||||
CNodeState() {
|
||||
nMisbehavior = 0;
|
||||
fShouldBan = false;
|
||||
}
|
||||
};
|
||||
|
||||
map<NodeId, CNodeState> mapNodeState;
|
||||
|
||||
// Requires cs_main.
|
||||
CNodeState *State(NodeId pnode) {
|
||||
map<NodeId, CNodeState>::iterator it = mapNodeState.find(pnode);
|
||||
if (it == mapNodeState.end())
|
||||
return NULL;
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
int GetHeight()
|
||||
{
|
||||
LOCK(cs_main);
|
||||
return chainActive.Height();
|
||||
}
|
||||
|
||||
void InitializeNode(NodeId nodeid, const CNode *pnode) {
|
||||
LOCK(cs_main);
|
||||
CNodeState &state = mapNodeState.insert(std::make_pair(nodeid, CNodeState())).first->second;
|
||||
state.name = pnode->addrName;
|
||||
}
|
||||
|
||||
void FinalizeNode(NodeId nodeid) {
|
||||
LOCK(cs_main);
|
||||
mapNodeState.erase(nodeid);
|
||||
}
|
||||
}
|
||||
|
||||
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) {
|
||||
LOCK(cs_main);
|
||||
CNodeState *state = State(nodeid);
|
||||
if (state == NULL)
|
||||
return false;
|
||||
stats.nMisbehavior = state->nMisbehavior;
|
||||
return true;
|
||||
}
|
||||
|
||||
void RegisterNodeSignals(CNodeSignals& nodeSignals)
|
||||
{
|
||||
nodeSignals.GetHeight.connect(&GetHeight);
|
||||
nodeSignals.ProcessMessages.connect(&ProcessMessages);
|
||||
nodeSignals.SendMessages.connect(&SendMessages);
|
||||
nodeSignals.InitializeNode.connect(&InitializeNode);
|
||||
nodeSignals.FinalizeNode.connect(&FinalizeNode);
|
||||
}
|
||||
|
||||
void UnregisterNodeSignals(CNodeSignals& nodeSignals)
|
||||
@@ -171,6 +220,8 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals)
|
||||
nodeSignals.GetHeight.disconnect(&GetHeight);
|
||||
nodeSignals.ProcessMessages.disconnect(&ProcessMessages);
|
||||
nodeSignals.SendMessages.disconnect(&SendMessages);
|
||||
nodeSignals.InitializeNode.disconnect(&InitializeNode);
|
||||
nodeSignals.FinalizeNode.disconnect(&FinalizeNode);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -2915,6 +2966,23 @@ bool static AlreadyHave(const CInv& inv)
|
||||
}
|
||||
|
||||
|
||||
void Misbehaving(NodeId pnode, int howmuch)
|
||||
{
|
||||
if (howmuch == 0)
|
||||
return;
|
||||
|
||||
CNodeState *state = State(pnode);
|
||||
if (state == NULL)
|
||||
return;
|
||||
|
||||
state->nMisbehavior += howmuch;
|
||||
if (state->nMisbehavior >= GetArg("-banscore", 100))
|
||||
{
|
||||
LogPrintf("Misbehaving: %s (%d -> %d) BAN THRESHOLD EXCEEDED\n", state->name.c_str(), state->nMisbehavior-howmuch, state->nMisbehavior);
|
||||
state->fShouldBan = true;
|
||||
} else
|
||||
LogPrintf("Misbehaving: %s (%d -> %d)\n", state->name.c_str(), state->nMisbehavior-howmuch, state->nMisbehavior);
|
||||
}
|
||||
|
||||
void static ProcessGetData(CNode* pfrom)
|
||||
{
|
||||
@@ -3048,7 +3116,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
if (pfrom->nVersion != 0)
|
||||
{
|
||||
pfrom->PushMessage("reject", strCommand, REJECT_DUPLICATE, string("Duplicate version message"));
|
||||
pfrom->Misbehaving(1);
|
||||
Misbehaving(pfrom->GetId(), 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3153,7 +3221,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
else if (pfrom->nVersion == 0)
|
||||
{
|
||||
// Must have a version message before anything else
|
||||
pfrom->Misbehaving(1);
|
||||
Misbehaving(pfrom->GetId(), 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3174,7 +3242,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
return true;
|
||||
if (vAddr.size() > 1000)
|
||||
{
|
||||
pfrom->Misbehaving(20);
|
||||
Misbehaving(pfrom->GetId(), 20);
|
||||
return error("message addr size() = %"PRIszu"", vAddr.size());
|
||||
}
|
||||
|
||||
@@ -3237,7 +3305,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
vRecv >> vInv;
|
||||
if (vInv.size() > MAX_INV_SZ)
|
||||
{
|
||||
pfrom->Misbehaving(20);
|
||||
Misbehaving(pfrom->GetId(), 20);
|
||||
return error("message inv size() = %"PRIszu"", vInv.size());
|
||||
}
|
||||
|
||||
@@ -3288,7 +3356,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
vRecv >> vInv;
|
||||
if (vInv.size() > MAX_INV_SZ)
|
||||
{
|
||||
pfrom->Misbehaving(20);
|
||||
Misbehaving(pfrom->GetId(), 20);
|
||||
return error("message getdata size() = %"PRIszu"", vInv.size());
|
||||
}
|
||||
|
||||
@@ -3461,7 +3529,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
pfrom->PushMessage("reject", strCommand, state.GetRejectCode(),
|
||||
state.GetRejectReason(), inv.hash);
|
||||
if (nDoS > 0)
|
||||
pfrom->Misbehaving(nDoS);
|
||||
Misbehaving(pfrom->GetId(), nDoS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3488,7 +3556,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
pfrom->PushMessage("reject", strCommand, state.GetRejectCode(),
|
||||
state.GetRejectReason(), inv.hash);
|
||||
if (nDoS > 0)
|
||||
pfrom->Misbehaving(nDoS);
|
||||
Misbehaving(pfrom->GetId(), nDoS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3631,7 +3699,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
// This isn't a Misbehaving(100) (immediate ban) because the
|
||||
// peer might be an older or different implementation with
|
||||
// a different signature key, etc.
|
||||
pfrom->Misbehaving(10);
|
||||
Misbehaving(pfrom->GetId(), 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3644,7 +3712,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
|
||||
if (!filter.IsWithinSizeConstraints())
|
||||
// There is no excuse for sending a too-large filter
|
||||
pfrom->Misbehaving(100);
|
||||
Misbehaving(pfrom->GetId(), 100);
|
||||
else
|
||||
{
|
||||
LOCK(pfrom->cs_filter);
|
||||
@@ -3665,13 +3733,13 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
// and thus, the maximum size any matched object can have) in a filteradd message
|
||||
if (vData.size() > MAX_SCRIPT_ELEMENT_SIZE)
|
||||
{
|
||||
pfrom->Misbehaving(100);
|
||||
Misbehaving(pfrom->GetId(), 100);
|
||||
} else {
|
||||
LOCK(pfrom->cs_filter);
|
||||
if (pfrom->pfilter)
|
||||
pfrom->pfilter->insert(vData);
|
||||
else
|
||||
pfrom->Misbehaving(100);
|
||||
Misbehaving(pfrom->GetId(), 100);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3936,6 +4004,16 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
||||
if (!lockMain)
|
||||
return true;
|
||||
|
||||
if (State(pto->GetId())->fShouldBan) {
|
||||
if (pto->addr.IsLocal())
|
||||
LogPrintf("Warning: not banning local node %s!\n", pto->addr.ToString().c_str());
|
||||
else {
|
||||
pto->fDisconnect = true;
|
||||
CNode::Ban(pto->addr);
|
||||
}
|
||||
State(pto->GetId())->fShouldBan = false;
|
||||
}
|
||||
|
||||
// Start block sync
|
||||
if (pto->fStartSync && !fImporting && !fReindex) {
|
||||
pto->fStartSync = false;
|
||||
|
||||
Reference in New Issue
Block a user