§ 09

§ 09 · Difficulty

Timestamps

Why a miner's clock matters when difficulty moves every block

A block’s timestamp is the miner’s word on when the block was made. Nobody can check it exactly: there is no clock everyone shares.

On Bitcoin a wrong timestamp matters much less, because difficulty looks at time only once every 2,016 blocks. On Pearl, difficulty moves after every block, using the gap between two timestamps. So Pearl needs rules that keep every gap positive and every lie small.

This page is about those rules and what they protect. How the 4 bytes are stored and decoded is on time.

Try it

Fake some slow blocks and watch the target loosen, then see the next blocks pull it back.

WTEMA simulator

Hashrate jumps; the target follows, a little after every block

Simulation Blocks arrive at random, as on the real network, but the hashrate and timeline are made up. Times are random draws, not chain data.

Demo run · Block 8,064 of 8,064 day 17.1 WTEMA avg 232 s · diff ×1.15 Bitcoin-style avg 272 s · diff ×1.36

After 8,064 blocks: hashrate ×1.00. WTEMA: last 144 blocks averaged 232 s, difficulty ×1.15. Bitcoin-style: 272 s, difficulty ×1.36.

This demo doubles the hashrate at block 1,500 and drops it back at 5,000. WTEMA starts correcting with the very next block and closes the gap smoothly, about 63% of it per week of clock time (its one-week time constant). The 2,016-block rule does nothing until its window ends, then jumps all at once, and lags again when the hashrate changes back: blocks run slow until its next window ends.

One step, exactly as pearld does it

The chart uses floating point for speed. pearld uses whole numbers: new target = old + ⌊(t − 194) × old ÷ 604,800⌋, clamped to [1, PowLimit], then rounded into bits.

old target
0x6af3a60000000000000000000000000000000000000000
t − T
300 − 194 = 106 s
adjustment
⌊106 × old ÷ 604,800⌋ = 0x4cc76689133bde689133bde689133bde689133bde68
new target
0x6af87276689133bde689133bde689133bde689133bde68
next bits
0x176af3a6 → 0x176af872
difficulty
40,157,376.49334089 → 40,150,342.21117200 (-0.0175%)

Slower than 194 s, so the target rises a little: the next block gets slightly easier. One block moves it by a fraction of a percent, but the steps compound: if blocks run late by 604,800 seconds in total (one week), the target grows by a factor of about e ≈ 2.72.

Runs in your browser · simulated, not chain data src/lib/wtema.ts · T = 194 s, τ = 604,800 s

What are the rules?

A node accepts a block’s timestamp only inside this window:

Pearl's timestamp window
Field Size Description
Lower bound — At least 1 second after the parent's timestamp. Anything earlier fails with ErrTimeTooOld.
Upper bound — At most 5 minutes past the node's network-adjusted time. Anything later fails with ErrTimeTooNew.

Pearl’s own code was run on the edges: the parent’s second is rejected, parent + 1 s is accepted, the node’s adjusted time + 5 min 0 s is accepted, and + 5 min 1 s is rejected.

The upper bound is checked against the receiving node’s own idea of the time, so it can differ slightly from node to node. The lower bound depends only on the chain, so every node agrees on it.

What is network-adjusted time?

Every node has its own clock, and some clocks are wrong. So a node uses network-adjusted time: its own clock, shifted by the median of the time differences its peers report when they connect. Offsets beyond ±70 minutes are ignored. This is btcd’s logic, unchanged.

Why did Pearl drop the median rule?

Bitcoin only requires a block to be later than the median time past (MTP), the median of the previous 11 timestamps. That lets block times go backwards a little, and the gap between a block and its parent can be zero or negative.

That would break Pearl’s difficulty rule. WTEMA computes the next target from the parent’s solve time, t = its timestamp minus its own parent’s:

Xnext=X+⌊(t−194)⋅X604,800⌋X_{\text{next}} = X + \left\lfloor \frac{(t - 194) \cdot X}{604{,}800} \right\rfloor

