I am trying to use ethash(hash(blockHeader),nonce) < TARGET to prove that the block was mined with at least a minimum difficulty.

Is the formula above correct?

When I try to use ehtereum.pow.ethash from pyethereum:

from ethereum.pow import ethash
difficulty = 3963642329
block_number = 4156209
nonce = int('0xf245822d3412da7f', 16)
block_hash = 0x47b8f62c1400dae65105d2f8e03824bfc58481c0b32f45788ad3378fbc05e9f6
cache = ethash.mkcache(block_number)
ethash = hashimoto_light(block_number, cache, block_hash, nonce)

I get this error:

Traceback (most recent call last):
  File "test.py", line 10, in <module>
    cache = ethash.mkcache(block_number)
  File "(environment_path)/lib/python3.6/site-packages/ethereum/pow/ethash.py", line 15, in mkcache
    while len(cache_seeds) <= block_number // EPOCH_LENGTH:
NameError: name 'EPOCH_LENGTH' is not defined

Am I doing it wrong? Or is there a bug in ethereum.pow.ethash?


The ethereum module is not maintained. Check out pyethash for the same purpose.

You can import like:

from pyethash import (

py-evm uses it to check proof of work like so:

def check_pow(block_number: int,
              mining_hash: Hash32,
              mix_hash: Hash32,
              nonce: bytes,
              difficulty: int) -> None:
    validate_length(mix_hash, 32, title="Mix Hash")
    validate_length(mining_hash, 32, title="Mining Hash")
    validate_length(nonce, 8, title="POW Nonce")
    cache = get_cache(block_number)
    mining_output = hashimoto_light(
        block_number, cache, mining_hash, big_endian_to_int(nonce))
    if mining_output[b'mix digest'] != mix_hash:
        raise ValidationError("mix hash mismatch; {0} != {1}".format(
            encode_hex(mining_output[b'mix digest']), encode_hex(mix_hash)))
    result = big_endian_to_int(mining_output[b'result'])
    validate_lte(result, 2**256 // difficulty, title="POW Difficulty")

Where the cache is generated and stored with:

# Type annotation here is to ensure we don't accidentally use strings instead of bytes.
cache_seeds = [b'\x00' * 32]  # type: List[bytes]
cache_by_seed = OrderedDict()  # type: OrderedDict[bytes, bytearray]

def get_cache(block_number: int) -> bytes:
    while len(cache_seeds) <= block_number // EPOCH_LENGTH:
    seed = cache_seeds[block_number // EPOCH_LENGTH]
    if seed in cache_by_seed:
        c = cache_by_seed.pop(seed)  # pop and append at end
        cache_by_seed[seed] = c
        return c
    c = mkcache_bytes(block_number)
    cache_by_seed[seed] = c
    if len(cache_by_seed) > CACHE_MAX_ITEMS:
        cache_by_seed.popitem(last=False)  # remove last recently accessed
    return c
| improve this answer | |
  • Thank You. I tried this, but it says that mix_hash != result. What am I doing wrong? block_number = 4156209 difficulty = 3963642329 nonce = unhexlify('0xf245822d3412da7f'[2:]) block_hash = unhexlify( '0x47b8f62c1400dae65105d2f8e03824bfc58481c0b32f45788ad3378fbc05e9f6'[2:]) mix_hash = unhexlify( '0x0c0026c706351083c0a913e084dee16ca133b813baa6a174e4fb179d9f2ecc52'[2:]) – SimonSchuler Oct 23 '18 at 13:01
  • And it tells me that my difficulty somehow mismatches. Dose this have to do with the fact that I am using a block from ropsten? – SimonSchuler Oct 23 '18 at 13:04
  • Ropsten will work too. Trinity (built on py-evm) is validating pow using that code on Ropsten. – carver Oct 23 '18 at 18:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.