Merge #780: Change elements mode to activating BIP9 signaling based on height

6fc3fe04e Change elements mode to activating BIP9 signaling based on height (Gregory Sanders)

Pull request description:

  When based on block time, it's really hard to engineer principled tests for activation of consensus changes.

  resolves https://github.com/ElementsProject/elements/issues/779

Tree-SHA512: c5672d54a3a906d1318c82197022b9effd39e951e3f9e5ca4dc92055f2fa638a6359797662014c4928be25795ddd6b3f401769d53a967cf08d4f564210926773
This commit is contained in:
Steven Roose 2019-11-14 11:40:23 +00:00
commit ccf6697e3b
No known key found for this signature in database
GPG key ID: 2F2A88D7F8D68E87
4 changed files with 32 additions and 6 deletions

View file

@ -135,6 +135,7 @@ public:
g_con_elementsmode = false;
g_con_blockheightinheader = false;
consensus.total_valid_epochs = 0;
consensus.elements_mode = g_con_elementsmode;
/**
* The message start string is designed to be unlikely to occur in normal data.
@ -265,6 +266,7 @@ public:
g_con_elementsmode = false;
g_con_blockheightinheader = false;
consensus.total_valid_epochs = 0;
consensus.elements_mode = g_con_elementsmode;
pchMessageStart[0] = 0x0b;
pchMessageStart[1] = 0x11;
@ -367,6 +369,7 @@ public:
consensus.has_parent_chain = false;
g_signed_blocks = false;
g_con_elementsmode = false;
consensus.elements_mode = g_con_elementsmode;
g_con_blockheightinheader = false;
consensus.total_valid_epochs = 0;
@ -552,6 +555,7 @@ class CCustomParams : public CRegTestParams {
// Default to true for custom chains.
g_con_blockheightinheader = args.GetBoolArg("-con_blockheightinheader", true);
g_con_elementsmode = args.GetBoolArg("-con_elementsmode", true);
consensus.elements_mode = g_con_elementsmode;
// No subsidy for custom chains by default
consensus.genesis_subsidy = args.GetArg("-con_blocksubsidy", 0);
@ -726,6 +730,7 @@ public:
g_con_blockheightinheader = true;
g_con_elementsmode = true;
consensus.elements_mode = g_con_elementsmode;
// TODO: Pick appropriate value for this network.
consensus.total_valid_epochs = 2;

View file

@ -108,6 +108,7 @@ struct Params {
// Used to allow M-epoch-old peg-in addresses as deposits
// default 1 to not break legacy chains implicitly.
size_t total_valid_epochs = 1;
bool elements_mode = false;
};
} // namespace Consensus

View file

@ -5,10 +5,20 @@
#include <versionbits.h>
#include <consensus/params.h>
// Elements: We use height, not time!
int64_t GetBIP9Time(const CBlockIndex* pindexPrev, const Consensus::Params& params) {
if (params.elements_mode) {
return pindexPrev->nHeight;
} else {
return pindexPrev->GetMedianTimePast();
}
}
ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const
{
int nPeriod = Period(params);
int nThreshold = Threshold(params);
// ELEMENTS: We interpret this as block height, not block time!
int64_t nTimeStart = BeginTime(params);
int64_t nTimeTimeout = EndTime(params);
@ -30,7 +40,7 @@ ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex*
cache[pindexPrev] = ThresholdState::DEFINED;
break;
}
if (pindexPrev->GetMedianTimePast() < nTimeStart) {
if (GetBIP9Time(pindexPrev, params) < nTimeStart) {
// Optimization: don't recompute down further, as we know every earlier block will be before the start time
cache[pindexPrev] = ThresholdState::DEFINED;
break;
@ -51,15 +61,15 @@ ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex*
switch (state) {
case ThresholdState::DEFINED: {
if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
if (GetBIP9Time(pindexPrev, params) >= nTimeTimeout) {
stateNext = ThresholdState::FAILED;
} else if (pindexPrev->GetMedianTimePast() >= nTimeStart) {
} else if (GetBIP9Time(pindexPrev, params) >= nTimeStart) {
stateNext = ThresholdState::STARTED;
}
break;
}
case ThresholdState::STARTED: {
if (pindexPrev->GetMedianTimePast() >= nTimeTimeout) {
if (GetBIP9Time(pindexPrev, params) >= nTimeTimeout) {
stateNext = ThresholdState::FAILED;
break;
}

View file

@ -63,7 +63,7 @@ class DynaFedTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 2
# We want to test activation of dynafed
self.extra_args = [["-con_dyna_deploy_start=0", "-enforce_pak=1", "-con_parent_chain_signblockscript=51", "-peginconfirmationdepth=1", "-parentscriptprefix=75", "-parent_bech32_hrp=ert"] for i in range(self.num_nodes)]
self.extra_args = [["-con_dyna_deploy_start=1000", "-enforce_pak=1", "-con_parent_chain_signblockscript=51", "-peginconfirmationdepth=1", "-parentscriptprefix=75", "-parent_bech32_hrp=ert"] for i in range(self.num_nodes)]
# second node will not mine transactions
self.extra_args[1].append("-blocksonly=1")
@ -105,8 +105,18 @@ class DynaFedTest(BitcoinTestFramework):
def test_dynafed_activation(self):
self.log.info("Testing dynafed versionbits activation...")
# Signaling window is in height, not time, so first block that will signal is
# at height 1008 which is evenly disible by 144(regtest bip9 window size)
# Giving funds to node 1 to avoid a transaction size blowup when sweeping later
blocks = self.nodes[0].generatetoaddress(1006, self.nodes[1].getnewaddress())
assert_equal(self.nodes[0].getblockchaininfo()["bip9_softforks"]["dynafed"]["status"], "defined")
blocks += self.nodes[0].generatetoaddress(1, self.nodes[0].getnewaddress())
assert_equal(self.nodes[0].getblockchaininfo()["bip9_softforks"]["dynafed"]["status"], "started")
blocks += self.nodes[0].generatetoaddress(144, self.nodes[0].getnewaddress())
assert_equal(self.nodes[0].getblockchaininfo()["bip9_softforks"]["dynafed"]["status"], "locked_in")
# Move chain forward to activation, any new blocks will be enforced
blocks = self.nodes[0].generatetoaddress(431, self.nodes[0].getnewaddress())
blocks += self.nodes[0].generatetoaddress(144, self.nodes[0].getnewaddress())
self.sync_all()
assert_equal(self.nodes[0].getblockchaininfo()["bip9_softforks"]["dynafed"]["status"], "active")