public ProtocolSpec getByBlockHeaderWithTransitionReorgHandling(
      final ProcessableBlockHeader blockHeader) {
    // if we do not have a finalized block we might return pre or post merge protocol schedule:
    if (mergeContext.getFinalized().isEmpty()) {

      // if head is not post-merge, return pre-merge schedule:
      if (!mergeContext.isPostMerge()) {
        LOG.atDebug()
            .setMessage("for {} returning a pre-merge schedule because we are not post-merge")
            .addArgument(blockHeader::toLogString)
            .log();
        return getPreMergeSchedule().getByBlockHeader(blockHeader);
      }

      // otherwise check to see if this block represents a re-org TTD block:
      Difficulty parentDifficulty =
          protocolContext
              .getBlockchain()
              .getTotalDifficultyByHash(blockHeader.getParentHash())
              .orElse(Difficulty.ZERO);
      Difficulty thisDifficulty = parentDifficulty.add(blockHeader.getDifficulty());
      Difficulty terminalDifficulty = mergeContext.getTerminalTotalDifficulty();
      LOG.atDebug()
          .setMessage(" block {} ttd is: {}, parent total diff is: {}, this total diff is: {}")
          .addArgument(blockHeader::toLogString)
          .addArgument(terminalDifficulty)
          .addArgument(parentDifficulty)
          .addArgument(thisDifficulty)
          .log();

      // if this block is pre-merge or a TTD block
      if (thisDifficulty.lessThan(terminalDifficulty)
          || TransitionUtils.isTerminalProofOfWorkBlock(blockHeader, protocolContext)) {
        LOG.atDebug()
            .setMessage("returning a pre-merge schedule because block {} is pre-merge or TTD")
            .addArgument(blockHeader::toLogString)
            .log();
        return getPreMergeSchedule().getByBlockHeader(blockHeader);
      }
    }
    // else return post-merge schedule
    LOG.atDebug()
        .setMessage(" for {} returning a post-merge schedule")
        .addArgument(blockHeader::toLogString)
        .log();
    return getPostMergeSchedule().getByBlockHeader(blockHeader);
  }
Gets the protocol spec by block header, with some additional logic used by backwards sync (BWS)

@param blockHeader the block header
@return the ProtocolSpec to be used by the provided block
consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/TransitionProtocolSchedule.java