code: def build_fork_graph(chains, tails):
      
      graph = ForkGraph()
      bad_chains = []
  
      # Add tails to the graph first
      for i, tail in tails.items():
          for block in reversed(tail):
              graph.add_block(i, block)
  
      # If we are already at the common ancestor, stop
      if _compare_across(
          [tail[0] for tail in tails.values()], key=lambda block: block.ident
      ):
          return graph, bad_chains
  
      # Chains should now all be at the same height, so we can walk back
      # to common ancestor
      while True:
          heads = []
          for i, chain in chains.items():
              if i not in bad_chains:
                  try:
                      head = next(chain)
                  except StopIteration:
                      bad_chains.append(i)
                  heads.append((i, head))
  
          for i, block in heads:
              graph.add_block(i, block)
          if _compare_across(heads, key=lambda head: head[1].ident):
              break
  
      prune_unreporting_peers(graph, bad_chains)
  
      return graph, bad_chains
docs: Args:
          An ordered collection of block generators which have been consumed to
          the point where they are all at the same block height and the tails of
          the chains from that block height (in the same order).
  
      Returns:
          A ForkGraph
          A list of indexes of the chains that had communication problems.