difficulty-adjustment-algorithm.md raw

Limenka Difficulty Adjustment Algorithm

The fork replaces Bitcoin's 2016-block retarget with a continuous single-lane PI difficulty controller that activates at the fork gate and runs for every fork-era block. Everything below is per-block, no windows.

Activation

MTP(pindexPrev) + nForkActivationBias >= nForkActivationMTP.

blocks back, so the bias compensates the lag and activation lands near the intended wall time (handoff sim: ~1.7h lag vs 6-8h unbiased).

parent chain's difficulty without a jump.

Measurement

stamp delta, not a window average).

nTime <= now + 60s (nForkFutureLimit).

PI controller (asymmetric)

600 because the asymmetric integral rectifies: fast blocks get a small correction (slow to raise), slow blocks get a large one (fast to lower), so the naive 600 setpoint would land long-term above 600. With 617 the steady-state mean measures 601.1s over 10 seeds.

kp = 10,000,000.

avg = 0.95 * avg + 0.05 * error (alpha = 0.05). Asymmetric gains: ki_up = 5,000,000 when the chain is fast (raise slowly, flood-proof), ki_down = 50,000,000 when slow (lower fast, quick restore) - a 10x asymmetry.

SNR 1, and the derivative carries 3-5x more noise than signal.

correction = (ki avg + kp error) / 1e6 denom = clamp(1e6 + correction, 1e5, 1e7) target = prev_target * 1e6 / denom

The denominator clamp bounds any single block's difficulty change to a factor of 10 up or down.

State and persistence

nForkAvgError (the EMA accumulator), nForkLastBlockTime (the previous fork block's stamp), and nForkAggregateSeconds (the halving counter, below).

(no reset), the first interval is assumed to be the 617s setpoint, and the EMA starts at zero.

is missing (headers-first sync, restart with an older index, freshly loaded blocks) it is recomputed deterministically from the activation point and memoized on the entries - the validity function is identical for an uptime node, a restarted node, and a fresh sync.

Time-proportional block weight

fixed 4 MW cap:

payloadlimit = Smax * e / 600

where S_max is the 4 MW block budget, and the header plus coinbase are subtracted by the caller. A late block clears the backlog accumulated during a stall; a fast block carries less.

serialized size, so the cap and the fee market price bytes honestly.

Time-proportional subsidy

halvings = nForkAggregateSeconds / (600 * 210000) subsidy = (50 COIN >> halvings) * e / 600

The shift is capped at 63 (past that the subsidy is zero) so the shift is never undefined behavior.

(time-anchored halving tracks wall clock). At the activation boundary it seeds from height * 600 so the fork continues the parent chain's halving schedule instead of restarting at 50 COIN.

identical e the consensus checks, including the floor at 1.

Sim-validated behavior

setpoint.

Related fork machinery (not part of the DAA)

~60s on reference hardware, committed in the coinbase) is a separate per-block consensus feature. It cannot be precomputed, so it indirectly disciplines cadence by making every fork block cost its miner a fixed sequential 60 seconds.

powLimit, no DAA - used by the functional tests and testnet bootstrap.