Enable future timestamp soft fork at varying heights according to network.
Signed-off-by: Daira Hopwood <daira@jacaranda.org>
This commit is contained in:
parent
5199ecdf41
commit
4ab896c69d
|
@ -323,6 +323,22 @@ public:
|
|||
consensus.vUpgrades[Consensus::UPGRADE_HEARTWOOD].nActivationHeight =
|
||||
Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT;
|
||||
|
||||
// On testnet we activate this rule 6 blocks after Blossom activation. From block 299188 and
|
||||
// prior to Blossom activation, the testnet minimum-difficulty threshold was 15 minutes (i.e.
|
||||
// a minimum difficulty block can be mined if no block is mined normally within 15 minutes):
|
||||
// <https://zips.z.cash/zip-0205#change-to-difficulty-adjustment-on-testnet>
|
||||
// However the median-time-past is 6 blocks behind, and the worst-case time for 7 blocks at a
|
||||
// 15-minute spacing is ~105 minutes, which is exceeds the limit imposed by the soft fork of
|
||||
// 90 minutes.
|
||||
//
|
||||
// After Blossom, the minimum difficulty threshold time is changed to 6 times the block target
|
||||
// spacing, which is 7.5 minutes:
|
||||
// <https://zips.z.cash/zip-0208#minimum-difficulty-blocks-on-the-test-network>
|
||||
// 7 times that is 52.5 minutes which is well within the limit imposed by the soft fork.
|
||||
|
||||
static_assert(6 * Consensus::POST_BLOSSOM_POW_TARGET_SPACING * 7 < MAX_FUTURE_BLOCK_TIME_MTP - 60);
|
||||
consensus.nFutureTimestampSoftForkHeight = consensus.vUpgrades[Consensus::UPGRADE_BLOSSOM].nActivationHeight + 6;
|
||||
|
||||
// The best chain should have at least this much work.
|
||||
consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000000000000000001dbb4c4224");
|
||||
|
||||
|
|
|
@ -11,6 +11,10 @@ namespace Consensus {
|
|||
return NetworkUpgradeState(nHeight, *this, idx) == UPGRADE_ACTIVE;
|
||||
}
|
||||
|
||||
bool Params::FutureTimestampSoftForkActive(int nHeight) const {
|
||||
return nHeight >= nFutureTimestampSoftForkHeight;
|
||||
}
|
||||
|
||||
int Params::Halving(int nHeight) const {
|
||||
// zip208
|
||||
// Halving(height) :=
|
||||
|
|
|
@ -96,6 +96,8 @@ struct Params {
|
|||
*/
|
||||
bool NetworkUpgradeActive(int nHeight, Consensus::UpgradeIndex idx) const;
|
||||
|
||||
bool FutureTimestampSoftForkActive(int nHeight) const;
|
||||
|
||||
uint256 hashGenesisBlock;
|
||||
|
||||
bool fCoinbaseMustBeShielded;
|
||||
|
@ -126,6 +128,47 @@ struct Params {
|
|||
int nMajorityRejectBlockOutdated;
|
||||
int nMajorityWindow;
|
||||
NetworkUpgrade vUpgrades[MAX_NETWORK_UPGRADES];
|
||||
|
||||
/**
|
||||
* Default block height at which the future timestamp soft fork rule activates.
|
||||
*
|
||||
* Genesis blocks are hard-coded into the binary for all networks
|
||||
* (mainnet, testnet, regtest), and have now-ancient timestamps. So we need to
|
||||
* handle the case where we might use the genesis block's timestamp as the
|
||||
* median-time-past.
|
||||
*
|
||||
* GetMedianTimePast() is implemented such that the chosen block is the
|
||||
* median of however many blocks we are able to select up to
|
||||
* nMedianTimeSpan = 11. For example, if nHeight == 6:
|
||||
*
|
||||
* ,-<pmedian ,-<pbegin ,-<pend
|
||||
* [-, -, -, -, 0, 1, 2, 3, 4, 5, 6] -
|
||||
*
|
||||
* and thus pbegin[(pend - pbegin)/2] will select block height 3, assuming
|
||||
* that the block timestamps are all greater than the genesis block's
|
||||
* timestamp. For regtest mode, this is a valid assumption; we generate blocks
|
||||
* deterministically and in-order. For mainnet it was true in practice, and
|
||||
* we aren't going to be starting a new chain linked directly from the mainnet
|
||||
* genesis block.
|
||||
*
|
||||
* Therefore, for regtest and mainnet we only risk using the regtest genesis
|
||||
* block's timestamp for nHeight < 2 (as GetMedianTimePast() uses floor division).
|
||||
*
|
||||
* Separately, for mainnet this is also necessary because there was a long time
|
||||
* between starting to find the mainnet genesis block (which was mined with a
|
||||
* single laptop) and mining the block at height 1. For any new mainnet chain
|
||||
* using Zcash code, the soft fork rule would be enabled from the start so that
|
||||
* miners would limit their timestamps accordingly.
|
||||
*
|
||||
* For testnet, the future timestamp soft fork rule was violated for many
|
||||
* blocks prior to Blossom activation. At Blossom, the time threshold for the
|
||||
* (testnet-specific) minimum difficulty rule was changed in such a way that
|
||||
* starting from shortly after the Blossom activation, no further blocks
|
||||
* violate the soft fork rule. So for testnet we override the soft fork
|
||||
* activation height in chainparams.cpp.
|
||||
*/
|
||||
int nFutureTimestampSoftForkHeight = 2;
|
||||
|
||||
/** Proof of work parameters */
|
||||
unsigned int nEquihashN = 0;
|
||||
unsigned int nEquihashK = 0;
|
||||
|
|
29
src/main.cpp
29
src/main.cpp
|
@ -3784,29 +3784,14 @@ bool ContextualCheckBlockHeader(
|
|||
REJECT_INVALID, "time-too-old");
|
||||
}
|
||||
|
||||
// Genesis blocks are hard-coded into the binary, and both testnet and
|
||||
// regtest have now-ancient timestamps, so we need to handle the case
|
||||
// where we might use the genesis block's timestamp as the median-time-past.
|
||||
// Check future timestamp soft fork rule introduced in v2.1.1-1.
|
||||
// This retrospectively activates at block height 2 for mainnet and regtest,
|
||||
// and 6 blocks after Blossom activation for testnet.
|
||||
// Explanations of these activation heights are in src/consensus/params.h
|
||||
// and chainparams.cpp.
|
||||
//
|
||||
// GetMedianTimePast() is implemented such that the chosen block is the
|
||||
// median of however many blocks we are able to select up to
|
||||
// nMedianTimeSpan = 11. For example, if nHeight == 6:
|
||||
//
|
||||
// ,-<pmedian ,-<pbegin ,-<pend
|
||||
// [-, -, -, -, 0, 1, 2, 3, 4, 5, 6] -
|
||||
//
|
||||
// and thus pbegin[(pend - pbegin)/2] will select block height 3, assuming
|
||||
// that the block timestamps are all greater than the genesis block's
|
||||
// timestamp.
|
||||
//
|
||||
// Therefore, we only risk using the regtest genesis block's timestamp for
|
||||
// nHeight < 2 (as GetMedianTimePast() uses floor division).
|
||||
//
|
||||
// Separately, this is also necessary because there was a long time between
|
||||
// starting to find the mainnet genesis block (which was mined with a single
|
||||
// laptop) and mining the block at height 1.
|
||||
//
|
||||
if (nHeight >= 2 && block.GetBlockTime() > medianTimePast + MAX_FUTURE_BLOCK_TIME_MTP) {
|
||||
if (consensusParams.FutureTimestampSoftForkActive(nHeight) &&
|
||||
block.GetBlockTime() > medianTimePast + MAX_FUTURE_BLOCK_TIME_MTP) {
|
||||
return state.Invalid(error("%s: block at height %d, timestamp %d is too far ahead of median-time-past, limit is %d",
|
||||
__func__, nHeight, block.GetBlockTime(), medianTimePast + MAX_FUTURE_BLOCK_TIME_MTP),
|
||||
REJECT_INVALID, "time-too-far-ahead-of-mtp");
|
||||
|
|
|
@ -102,7 +102,7 @@ void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams,
|
|||
auto medianTimePast = pindexPrev->GetMedianTimePast();
|
||||
auto nTime = std::max(medianTimePast + 1, GetAdjustedTime());
|
||||
// See the comment in ContextualCheckBlockHeader() for background.
|
||||
if (pindexPrev->nHeight >= 1) {
|
||||
if (consensusParams.FutureTimestampSoftForkActive(pindexPrev->nHeight + 1)) {
|
||||
nTime = std::min(nTime, medianTimePast + MAX_FUTURE_BLOCK_TIME_MTP);
|
||||
}
|
||||
pblock->nTime = nTime;
|
||||
|
|
Loading…
Reference in New Issue