private boolean extraDataIsValid(
      final Collection<Address> expectedValidators, final BlockHeader header) {

    final CliqueExtraData cliqueExtraData = CliqueExtraData.decode(header);
    final Address proposer = cliqueExtraData.getProposerAddress();

    if (!expectedValidators.contains(proposer)) {
      LOG.info("Invalid block header: Proposer sealing block is not a member of the signers.");
      return false;
    }

    if (epochManager.isEpochBlock(header.getNumber())) {
      if (!Iterables.elementsEqual(cliqueExtraData.getValidators(), expectedValidators)) {
        LOG.info(
            "Invalid block header: Incorrect signers. Expected {} but got {}.",
            expectedValidators,
            cliqueExtraData.getValidators());
        return false;
      }
    } else {
      if (!cliqueExtraData.getValidators().isEmpty()) {
        LOG.info("Invalid block header: Signer list on non-epoch blocks must be empty.");
        return false;
      }
    }

    return true;
  }
Responsible for determining the validity of the extra data field. Ensures:

<ul>
  <li>Bytes in the extra data field can be decoded as per Clique specification
  <li>Proposer (derived from the proposerSeal) is a member of the validators
  <li>Validators are only validated on epoch blocks.
</ul>

@param header the block header containing the extraData to be validated.
@return True if the extraData successfully produces an CliqueExtraData object, false otherwise
consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/headervalidationrules/CliqueExtraDataValidationRule.java