diff --git a/src/main.cpp b/src/main.cpp index 50bd49620..f6170ab60 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4418,8 +4418,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } // Get recent addresses - pfrom->PushMessage("getaddr"); - pfrom->fGetAddr = true; + if (pfrom->fOneShot || pfrom->nVersion >= CADDR_TIME_VERSION || addrman.size() < 1000) + { + pfrom->PushMessage("getaddr"); + pfrom->fGetAddr = true; + } addrman.Good(pfrom->addr); } else { if (((CNetAddr)pfrom->addr) == (CNetAddr)addrFrom) @@ -4478,6 +4481,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, vector vAddr; vRecv >> vAddr; + // 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); @@ -4512,6 +4518,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, multimap mapMix; BOOST_FOREACH(CNode* pnode, vNodes) { + if (pnode->nVersion < CADDR_TIME_VERSION) + continue; unsigned int nPointer; memcpy(&nPointer, &pnode, sizeof(nPointer)); uint256 hashKey = ArithToUint256(UintToArith256(hashRand) ^ nPointer); @@ -4962,20 +4970,23 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, else if (strCommand == "ping") { - uint64_t nonce = 0; - vRecv >> nonce; - // Echo the message back with the nonce. This allows for two useful features: - // - // 1) A remote node can quickly check if the connection is operational - // 2) Remote nodes can measure the latency of the network thread. If this node - // is overloaded it won't respond to pings quickly and the remote node can - // avoid sending us more work, like chain download requests. - // - // The nonce stops the remote getting confused between different pings: without - // it, if the remote node sends a ping once per second and this node takes 5 - // seconds to respond to each, the 5th ping the remote sends would appear to - // return very quickly. - pfrom->PushMessage("pong", nonce); + if (pfrom->nVersion > BIP0031_VERSION) + { + uint64_t nonce = 0; + vRecv >> nonce; + // Echo the message back with the nonce. This allows for two useful features: + // + // 1) A remote node can quickly check if the connection is operational + // 2) Remote nodes can measure the latency of the network thread. If this node + // is overloaded it won't respond to pings quickly and the remote node can + // avoid sending us more work, like chain download requests. + // + // The nonce stops the remote getting confused between different pings: without + // it, if the remote node sends a ping once per second and this node takes 5 + // seconds to respond to each, the 5th ping the remote sends would appear to + // return very quickly. + pfrom->PushMessage("pong", nonce); + } } @@ -5303,8 +5314,14 @@ bool SendMessages(CNode* pto, bool fSendTrickle) } pto->fPingQueued = false; pto->nPingUsecStart = GetTimeMicros(); - pto->nPingNonceSent = nonce; - pto->PushMessage("ping", nonce); + if (pto->nVersion > BIP0031_VERSION) { + pto->nPingNonceSent = nonce; + pto->PushMessage("ping", nonce); + } else { + // Peer is too old to support ping command with nonce, pong will never arrive. + pto->nPingNonceSent = 0; + pto->PushMessage("ping"); + } } TRY_LOCK(cs_main, lockMain); // Acquire cs_main for IsInitialBlockDownload() and CNodeState() diff --git a/src/net.cpp b/src/net.cpp index d49af2610..de624c72a 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1194,7 +1194,7 @@ void ThreadSocketHandler() LogPrintf("socket sending timeout: %is\n", nTime - pnode->nLastSend); pnode->fDisconnect = true; } - else if (nTime - pnode->nLastRecv > TIMEOUT_INTERVAL) + else if (nTime - pnode->nLastRecv > (pnode->nVersion > BIP0031_VERSION ? TIMEOUT_INTERVAL : 90*60)) { LogPrintf("socket receive timeout: %is\n", nTime - pnode->nLastRecv); pnode->fDisconnect = true; diff --git a/src/protocol.h b/src/protocol.h index 8bcf6e2ab..b5e65032a 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -103,7 +103,8 @@ public: Init(); if (nType & SER_DISK) READWRITE(nVersion); - if ((nType & SER_DISK) || !(nType & SER_GETHASH)) + if ((nType & SER_DISK) || + (nVersion >= CADDR_TIME_VERSION && !(nType & SER_GETHASH))) READWRITE(nTime); READWRITE(nServices); READWRITE(*(CService*)this); diff --git a/src/version.h b/src/version.h index bd71a5574..91a464030 100644 --- a/src/version.h +++ b/src/version.h @@ -12,9 +12,26 @@ static const int PROTOCOL_VERSION = 170002; //! initial proto version, to be increased after version/verack negotiation -static const int INIT_PROTO_VERSION = 170002; +static const int INIT_PROTO_VERSION = 209; + +//! In this version, 'getheaders' was introduced. +static const int GETHEADERS_VERSION = 31800; //! disconnect from peers older than this proto version static const int MIN_PEER_PROTO_VERSION = 170002; +//! nTime field added to CAddress, starting with this version; +//! if possible, avoid requesting addresses nodes older than this +static const int CADDR_TIME_VERSION = 31402; + +//! only request blocks from nodes outside this range of versions +static const int NOBLKS_VERSION_START = 32000; +static const int NOBLKS_VERSION_END = 32400; + +//! BIP 0031, pong message, is enabled for all versions AFTER this one +static const int BIP0031_VERSION = 60000; + +//! "mempool" command, enhanced "getdata" behavior starts with this version +static const int MEMPOOL_GD_VERSION = 60002; + #endif // BITCOIN_VERSION_H