Skip to content

Commit

Permalink
Preferentially peer with doublespend-relaying nodes
Browse files Browse the repository at this point in the history
Tries to maintain 8 outgoing connections and reserves 3/4 of the
incoming connections for nodes that relay doublespends.
  • Loading branch information
petertodd committed Jan 6, 2016
1 parent 52dc8c5 commit 3e541f4
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 1 deletion.
19 changes: 19 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4256,6 +4256,25 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
return false;
}

// Disconnect if we have already met our quota of non-doublespend-relaying nodes.
if (!(pfrom->nServices & NODE_RELAYS_DOUBLESPENDS))
{
int nNonDoubleSpendRelaying = 0;

LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes) {
if (!(pnode->nServices & NODE_RELAYS_DOUBLESPENDS))
nNonDoubleSpendRelaying++;
}

if (nNonDoubleSpendRelaying > nMaxConnections / 4) {
LogPrint("net", "reached quota of non-doublespend-relaying nodes; disconnecting %s\n",
pfrom->addr.ToString());
pfrom->fDisconnect = true;
return false;
}
}

if (pfrom->nVersion == 10300)
pfrom->nVersion = 300;
if (!vRecv.empty())
Expand Down
24 changes: 23 additions & 1 deletion src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@
using namespace std;

namespace {
const int MAX_OUTBOUND_CONNECTIONS = 8;
const int MAX_STD_OUTBOUND_CONNECTIONS = 8;
const int MIN_REPLACE_BY_FEE_OUTBOUND_CONNECTIONS = 8;

const int MAX_OUTBOUND_CONNECTIONS = MAX_STD_OUTBOUND_CONNECTIONS + MIN_REPLACE_BY_FEE_OUTBOUND_CONNECTIONS;

struct ListenSocket {
SOCKET socket;
Expand Down Expand Up @@ -1555,13 +1558,17 @@ void ThreadOpenConnections()
// Only connect out to one peer per network group (/16 for IPv4).
// Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
int nOutbound = 0;
int nDoubleSpendRelayingOutbound = 0;
set<vector<unsigned char> > setConnected;
{
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes) {
if (!pnode->fInbound) {
setConnected.insert(pnode->addr.GetGroup());
nOutbound++;

if (pnode->nServices & NODE_RELAYS_DOUBLESPENDS)
nDoubleSpendRelayingOutbound++;
}
}
}
Expand Down Expand Up @@ -1595,6 +1602,21 @@ void ThreadOpenConnections()
if (addr.GetPort() != Params().GetDefaultPort() && nTries < 50)
continue;

// Reserve some outbound connections for nodes that relay
// double-spends.
//
// Unfortunately nServices seems to end up corrupted at times,
// leading us to adding more nodes than expected, so this is a more
// strict test than might otherwise be expected.
//
// Also, we'll still end up with too many at times, because we'll
// find out afterwords that what we thought was a node's nServices
// was incorrect; Bitcoin Core will even stay connected to nodes
// not advertising NODE_NETWORK in this case.
if (!((addr.nServices & NODE_RELAYS_DOUBLESPENDS) && (addr.nServices & ~NODE_RELAYS_DOUBLESPENDS) == NODE_NETWORK)
&& (nOutbound - nDoubleSpendRelayingOutbound >= MAX_STD_OUTBOUND_CONNECTIONS))
continue;

addrConnect = addr;
break;
}
Expand Down
3 changes: 3 additions & 0 deletions src/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ enum {
// set by all Bitcoin Core nodes, and is unset by SPV clients or other peers that just want
// network services but don't provide them.
NODE_NETWORK = (1 << 0),

// NODE_GETUTXO means the node is capable of responding to the getutxo protocol request.
// Bitcoin Core does not support this but a patch set called Bitcoin XT does.
// See BIP 64 for details on how this is implemented.
Expand All @@ -250,6 +251,8 @@ enum {
NODE_REPLACE_BY_FEE = (1 << 26),
};

const uint64_t NODE_RELAYS_DOUBLESPENDS = NODE_REPLACE_BY_FEE;

/** A CService with information about it as peer */
class CAddress : public CService
{
Expand Down

0 comments on commit 3e541f4

Please sign in to comment.