Auto merge of #3512 - str4d:3487-nu-peer-management, r=ebfull
Make NU peer management logic upgrade-agnostic Closes #3487.
This commit is contained in:
commit
49356ed798
|
@ -57,7 +57,7 @@ testScripts=(
|
||||||
'getblocktemplate.py'
|
'getblocktemplate.py'
|
||||||
'bip65-cltv-p2p.py'
|
'bip65-cltv-p2p.py'
|
||||||
'bipdersig-p2p.py'
|
'bipdersig-p2p.py'
|
||||||
'overwinter_peer_management.py'
|
'p2p_nu_peer_management.py'
|
||||||
'rewind_index.py'
|
'rewind_index.py'
|
||||||
'p2p_txexpiry_dos.py'
|
'p2p_txexpiry_dos.py'
|
||||||
'p2p_node_bloom.py'
|
'p2p_node_bloom.py'
|
||||||
|
|
|
@ -1,118 +0,0 @@
|
||||||
#!/usr/bin/env python2
|
|
||||||
# Copyright (c) 2018 The Zcash developers
|
|
||||||
# Distributed under the MIT software license, see the accompanying
|
|
||||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
||||||
|
|
||||||
from test_framework.mininode import NodeConn, NodeConnCB, NetworkThread, \
|
|
||||||
msg_ping, SPROUT_PROTO_VERSION, OVERWINTER_PROTO_VERSION
|
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
|
||||||
from test_framework.util import initialize_chain_clean, start_nodes, \
|
|
||||||
p2p_port, assert_equal
|
|
||||||
|
|
||||||
import time
|
|
||||||
|
|
||||||
#
|
|
||||||
# In this test we connect Sprout and Overwinter mininodes to a Zcashd node
|
|
||||||
# which will activate Overwinter at block 10.
|
|
||||||
#
|
|
||||||
# We test:
|
|
||||||
# 1. the mininodes stay connected to Zcash with Sprout consensus rules
|
|
||||||
# 2. when Overwinter activates, the Sprout mininodes are dropped
|
|
||||||
# 3. new Overwinter nodes can connect to Zcash
|
|
||||||
# 4. new Sprout nodes cannot connect to Zcash
|
|
||||||
#
|
|
||||||
# This test *does not* verify that prior to Overwinter activation, the Zcashd
|
|
||||||
# node will prefer connections with Overwinter nodes, with an eviction process
|
|
||||||
# that prioritizes Sprout connections.
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
||||||
class TestManager(NodeConnCB):
|
|
||||||
def __init__(self):
|
|
||||||
NodeConnCB.__init__(self)
|
|
||||||
self.create_callback_map()
|
|
||||||
|
|
||||||
def on_close(self, conn):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def on_reject(self, conn, message):
|
|
||||||
conn.rejectMessage = message
|
|
||||||
|
|
||||||
|
|
||||||
class OverwinterPeerManagementTest(BitcoinTestFramework):
|
|
||||||
|
|
||||||
def setup_chain(self):
|
|
||||||
print "Initializing test directory "+self.options.tmpdir
|
|
||||||
initialize_chain_clean(self.options.tmpdir, 1)
|
|
||||||
|
|
||||||
def setup_network(self):
|
|
||||||
self.nodes = start_nodes(1, self.options.tmpdir,
|
|
||||||
extra_args=[['-nuparams=5ba81b19:10', '-debug', '-whitelist=127.0.0.1']])
|
|
||||||
|
|
||||||
def run_test(self):
|
|
||||||
test = TestManager()
|
|
||||||
|
|
||||||
# Launch 10 Sprout and 10 Overwinter mininodes
|
|
||||||
nodes = []
|
|
||||||
for x in xrange(10):
|
|
||||||
nodes.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0],
|
|
||||||
test, "regtest", SPROUT_PROTO_VERSION))
|
|
||||||
nodes.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0],
|
|
||||||
test, "regtest", OVERWINTER_PROTO_VERSION))
|
|
||||||
|
|
||||||
# Start up network handling in another thread
|
|
||||||
NetworkThread().start()
|
|
||||||
|
|
||||||
# Sprout consensus rules apply at block height 9
|
|
||||||
self.nodes[0].generate(9)
|
|
||||||
assert_equal(9, self.nodes[0].getblockcount())
|
|
||||||
|
|
||||||
# Verify mininodes are still connected to zcashd node
|
|
||||||
peerinfo = self.nodes[0].getpeerinfo()
|
|
||||||
versions = [x["version"] for x in peerinfo]
|
|
||||||
assert_equal(10, versions.count(SPROUT_PROTO_VERSION))
|
|
||||||
assert_equal(10, versions.count(OVERWINTER_PROTO_VERSION))
|
|
||||||
|
|
||||||
# Overwinter consensus rules activate at block height 10
|
|
||||||
self.nodes[0].generate(1)
|
|
||||||
assert_equal(10, self.nodes[0].getblockcount())
|
|
||||||
|
|
||||||
# Mininodes send ping message to zcashd node.
|
|
||||||
pingCounter = 1
|
|
||||||
for node in nodes:
|
|
||||||
node.send_message(msg_ping(pingCounter))
|
|
||||||
pingCounter = pingCounter + 1
|
|
||||||
|
|
||||||
time.sleep(3)
|
|
||||||
|
|
||||||
# Verify Sprout mininodes have been dropped and Overwinter mininodes are still connected.
|
|
||||||
peerinfo = self.nodes[0].getpeerinfo()
|
|
||||||
versions = [x["version"] for x in peerinfo]
|
|
||||||
assert_equal(0, versions.count(SPROUT_PROTO_VERSION))
|
|
||||||
assert_equal(10, versions.count(OVERWINTER_PROTO_VERSION))
|
|
||||||
|
|
||||||
# Extend the Overwinter chain with another block.
|
|
||||||
self.nodes[0].generate(1)
|
|
||||||
|
|
||||||
# Connect a new Overwinter mininode to the zcashd node, which is accepted.
|
|
||||||
nodes.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test, "regtest", OVERWINTER_PROTO_VERSION))
|
|
||||||
time.sleep(3)
|
|
||||||
assert_equal(11, len(self.nodes[0].getpeerinfo()))
|
|
||||||
|
|
||||||
# Try to connect a new Sprout mininode to the zcashd node, which is rejected.
|
|
||||||
sprout = NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test, "regtest", SPROUT_PROTO_VERSION)
|
|
||||||
nodes.append(sprout)
|
|
||||||
time.sleep(3)
|
|
||||||
assert("Version must be 170003 or greater" in str(sprout.rejectMessage))
|
|
||||||
|
|
||||||
# Verify that only Overwinter mininodes are connected.
|
|
||||||
peerinfo = self.nodes[0].getpeerinfo()
|
|
||||||
versions = [x["version"] for x in peerinfo]
|
|
||||||
assert_equal(0, versions.count(SPROUT_PROTO_VERSION))
|
|
||||||
assert_equal(11, versions.count(OVERWINTER_PROTO_VERSION))
|
|
||||||
|
|
||||||
for node in nodes:
|
|
||||||
node.disconnect_node()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
OverwinterPeerManagementTest().main()
|
|
|
@ -0,0 +1,192 @@
|
||||||
|
#!/usr/bin/env python2
|
||||||
|
# Copyright (c) 2018 The Zcash developers
|
||||||
|
# Distributed under the MIT software license, see the accompanying
|
||||||
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
from test_framework.mininode import (
|
||||||
|
NodeConn,
|
||||||
|
NodeConnCB,
|
||||||
|
NetworkThread,
|
||||||
|
msg_ping,
|
||||||
|
SPROUT_PROTO_VERSION,
|
||||||
|
OVERWINTER_PROTO_VERSION,
|
||||||
|
SAPLING_PROTO_VERSION,
|
||||||
|
)
|
||||||
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
|
from test_framework.util import initialize_chain_clean, start_nodes, \
|
||||||
|
p2p_port, assert_equal
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
#
|
||||||
|
# In this test we connect Sprout, Overwinter, and Sapling mininodes to a Zcashd
|
||||||
|
# node which will activate Overwinter at block 10 and Sapling at block 15.
|
||||||
|
#
|
||||||
|
# We test:
|
||||||
|
# 1. the mininodes stay connected to Zcash with Sprout consensus rules
|
||||||
|
# 2. when Overwinter activates, the Sprout mininodes are dropped
|
||||||
|
# 3. new Overwinter and Sapling nodes can connect to Zcash
|
||||||
|
# 4. new Sprout nodes cannot connect to Zcash
|
||||||
|
# 5. when Sapling activates, the Overwinter mininodes are dropped
|
||||||
|
# 6. new Sapling nodes can connect to Zcash
|
||||||
|
# 7. new Sprout and Overwinter nodes cannot connect to Zcash
|
||||||
|
#
|
||||||
|
# This test *does not* verify that prior to each activation, the Zcashd
|
||||||
|
# node will prefer connections with NU-aware nodes, with an eviction process
|
||||||
|
# that prioritizes non-NU-aware connections.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
class TestManager(NodeConnCB):
|
||||||
|
def __init__(self):
|
||||||
|
NodeConnCB.__init__(self)
|
||||||
|
self.create_callback_map()
|
||||||
|
|
||||||
|
def on_close(self, conn):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def on_reject(self, conn, message):
|
||||||
|
conn.rejectMessage = message
|
||||||
|
|
||||||
|
|
||||||
|
class NUPeerManagementTest(BitcoinTestFramework):
|
||||||
|
|
||||||
|
def setup_chain(self):
|
||||||
|
print "Initializing test directory "+self.options.tmpdir
|
||||||
|
initialize_chain_clean(self.options.tmpdir, 1)
|
||||||
|
|
||||||
|
def setup_network(self):
|
||||||
|
self.nodes = start_nodes(1, self.options.tmpdir, extra_args=[[
|
||||||
|
'-nuparams=5ba81b19:10', # Overwinter
|
||||||
|
'-nuparams=76b809bb:15', # Sapling
|
||||||
|
'-debug',
|
||||||
|
'-whitelist=127.0.0.1',
|
||||||
|
]])
|
||||||
|
|
||||||
|
def run_test(self):
|
||||||
|
test = TestManager()
|
||||||
|
|
||||||
|
# Launch Sprout, Overwinter, and Sapling mininodes
|
||||||
|
nodes = []
|
||||||
|
for x in xrange(10):
|
||||||
|
nodes.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0],
|
||||||
|
test, "regtest", SPROUT_PROTO_VERSION))
|
||||||
|
nodes.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0],
|
||||||
|
test, "regtest", OVERWINTER_PROTO_VERSION))
|
||||||
|
nodes.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0],
|
||||||
|
test, "regtest", SAPLING_PROTO_VERSION))
|
||||||
|
|
||||||
|
# Start up network handling in another thread
|
||||||
|
NetworkThread().start()
|
||||||
|
|
||||||
|
# Sprout consensus rules apply at block height 9
|
||||||
|
self.nodes[0].generate(9)
|
||||||
|
assert_equal(9, self.nodes[0].getblockcount())
|
||||||
|
|
||||||
|
# Verify mininodes are still connected to zcashd node
|
||||||
|
peerinfo = self.nodes[0].getpeerinfo()
|
||||||
|
versions = [x["version"] for x in peerinfo]
|
||||||
|
assert_equal(10, versions.count(SPROUT_PROTO_VERSION))
|
||||||
|
assert_equal(10, versions.count(OVERWINTER_PROTO_VERSION))
|
||||||
|
assert_equal(10, versions.count(SAPLING_PROTO_VERSION))
|
||||||
|
|
||||||
|
# Overwinter consensus rules activate at block height 10
|
||||||
|
self.nodes[0].generate(1)
|
||||||
|
assert_equal(10, self.nodes[0].getblockcount())
|
||||||
|
print('Overwinter active')
|
||||||
|
|
||||||
|
# Mininodes send ping message to zcashd node.
|
||||||
|
pingCounter = 1
|
||||||
|
for node in nodes:
|
||||||
|
node.send_message(msg_ping(pingCounter))
|
||||||
|
pingCounter = pingCounter + 1
|
||||||
|
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
# Verify Sprout mininodes have been dropped, while Overwinter and
|
||||||
|
# Sapling mininodes are still connected.
|
||||||
|
peerinfo = self.nodes[0].getpeerinfo()
|
||||||
|
versions = [x["version"] for x in peerinfo]
|
||||||
|
assert_equal(0, versions.count(SPROUT_PROTO_VERSION))
|
||||||
|
assert_equal(10, versions.count(OVERWINTER_PROTO_VERSION))
|
||||||
|
assert_equal(10, versions.count(SAPLING_PROTO_VERSION))
|
||||||
|
|
||||||
|
# Extend the Overwinter chain with another block.
|
||||||
|
self.nodes[0].generate(1)
|
||||||
|
|
||||||
|
# Connect a new Overwinter mininode to the zcashd node, which is accepted.
|
||||||
|
nodes.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test, "regtest", OVERWINTER_PROTO_VERSION))
|
||||||
|
time.sleep(3)
|
||||||
|
assert_equal(21, len(self.nodes[0].getpeerinfo()))
|
||||||
|
|
||||||
|
# Connect a new Sapling mininode to the zcashd node, which is accepted.
|
||||||
|
nodes.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test, "regtest", SAPLING_PROTO_VERSION))
|
||||||
|
time.sleep(3)
|
||||||
|
assert_equal(22, len(self.nodes[0].getpeerinfo()))
|
||||||
|
|
||||||
|
# Try to connect a new Sprout mininode to the zcashd node, which is rejected.
|
||||||
|
sprout = NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test, "regtest", SPROUT_PROTO_VERSION)
|
||||||
|
nodes.append(sprout)
|
||||||
|
time.sleep(3)
|
||||||
|
assert("Version must be 170003 or greater" in str(sprout.rejectMessage))
|
||||||
|
|
||||||
|
# Verify that only Overwinter and Sapling mininodes are connected.
|
||||||
|
peerinfo = self.nodes[0].getpeerinfo()
|
||||||
|
versions = [x["version"] for x in peerinfo]
|
||||||
|
assert_equal(0, versions.count(SPROUT_PROTO_VERSION))
|
||||||
|
assert_equal(11, versions.count(OVERWINTER_PROTO_VERSION))
|
||||||
|
assert_equal(11, versions.count(SAPLING_PROTO_VERSION))
|
||||||
|
|
||||||
|
# Sapling consensus rules activate at block height 15
|
||||||
|
self.nodes[0].generate(4)
|
||||||
|
assert_equal(15, self.nodes[0].getblockcount())
|
||||||
|
print('Sapling active')
|
||||||
|
|
||||||
|
# Mininodes send ping message to zcashd node.
|
||||||
|
pingCounter = 1
|
||||||
|
for node in nodes:
|
||||||
|
node.send_message(msg_ping(pingCounter))
|
||||||
|
pingCounter = pingCounter + 1
|
||||||
|
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
# Verify Sprout and Overwinter mininodes have been dropped, while
|
||||||
|
# Sapling mininodes are still connected.
|
||||||
|
peerinfo = self.nodes[0].getpeerinfo()
|
||||||
|
versions = [x["version"] for x in peerinfo]
|
||||||
|
assert_equal(0, versions.count(SPROUT_PROTO_VERSION))
|
||||||
|
assert_equal(0, versions.count(OVERWINTER_PROTO_VERSION))
|
||||||
|
assert_equal(11, versions.count(SAPLING_PROTO_VERSION))
|
||||||
|
|
||||||
|
# Extend the Sapling chain with another block.
|
||||||
|
self.nodes[0].generate(1)
|
||||||
|
|
||||||
|
# Connect a new Sapling mininode to the zcashd node, which is accepted.
|
||||||
|
nodes.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test, "regtest", SAPLING_PROTO_VERSION))
|
||||||
|
time.sleep(3)
|
||||||
|
assert_equal(12, len(self.nodes[0].getpeerinfo()))
|
||||||
|
|
||||||
|
# Try to connect a new Sprout mininode to the zcashd node, which is rejected.
|
||||||
|
sprout = NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test, "regtest", SPROUT_PROTO_VERSION)
|
||||||
|
nodes.append(sprout)
|
||||||
|
time.sleep(3)
|
||||||
|
assert("Version must be 170006 or greater" in str(sprout.rejectMessage))
|
||||||
|
|
||||||
|
# Try to connect a new Overwinter mininode to the zcashd node, which is rejected.
|
||||||
|
sprout = NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test, "regtest", OVERWINTER_PROTO_VERSION)
|
||||||
|
nodes.append(sprout)
|
||||||
|
time.sleep(3)
|
||||||
|
assert("Version must be 170006 or greater" in str(sprout.rejectMessage))
|
||||||
|
|
||||||
|
# Verify that only Sapling mininodes are connected.
|
||||||
|
peerinfo = self.nodes[0].getpeerinfo()
|
||||||
|
versions = [x["version"] for x in peerinfo]
|
||||||
|
assert_equal(0, versions.count(SPROUT_PROTO_VERSION))
|
||||||
|
assert_equal(0, versions.count(OVERWINTER_PROTO_VERSION))
|
||||||
|
assert_equal(12, versions.count(SAPLING_PROTO_VERSION))
|
||||||
|
|
||||||
|
for node in nodes:
|
||||||
|
node.disconnect_node()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
NUPeerManagementTest().main()
|
|
@ -42,6 +42,7 @@ from .equihash import (
|
||||||
OVERWINTER_PROTO_VERSION = 170003
|
OVERWINTER_PROTO_VERSION = 170003
|
||||||
BIP0031_VERSION = 60000
|
BIP0031_VERSION = 60000
|
||||||
SPROUT_PROTO_VERSION = 170002 # past bip-31 for ping/pong
|
SPROUT_PROTO_VERSION = 170002 # past bip-31 for ping/pong
|
||||||
|
SAPLING_PROTO_VERSION = 170006
|
||||||
MY_SUBVERSION = "/python-mininode-tester:0.0.1/"
|
MY_SUBVERSION = "/python-mininode-tester:0.0.1/"
|
||||||
|
|
||||||
OVERWINTER_VERSION_GROUP_ID = 0x03C48270
|
OVERWINTER_VERSION_GROUP_ID = 0x03C48270
|
||||||
|
@ -1415,7 +1416,7 @@ class NodeConn(asyncore.dispatcher):
|
||||||
vt.addrFrom.port = 0
|
vt.addrFrom.port = 0
|
||||||
self.send_message(vt, True)
|
self.send_message(vt, True)
|
||||||
print 'MiniNode: Connecting to Bitcoin Node IP # ' + dstaddr + ':' \
|
print 'MiniNode: Connecting to Bitcoin Node IP # ' + dstaddr + ':' \
|
||||||
+ str(dstport)
|
+ str(dstport) + ' using version ' + str(protocol_version)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.connect((dstaddr, dstport))
|
self.connect((dstaddr, dstport))
|
||||||
|
|
|
@ -114,20 +114,28 @@ bool IsActivationHeightForAnyUpgrade(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<int> NextActivationHeight(
|
boost::optional<int> NextEpoch(int nHeight, const Consensus::Params& params) {
|
||||||
int nHeight,
|
|
||||||
const Consensus::Params& params)
|
|
||||||
{
|
|
||||||
if (nHeight < 0) {
|
if (nHeight < 0) {
|
||||||
return boost::none;
|
return boost::none;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't count Sprout as an activation height
|
// Sprout is never pending
|
||||||
for (auto idx = Consensus::BASE_SPROUT + 1; idx < Consensus::MAX_NETWORK_UPGRADES; idx++) {
|
for (auto idx = Consensus::BASE_SPROUT + 1; idx < Consensus::MAX_NETWORK_UPGRADES; idx++) {
|
||||||
if (NetworkUpgradeState(nHeight, params, Consensus::UpgradeIndex(idx)) == UPGRADE_PENDING) {
|
if (NetworkUpgradeState(nHeight, params, Consensus::UpgradeIndex(idx)) == UPGRADE_PENDING) {
|
||||||
return params.vUpgrades[idx].nActivationHeight;
|
return idx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return boost::none;
|
return boost::none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::optional<int> NextActivationHeight(
|
||||||
|
int nHeight,
|
||||||
|
const Consensus::Params& params)
|
||||||
|
{
|
||||||
|
auto idx = NextEpoch(nHeight, params);
|
||||||
|
if (idx) {
|
||||||
|
return params.vUpgrades[idx.get()].nActivationHeight;
|
||||||
|
}
|
||||||
|
return boost::none;
|
||||||
|
}
|
||||||
|
|
|
@ -79,6 +79,12 @@ bool IsActivationHeightForAnyUpgrade(
|
||||||
int nHeight,
|
int nHeight,
|
||||||
const Consensus::Params& params);
|
const Consensus::Params& params);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the index of the next upgrade after the given block height, or
|
||||||
|
* boost::none if there are no more known upgrades.
|
||||||
|
*/
|
||||||
|
boost::optional<int> NextEpoch(int nHeight, const Consensus::Params& params);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the activation height for the next upgrade after the given block height,
|
* Returns the activation height for the next upgrade after the given block height,
|
||||||
* or boost::none if there are no more known upgrades.
|
* or boost::none if there are no more known upgrades.
|
||||||
|
|
|
@ -143,6 +143,35 @@ TEST_F(UpgradesTest, IsActivationHeightForAnyUpgrade) {
|
||||||
EXPECT_FALSE(IsActivationHeightForAnyUpgrade(1000000, params));
|
EXPECT_FALSE(IsActivationHeightForAnyUpgrade(1000000, params));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(UpgradesTest, NextEpoch) {
|
||||||
|
SelectParams(CBaseChainParams::REGTEST);
|
||||||
|
const Consensus::Params& params = Params().GetConsensus();
|
||||||
|
|
||||||
|
// Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT
|
||||||
|
EXPECT_EQ(NextEpoch(-1, params), boost::none);
|
||||||
|
EXPECT_EQ(NextEpoch(0, params), boost::none);
|
||||||
|
EXPECT_EQ(NextEpoch(1, params), boost::none);
|
||||||
|
EXPECT_EQ(NextEpoch(1000000, params), boost::none);
|
||||||
|
|
||||||
|
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_TESTDUMMY, Consensus::NetworkUpgrade::ALWAYS_ACTIVE);
|
||||||
|
|
||||||
|
EXPECT_EQ(NextEpoch(-1, params), boost::none);
|
||||||
|
EXPECT_EQ(NextEpoch(0, params), boost::none);
|
||||||
|
EXPECT_EQ(NextEpoch(1, params), boost::none);
|
||||||
|
EXPECT_EQ(NextEpoch(1000000, params), boost::none);
|
||||||
|
|
||||||
|
int nActivationHeight = 100;
|
||||||
|
UpdateNetworkUpgradeParameters(Consensus::UPGRADE_TESTDUMMY, nActivationHeight);
|
||||||
|
|
||||||
|
EXPECT_EQ(NextEpoch(-1, params), boost::none);
|
||||||
|
EXPECT_EQ(NextEpoch(0, params), static_cast<int>(Consensus::UPGRADE_TESTDUMMY));
|
||||||
|
EXPECT_EQ(NextEpoch(1, params), static_cast<int>(Consensus::UPGRADE_TESTDUMMY));
|
||||||
|
EXPECT_EQ(NextEpoch(nActivationHeight - 1, params), static_cast<int>(Consensus::UPGRADE_TESTDUMMY));
|
||||||
|
EXPECT_EQ(NextEpoch(nActivationHeight, params), boost::none);
|
||||||
|
EXPECT_EQ(NextEpoch(nActivationHeight + 1, params), boost::none);
|
||||||
|
EXPECT_EQ(NextEpoch(1000000, params), boost::none);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(UpgradesTest, NextActivationHeight) {
|
TEST_F(UpgradesTest, NextActivationHeight) {
|
||||||
SelectParams(CBaseChainParams::REGTEST);
|
SelectParams(CBaseChainParams::REGTEST);
|
||||||
const Consensus::Params& params = Params().GetConsensus();
|
const Consensus::Params& params = Params().GetConsensus();
|
||||||
|
|
18
src/main.cpp
18
src/main.cpp
|
@ -5016,15 +5016,15 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// When Overwinter is active, reject incoming connections from non-Overwinter nodes
|
// Reject incoming connections from nodes that don't know about the current epoch
|
||||||
const Consensus::Params& params = Params().GetConsensus();
|
const Consensus::Params& params = Params().GetConsensus();
|
||||||
if (NetworkUpgradeActive(GetHeight(), params, Consensus::UPGRADE_OVERWINTER)
|
auto currentEpoch = CurrentEpoch(GetHeight(), params);
|
||||||
&& pfrom->nVersion < params.vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion)
|
if (pfrom->nVersion < params.vUpgrades[currentEpoch].nProtocolVersion)
|
||||||
{
|
{
|
||||||
LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, pfrom->nVersion);
|
LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, pfrom->nVersion);
|
||||||
pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE,
|
pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE,
|
||||||
strprintf("Version must be %d or greater",
|
strprintf("Version must be %d or greater",
|
||||||
params.vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion));
|
params.vUpgrades[currentEpoch].nProtocolVersion));
|
||||||
pfrom->fDisconnect = true;
|
pfrom->fDisconnect = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -5149,15 +5149,15 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||||
|
|
||||||
// Disconnect existing peer connection when:
|
// Disconnect existing peer connection when:
|
||||||
// 1. The version message has been received
|
// 1. The version message has been received
|
||||||
// 2. Overwinter is active
|
// 2. Peer version is below the minimum version for the current epoch
|
||||||
// 3. Peer version is pre-Overwinter
|
else if (pfrom->nVersion < chainparams.GetConsensus().vUpgrades[
|
||||||
else if (NetworkUpgradeActive(GetHeight(), chainparams.GetConsensus(), Consensus::UPGRADE_OVERWINTER)
|
CurrentEpoch(GetHeight(), chainparams.GetConsensus())].nProtocolVersion)
|
||||||
&& (pfrom->nVersion < chainparams.GetConsensus().vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion))
|
|
||||||
{
|
{
|
||||||
LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, pfrom->nVersion);
|
LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, pfrom->nVersion);
|
||||||
pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE,
|
pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE,
|
||||||
strprintf("Version must be %d or greater",
|
strprintf("Version must be %d or greater",
|
||||||
chainparams.GetConsensus().vUpgrades[Consensus::UPGRADE_OVERWINTER].nProtocolVersion));
|
chainparams.GetConsensus().vUpgrades[
|
||||||
|
CurrentEpoch(GetHeight(), chainparams.GetConsensus())].nProtocolVersion));
|
||||||
pfrom->fDisconnect = true;
|
pfrom->fDisconnect = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
12
src/net.cpp
12
src/net.cpp
|
@ -820,15 +820,18 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const Consensus::Params& params = Params().GetConsensus();
|
const Consensus::Params& params = Params().GetConsensus();
|
||||||
int nActivationHeight = params.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight;
|
auto nextEpoch = NextEpoch(height, params);
|
||||||
|
if (nextEpoch) {
|
||||||
|
auto idx = nextEpoch.get();
|
||||||
|
int nActivationHeight = params.vUpgrades[idx].nActivationHeight;
|
||||||
|
|
||||||
if (nActivationHeight > 0 &&
|
if (nActivationHeight > 0 &&
|
||||||
height < nActivationHeight &&
|
height < nActivationHeight &&
|
||||||
height >= nActivationHeight - NETWORK_UPGRADE_PEER_PREFERENCE_BLOCK_PERIOD)
|
height >= nActivationHeight - NETWORK_UPGRADE_PEER_PREFERENCE_BLOCK_PERIOD)
|
||||||
{
|
{
|
||||||
// Find any nodes which don't support Overwinter protocol version
|
// Find any nodes which don't support the protocol version for the next upgrade
|
||||||
BOOST_FOREACH(const CNodeRef &node, vEvictionCandidates) {
|
for (const CNodeRef &node : vEvictionCandidates) {
|
||||||
if (node->nVersion < params.vUpgrades[Consensus::UPGRADE_SAPLING].nProtocolVersion) {
|
if (node->nVersion < params.vUpgrades[idx].nProtocolVersion) {
|
||||||
vTmpEvictionCandidates.push_back(node);
|
vTmpEvictionCandidates.push_back(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -838,6 +841,7 @@ static bool AttemptToEvictConnection(bool fPreferNewConnection) {
|
||||||
vEvictionCandidates = vTmpEvictionCandidates;
|
vEvictionCandidates = vTmpEvictionCandidates;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Deterministically select 4 peers to protect by netgroup.
|
// Deterministically select 4 peers to protect by netgroup.
|
||||||
// An attacker cannot predict which netgroups will be protected.
|
// An attacker cannot predict which netgroups will be protected.
|
||||||
|
|
Loading…
Reference in New Issue