|
|
@ -153,17 +153,66 @@ void SyncWithWallets(const uint256 &hash, const CTransaction &tx, const CBlock * |
|
|
|
// Registration of network node signals.
|
|
|
|
// 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); |
|
|
|
LOCK(cs_main); |
|
|
|
return chainActive.Height(); |
|
|
|
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) |
|
|
|
void RegisterNodeSignals(CNodeSignals& nodeSignals) |
|
|
|
{ |
|
|
|
{ |
|
|
|
nodeSignals.GetHeight.connect(&GetHeight); |
|
|
|
nodeSignals.GetHeight.connect(&GetHeight); |
|
|
|
nodeSignals.ProcessMessages.connect(&ProcessMessages); |
|
|
|
nodeSignals.ProcessMessages.connect(&ProcessMessages); |
|
|
|
nodeSignals.SendMessages.connect(&SendMessages); |
|
|
|
nodeSignals.SendMessages.connect(&SendMessages); |
|
|
|
|
|
|
|
nodeSignals.InitializeNode.connect(&InitializeNode); |
|
|
|
|
|
|
|
nodeSignals.FinalizeNode.connect(&FinalizeNode); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void UnregisterNodeSignals(CNodeSignals& nodeSignals) |
|
|
|
void UnregisterNodeSignals(CNodeSignals& nodeSignals) |
|
|
@ -171,6 +220,8 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals) |
|
|
|
nodeSignals.GetHeight.disconnect(&GetHeight); |
|
|
|
nodeSignals.GetHeight.disconnect(&GetHeight); |
|
|
|
nodeSignals.ProcessMessages.disconnect(&ProcessMessages); |
|
|
|
nodeSignals.ProcessMessages.disconnect(&ProcessMessages); |
|
|
|
nodeSignals.SendMessages.disconnect(&SendMessages); |
|
|
|
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) |
|
|
|
void static ProcessGetData(CNode* pfrom) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -3048,7 +3116,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) |
|
|
|
if (pfrom->nVersion != 0) |
|
|
|
if (pfrom->nVersion != 0) |
|
|
|
{ |
|
|
|
{ |
|
|
|
pfrom->PushMessage("reject", strCommand, REJECT_DUPLICATE, string("Duplicate version message")); |
|
|
|
pfrom->PushMessage("reject", strCommand, REJECT_DUPLICATE, string("Duplicate version message")); |
|
|
|
pfrom->Misbehaving(1); |
|
|
|
Misbehaving(pfrom->GetId(), 1); |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -3153,7 +3221,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) |
|
|
|
else if (pfrom->nVersion == 0) |
|
|
|
else if (pfrom->nVersion == 0) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// Must have a version message before anything else
|
|
|
|
// Must have a version message before anything else
|
|
|
|
pfrom->Misbehaving(1); |
|
|
|
Misbehaving(pfrom->GetId(), 1); |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -3174,7 +3242,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
if (vAddr.size() > 1000) |
|
|
|
if (vAddr.size() > 1000) |
|
|
|
{ |
|
|
|
{ |
|
|
|
pfrom->Misbehaving(20); |
|
|
|
Misbehaving(pfrom->GetId(), 20); |
|
|
|
return error("message addr size() = %"PRIszu"", vAddr.size()); |
|
|
|
return error("message addr size() = %"PRIszu"", vAddr.size()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -3237,7 +3305,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) |
|
|
|
vRecv >> vInv; |
|
|
|
vRecv >> vInv; |
|
|
|
if (vInv.size() > MAX_INV_SZ) |
|
|
|
if (vInv.size() > MAX_INV_SZ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
pfrom->Misbehaving(20); |
|
|
|
Misbehaving(pfrom->GetId(), 20); |
|
|
|
return error("message inv size() = %"PRIszu"", vInv.size()); |
|
|
|
return error("message inv size() = %"PRIszu"", vInv.size()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -3288,7 +3356,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) |
|
|
|
vRecv >> vInv; |
|
|
|
vRecv >> vInv; |
|
|
|
if (vInv.size() > MAX_INV_SZ) |
|
|
|
if (vInv.size() > MAX_INV_SZ) |
|
|
|
{ |
|
|
|
{ |
|
|
|
pfrom->Misbehaving(20); |
|
|
|
Misbehaving(pfrom->GetId(), 20); |
|
|
|
return error("message getdata size() = %"PRIszu"", vInv.size()); |
|
|
|
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(), |
|
|
|
pfrom->PushMessage("reject", strCommand, state.GetRejectCode(), |
|
|
|
state.GetRejectReason(), inv.hash); |
|
|
|
state.GetRejectReason(), inv.hash); |
|
|
|
if (nDoS > 0) |
|
|
|
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(), |
|
|
|
pfrom->PushMessage("reject", strCommand, state.GetRejectCode(), |
|
|
|
state.GetRejectReason(), inv.hash); |
|
|
|
state.GetRejectReason(), inv.hash); |
|
|
|
if (nDoS > 0) |
|
|
|
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
|
|
|
|
// This isn't a Misbehaving(100) (immediate ban) because the
|
|
|
|
// peer might be an older or different implementation with
|
|
|
|
// peer might be an older or different implementation with
|
|
|
|
// a different signature key, etc.
|
|
|
|
// 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()) |
|
|
|
if (!filter.IsWithinSizeConstraints()) |
|
|
|
// There is no excuse for sending a too-large filter
|
|
|
|
// There is no excuse for sending a too-large filter
|
|
|
|
pfrom->Misbehaving(100); |
|
|
|
Misbehaving(pfrom->GetId(), 100); |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
LOCK(pfrom->cs_filter); |
|
|
|
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
|
|
|
|
// and thus, the maximum size any matched object can have) in a filteradd message
|
|
|
|
if (vData.size() > MAX_SCRIPT_ELEMENT_SIZE) |
|
|
|
if (vData.size() > MAX_SCRIPT_ELEMENT_SIZE) |
|
|
|
{ |
|
|
|
{ |
|
|
|
pfrom->Misbehaving(100); |
|
|
|
Misbehaving(pfrom->GetId(), 100); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
LOCK(pfrom->cs_filter); |
|
|
|
LOCK(pfrom->cs_filter); |
|
|
|
if (pfrom->pfilter) |
|
|
|
if (pfrom->pfilter) |
|
|
|
pfrom->pfilter->insert(vData); |
|
|
|
pfrom->pfilter->insert(vData); |
|
|
|
else |
|
|
|
else |
|
|
|
pfrom->Misbehaving(100); |
|
|
|
Misbehaving(pfrom->GetId(), 100); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -3936,6 +4004,16 @@ bool SendMessages(CNode* pto, bool fSendTrickle) |
|
|
|
if (!lockMain) |
|
|
|
if (!lockMain) |
|
|
|
return true; |
|
|
|
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
|
|
|
|
// Start block sync
|
|
|
|
if (pto->fStartSync && !fImporting && !fReindex) { |
|
|
|
if (pto->fStartSync && !fImporting && !fReindex) { |
|
|
|
pto->fStartSync = false; |
|
|
|
pto->fStartSync = false; |
|
|
|