private Optional<ValidatorVote> determineCliqueVote(
      final SealableBlockHeader sealableBlockHeader) {
    BlockHeader parentHeader =
        protocolContext.getBlockchain().getBlockHeader(sealableBlockHeader.getParentHash()).get();
    if (epochManager.isEpochBlock(sealableBlockHeader.getNumber())) {
      return Optional.empty();
    } else {
      final CliqueContext cliqueContext = protocolContext.getConsensusContext(CliqueContext.class);
      checkState(
          cliqueContext.getValidatorProvider().getVoteProviderAtHead().isPresent(),
          "Clique requires a vote provider");
      return cliqueContext
          .getValidatorProvider()
          .getVoteProviderAtHead()
          .get()
          .getVoteAfterBlock(parentHeader, Util.publicKeyToAddress(nodeKey.getPublicKey()));
    }
  }
Responsible for signing (hash of) the block (including MixHash and Nonce), and then injecting
the seal into the extraData. This is called after a suitable set of transactions have been
identified, and all resulting hashes have been inserted into the passed-in SealableBlockHeader.

@param sealableBlockHeader A block header containing StateRoots, TransactionHashes etc.
@return The blockhead which is to be added to the block being proposed.
consensus/clique/src/main/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreator.java