Skip to content

Commit ef8dfe4

Browse files
committed
Prevent block.nTime from decreasing
Under some circumstances it is possible for there to be a significant, discontinuous jump in a node's clock value. On mining nodes, this can result in block templates which are no longer valid due to time-based nLockTime constraints. UpdateTime() is modified so that it will never decrease a block's nLockTime, thereby preventing such invalidations.
1 parent ce56f56 commit ef8dfe4

File tree

2 files changed

+14
-5
lines changed

2 files changed

+14
-5
lines changed

src/miner.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,19 @@ class TxPriorityCompare
8181
}
8282
};
8383

84-
void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
84+
int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
8585
{
86-
pblock->nTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
86+
int64_t nOldTime = pblock->nTime;
87+
int64_t nNewTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
88+
89+
if (nOldTime < nNewTime)
90+
pblock->nTime = nNewTime;
8791

8892
// Updating time can change work required on testnet:
8993
if (consensusParams.fPowAllowMinDifficultyBlocks)
9094
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
95+
96+
return nNewTime - nOldTime;
9197
}
9298

9399
CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
@@ -138,6 +144,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
138144
LOCK2(cs_main, mempool.cs);
139145
CBlockIndex* pindexPrev = chainActive.Tip();
140146
const int nHeight = pindexPrev->nHeight + 1;
147+
pblock->nTime = GetAdjustedTime();
141148
CCoinsViewCache view(pcoinsTip);
142149

143150
// Priority order to process transactions
@@ -152,7 +159,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
152159
mi != mempool.mapTx.end(); ++mi)
153160
{
154161
const CTransaction& tx = mi->second.GetTx();
155-
if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight))
162+
if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight, pblock->nTime))
156163
continue;
157164

158165
COrphan* porphan = NULL;
@@ -529,7 +536,9 @@ void static BitcoinMiner(CWallet *pwallet)
529536
break;
530537

531538
// Update nTime every few seconds
532-
UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev);
539+
if (UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev) < 0)
540+
break; // Recreate the block if the clock has run backwards,
541+
// so that we can use the correct time.
533542
if (chainparams.GetConsensus().fPowAllowMinDifficultyBlocks)
534543
{
535544
// Changing pblock->nTime can change work required on testnet:

src/miner.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,6 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn);
3030
CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey);
3131
/** Modify the extranonce in a block */
3232
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
33-
void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev);
33+
int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev);
3434

3535
#endif // BITCOIN_MINER_H

0 commit comments

Comments
 (0)