def get_tails(chains):
    """
    Args:
        An ordered collection of block generators.

    Returns
        A dictionary of lists of blocks for all chains where:
            1. The first block in all the lists has the same block number
            2. Each list has all blocks from the common block to the current
               block in increasing order
            3. The dictionary key is the index of the chain in `chains` that
               the list was generated from
        A list of indexes of the chains that had communication problems.
    """

    def get_num_of_oldest(blocks):
        return blocks[0].num

    # Get the first block from every chain
    tails = {}
    bad_chains = []
    for i, chain in chains.items():
        try:
            tails[i] = [next(chain)]
        except StopIteration:
            bad_chains.append(i)

    # Find the minimum block number between all chains
    min_block_num = min(map(get_num_of_oldest, tails.values()))

    # Walk all chains back to the minimum block number, adding blocks to the
    # chain lists as we go
    for i, chain in chains.items():
        if i not in bad_chains:
            tail = tails[i]
            while get_num_of_oldest(tail) > min_block_num:
                try:
                    block = next(chain)
                except StopIteration:
                    bad_chains.append(i)
                    break
                tail.insert(0, block)

    return tails, bad_chains
Args:
        An ordered collection of block generators.

    Returns
        A dictionary of lists of blocks for all chains where:
            1. The first block in all the lists has the same block number
            2. Each list has all blocks from the common block to the current
               block in increasing order
            3. The dictionary key is the index of the chain in `chains` that
               the list was generated from
        A list of indexes of the chains that had communication problems.