A negative t would be read as a block found impossibly fast. So Pearl requires t ≥ 1. The code comment says it plainly: the rule “is stricter than the original median-time rule and makes the median time check redundant. Required for WTEMA difficulty adjustment.”

It also caps how fast difficulty can climb: with t ≥ 1, one block can shrink the target by at most a factor of (1 − 193 ÷ 604,800) = 0.99968.

Can a miner cheat with the clock?

Not by much. Here is why.

Each block multiplies the target by about (1 + (t − 194) ÷ 604,800). Over several blocks the factors multiply, and the gaps t add up. But the gaps telescope: their sum is just the newest timestamp minus the oldest. So, to a very good approximation, the target after a run of blocks depends on the newest timestamp, not on the ones in between. A lie in the middle is undone by the blocks after it, which must be stamped later still.

The only timestamp that is never “undone” is the newest one, and the 5-minute rule limits it. Five minutes of fake lateness moves the next target by at most 300 ÷ 604,800, about 0.05%.

Where does the median time past still matter?

In lock times. The rule for blocks changed; the rule for transactions did not. A transaction locked until a certain time becomes valid when the MTP of the last 11 blocks passes that time (BIP-113), and relative time locks (BIP-68) measure from the MTP too, exactly as in Bitcoin. See locktime and sequence.

On Pearl, the MTP has a neat shortcut. Every timestamp is later than its parent’s, so the last 11 are already in order, and their median is just the 6th newest. At the normal pace that’s about 5 × 194 = 970 seconds, roughly 16 minutes, behind the newest block.

What did launch look like?

Genesis is stamped 1,777,280,400: 2026-04-27 09:00:00 UTC. Blocks 1 to 5 followed at 1,777,280,401, …402, …403, …404 and …405: exactly one second apart, the minimum the rules allow.

At difficulty 1 that was all the time miners needed. Each 1-second block tightened the target by the largest step WTEMA allows, which is how difficulty began its climb. The full story is on WTEMA.

Make a guess

Could a miner stamp a block 90 minutes in the future, which Bitcoin's 2-hour rule allows?

Think of your answer first, then check it.

Answer No. Every node rejects it as too new.

Pearl’s limit is 5 minutes past network-adjusted time, so a node that receives a block stamped 90 minutes ahead fails it with ErrTimeTooNew. On Bitcoin, the same block would pass the time check.

Code: the two checks and their parameters

The lower bound, from validate.go (node/blockchain/validate.go:686-696 at v1.5.2, on GitHub), with MinTimestampDeltaSeconds = 1 at line 26 (node/blockchain/validate.go:23-26 at v1.5.2, on GitHub):

node/blockchain/validate.go Go
prevTimestamp := time.Unix(prevNode.Timestamp(), 0)
minTimestamp := prevTimestamp.Add(time.Duration(MinTimestampDeltaSeconds) * time.Second)
if header.Timestamp.Before(minTimestamp) {
	return ruleError(ErrTimeTooOld, str)
}

The upper bound, from validate.go (node/blockchain/validate.go:390-396 at v1.5.2, on GitHub), with MaxTimeOffsetMinutes: 5 in params.go (node/chaincfg/params.go:362 at v1.5.2, on GitHub) (regtest and simnet use 120):

node/blockchain/validate.go Go
maxTimestamp := timeSource.AdjustedTime().Add(time.Minute * time.Duration(maxTimeOffsetMinutes))
if header.Timestamp.After(maxTimestamp) {
	return ruleError(ErrTimeTooNew, str)
}

The adjusted time comes from mediantime.go (node/blockchain/mediantime.go:14-30 at v1.5.2, on GitHub), and lock-time finality still uses CalcPastMedianTime in validate.go (node/blockchain/validate.go:768-781 at v1.5.2, on GitHub).

The codex

Suggested

Up and down arrows move through the results, Enter opens one, Escape closes. Anywhere on the site, slash or Command K opens this search, and the square brackets [ and ] go to the previous and next page.