mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-05 14:06:27 -05:00
miner: adjust clock to timewarp rule
This commit is contained in:
parent
e929054e12
commit
59ff17e5af
4 changed files with 24 additions and 15 deletions
|
@ -27,4 +27,11 @@ static const size_t MIN_SERIALIZABLE_TRANSACTION_WEIGHT = WITNESS_SCALE_FACTOR *
|
||||||
/** Interpret sequence numbers as relative lock-time constraints. */
|
/** Interpret sequence numbers as relative lock-time constraints. */
|
||||||
static constexpr unsigned int LOCKTIME_VERIFY_SEQUENCE = (1 << 0);
|
static constexpr unsigned int LOCKTIME_VERIFY_SEQUENCE = (1 << 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of seconds that the timestamp of the first
|
||||||
|
* block of a difficulty adjustment period is allowed to
|
||||||
|
* be earlier than the last block of the previous period (BIP94).
|
||||||
|
*/
|
||||||
|
static constexpr int64_t MAX_TIMEWARP = 600;
|
||||||
|
|
||||||
#endif // BITCOIN_CONSENSUS_CONSENSUS_H
|
#endif // BITCOIN_CONSENSUS_CONSENSUS_H
|
||||||
|
|
|
@ -33,6 +33,14 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam
|
||||||
int64_t nOldTime = pblock->nTime;
|
int64_t nOldTime = pblock->nTime;
|
||||||
int64_t nNewTime{std::max<int64_t>(pindexPrev->GetMedianTimePast() + 1, TicksSinceEpoch<std::chrono::seconds>(NodeClock::now()))};
|
int64_t nNewTime{std::max<int64_t>(pindexPrev->GetMedianTimePast() + 1, TicksSinceEpoch<std::chrono::seconds>(NodeClock::now()))};
|
||||||
|
|
||||||
|
if (consensusParams.enforce_BIP94) {
|
||||||
|
// Height of block to be mined.
|
||||||
|
const int height{pindexPrev->nHeight + 1};
|
||||||
|
if (height % consensusParams.DifficultyAdjustmentInterval() == 0) {
|
||||||
|
nNewTime = std::max<int64_t>(nNewTime, pindexPrev->GetBlockTime() - MAX_TIMEWARP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (nOldTime < nNewTime) {
|
if (nOldTime < nNewTime) {
|
||||||
pblock->nTime = nNewTime;
|
pblock->nTime = nNewTime;
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,13 +107,6 @@ const std::vector<std::string> CHECKLEVEL_DOC {
|
||||||
* */
|
* */
|
||||||
static constexpr int PRUNE_LOCK_BUFFER{10};
|
static constexpr int PRUNE_LOCK_BUFFER{10};
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum number of seconds that the timestamp of the first
|
|
||||||
* block of a difficulty adjustment period is allowed to
|
|
||||||
* be earlier than the last block of the previous period (BIP94).
|
|
||||||
*/
|
|
||||||
static constexpr int64_t MAX_TIMEWARP = 600;
|
|
||||||
|
|
||||||
GlobalMutex g_best_block_mutex;
|
GlobalMutex g_best_block_mutex;
|
||||||
std::condition_variable g_best_block_cv;
|
std::condition_variable g_best_block_cv;
|
||||||
uint256 g_best_block;
|
uint256 g_best_block;
|
||||||
|
|
|
@ -28,6 +28,7 @@ from test_framework.p2p import P2PDataStore
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import (
|
from test_framework.util import (
|
||||||
assert_equal,
|
assert_equal,
|
||||||
|
assert_greater_than_or_equal,
|
||||||
assert_raises_rpc_error,
|
assert_raises_rpc_error,
|
||||||
get_fee,
|
get_fee,
|
||||||
)
|
)
|
||||||
|
@ -139,24 +140,24 @@ class MiningTest(BitcoinTestFramework):
|
||||||
|
|
||||||
self.log.info("First block template of retarget period can't use wall clock time")
|
self.log.info("First block template of retarget period can't use wall clock time")
|
||||||
self.nodes[0].setmocktime(t)
|
self.nodes[0].setmocktime(t)
|
||||||
assert_raises_rpc_error(-1, "time-timewarp-attack, block's timestamp is too early on diff adjustment block",
|
# The template will have an adjusted timestamp, which we then modify
|
||||||
lambda: node.getblocktemplate(NORMAL_GBT_REQUEST_PARAMS))
|
|
||||||
|
|
||||||
# Create template with an acceptable timestamp and then modify it
|
|
||||||
self.nodes[0].setmocktime(t + MAX_FUTURE_BLOCK_TIME)
|
|
||||||
tmpl = node.getblocktemplate(NORMAL_GBT_REQUEST_PARAMS)
|
tmpl = node.getblocktemplate(NORMAL_GBT_REQUEST_PARAMS)
|
||||||
|
assert_greater_than_or_equal(tmpl['curtime'], t + MAX_FUTURE_BLOCK_TIME - MAX_TIMEWARP)
|
||||||
|
|
||||||
block = CBlock()
|
block = CBlock()
|
||||||
block.nVersion = tmpl["version"]
|
block.nVersion = tmpl["version"]
|
||||||
block.hashPrevBlock = int(tmpl["previousblockhash"], 16)
|
block.hashPrevBlock = int(tmpl["previousblockhash"], 16)
|
||||||
block.nTime = t
|
block.nTime = tmpl["curtime"]
|
||||||
block.nBits = int(tmpl["bits"], 16)
|
block.nBits = int(tmpl["bits"], 16)
|
||||||
block.nNonce = 0
|
block.nNonce = 0
|
||||||
block.vtx = [create_coinbase(height=int(tmpl["height"]))]
|
block.vtx = [create_coinbase(height=int(tmpl["height"]))]
|
||||||
block.solve()
|
block.solve()
|
||||||
|
assert_template(node, block, None)
|
||||||
|
|
||||||
self.nodes[0].setmocktime(t)
|
bad_block = copy.deepcopy(block)
|
||||||
assert_raises_rpc_error(-25, 'time-timewarp-attack', lambda: node.submitheader(hexdata=CBlockHeader(block).serialize().hex()))
|
bad_block.nTime = t
|
||||||
|
bad_block.solve()
|
||||||
|
assert_raises_rpc_error(-25, 'time-timewarp-attack', lambda: node.submitheader(hexdata=CBlockHeader(bad_block).serialize().hex()))
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
node = self.nodes[0]
|
node = self.nodes[0]
|
||||||
|
|
Loading…
Add table
Reference in a new issue