-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Network upgrade activation mechanism #2898
Changes from all commits
780f526
b174b7e
f52da91
89f2045
9e85145
5486837
149d69e
828940b
5009136
cad27eb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -90,6 +90,13 @@ class CMainParams : public CChainParams { | |
consensus.nPowMaxAdjustDown = 32; // 32% adjustment down | ||
consensus.nPowMaxAdjustUp = 16; // 16% adjustment up | ||
consensus.nPowTargetSpacing = 2.5 * 60; | ||
consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight = | ||
Consensus::NetworkUpgrade::ALWAYS_ACTIVE; | ||
consensus.vUpgrades[Consensus::UPGRADE_TESTDUMMY].nActivationHeight = | ||
Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; | ||
consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = | ||
Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; | ||
|
||
/** | ||
* The message start string should be awesome! ⓩ❤ | ||
*/ | ||
|
@@ -241,6 +248,13 @@ class CTestNetParams : public CChainParams { | |
consensus.nPowMaxAdjustDown = 32; // 32% adjustment down | ||
consensus.nPowMaxAdjustUp = 16; // 16% adjustment up | ||
consensus.nPowTargetSpacing = 2.5 * 60; | ||
consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight = | ||
Consensus::NetworkUpgrade::ALWAYS_ACTIVE; | ||
consensus.vUpgrades[Consensus::UPGRADE_TESTDUMMY].nActivationHeight = | ||
Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; | ||
consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = | ||
Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; | ||
|
||
pchMessageStart[0] = 0xfa; | ||
pchMessageStart[1] = 0x1a; | ||
pchMessageStart[2] = 0xf9; | ||
|
@@ -341,6 +355,12 @@ class CRegTestParams : public CChainParams { | |
consensus.nPowMaxAdjustDown = 0; // Turn off adjustment down | ||
consensus.nPowMaxAdjustUp = 0; // Turn off adjustment up | ||
consensus.nPowTargetSpacing = 2.5 * 60; | ||
consensus.vUpgrades[Consensus::BASE_SPROUT].nActivationHeight = | ||
Consensus::NetworkUpgrade::ALWAYS_ACTIVE; | ||
consensus.vUpgrades[Consensus::UPGRADE_TESTDUMMY].nActivationHeight = | ||
Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; | ||
consensus.vUpgrades[Consensus::UPGRADE_OVERWINTER].nActivationHeight = | ||
Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; | ||
|
||
pchMessageStart[0] = 0xaa; | ||
pchMessageStart[1] = 0xe8; | ||
|
@@ -394,6 +414,12 @@ class CRegTestParams : public CChainParams { | |
vFoundersRewardAddress = { "t2FwcEhFdNXuFMv1tcYwaBJtYVtMj8b1uTg" }; | ||
assert(vFoundersRewardAddress.size() <= consensus.GetLastFoundersRewardBlockHeight()); | ||
} | ||
|
||
void UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex idx, int nActivationHeight) | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
assert(idx > Consensus::BASE_SPROUT && idx < Consensus::MAX_NETWORK_UPGRADES); | ||
consensus.vUpgrades[idx].nActivationHeight = nActivationHeight; | ||
} | ||
}; | ||
static CRegTestParams regTestParams; | ||
|
||
|
@@ -467,3 +493,8 @@ std::string CChainParams::GetFoundersRewardAddressAtIndex(int i) const { | |
assert(i >= 0 && i < vFoundersRewardAddress.size()); | ||
return vFoundersRewardAddress[i]; | ||
} | ||
|
||
void UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex idx, int nActivationHeight) | ||
{ | ||
regTestParams.UpdateNetworkUpgradeParameters(idx, nActivationHeight); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Upstream has a similar function for their BIP9 tests, which they later changed to be usable on any params for testing flexibility (while still only allowing regtest-level configuration from outside the binary). I will end up doing the same thing when I pull in bitcoin/bitcoin#8855 (which as a reminder to myself requires bitcoin/bitcoin#6235). |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,49 @@ | |
#include "uint256.h" | ||
|
||
namespace Consensus { | ||
|
||
/** | ||
* Index into Params.vUpgrades and NetworkUpgradeInfo | ||
* | ||
* Being array indices, these MUST be numbered consecutively. | ||
* | ||
* The order of these indices MUST match the order of the upgrades on-chain, as | ||
* several functions depends on the enum being sorted. | ||
*/ | ||
enum UpgradeIndex { | ||
// Sprout must be first | ||
BASE_SPROUT, | ||
UPGRADE_TESTDUMMY, | ||
UPGRADE_OVERWINTER, | ||
// NOTE: Also add new upgrades to NetworkUpgradeInfo in upgrades.cpp | ||
MAX_NETWORK_UPGRADES | ||
}; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe add static asserts to ensure UPGRADE_SPROUT==1 and UPGRADE_SPROUT < UPGRADE_OVERWINTER etc? Just in case a developer changes thing around? Although a stronger comment to the effect of "Do not reorder these enum constants!" could also work. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Happy to add the latter. Not adding the former, per above comment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Decided to strongly-word the comment instead. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also add a comment that they must be consecutively numbered. |
||
struct NetworkUpgrade { | ||
/** | ||
* Height of the first block for which the new consensus rules will be active | ||
*/ | ||
int nActivationHeight; | ||
|
||
/** | ||
* Special value for nActivationHeight indicating that the upgrade is always active. | ||
* This is useful for testing, as it means tests don't need to deal with the activation | ||
* process (namely, faking a chain of somewhat-arbitrary length). | ||
* | ||
* New blockchains that want to enable upgrade rules from the beginning can also use | ||
* this value. However, additional care must be taken to ensure the genesis block | ||
* satisfies the enabled rules. | ||
*/ | ||
static constexpr int ALWAYS_ACTIVE = 0; | ||
|
||
/** | ||
* Special value for nActivationHeight indicating that the upgrade will never activate. | ||
* This is useful when adding upgrade code that has a testnet activation height, but | ||
* should remain disabled on mainnet. | ||
*/ | ||
static constexpr int NO_ACTIVATION_HEIGHT = -1; | ||
}; | ||
|
||
/** | ||
* Parameters that influence chain consensus. | ||
*/ | ||
|
@@ -39,6 +82,7 @@ struct Params { | |
int nMajorityEnforceBlockUpgrade; | ||
int nMajorityRejectBlockOutdated; | ||
int nMajorityWindow; | ||
NetworkUpgrade vUpgrades[MAX_NETWORK_UPGRADES]; | ||
/** Proof of work parameters */ | ||
uint256 powLimit; | ||
int64_t nPowAveragingWindow; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
// 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. | ||
|
||
#include "consensus/upgrades.h" | ||
|
||
/** | ||
* General information about each network upgrade. | ||
* Ordered by Consensus::UpgradeIndex. | ||
*/ | ||
const struct NUInfo NetworkUpgradeInfo[Consensus::MAX_NETWORK_UPGRADES] = { | ||
{ | ||
/*.nBranchId =*/ 0, | ||
/*.strName =*/ "Sprout", | ||
/*.strInfo =*/ "The Zcash network at launch", | ||
}, | ||
{ | ||
/*.nBranchId =*/ 0x74736554, | ||
/*.strName =*/ "Test dummy", | ||
/*.strInfo =*/ "Test dummy info", | ||
}, | ||
{ | ||
/*.nBranchId =*/ 0x5ba81b19, | ||
/*.strName =*/ "Overwinter", | ||
/*.strInfo =*/ "TBD", | ||
} | ||
}; | ||
|
||
UpgradeState NetworkUpgradeState( | ||
int nHeight, | ||
const Consensus::Params& params, | ||
Consensus::UpgradeIndex idx) | ||
{ | ||
assert(nHeight >= 0); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
assert(idx >= Consensus::BASE_SPROUT && idx < Consensus::MAX_NETWORK_UPGRADES); | ||
auto nActivationHeight = params.vUpgrades[idx].nActivationHeight; | ||
|
||
if (nActivationHeight == Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT) { | ||
return UPGRADE_DISABLED; | ||
} else if (nHeight >= nActivationHeight) { | ||
// From ZIP 200: | ||
// | ||
// ACTIVATION_HEIGHT | ||
// The non-zero block height at which the network upgrade rules will come | ||
// into effect, and be enforced as part of the blockchain consensus. | ||
// | ||
// For removal of ambiguity, the block at height ACTIVATION_HEIGHT - 1 is | ||
// subject to the pre-upgrade consensus rules, and would be the last common | ||
// block in the event of a persistent pre-upgrade branch. | ||
return UPGRADE_ACTIVE; | ||
} else { | ||
return UPGRADE_PENDING; | ||
} | ||
} | ||
|
||
bool NetworkUpgradeActive( | ||
int nHeight, | ||
const Consensus::Params& params, | ||
Consensus::UpgradeIndex idx) | ||
{ | ||
return NetworkUpgradeState(nHeight, params, idx) == UPGRADE_ACTIVE; | ||
} | ||
|
||
int CurrentEpoch(int nHeight, const Consensus::Params& params) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't bother here because There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's possible that the caller passes in -1 for nHeight. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is possible, but per above comment, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I really wish we were writing in a language with integer range types. (cf #627) |
||
for (auto idxInt = Consensus::MAX_NETWORK_UPGRADES - 1; idxInt >= Consensus::BASE_SPROUT; idxInt--) { | ||
if (NetworkUpgradeActive(nHeight, params, Consensus::UpgradeIndex(idxInt))) { | ||
return idxInt; | ||
} | ||
} | ||
} | ||
|
||
uint32_t CurrentEpochBranchId(int nHeight, const Consensus::Params& params) { | ||
return NetworkUpgradeInfo[CurrentEpoch(nHeight, params)].nBranchId; | ||
} | ||
|
||
bool IsActivationHeight( | ||
int nHeight, | ||
const Consensus::Params& params, | ||
Consensus::UpgradeIndex idx) | ||
{ | ||
assert(idx >= Consensus::BASE_SPROUT && idx < Consensus::MAX_NETWORK_UPGRADES); | ||
|
||
// Don't count Sprout as an activation height | ||
if (idx == Consensus::BASE_SPROUT) { | ||
return false; | ||
} | ||
|
||
return nHeight >= 0 && nHeight == params.vUpgrades[idx].nActivationHeight; | ||
} | ||
|
||
bool IsActivationHeightForAnyUpgrade( | ||
int nHeight, | ||
const Consensus::Params& params) | ||
{ | ||
if (nHeight < 0) { | ||
return false; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Oh, yes it is because |
||
|
||
// Don't count Sprout as an activation height | ||
for (int idx = Consensus::BASE_SPROUT + 1; idx < Consensus::MAX_NETWORK_UPGRADES; idx++) { | ||
if (nHeight == params.vUpgrades[idx].nActivationHeight) | ||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
boost::optional<int> NextActivationHeight( | ||
int nHeight, | ||
const Consensus::Params& params) | ||
{ | ||
if (nHeight < 0) { | ||
return boost::none; | ||
} | ||
|
||
// Don't count Sprout as an activation height | ||
for (auto idx = Consensus::BASE_SPROUT + 1; idx < Consensus::MAX_NETWORK_UPGRADES; idx++) { | ||
if (NetworkUpgradeState(nHeight, params, Consensus::UpgradeIndex(idx)) == UPGRADE_PENDING) { | ||
return params.vUpgrades[idx].nActivationHeight; | ||
} | ||
} | ||
|
||
return boost::none; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the moment, this means that all the RPC tests will default to Sprout mode. I think we should at some point change this to
ALWAYS_ACTIVE
(updatingsrc/gtest/test_upgrades.cpp
accordingly), and have a few specific RPC tests that disable Overwinter.