Background
The original Great Consensus Cleanup soft fork proposal by @MattCorallo says the following:
- Sadly, some deployed mining hardware relies on the ability to roll nTime forward by up to 600 seconds[3]. Thus, only requiring that the nTime field move forward during difficulty adjustment would allow a malicious miner to prevent some competitors from mining the next block by setting their timestamp to two hours in the future. Thus, we allow nTime to go backwards by 600 seconds, ensuring that even a block with a timestamp two hours in the future allows for 600 seconds of nTime rolling on the next block.
The footnote explains why 600 is probably the upper bound:
[3] While no official stratum specification exists, the btc.com pool server (one of the most popular pool servers today) rejects shares with timestamps more than 600 seconds in the future at btcpool-ABANDONED/src/bitcoin/StratumServerBitcoin.cc at e7c536834fd6785af7d7d68ff29111ed81209cdf · btccom/btcpool-ABANDONED · GitHub. While there are few resources describing hardware operation today, timestamp rolling can be observed on the chain (in some rare cases) as block timestamps go backwards when a miner rolled one block nTime forward and the next does not, but only incredibly rarely more than 600 seconds.
nTime
rolling is also not likely to go away. It’s potentially useful for ASIC devices that can go beyond 280 TH/s. As explained in sv2-spec/05-Mining-Protocol.md at 52e1fa22f68c343a3d25a2b1a04f93f8e701eced · stratum-mining/sv2-spec · GitHub :
The size of the search space for one Standard Job, given a fixed
nTime
field, is2^(NONCE_BITS + BIP320_VERSION_ROLLING_BITS) = ~280Th
, whereNONCE_BITS = 32
andBIP320_VERSION_ROLLING_BITS = 16
. This is a guaranteed space beforenTime
rolling (or changing the Merkle Root by sending a new Job).
This nTime
rolling could be limited to similar numbers. E.g. a hypothetical 3 peta hash beast would need to roll the timestamp by 10 seconds every second. If it gets a new template every 30 seconds, it would roll by 300 seconds. Beyond that a pool proxy could (and should) just roll the extranonce and feed the miner a new template more frequently.
Current proposal and implementation
The timewarp fix currently deployed on testnet4 also allows nTime
to go backwards by 600 seconds.
Currently when Bitcoin Core proposes a new block template it will determine the timestamp as follows:
- Current time
- If the MTP rule requires it, bump time
- On testnet4, for the first block of a retarget period, if the previous block is from the future, bump time again, but minus 10 minutes.
See bitcoin/src/node/miner.cpp at 733fa0b0a140fc1e40c644a29953db090baa2890 · bitcoin/bitcoin · GitHub
The problem
The 600 second grace period is cutting it too close imo, and we should consider increasing it to 2 hours for any future proposal (see Zawy’s Alternating Timestamp Attack and https://delvingbitcoin.org/t/great-consensus-cleanup-revival/).
For the discussion here I’ll assume that the pool software[0] and miner firmware doesn’t ignore the template timestamp.
Now if a malicious miners set their timestamp 2 hours in the future, relative to our node clock, and if our template is used by an ASIC that wants to roll nTime forward by up to 600 seconds, this is only safe if we assume all our peers have a matching clock. But that defeats the purpose of the 2 hour future rule: we shouldn’t assume nodes have accurate clocks.
We should also strongly discourage nTime
rolling beyond a few minutes, so as to not eat too much into the network wide two hour tolerance for inaccurate clocks.
[0] public-pool (Ensure mintime is considered for jobs · benjamin-wilson/public-pool@4282233 · GitHub) and SRI (fix coming) ignored the template timestamp, which only became obvious on testnet4 because its timestamps are far in the future. But these are not production environments.