public void exportBlocks(
      final File outputFile,
      final Optional<Long> maybeStartBlock,
      final Optional<Long> maybeEndBlock)
      throws IOException {

    // Get range to export
    final long startBlock = maybeStartBlock.orElse(BlockHeader.GENESIS_BLOCK_NUMBER);
    final long endBlock = maybeEndBlock.orElse(blockchain.getChainHeadBlockNumber() + 1L);
    checkArgument(startBlock >= 0 && endBlock >= 0, "Start and end blocks must be greater than 0.");
    checkArgument(startBlock < endBlock, "Start block must be less than end block");

    // Append to file if a range is specified
    final boolean append = maybeStartBlock.isPresent();
    FileOutputStream outputStream = new FileOutputStream(outputFile, append);

    LOG.info(
        "Exporting blocks [{},{}) to file {} (appending: {})",
        startBlock,
        endBlock,
        outputFile.toString(),
        Boolean.toString(append));

    long blockNumber = 0L;
    for (long i = startBlock; i < endBlock; i++) {
      Optional<Block> maybeBlock = blockchain.getBlockByNumber(i);
      if (maybeBlock.isEmpty()) {
        LOG.warn("Unable to export blocks [{} - {}).  Blocks not found.", i, endBlock);
        break;
      }

      final Block block = maybeBlock.get();
      blockNumber = block.getHeader().getNumber();
      if (blockNumber % 100 == 0) {
        LOG.info("Export at block {}", blockNumber);
      }

      exportBlock(outputStream, block);
    }

    outputStream.close();
    LOG.info("Export complete at block {}", blockNumber);
  }
Export blocks that are stored in Besu's block storage.

@param outputFile the path at which to save the exported block data
@param maybeStartBlock the starting index of the block list to export (inclusive)
@param maybeEndBlock the ending index of the block list to export (exclusive), if not specified
    a single block will be export
@throws IOException if an I/O error occurs while writing data to disk
app/src/main/java/org/hyperledger/besu/chainexport/BlockExporter.java