def METHOD_NAME(
    constants: ConsensusConstants,
    blocks: BlockchainInterface,
    blocks_included_height: uint32,
    prev_prev_block: BlockRecord,
    new_difficulty: Optional[uint64],
    new_sub_slot_iters: Optional[uint64],
) -> SubEpochSummary:
    """
    Creates a sub-epoch-summary object, assuming that the first block in the new sub-epoch is at height
    "blocks_included_height". Prev_prev_b is the second to last block in the previous sub-epoch. On a new epoch,
    new_difficulty and new_sub_slot_iters are also added.
    Args:
        constants: consensus constants being used for this chain
        blocks: dictionary from header hash to SBR of all included SBR
        blocks_included_height: block height in which the SES will be included
        prev_prev_block: second to last block in epoch
        new_difficulty: difficulty in new epoch
        new_sub_slot_iters: sub slot iters in new epoch
    """
    assert prev_prev_block.height == blocks_included_height - 2
    # First sub_epoch
    # This is not technically because more blocks can potentially be included than 2*MAX_SUB_SLOT_BLOCKS,
    # But assuming less than 128 overflow blocks get infused in the first 2 slots, it's not an issue
    if (blocks_included_height + constants.MAX_SUB_SLOT_BLOCKS) // constants.SUB_EPOCH_BLOCKS <= 1:
        return SubEpochSummary(
            constants.GENESIS_CHALLENGE,
            constants.GENESIS_CHALLENGE,
            uint8(0),
            None,
            None,
        )
    curr: BlockRecord = prev_prev_block
    while curr.sub_epoch_summary_included is None:
        curr = blocks.block_record(curr.prev_hash)
    assert curr is not None
    assert curr.finished_reward_slot_hashes is not None
    prev_ses = curr.sub_epoch_summary_included.get_hash()
    return SubEpochSummary(
        prev_ses,
        curr.finished_reward_slot_hashes[-1],
        uint8(curr.height % constants.SUB_EPOCH_BLOCKS),
        new_difficulty,
        new_sub_slot_iters,
    )