Skip to content

Commit 4b046bb

Browse files
UdjinM6PastaPastaPasta
authored andcommitted
use deployment nStartTime as a signal expiration mark, adjust tests
if a signal is mined prior to nStartTime then it means it was mined for one of the previous deployments with the same bit and we can ignore it
1 parent d83dbd2 commit 4b046bb

File tree

4 files changed

+50
-42
lines changed

4 files changed

+50
-42
lines changed

src/chainparams.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,6 @@ class CMainParams : public CChainParams {
195195
consensus.DIP0024Height = 1737792; // 0000000000000001342be9c0b75ad40c276beaad91616423c4d9cb101b3db438
196196
consensus.V19Height = 1899072; // 0000000000000015e32e73052d663626327004c81c5c22cb8b42c361015c0eae
197197
consensus.MinBIP9WarningHeight = 1899072 + 2016; // V19 activation height + miner confirmation window
198-
consensus.nExpireEHF = 576 * 365; // one year
199198
consensus.powLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 20
200199
consensus.nPowTargetTimespan = 24 * 60 * 60; // Dash: 1 day
201200
consensus.nPowTargetSpacing = 2.5 * 60; // Dash: 2.5 minutes
@@ -393,7 +392,6 @@ class CTestNetParams : public CChainParams {
393392
consensus.DIP0024Height = 769700; // 0000008d84e4efd890ae95c70a7a6126a70a80e5c19e4cb264a5b3469aeef172
394393
consensus.V19Height = 850100; // 000004728b8ff2a16b9d4eebb0fd61eeffadc9c7fe4b0ec0b5a739869401ab5b
395394
consensus.MinBIP9WarningHeight = 850100 + 2016; // v19 activation height + miner confirmation window
396-
consensus.nExpireEHF = 576 * 365; // one year
397395
consensus.powLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 20
398396
consensus.nPowTargetTimespan = 24 * 60 * 60; // Dash: 1 day
399397
consensus.nPowTargetSpacing = 2.5 * 60; // Dash: 2.5 minutes
@@ -565,7 +563,6 @@ class CDevNetParams : public CChainParams {
565563
consensus.DIP0024Height = 300;
566564
consensus.V19Height = 300;
567565
consensus.MinBIP9WarningHeight = 300 + 2016; // v19 activation height + miner confirmation window
568-
consensus.nExpireEHF = 576 * 365; // one year
569566
consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 1
570567
consensus.nPowTargetTimespan = 24 * 60 * 60; // Dash: 1 day
571568
consensus.nPowTargetSpacing = 2.5 * 60; // Dash: 2.5 minutes
@@ -804,7 +801,6 @@ class CRegTestParams : public CChainParams {
804801
consensus.DIP0024Height = 900;
805802
consensus.V19Height = 900;
806803
consensus.MinBIP9WarningHeight = 0;
807-
consensus.nExpireEHF = 576; // one day for RegTest
808804
consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 1
809805
consensus.nPowTargetTimespan = 24 * 60 * 60; // Dash: 1 day
810806
consensus.nPowTargetSpacing = 2.5 * 60; // Dash: 2.5 minutes

src/consensus/params.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,6 @@ struct Params {
112112
/** Don't warn about unknown BIP 9 activations below this height.
113113
* This prevents us from warning about the CSV and DIP activations. */
114114
int MinBIP9WarningHeight;
115-
/** this value is used to expire signals of EHF */
116-
int nExpireEHF;
117115
/**
118116
* Minimum blocks including miner confirmation of the total of nMinerConfirmationWindow blocks in a retargeting period,
119117
* (nPowTargetTimespan / nPowTargetSpacing) which is also used for BIP9 deployments.

src/evo/mnhftx.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,28 @@ CMNHFManager::Signals CMNHFManager::GetSignalsStage(const CBlockIndex* const pin
2727
Signals signals = GetFromCache(pindexPrev);
2828
const int height = pindexPrev->nHeight + 1;
2929
for (auto it = signals.begin(); it != signals.end(); ) {
30-
if (height > it->second + Params().GetConsensus().nExpireEHF) {
31-
LogPrintf("CMNHFManager::GetSignalsStage: mnhf signal bit=%d height:%d is expired at height=%d\n", it->first, it->second, height);
30+
bool found{false};
31+
const auto signal_pindex = pindexPrev->GetAncestor(it->second);
32+
assert(signal_pindex != nullptr);
33+
const int64_t signal_time = signal_pindex->GetMedianTimePast();
34+
for (int index = 0; index < Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++index) {
35+
const auto& deployment = Params().GetConsensus().vDeployments[index];
36+
if (deployment.bit != it->first) continue;
37+
if (signal_time < deployment.nStartTime) {
38+
// new deployment is using the same bit as the old one
39+
LogPrintf("CMNHFManager::GetSignalsStage: mnhf signal bit=%d height:%d is expired at height=%d\n", it->first, it->second, height);
40+
it = signals.erase(it);
41+
} else {
42+
++it;
43+
}
44+
found = true;
45+
break;
46+
}
47+
if (!found) {
48+
// no deployment means we buried it and aren't using the same bit (yet)
49+
LogPrintf("CMNHFManager::GetSignalsStage: mnhf signal bit=%d height:%d is not known at height=%d\n", it->first, it->second, height);
3250
it = signals.erase(it);
33-
} else {
34-
++it;
35-
}
51+
}
3652
}
3753
return signals;
3854
}

test/functional/feature_mnehf.py

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
class MnehfTest(DashTestFramework):
2727
def set_test_params(self):
28-
extra_args = [["-vbparams=testdummy:0:999999999999:12:12:12:5:0"] for _ in range(4)]
28+
extra_args = [["-vbparams=testdummy:0:999999999999:12:12:12:5:0", "-persistmempool=0"] for _ in range(4)]
2929
self.set_dash_test_params(4, 3, fast_dip3_enforcement=True, extra_args=extra_args)
3030

3131
def skip_test_if_missing_module(self):
@@ -164,14 +164,12 @@ def run_test(self):
164164
ehf_tx_sent = self.send_tx(ehf_tx)
165165
ehf_unknown_tx_sent = self.send_tx(ehf_unknown_tx)
166166
self.send_tx(ehf_invalid_tx, expected_error='bad-mnhf-non-ehf')
167-
node.generate(1)
168-
ehf_height = node.getblockcount()
167+
ehf_blockhash = node.generate(1)[0]
169168
self.sync_all()
170169

171-
ehf_block = node.getbestblockhash()
172-
self.log.info(f"Check MnEhfTx {ehf_tx_sent} was mined in {ehf_block}")
173-
assert ehf_tx_sent in node.getblock(ehf_block)['tx']
174-
assert ehf_unknown_tx_sent in node.getblock(ehf_block)['tx']
170+
self.log.info(f"Check MnEhfTx {ehf_tx_sent} was mined in {ehf_blockhash}")
171+
assert ehf_tx_sent in node.getblock(ehf_blockhash)['tx']
172+
assert ehf_unknown_tx_sent in node.getblock(ehf_blockhash)['tx']
175173

176174
self.log.info(f"MnEhf tx: '{ehf_tx}' is sent: {ehf_tx_sent}")
177175
self.log.info(f"MnEhf 'unknown' tx: '{ehf_unknown_tx}' is sent: {ehf_unknown_tx_sent}")
@@ -201,10 +199,10 @@ def run_test(self):
201199

202200
self.check_fork('active')
203201

204-
block_fork_active = node.getbestblockhash()
205-
self.log.info(f"Invalidate block: {ehf_block} with tip {block_fork_active}")
202+
fork_active_blockhash = node.getbestblockhash()
203+
self.log.info(f"Invalidate block: {ehf_blockhash} with tip {fork_active_blockhash}")
206204
for inode in self.nodes:
207-
inode.invalidateblock(ehf_block)
205+
inode.invalidateblock(ehf_blockhash)
208206

209207
self.log.info("Expecting for fork to be defined in next blocks because no MnEHF tx here")
210208
for i in range(12):
@@ -215,12 +213,11 @@ def run_test(self):
215213

216214
self.log.info("Re-sending MnEHF for new fork")
217215
tx_sent_2 = self.send_tx(ehf_tx)
218-
node.generate(1)
216+
ehf_blockhash_2 = node.generate(1)[0]
219217
self.sync_all()
220218

221-
ehf_block_2 = node.getbestblockhash()
222-
self.log.info(f"Check MnEhfTx again {tx_sent_2} was mined in {ehf_block_2}")
223-
assert tx_sent_2 in node.getblock(ehf_block_2)['tx']
219+
self.log.info(f"Check MnEhfTx again {tx_sent_2} was mined in {ehf_blockhash_2}")
220+
assert tx_sent_2 in node.getblock(ehf_blockhash_2)['tx']
224221

225222
self.log.info(f"Generate some more block to jump to `started` status")
226223
for i in range(12):
@@ -230,42 +227,43 @@ def run_test(self):
230227
self.check_fork('started')
231228

232229

233-
self.log.info(f"Re-consider block {ehf_block} to the old MnEHF and forget new fork")
230+
self.log.info(f"Re-consider block {ehf_blockhash} to the old MnEHF and forget new fork")
234231
for inode in self.nodes:
235-
inode.reconsiderblock(ehf_block)
236-
assert_equal(node.getbestblockhash(), block_fork_active)
232+
inode.reconsiderblock(ehf_blockhash)
233+
assert_equal(node.getbestblockhash(), fork_active_blockhash)
237234

238235
self.check_fork('active')
239236
self.restart_all_nodes()
240237
self.check_fork('active')
241238

239+
self.log.info("Testing duplicate EHF signal with same bit")
240+
ehf_tx_duplicate = self.send_tx(self.create_mnehf(28, pubkey))
241+
tip_blockhash = node.generate(1)[0]
242+
self.sync_blocks()
243+
block = node.getblock(tip_blockhash)
244+
assert ehf_tx_duplicate in node.getrawmempool() and ehf_tx_duplicate not in block['tx']
245+
246+
self.log.info("Testing EHF signal with same bit but with newer start time")
242247
self.bump_mocktime(int(60 * 60 * 24 * 14))
243248
node.generate(1)
244-
self.sync_all()
249+
self.sync_blocks()
245250
self.restart_all_nodes(params=[self.mocktime, self.mocktime + 1000000])
246251
self.mine_quorum()
247252

248-
ehf_tx_second = self.create_mnehf(28, pubkey)
249-
assert_equal(get_bip9_details(node, 'testdummy')['status'], 'defined')
253+
ehf_tx_new_start = self.create_mnehf(28, pubkey)
254+
self.check_fork('defined')
250255

251-
self.log.info("Testing EHF signal with same bit")
252-
self.log.info(f"Previous signal at height={ehf_height}, total blocks={node.getblockcount()}, should success at {ehf_height + 576}")
253-
self.slowly_generate_batch(576 - (node.getblockcount() - ehf_height) - 1)
254-
ehf_tx_sent = self.send_tx(ehf_tx_second)
255-
self.log.info("Mine block and ensure not mined yet...")
256-
node.generate(1)
257-
self.ensure_tx_is_not_mined(ehf_tx_sent)
258-
node.generate(1)
256+
self.log.info("Mine one block and ensure EHF tx for the new deployment is mined")
257+
ehf_tx_sent = self.send_tx(ehf_tx_new_start)
258+
tip_blockhash = node.generate(1)[0]
259259
self.sync_all()
260-
self.log.info("Mine one more block and ensure it is mined")
261-
block = node.getblock(node.getbestblockhash())
260+
block = node.getblock(tip_blockhash)
262261
assert ehf_tx_sent in block['tx']
263262

264263
self.check_fork('defined')
265264
self.slowly_generate_batch(12 * 4)
266265
self.check_fork('active')
267266

268267

269-
270268
if __name__ == '__main__':
271269
MnehfTest().main()

0 commit comments

Comments
 (0)