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.
This commit is contained in:
Mark Friedenbach 2015-05-22 14:49:50 -07:00
parent ce56f5621a
commit ef8dfe41d1
2 changed files with 14 additions and 5 deletions

View file

@ -81,13 +81,19 @@ public:
} }
}; };
void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev) int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
{ {
pblock->nTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); int64_t nOldTime = pblock->nTime;
int64_t nNewTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
if (nOldTime < nNewTime)
pblock->nTime = nNewTime;
// Updating time can change work required on testnet: // Updating time can change work required on testnet:
if (consensusParams.fPowAllowMinDifficultyBlocks) if (consensusParams.fPowAllowMinDifficultyBlocks)
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams); pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
return nNewTime - nOldTime;
} }
CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
@ -138,6 +144,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
LOCK2(cs_main, mempool.cs); LOCK2(cs_main, mempool.cs);
CBlockIndex* pindexPrev = chainActive.Tip(); CBlockIndex* pindexPrev = chainActive.Tip();
const int nHeight = pindexPrev->nHeight + 1; const int nHeight = pindexPrev->nHeight + 1;
pblock->nTime = GetAdjustedTime();
CCoinsViewCache view(pcoinsTip); CCoinsViewCache view(pcoinsTip);
// Priority order to process transactions // Priority order to process transactions
@ -152,7 +159,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
mi != mempool.mapTx.end(); ++mi) mi != mempool.mapTx.end(); ++mi)
{ {
const CTransaction& tx = mi->second.GetTx(); const CTransaction& tx = mi->second.GetTx();
if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight)) if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight, pblock->nTime))
continue; continue;
COrphan* porphan = NULL; COrphan* porphan = NULL;
@ -529,7 +536,9 @@ void static BitcoinMiner(CWallet *pwallet)
break; break;
// Update nTime every few seconds // Update nTime every few seconds
UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); if (UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev) < 0)
break; // Recreate the block if the clock has run backwards,
// so that we can use the correct time.
if (chainparams.GetConsensus().fPowAllowMinDifficultyBlocks) if (chainparams.GetConsensus().fPowAllowMinDifficultyBlocks)
{ {
// Changing pblock->nTime can change work required on testnet: // Changing pblock->nTime can change work required on testnet:

View file

@ -30,6 +30,6 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn);
CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey); CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey);
/** Modify the extranonce in a block */ /** Modify the extranonce in a block */
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce); void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev); int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev);
#endif // BITCOIN_MINER_H #endif // BITCOIN_MINER_H