aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMark Friedenbach <mark@friedenbach.org>2015-05-22 14:49:50 -0700
committerMark Friedenbach <mark@friedenbach.org>2015-05-27 14:03:11 -0700
commitef8dfe41d1eba0de6d6554e25e658169f97313b5 (patch)
treefb269c424ccf2fe715c639df712dba7ae1cf34dc /src
parentce56f5621a94dcc2159ebe57e43da727eab18e6c (diff)
downloadbitcoin-ef8dfe41d1eba0de6d6554e25e658169f97313b5.tar.xz
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.
Diffstat (limited to 'src')
-rw-r--r--src/miner.cpp17
-rw-r--r--src/miner.h2
2 files changed, 14 insertions, 5 deletions
diff --git a/src/miner.cpp b/src/miner.cpp
index 7a57b42e30..693e04dec2 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -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:
if (consensusParams.fPowAllowMinDifficultyBlocks)
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
+
+ return nNewTime - nOldTime;
}
CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
@@ -138,6 +144,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
LOCK2(cs_main, mempool.cs);
CBlockIndex* pindexPrev = chainActive.Tip();
const int nHeight = pindexPrev->nHeight + 1;
+ pblock->nTime = GetAdjustedTime();
CCoinsViewCache view(pcoinsTip);
// Priority order to process transactions
@@ -152,7 +159,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
mi != mempool.mapTx.end(); ++mi)
{
const CTransaction& tx = mi->second.GetTx();
- if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight))
+ if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight, pblock->nTime))
continue;
COrphan* porphan = NULL;
@@ -529,7 +536,9 @@ void static BitcoinMiner(CWallet *pwallet)
break;
// 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)
{
// Changing pblock->nTime can change work required on testnet:
diff --git a/src/miner.h b/src/miner.h
index 96a6b70ecd..d46f4b1f2d 100644
--- a/src/miner.h
+++ b/src/miner.h
@@ -30,6 +30,6 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn);
CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey);
/** Modify the extranonce in a block */
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