Skip to content

Commit 9831458

Browse files
committed
Ensure that the "future timestamp" rule is correctly applied by block
template construction. fixes zcash#6960 Signed-off-by: Daira-Emma Hopwood <[email protected]>
1 parent a0602eb commit 9831458

File tree

2 files changed

+36
-5
lines changed

2 files changed

+36
-5
lines changed

src/miner.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam
7575
nNewTime = std::min(nNewTime, medianTimePast + MAX_FUTURE_BLOCK_TIME_MTP);
7676
}
7777

78+
// The timestamp of a given block template should not go backwards.
7879
if (nOldTime < nNewTime)
7980
pblock->nTime = nNewTime;
8081

@@ -366,7 +367,11 @@ CBlockTemplate* BlockAssembler::CreateNewBlock(
366367
if (chainparams.MineBlocksOnDemand())
367368
pblock->nVersion = GetArg("-blockversion", pblock->nVersion);
368369

369-
pblock->nTime = GetTime();
370+
// Setting nTime to 0 and then calling UpdateTime ensures that it is set to the
371+
// nearest timestamp to the current time in the consensus-valid range (see #6960).
372+
pblock->nTime = 0;
373+
UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev);
374+
370375
const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast();
371376
CCoinsViewCache view(pcoinsTip);
372377

src/test/miner_tests.cpp

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -372,18 +372,44 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
372372
// Stop here if we needed to mine more blocks.
373373
assert(nblocks == sizeof(blockinfo)/sizeof(*blockinfo));
374374

375+
auto nTime = pblocktemplate->block.nTime;
376+
delete pblocktemplate;
377+
375378
// Set the clock to be just ahead of the last "mined" block, to ensure we satisfy the
376379
// future timestamp soft fork rule.
377-
auto curTime = GetTime();
378-
OffsetClock::SetGlobal();
379-
OffsetClock::Instance()->Set(std::chrono::seconds(-curTime + pblocktemplate->block.nTime));
380+
FixedClock::SetGlobal();
381+
FixedClock::Instance()->Set(std::chrono::seconds(nTime));
380382

383+
// Just to make sure we can still make simple blocks
384+
BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey));
385+
BOOST_CHECK_EQUAL(pblocktemplate->block.nTime, nTime);
386+
387+
auto mtp = chainActive.Tip()->GetMedianTimePast();
381388
delete pblocktemplate;
389+
auto minTime = mtp + 1;
390+
auto maxTime = mtp + MAX_FUTURE_BLOCK_TIME_MTP;
382391

383-
// Just to make sure we can still make simple blocks
392+
// Set the clock to be too far ahead of the MTP, violating the future timestamp rule.
393+
FixedClock::Instance()->Set(std::chrono::seconds(maxTime + 1));
394+
395+
// This should succeed, and nTime should be clamped to the maximum consensus-valid value.
396+
BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey));
397+
BOOST_CHECK_EQUAL(pblocktemplate->block.nTime, maxTime);
398+
delete pblocktemplate;
399+
400+
// Set the clock to be equal to the median-time-past, violating the rule that it must
401+
// be after the MTP.
402+
FixedClock::Instance()->Set(std::chrono::seconds(minTime - 1));
403+
404+
// This should succeed, and nTime should be clamped to the minimum consensus-valid value.
384405
BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey));
406+
BOOST_CHECK_EQUAL(pblocktemplate->block.nTime, minTime);
385407
delete pblocktemplate;
386408

409+
auto curTime = GetTime();
410+
OffsetClock::SetGlobal();
411+
OffsetClock::Instance()->Set(std::chrono::seconds(-curTime + nTime));
412+
387413
TestMemPoolEntryHelper entry;
388414
entry.nFee = 0;
389415
entry.nHeight = 0;

0 commit comments

Comments
 (0)