class CheckpointHeaderValidationStep implements Function<CheckpointRangeHeaders, Stream<BlockHeader>> {

  @Override
  public Stream<BlockHeader> apply(final CheckpointRangeHeaders checkpointRangeHeaders) {
    final BlockHeader rangeStart = checkpointRangeHeaders.getCheckpointRange().getStart();
    final BlockHeader firstHeaderToImport = checkpointRangeHeaders.getFirstHeaderToImport();

    if (isValid(rangeStart, firstHeaderToImport)) {
      return checkpointRangeHeaders.getHeadersToImport().stream();
    } else {
      final String rangeEndDescription;
      if (checkpointRangeHeaders.getCheckpointRange().hasEnd()) {
        final BlockHeader rangeEnd = checkpointRangeHeaders.getCheckpointRange().getEnd();
        rangeEndDescription =
            String.format("#%d (%s)", rangeEnd.getNumber(), rangeEnd.getBlockHash());
      } else {
        rangeEndDescription = "chain head";
      }
      final String errorMessage =
          String.format(
              "Invalid checkpoint headers.  Headers downloaded between #%d (%s) and %s do not connect at #%d (%s)",
              rangeStart.getNumber(),
              rangeStart.getHash(),
              rangeEndDescription,
              firstHeaderToImport.getNumber(),
              firstHeaderToImport.getHash());
      throw new InvalidBlockException(
          errorMessage, firstHeaderToImport.getNumber(), firstHeaderToImport.getHash());
    }
  }

  public  CheckpointHeaderValidationStep(
      final ProtocolSchedule protocolSchedule,
      final ProtocolContext protocolContext,
      final ValidationPolicy validationPolicy);

}