@@ -153,24 +153,75 @@ void SyncWithWallets(const uint256 &hash, const CTransaction &tx, const CBlock *
153
153
// Registration of network node signals.
154
154
//
155
155
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 ()
157
183
{
158
184
LOCK (cs_main);
159
185
return chainActive.Height ();
160
186
}
161
187
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
+
162
209
void RegisterNodeSignals (CNodeSignals& nodeSignals)
163
210
{
164
211
nodeSignals.GetHeight .connect (&GetHeight);
165
212
nodeSignals.ProcessMessages .connect (&ProcessMessages);
166
213
nodeSignals.SendMessages .connect (&SendMessages);
214
+ nodeSignals.InitializeNode .connect (&InitializeNode);
215
+ nodeSignals.FinalizeNode .connect (&FinalizeNode);
167
216
}
168
217
169
218
void UnregisterNodeSignals (CNodeSignals& nodeSignals)
170
219
{
171
220
nodeSignals.GetHeight .disconnect (&GetHeight);
172
221
nodeSignals.ProcessMessages .disconnect (&ProcessMessages);
173
222
nodeSignals.SendMessages .disconnect (&SendMessages);
223
+ nodeSignals.InitializeNode .disconnect (&InitializeNode);
224
+ nodeSignals.FinalizeNode .disconnect (&FinalizeNode);
174
225
}
175
226
176
227
// ////////////////////////////////////////////////////////////////////////////
@@ -2915,6 +2966,23 @@ bool static AlreadyHave(const CInv& inv)
2915
2966
}
2916
2967
2917
2968
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
+ }
2918
2986
2919
2987
void static ProcessGetData (CNode* pfrom)
2920
2988
{
@@ -3048,7 +3116,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
3048
3116
if (pfrom->nVersion != 0 )
3049
3117
{
3050
3118
pfrom->PushMessage (" reject" , strCommand, REJECT_DUPLICATE, string (" Duplicate version message" ));
3051
- pfrom->Misbehaving ( 1 );
3119
+ Misbehaving ( pfrom->GetId (), 1 );
3052
3120
return false ;
3053
3121
}
3054
3122
@@ -3153,7 +3221,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
3153
3221
else if (pfrom->nVersion == 0 )
3154
3222
{
3155
3223
// Must have a version message before anything else
3156
- pfrom->Misbehaving ( 1 );
3224
+ Misbehaving ( pfrom->GetId (), 1 );
3157
3225
return false ;
3158
3226
}
3159
3227
@@ -3174,7 +3242,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
3174
3242
return true ;
3175
3243
if (vAddr.size () > 1000 )
3176
3244
{
3177
- pfrom->Misbehaving ( 20 );
3245
+ Misbehaving ( pfrom->GetId (), 20 );
3178
3246
return error (" message addr size() = %" PRIszu" " , vAddr.size ());
3179
3247
}
3180
3248
@@ -3237,7 +3305,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
3237
3305
vRecv >> vInv;
3238
3306
if (vInv.size () > MAX_INV_SZ)
3239
3307
{
3240
- pfrom->Misbehaving ( 20 );
3308
+ Misbehaving ( pfrom->GetId (), 20 );
3241
3309
return error (" message inv size() = %" PRIszu" " , vInv.size ());
3242
3310
}
3243
3311
@@ -3288,7 +3356,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
3288
3356
vRecv >> vInv;
3289
3357
if (vInv.size () > MAX_INV_SZ)
3290
3358
{
3291
- pfrom->Misbehaving ( 20 );
3359
+ Misbehaving ( pfrom->GetId (), 20 );
3292
3360
return error (" message getdata size() = %" PRIszu" " , vInv.size ());
3293
3361
}
3294
3362
@@ -3461,7 +3529,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
3461
3529
pfrom->PushMessage (" reject" , strCommand, state.GetRejectCode (),
3462
3530
state.GetRejectReason (), inv.hash );
3463
3531
if (nDoS > 0 )
3464
- pfrom->Misbehaving ( nDoS);
3532
+ Misbehaving ( pfrom->GetId (), nDoS);
3465
3533
}
3466
3534
}
3467
3535
@@ -3488,7 +3556,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
3488
3556
pfrom->PushMessage (" reject" , strCommand, state.GetRejectCode (),
3489
3557
state.GetRejectReason (), inv.hash );
3490
3558
if (nDoS > 0 )
3491
- pfrom->Misbehaving ( nDoS);
3559
+ Misbehaving ( pfrom->GetId (), nDoS);
3492
3560
}
3493
3561
}
3494
3562
@@ -3631,7 +3699,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
3631
3699
// This isn't a Misbehaving(100) (immediate ban) because the
3632
3700
// peer might be an older or different implementation with
3633
3701
// a different signature key, etc.
3634
- pfrom->Misbehaving ( 10 );
3702
+ Misbehaving ( pfrom->GetId (), 10 );
3635
3703
}
3636
3704
}
3637
3705
}
@@ -3644,7 +3712,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
3644
3712
3645
3713
if (!filter.IsWithinSizeConstraints ())
3646
3714
// There is no excuse for sending a too-large filter
3647
- pfrom->Misbehaving ( 100 );
3715
+ Misbehaving ( pfrom->GetId (), 100 );
3648
3716
else
3649
3717
{
3650
3718
LOCK (pfrom->cs_filter );
@@ -3665,13 +3733,13 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
3665
3733
// and thus, the maximum size any matched object can have) in a filteradd message
3666
3734
if (vData.size () > MAX_SCRIPT_ELEMENT_SIZE)
3667
3735
{
3668
- pfrom->Misbehaving ( 100 );
3736
+ Misbehaving ( pfrom->GetId (), 100 );
3669
3737
} else {
3670
3738
LOCK (pfrom->cs_filter );
3671
3739
if (pfrom->pfilter )
3672
3740
pfrom->pfilter ->insert (vData);
3673
3741
else
3674
- pfrom->Misbehaving ( 100 );
3742
+ Misbehaving ( pfrom->GetId (), 100 );
3675
3743
}
3676
3744
}
3677
3745
@@ -3936,6 +4004,16 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
3936
4004
if (!lockMain)
3937
4005
return true ;
3938
4006
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
+
3939
4017
// Start block sync
3940
4018
if (pto->fStartSync && !fImporting && !fReindex ) {
3941
4019
pto->fStartSync = false ;
0 commit comments