Bitcoin local reputation management system for peer nodes

by Albert Szmigielski 

Recently I have heard about a Bitcoin local reputation management system for peer nodes , so i decided to look into it.
The system is in the source code, mainly in main.cpp
I looked at Version 0.11.99.0 (from clientversion.h)

main.h
/** Increase a node’s misbehavior score. */
void Misbehaving(NodeId nodeid, int howmuch);

main.cpp
int nMisbehavior;

void Misbehaving(NodeId pnode, int howmuch)
{
if (howmuch == 0)
return;

    CNodeState *state = State(pnode);
if (state == NULL)
return;

    state->nMisbehavior += howmuch;
int banscore = GetArg(“-banscore”, 100);
if (state->nMisbehavior >= banscore && state->nMisbehavior – howmuch < banscore)
{
LogPrintf(“Misbehaving: %s (%d -> %d) BAN THRESHOLD EXCEEDED\n”, state->name, state->nMisbehavior-howmuch, state->nMisbehavior);
state->fShouldBan = true;
} else
LogPrintf(“Misbehaving: %s (%d -> %d)\n”, state->name, state->nMisbehavior-howmuch, state->nMisbehavior);
    }

  • Looks like sending a duplicate version message earns you one negative point:

      if (strCommand == “version”)
      {
        // Each connection can only send one version message
        if (pfrom->nVersion != 0)
{
pfrom->PushMessage(“reject”, strCommand, REJECT_DUPLICATE, string(“Duplicate version message”));
Misbehaving(pfrom->GetId(), 1);
return false;
}

  • 20 points for large address size:

       // Don’t want addr from older versions unless seeding
       if (pfrom->nVersion < CADDR_TIME_VERSION && addrman.size() > 1000)
            return true;
        if (vAddr.size() > 1000)
        {
            Misbehaving(pfrom->GetId(), 20);
            return error(“message addr size() = %u”, vAddr.size());
        }

  • 20 points for larger than maximum inv size:

      if (vInv.size() > MAX_INV_SZ)
        {
Misbehaving(pfrom->GetId(), 20);
return error(“message inv size() = %u”, vInv.size());
}

  • 50 points for what looks like buffer overflow attempts (did not investigate this further)

         if (pfrom->nSendSize > (SendBufferSize() * 2)) {
                Misbehaving(pfrom->GetId(), 50);
                return error(“send buffer size() = %u”, pfrom->nSendSize);
            }

  • 20 points for large headers size

        if (nCount > MAX_HEADERS_RESULTS) {
            Misbehaving(pfrom->GetId(), 20);
            return error(“headers message size = %u”, nCount);
        }

  • 20 points for non-continuous headers sequence

            if (pindexLast != NULL && header.hashPrevBlock != pindexLast->GetBlockHash()) {
                Misbehaving(pfrom->GetId(), 20);
return error(“non-continuous headers sequence”);
}

  • 10 points for: duplicate/expired/invalid-signature/whatever alerts

               else {
                // Small DoS penalty so peers that send us lots of
                // duplicate/expired/invalid-signature/whatever alerts
                // eventually get banned.
                // This isn’t a Misbehaving(100) (immediate ban) because the
                // peer might be an older or different implementation with
                // a different signature key, etc.
                Misbehaving(pfrom->GetId(), 10);
            }

  • 100 points (immediate ban) if the node is newer than or equivalent to NO_BLOOM_VERSION (70011) and is asking for filter* commands with NODE_BLOOM

    else if (!(nLocalServices & NODE_BLOOM) &&
(strCommand == “filterload” ||
strCommand == “filteradd” ||
strCommand == “filterclear”) &&
//TODO: Remove this line after reasonable network upgrade
pfrom->nVersion >= NO_BLOOM_VERSION)
{
if (pfrom->nVersion >= NO_BLOOM_VERSION)
Misbehaving(pfrom->GetId(), 100);
//TODO: Enable this after reasonable network upgrade
//else
//    pfrom->fDisconnect = true;
}

  • 100 points (immediate ban) for large filter

            if (!filter.IsWithinSizeConstraints())
            // There is no excuse for sending a too-large filter
            Misbehaving(pfrom->GetId(), 100);

  • 100 points (immediate ban) for sending a data item over 520 bytes

        // Nodes must NEVER send a data item > 520 bytes (the max size for a script data object,
        // and thus, the maximum size any matched object can have) in a filteradd message
if (vData.size() > MAX_SCRIPT_ELEMENT_SIZE)
{
Misbehaving(pfrom->GetId(), 100);
} else {
LOCK(pfrom->cs_filter);
if (pfrom->pfilter)
pfrom->pfilter->insert(vData);
else
Misbehaving(pfrom->GetId(), 100);
}

Leave a Reply

Your email address will not be published. Required fields are marked *