public BftProtocolSchedule create(
      final NavigableSet<ForkSpec<ProtocolSchedule>> forkSpecs,
      final Optional<BigInteger> chainId) {
    final BftProtocolSchedule combinedProtocolSchedule =
        new BftProtocolSchedule(new DefaultProtocolSchedule(chainId));
    for (ForkSpec<ProtocolSchedule> spec : forkSpecs) {
      checkState(
          spec.getValue() instanceof DefaultProtocolSchedule,
          "Consensus migration requires a DefaultProtocolSchedule");
      final BftProtocolSchedule protocolSchedule =
          new BftProtocolSchedule((DefaultProtocolSchedule) spec.getValue());

      final Optional<Long> endBlock =
          Optional.ofNullable(forkSpecs.higher(spec)).map(ForkSpec::getBlock);
      protocolSchedule.getScheduledProtocolSpecs().stream()
          .filter(protocolSpecMatchesConsensusBlockRange(spec.getBlock(), endBlock))
          .forEach(
              s -> {
                if (s instanceof ScheduledProtocolSpec.TimestampProtocolSpec) {
                  combinedProtocolSchedule.putTimestampMilestone(s.fork().milestone(), s.spec());
                } else if (s instanceof ScheduledProtocolSpec.BlockNumberProtocolSpec) {
                  combinedProtocolSchedule.putBlockNumberMilestone(s.fork().milestone(), s.spec());
                } else {
                  throw new IllegalStateException(
                      "Unexpected milestone: " + s + " for milestone: " + s.fork().milestone());
                }
              });

      // When moving to a new consensus mechanism we want to use the last milestone but created by
      // our consensus mechanism's BesuControllerBuilder so any additional rules are applied
      if (spec.getBlock() > 0) {
        combinedProtocolSchedule.putBlockNumberMilestone(
            spec.getBlock(), protocolSchedule.getByBlockNumberOrTimestamp(spec.getBlock(), 0L));
      }
    }
    return combinedProtocolSchedule;
  }
Create protocol schedule.

@param forkSpecs the fork specs
@param chainId the chain id
@return the protocol schedule
consensus/common/src/main/java/org/hyperledger/besu/consensus/common/CombinedProtocolScheduleFactory.java