1

I read up on the fields in Ethereum blocks, but I was unable to find exactly how the POW hash is calculated. I would assume that it is an RLP encoded value of the previous block hash, ommer hashes, nonce, state trie root hash etc.

Can anyone show me the exact calculation in terms of ETHASH? You don't have to show how ETHASH works, just what the input to ETHASH is.

By PoW hash, I mean the block hash that must be lower than the target threshold (which is reciprocal to the target difficulty).

1 Answer 1

1

The main Hashimoto mining loop is defined in the following Python pseudo-code (found here):

def mine(full_size, dataset, header, difficulty):
    # zero-pad target to compare with hash on the same digit
    target = zpad(encode_int(2**256 // difficulty), 64)[::-1]
    from random import randint
    nonce = randint(0, 2**64)
    while hashimoto_full(full_size, dataset, header, nonce) > target:
        nonce = (nonce + 1) % 2**64
    return nonce

I would assume that it is an RLP-encoded value of the previous block hash, ommer hashes, nonce, state trie root hash etc.

The Hashimoto function requires the truncated RPL-encoded header of the current block being mined, which itself contains the parentHash (Hp in the Yellow Paper), together with the mining nonce. The truncated header doesn't contain the mixHash (Hm) or header nonce (Hn).

Here's the code:

def hashimoto(header, nonce, full_size, dataset_lookup):
    n = full_size / HASH_BYTES
    w = MIX_BYTES // WORD_BYTES
    mixhashes = MIX_BYTES / HASH_BYTES
    # combine header+nonce into a 64 byte seed
    s = sha3_512(header + nonce[::-1])
    # start the mix with replicated s
    mix = []
    for _ in range(MIX_BYTES / HASH_BYTES):
        mix.extend(s)
    # mix in random dataset nodes
    for i in range(ACCESSES):
        p = fnv(i ^ s[0], mix[i % w]) % (n // mixhashes) * mixhashes
        newdata = []
        for j in range(MIX_BYTES / HASH_BYTES):
            newdata.extend(dataset_lookup(p + j))
        mix = map(fnv, mix, newdata)
    # compress mix
    cmix = []
    for i in range(0, len(mix), 4):
        cmix.append(fnv(fnv(fnv(mix[i], mix[i+1]), mix[i+2]), mix[i+3]))
    return {
        "mix digest": serialize_hash(cmix),
        "result": serialize_hash(sha3_256(s+cmix))
    }
3
  • So the truncated RLP-encoded header has all the block header fields except mixHash and nonce. I.e. header above is: KECCAK(RLP(parentHash || ommersHash || beneficiary || stateRoot || transactionsRoot || receiptsRoot || logsBloom || difficulty || number || gasLimit || gasUsed || timestamp || extraData)) Commented Apr 22, 2021 at 20:26
  • 1
    Yes, although the Yellow Paper doesn't list them out, and I can't pinpoint it in the code. See Appendix J in the Yellow Paper for the overall equation, with reference to equation 49 earlier in the paper for a definition of the truncated header. Commented Apr 22, 2021 at 21:00
  • Could you be a bit more explicit about the content of the truncated block header in the above answer? Then I would gladly accept it. Commented Apr 22, 2021 at 21:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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