From 72b2192950f3c775226e6d4ca58f45b148aa0b75 Mon Sep 17 00:00:00 2001 From: Simon Date: Tue, 20 Feb 2018 11:03:40 -0800 Subject: [PATCH] Overwinter peer management and network handshaking. Implements ZIP 201. --- src/main.cpp | 29 +++++++++++++++++++++++++++++ src/net.cpp | 29 +++++++++++++++++++++++++++++ src/net.h | 2 ++ src/version.h | 2 +- 4 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 9e41d9c4e..5d45a29ff 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4721,6 +4721,19 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, return false; } + // When Overwinter is active, reject incoming connections from non-Overwinter nodes + const Consensus::Params& params = Params().GetConsensus(); + if (NetworkUpgradeActive(GetHeight(), params, Consensus::UPGRADE_OVERWINTER) + && pfrom->nVersion < params.vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion) + { + LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, pfrom->nVersion); + pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE, + strprintf("Version must be %d or greater", + params.vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion)); + pfrom->fDisconnect = true; + return false; + } + if (pfrom->nVersion == 10300) pfrom->nVersion = 300; if (!vRecv.empty()) @@ -4839,6 +4852,22 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, } + // Disconnect existing peer connection when: + // 1. The version message has been received + // 2. Overwinter is active + // 3. Peer version is pre-Overwinter + else if (NetworkUpgradeActive(GetHeight(), chainparams.GetConsensus(), Consensus::UPGRADE_OVERWINTER) + && (pfrom->nVersion < chainparams.GetConsensus().vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion)) + { + LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, pfrom->nVersion); + pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE, + strprintf("Version must be %d or greater", + chainparams.GetConsensus().vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion)); + pfrom->fDisconnect = true; + return false; + } + + else if (strCommand == "addr") { vector vAddr; diff --git a/src/net.cpp b/src/net.cpp index 05f427707..72ef82d5a 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -7,6 +7,7 @@ #include "config/bitcoin-config.h" #endif +#include "main.h" #include "net.h" #include "addrman.h" @@ -812,6 +813,34 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) { // Protect connections with certain characteristics + // Check version of eviction candidates and prioritize nodes which do not support network upgrade. + std::vector vTmpEvictionCandidates; + int height; + { + LOCK(cs_main); + height = chainActive.Height(); + } + + const Consensus::Params& params = Params().GetConsensus(); + int nActivationHeight = params.vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight; + + if (nActivationHeight > 0 && + height < nActivationHeight && + height >= nActivationHeight - NETWORK_UPGRADE_PEER_PREFERENCE_BLOCK_PERIOD) + { + // Find any nodes which don't support Overwinter protocol version + BOOST_FOREACH(const CNodeRef &node, vEvictionCandidates) { + if (node->nVersion < params.vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion) { + vTmpEvictionCandidates.push_back(node); + } + } + + // Prioritize these nodes by replacing eviction set with them + if (vTmpEvictionCandidates.size() > 0) { + vEvictionCandidates = vTmpEvictionCandidates; + } + } + // Deterministically select 4 peers to protect by netgroup. // An attacker cannot predict which netgroups will be protected. static CompareNetGroupKeyed comparerNetGroupKeyed; diff --git a/src/net.h b/src/net.h index 6fd49536d..55190baa5 100644 --- a/src/net.h +++ b/src/net.h @@ -57,6 +57,8 @@ static const size_t MAPASKFOR_MAX_SZ = MAX_INV_SZ; static const size_t SETASKFOR_MAX_SZ = 2 * MAX_INV_SZ; /** The maximum number of peer connections to maintain. */ static const unsigned int DEFAULT_MAX_PEER_CONNECTIONS = 125; +/** The period before a network upgrade activates, where connections to upgrading peers are preferred (in blocks). */ +static const int NETWORK_UPGRADE_PEER_PREFERENCE_BLOCK_PERIOD = 24 * 24 * 3; unsigned int ReceiveFloodSize(); unsigned int SendBufferSize(); diff --git a/src/version.h b/src/version.h index b68bafc87..25527895d 100644 --- a/src/version.h +++ b/src/version.h @@ -9,7 +9,7 @@ * network protocol versioning */ -static const int PROTOCOL_VERSION = 170002; +static const int PROTOCOL_VERSION = 170003; //! initial proto version, to be increased after version/verack negotiation static const int INIT_PROTO_VERSION = 209;