class ForkChoice {

  public SafeFuture<BlockImportResult> onBlock(
      final SignedBeaconBlock block, Optional<BeaconState> preState) {
    return onForkChoiceThread(
        () -> {
          final ForkChoiceStrategy forkChoiceStrategy = getForkChoiceStrategy();
          final StoreTransaction transaction = recentChainData.startStoreTransaction();
          final CapturingIndexedAttestationProvider indexedAttestationProvider =
              new CapturingIndexedAttestationProvider();
          final BlockImportResult result =
              on_block(
                  transaction,
                  block,
                  preState,
                  stateTransition,
                  forkChoiceStrategy,
                  beaconState ->
                      transaction.putStateRoot(
                          beaconState.hash_tree_root(),
                          new SlotAndBlockRoot(
                              beaconState.getSlot(),
                              beaconState.getLatest_block_header().hash_tree_root())),
                  indexedAttestationProvider);

          if (!result.isSuccessful()) {
            return SafeFuture.completedFuture(result);
          }
          indexedAttestationProvider.getIndexedAttestations().stream()
              .filter(
                  attestation ->
                      forkChoiceStrategy.contains(attestation.getData().getBeacon_block_root()))
              .forEach(
                  indexedAttestation ->
                      forkChoiceStrategy.onAttestation(transaction, indexedAttestation));
          return transaction
              .commit()
              .thenRun(() -> updateForkChoiceForImportedBlock(block, forkChoiceStrategy, result))
              .thenApply(__ -> result);
        });
  }

  public  ForkChoice(
      final ForkChoiceExecutor forkChoiceExecutor,
      final RecentChainData recentChainData,
      final StateTransition stateTransition);

}