class ProofOfWorkValidationRule implements DetachedBlockHeaderValidationRule {

  @Override
  public boolean validate(final BlockHeader header, final BlockHeader parent) {
    if (includeBaseFee) {
      if (!ExperimentalEIPs.eip1559Enabled) {
        LOG.warn("Invalid block header: EIP-1559 feature flag must be enabled --Xeip1559-enabled");
        return false;
      } else if (header.getBaseFee().isEmpty()) {
        LOG.warn("Invalid block header: missing mandatory base fee.");
        return false;
      }
    }

    final byte[] hashBuffer = new byte[64];
    final Hash headerHash = hashHeader(header);
    HASHER.hash(hashBuffer, header.getNonce(), header.getNumber(), headerHash.toArray());

    if (header.getDifficulty().isZero()) {
      LOG.trace("Rejecting header because difficulty is 0");
      return false;
    }
    final BigInteger difficulty = header.getDifficulty().toBytes().toUnsignedBigInteger();
    final UInt256 target =
        difficulty.equals(BigInteger.ONE)
            ? UInt256.MAX_VALUE
            : UInt256.valueOf(ETHASH_TARGET_UPPER_BOUND.divide(difficulty));
    final UInt256 result = UInt256.fromBytes(Bytes32.wrap(hashBuffer, 32));
    if (result.compareTo(target) > 0) {
      LOG.warn(
          "Invalid block header: the EthHash result {} was greater than the target {}.\n"
              + "Failing header:\n{}",
          result,
          target,
          header);
      return false;
    }

    final Hash mixedHash =
        Hash.wrap(Bytes32.leftPad(Bytes.wrap(hashBuffer).slice(0, Bytes32.SIZE)));
    if (!header.getMixHash().equals(mixedHash)) {
      LOG.warn(
          "Invalid block header: header mixed hash {} does not equal calculated mixed hash {}.\n"
              + "Failing header:\n{}",
          header.getMixHash(),
          mixedHash,
          header);
      return false;
    }

    return true;
  }

  public  ProofOfWorkValidationRule();
  public  ProofOfWorkValidationRule(final boolean includeBaseFee);

}