public static PoWSolution hashimoto(
      final Bytes header,
      final long size,
      final long nonce,
      final BiConsumer<byte[], Integer> datasetLookup) {
    final int n = (int) Long.divideUnsigned(size, MIX_BYTES);
    final MessageDigest keccak512 = KECCAK_512.get();
    keccak512.update(header.toArrayUnsafe());
    keccak512.update(Longs.toByteArray(Long.reverseBytes(nonce)));
    final byte[] seed = keccak512.digest();
    final ByteBuffer mixBuffer = ByteBuffer.allocate(MIX_BYTES).order(ByteOrder.LITTLE_ENDIAN);
    for (int i = 0; i < MIX_BYTES / HASH_BYTES; ++i) {
      mixBuffer.put(seed);
    }
    mixBuffer.position(0);
    final int[] mix = new int[MIX_BYTES / 4];
    for (int i = 0; i < MIX_BYTES / 4; ++i) {
      mix[i] = mixBuffer.getInt();
    }
    final byte[] lookupResult = new byte[HASH_BYTES];
    final byte[] temp = new byte[MIX_BYTES];
    for (int i = 0; i < ACCESSES; ++i) {
      final int p =
          Integer.remainderUnsigned(
              fnv(i ^ readLittleEndianInt(seed, 0), mix[i % (MIX_BYTES / WORD_BYTES)]), n);
      for (int j = 0; j < MIX_BYTES / HASH_BYTES; ++j) {
        datasetLookup.accept(lookupResult, 2 * p + j);
        System.arraycopy(lookupResult, 0, temp, j * HASH_BYTES, HASH_BYTES);
      }
      fnvHash(mix, temp);
    }
    final int[] cmix = new int[mix.length / 4];
    for (int i = 0; i < mix.length; i += 4) {
      cmix[i / 4] = fnv(fnv(fnv(mix[i], mix[i + 1]), mix[i + 2]), mix[i + 3]);
    }
    final byte[] result = new byte[32 + 32];
    intToByte(result, cmix);
    final MessageDigest keccak256 = DirectAcyclicGraphSeed.KECCAK_256.get();
    keccak256.update(seed);
    keccak256.update(result, 0, 32);
    try {
      keccak256.digest(result, 32, 32);
    } catch (final DigestException ex) {
      throw new IllegalStateException(ex);
    }

    return new PoWSolution(
        nonce,
        Hash.wrap(Bytes32.wrap(Arrays.copyOf(result, 32))),
        Bytes32.wrap(result, 32),
        header);
  }
Hashimoto Light Implementation.

@param size Dataset size for the given header hash
@param cache EthHash Cache
@param header Truncated BlockHeader hash
@param nonce Nonce to use for hashing
@return A byte array holding MixHash in its first 32 bytes and the EthHash result in the in
    bytes 32 to 63
ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/EthHash.java