ECIP 1099: Calibrate Epoch Duration Source

AuthorLuke Williams
TypeStandards Track
Replaces 1043


The purpose of this ECIP is to calibrate the epoch length used in DAG calculations.


The original intent of the DAG was to provide ASIC resistance to the mining protocol in order to prevent centralization of mining distributions and thereby provide for an objectively fair distribution of tokens. As evident by ASICs being developed that are capable of matching current GPU miners while being more energy efficient, the DAG has succeeded in leveling the playing field between GPU incumbents and ASIC challengers, avoiding ASIC takeover and domination, and leading to a competitive and large mining ecosystem. However the original parameters are proving too aggressive, resulting in obsoleting support for GPUs still in wide use today by miners.

Calibrating these parameters to better reflect todays hardware markets and mining ecosystem will bring the DAG growth back in sync with commonly used GPUs. Allowing the DAG system to continue to serve it’s purpose far into the future.


const oldEpochLength = 30000
const newEpochLength = 60000
const activationBlock = n

// calcEpochLength returns the epoch length for a given block number.
func calcEpochLength(blockNum uint64) uint64 {
  if(blockNum < activationBlock) {
    return oldEpochLength
  return newEpochLength

// calcEpoch returns the epoch for a given block number
func calcEpoch(block uint64) int {
  epochLength := calcEpochLength(block)
  epoch := int(block / epochLength)
  return epoch

// seedHash is the seed to use for generating a verification cache and the
// mining dataset.
func seedHash(block uint64) []byte {
  seed := make([]byte, 32)
  if block < oldEpochLength {
    return seed
  // keep using oldEpochLength here so seeds don't overlap
  keccak256 := makeHasher(sha3.NewLegacyKeccak256())
  for i := 0; i < int(block/oldEpochLength); i++ {
    keccak256(seed, seed)
  return seed

The oldEpochLength (30000) changes to newEpochLength (60000) at a given activationBlock (hardfork required).

This will result in the epoch (blockNumber/[old/new]EpochLength) halving upon activation. As the DAG cache and dataset sizes are calculated from epoch, the growth in which they have experienced too will half upon activation. DAG caches and dataset will then continue to grow as intended, however at half of the pre-activation rate. To avoid re-use of seeds oldEpochLength will continue to be used within the seedHash function.


At current epoch (372) the DAG size is 3.91 GB. 4GB GPUs are getting obsoleted while they still make up a significant amount of ethash hashrate. Activating this change at epoch 376 (for example), would reduce the DAG size from 3.94GB to 2.47GB. With the reduced growth rate, 4GB GPUs will remain supported for an additional 3+ years.


Hard fork required for activation. Mining software and pool implementations required.

For the smoothest possible transition activation should occur on a block in which an epoch transition to an even epoch number is occurring.

  • Epoch 374/2 = 187 (good) = block 11220000
  • Epoch 375/2 = 187.5 (bad) -
  • Epoch 376/2 = 188 (good) = block 11280000


  • [] core-geth
  • [] besu


  • [] open-ethereum-pool

    Mining Software

  • [] ethminer


This work is licensed under Apache License, Version 2.0.