def METHOD_NAME(
    prefix_hash: bytes,
    image: crypto.Point,
    pubs: list[crypto.Point],
    sec: crypto.Scalar,
    sec_idx: int,
    test: bool = False,
) -> Sig:
    """
    Generates ring signature with key image.
    void crypto_ops::generate_ring_signature()
    """
    from trezor.utils import memcpy
    from apps.monero.xmr import crypto
    Scalar = crypto.Scalar  # local_cache_attribute
    encodepoint_into = crypto.encodepoint_into  # local_cache_attribute
    if test:
        t = crypto.scalarmult_base_into(None, sec)
        if not crypto.point_eq(t, pubs[sec_idx]):
            raise ValueError("Invalid sec key")
        k_i = monero.generate_key_image(crypto_helpers.encodepoint(pubs[sec_idx]), sec)
        if not crypto.point_eq(k_i, image):
            raise ValueError("Key image invalid")
        for k in pubs:
            crypto.ge25519_check(k)
    buff_off = len(prefix_hash)
    buff = bytearray(buff_off + 2 * 32 * len(pubs))
    memcpy(buff, 0, prefix_hash, 0, buff_off)
    mvbuff = memoryview(buff)
    sum = Scalar(0)
    k = Scalar(0)
    sig = []
    for _ in range(len(pubs)):
        sig.append([Scalar(0), Scalar(0)])  # c, r
    for i in range(len(pubs)):
        if i == sec_idx:
            k = crypto.random_scalar()
            tmp3 = crypto.scalarmult_base_into(None, k)
            encodepoint_into(mvbuff[buff_off : buff_off + 32], tmp3)
            buff_off += 32
            tmp3 = crypto.hash_to_point_into(None, crypto_helpers.encodepoint(pubs[i]))
            tmp2 = crypto.scalarmult_into(None, tmp3, k)
            encodepoint_into(mvbuff[buff_off : buff_off + 32], tmp2)
            buff_off += 32
        else:
            sig[i] = [crypto.random_scalar(), crypto.random_scalar()]
            tmp3 = pubs[i]
            tmp2 = crypto.ge25519_double_scalarmult_vartime_into(
                None, tmp3, sig[i][0], sig[i][1]
            )
            encodepoint_into(mvbuff[buff_off : buff_off + 32], tmp2)
            buff_off += 32
            tmp3 = crypto.hash_to_point_into(None, crypto_helpers.encodepoint(tmp3))
            tmp2 = crypto.add_keys3_into(None, sig[i][1], tmp3, sig[i][0], image)
            encodepoint_into(mvbuff[buff_off : buff_off + 32], tmp2)
            buff_off += 32
            crypto.sc_add_into(sum, sum, sig[i][0])
    h = crypto.hash_to_scalar_into(None, buff)
    sig[sec_idx][0] = crypto.sc_sub_into(None, h, sum)
    sig[sec_idx][1] = crypto.sc_mulsub_into(None, sig[sec_idx][0], sec, k)
    return sig