@@ -153,24 +153,75 @@ void SyncWithWallets(const uint256 &hash, const CTransaction &tx, const CBlock *
153153// Registration of network node signals.
154154//
155155
156- int static GetHeight ()
156+ namespace {
157+ // Maintain validation-specific state about nodes, protected by cs_main, instead
158+ // by CNode's own locks. This simplifies asynchronous operation, where
159+ // processing of incoming data is done after the ProcessMessage call returns,
160+ // and we're no longer holding the node's locks.
161+ struct CNodeState {
162+ int nMisbehavior;
163+ bool fShouldBan ;
164+ std::string name;
165+
166+ CNodeState () {
167+ nMisbehavior = 0 ;
168+ fShouldBan = false ;
169+ }
170+ };
171+
172+ map<NodeId, CNodeState> mapNodeState;
173+
174+ // Requires cs_main.
175+ CNodeState *State (NodeId pnode) {
176+ map<NodeId, CNodeState>::iterator it = mapNodeState.find (pnode);
177+ if (it == mapNodeState.end ())
178+ return NULL ;
179+ return &it->second ;
180+ }
181+
182+ int GetHeight ()
157183{
158184 LOCK (cs_main);
159185 return chainActive.Height ();
160186}
161187
188+ void InitializeNode (NodeId nodeid, const CNode *pnode) {
189+ LOCK (cs_main);
190+ CNodeState &state = mapNodeState.insert (std::make_pair (nodeid, CNodeState ())).first ->second ;
191+ state.name = pnode->addrName ;
192+ }
193+
194+ void FinalizeNode (NodeId nodeid) {
195+ LOCK (cs_main);
196+ mapNodeState.erase (nodeid);
197+ }
198+ }
199+
200+ bool GetNodeStateStats (NodeId nodeid, CNodeStateStats &stats) {
201+ LOCK (cs_main);
202+ CNodeState *state = State (nodeid);
203+ if (state == NULL )
204+ return false ;
205+ stats.nMisbehavior = state->nMisbehavior ;
206+ return true ;
207+ }
208+
162209void RegisterNodeSignals (CNodeSignals& nodeSignals)
163210{
164211 nodeSignals.GetHeight .connect (&GetHeight);
165212 nodeSignals.ProcessMessages .connect (&ProcessMessages);
166213 nodeSignals.SendMessages .connect (&SendMessages);
214+ nodeSignals.InitializeNode .connect (&InitializeNode);
215+ nodeSignals.FinalizeNode .connect (&FinalizeNode);
167216}
168217
169218void UnregisterNodeSignals (CNodeSignals& nodeSignals)
170219{
171220 nodeSignals.GetHeight .disconnect (&GetHeight);
172221 nodeSignals.ProcessMessages .disconnect (&ProcessMessages);
173222 nodeSignals.SendMessages .disconnect (&SendMessages);
223+ nodeSignals.InitializeNode .disconnect (&InitializeNode);
224+ nodeSignals.FinalizeNode .disconnect (&FinalizeNode);
174225}
175226
176227// ////////////////////////////////////////////////////////////////////////////
@@ -2915,6 +2966,23 @@ bool static AlreadyHave(const CInv& inv)
29152966}
29162967
29172968
2969+ void Misbehaving (NodeId pnode, int howmuch)
2970+ {
2971+ if (howmuch == 0 )
2972+ return ;
2973+
2974+ CNodeState *state = State (pnode);
2975+ if (state == NULL )
2976+ return ;
2977+
2978+ state->nMisbehavior += howmuch;
2979+ if (state->nMisbehavior >= GetArg (" -banscore" , 100 ))
2980+ {
2981+ LogPrintf (" Misbehaving: %s (%d -> %d) BAN THRESHOLD EXCEEDED\n " , state->name .c_str (), state->nMisbehavior -howmuch, state->nMisbehavior );
2982+ state->fShouldBan = true ;
2983+ } else
2984+ LogPrintf (" Misbehaving: %s (%d -> %d)\n " , state->name .c_str (), state->nMisbehavior -howmuch, state->nMisbehavior );
2985+ }
29182986
29192987void static ProcessGetData (CNode* pfrom)
29202988{
@@ -3048,7 +3116,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
30483116 if (pfrom->nVersion != 0 )
30493117 {
30503118 pfrom->PushMessage (" reject" , strCommand, REJECT_DUPLICATE, string (" Duplicate version message" ));
3051- pfrom->Misbehaving ( 1 );
3119+ Misbehaving ( pfrom->GetId (), 1 );
30523120 return false ;
30533121 }
30543122
@@ -3153,7 +3221,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
31533221 else if (pfrom->nVersion == 0 )
31543222 {
31553223 // Must have a version message before anything else
3156- pfrom->Misbehaving ( 1 );
3224+ Misbehaving ( pfrom->GetId (), 1 );
31573225 return false ;
31583226 }
31593227
@@ -3174,7 +3242,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
31743242 return true ;
31753243 if (vAddr.size () > 1000 )
31763244 {
3177- pfrom->Misbehaving ( 20 );
3245+ Misbehaving ( pfrom->GetId (), 20 );
31783246 return error (" message addr size() = %" PRIszu" " , vAddr.size ());
31793247 }
31803248
@@ -3237,7 +3305,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
32373305 vRecv >> vInv;
32383306 if (vInv.size () > MAX_INV_SZ)
32393307 {
3240- pfrom->Misbehaving ( 20 );
3308+ Misbehaving ( pfrom->GetId (), 20 );
32413309 return error (" message inv size() = %" PRIszu" " , vInv.size ());
32423310 }
32433311
@@ -3288,7 +3356,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
32883356 vRecv >> vInv;
32893357 if (vInv.size () > MAX_INV_SZ)
32903358 {
3291- pfrom->Misbehaving ( 20 );
3359+ Misbehaving ( pfrom->GetId (), 20 );
32923360 return error (" message getdata size() = %" PRIszu" " , vInv.size ());
32933361 }
32943362
@@ -3461,7 +3529,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
34613529 pfrom->PushMessage (" reject" , strCommand, state.GetRejectCode (),
34623530 state.GetRejectReason (), inv.hash );
34633531 if (nDoS > 0 )
3464- pfrom->Misbehaving ( nDoS);
3532+ Misbehaving ( pfrom->GetId (), nDoS);
34653533 }
34663534 }
34673535
@@ -3488,7 +3556,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
34883556 pfrom->PushMessage (" reject" , strCommand, state.GetRejectCode (),
34893557 state.GetRejectReason (), inv.hash );
34903558 if (nDoS > 0 )
3491- pfrom->Misbehaving ( nDoS);
3559+ Misbehaving ( pfrom->GetId (), nDoS);
34923560 }
34933561 }
34943562
@@ -3631,7 +3699,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
36313699 // This isn't a Misbehaving(100) (immediate ban) because the
36323700 // peer might be an older or different implementation with
36333701 // a different signature key, etc.
3634- pfrom->Misbehaving ( 10 );
3702+ Misbehaving ( pfrom->GetId (), 10 );
36353703 }
36363704 }
36373705 }
@@ -3644,7 +3712,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
36443712
36453713 if (!filter.IsWithinSizeConstraints ())
36463714 // There is no excuse for sending a too-large filter
3647- pfrom->Misbehaving ( 100 );
3715+ Misbehaving ( pfrom->GetId (), 100 );
36483716 else
36493717 {
36503718 LOCK (pfrom->cs_filter );
@@ -3665,13 +3733,13 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
36653733 // and thus, the maximum size any matched object can have) in a filteradd message
36663734 if (vData.size () > MAX_SCRIPT_ELEMENT_SIZE)
36673735 {
3668- pfrom->Misbehaving ( 100 );
3736+ Misbehaving ( pfrom->GetId (), 100 );
36693737 } else {
36703738 LOCK (pfrom->cs_filter );
36713739 if (pfrom->pfilter )
36723740 pfrom->pfilter ->insert (vData);
36733741 else
3674- pfrom->Misbehaving ( 100 );
3742+ Misbehaving ( pfrom->GetId (), 100 );
36753743 }
36763744 }
36773745
@@ -3936,6 +4004,16 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
39364004 if (!lockMain)
39374005 return true ;
39384006
4007+ if (State (pto->GetId ())->fShouldBan ) {
4008+ if (pto->addr .IsLocal ())
4009+ LogPrintf (" Warning: not banning local node %s!\n " , pto->addr .ToString ().c_str ());
4010+ else {
4011+ pto->fDisconnect = true ;
4012+ CNode::Ban (pto->addr );
4013+ }
4014+ State (pto->GetId ())->fShouldBan = false ;
4015+ }
4016+
39394017 // Start block sync
39404018 if (pto->fStartSync && !fImporting && !fReindex ) {
39414019 pto->fStartSync = false ;
0 commit comments