def sweep_their_ctx(
        *, chan: 'Channel',
        ctx: Transaction) -> Optional[Dict[str, SweepInfo]]:
    """Handle the case when the remote force-closes with their ctx.
    Sweep outputs that do not have a CSV delay ('to_remote' and first-stage HTLCs).
    Outputs with CSV delay ('to_local' and second-stage HTLCs) are redeemed by LNWatcher.

    We sweep:
        to_local: if revoked
        to_remote: CSV delay with anchors, otherwise sweeping not needed
        htlc success: CSV delay with anchors, no delay otherwise, or revoked
        htlc timeout: CSV delay with anchors, CLTV locktime, or revoked
        second-stage htlc transactions: CSV delay

    Outputs with CSV/CLTV are redeemed by LNWatcher.
    """
    txs = {}  # type: Dict[str, SweepInfo]
    our_conf, their_conf = get_ordered_channel_configs(chan=chan, for_us=True)
    x = extract_ctx_secrets(chan, ctx)
    if not x:
        return
    ctn, their_pcp, is_revocation, per_commitment_secret = x
    # to_local
    our_revocation_pubkey = derive_blinded_pubkey(our_conf.revocation_basepoint.pubkey, their_pcp)
    their_delayed_pubkey = derive_pubkey(their_conf.delayed_basepoint.pubkey, their_pcp)
    witness_script = make_commitment_output_to_local_witness_script(
        our_revocation_pubkey, our_conf.to_self_delay, their_delayed_pubkey)
    to_local_address = redeem_script_to_address('p2wsh', witness_script)
    to_remote_address = None
    # test if this is their ctx
    found_to_local = bool(ctx.get_output_idxs_from_address(to_local_address))
    if not chan.is_backup():
        assert chan.is_static_remotekey_enabled()
        our_payment_pubkey = our_conf.payment_basepoint.pubkey
        to_remote_address = make_commitment_output_to_remote_address(our_payment_pubkey, has_anchors=chan.has_anchors())
        found_to_remote = bool(ctx.get_output_idxs_from_address(to_remote_address))
    else:
        found_to_remote = False
    if not found_to_local and not found_to_remote:
        return
    chan.logger.debug(f'(lnsweep) found their ctx: {to_local_address} {to_remote_address}')

    # remote anchor
    if chan.has_anchors():
        if txin := sweep_ctx_anchor(ctx=ctx, multisig_key=our_conf.multisig_key):
            txs[txin.prevout.to_str()] = SweepInfo(
                name='remote_anchor',
                cltv_abs=None,
                txin=txin,
                txout=None,
                can_be_batched=True,
            )

    # to_local is handled by lnwatcher
    if is_revocation:
        our_revocation_privkey = derive_blinded_privkey(our_conf.revocation_basepoint.privkey, per_commitment_secret)
        if txin := sweep_their_ctx_justice(chan, ctx, per_commitment_secret):
            txs[txin.prevout.to_str()] = SweepInfo(
                name='to_local_for_revoked_ctx',
                cltv_abs=None,
                txin=txin,
                txout=None,
                can_be_batched=False,
            )

    # to_remote
    if chan.has_anchors():
        sweep_to_remote = True
        our_payment_privkey = ecc.ECPrivkey(our_conf.payment_basepoint.privkey)
    else:
        assert chan.is_static_remotekey_enabled()
        sweep_to_remote = False
        our_payment_privkey = None

    if sweep_to_remote:
        assert our_payment_pubkey == our_payment_privkey.get_public_key_bytes(compressed=True)
        output_idxs = ctx.get_output_idxs_from_address(to_remote_address)
        if output_idxs:
            output_idx = output_idxs.pop()
            prevout = ctx.txid() + ':%d' % output_idx
            if txin := sweep_their_ctx_to_remote(
                    ctx=ctx,
                    output_idx=output_idx,
                    our_payment_privkey=our_payment_privkey,
                    has_anchors=chan.has_anchors()
            ):
                # todo: we might not want to sweep this at all, if we add it to the wallet addresses
                txs[prevout] = SweepInfo(
                    name='their_ctx_to_remote',
                    cltv_abs=None,
                    txin=txin,
                    txout=None,
                    can_be_batched=True,
                )

    # HTLCs
    our_htlc_privkey = derive_privkey(secret=int.from_bytes(our_conf.htlc_basepoint.privkey, 'big'), per_commitment_point=their_pcp)
    our_htlc_privkey = ecc.ECPrivkey.from_secret_scalar(our_htlc_privkey)
    their_htlc_pubkey = derive_pubkey(their_conf.htlc_basepoint.pubkey, their_pcp)
    def tx_htlc(
            *, htlc: 'UpdateAddHtlc',
            is_received_htlc: bool,
            ctx_output_idx: int,
            preimage: Optional[bytes]) -> None:
        htlc_output_witness_script = make_htlc_output_witness_script(
            is_received_htlc=is_received_htlc,
            remote_revocation_pubkey=our_revocation_pubkey,
            remote_htlc_pubkey=our_htlc_privkey.get_public_key_bytes(compressed=True),
            local_htlc_pubkey=their_htlc_pubkey,
            payment_hash=htlc.payment_hash,
            cltv_abs=htlc.cltv_abs,
            has_anchors=chan.has_anchors())

        cltv_abs = htlc.cltv_abs if is_received_htlc and not is_revocation else 0
        prevout = ctx.txid() + ':%d'%ctx_output_idx
        if txin := sweep_their_ctx_htlc(
                ctx=ctx,
                witness_script=htlc_output_witness_script,
                preimage=preimage,
                output_idx=ctx_output_idx,
                privkey=our_revocation_privkey if is_revocation else our_htlc_privkey.get_secret_bytes(),
                is_revocation=is_revocation,
                cltv_abs=cltv_abs,
                has_anchors=chan.has_anchors(),
        ):
            txs[prevout] = SweepInfo(
                name=f'their_ctx_htlc_{ctx_output_idx}{"_for_revoked_ctx" if is_revocation else ""}',
                cltv_abs=cltv_abs,
                txin=txin,
                txout=None,
                can_be_batched=False,   # both parties can spend
                # (still, in some cases we could batch, see comment in sweep_our_ctx)
            )
    # received HTLCs, in their ctx --> "timeout"
    # offered HTLCs, in their ctx --> "success"
    htlc_to_ctx_output_idx_map = map_htlcs_to_ctx_output_idxs(
        chan=chan,
        ctx=ctx,
        pcp=their_pcp,
        subject=REMOTE,
        ctn=ctn)
    for (direction, htlc), (ctx_output_idx, htlc_relative_idx) in htlc_to_ctx_output_idx_map.items():
        is_received_htlc = direction == RECEIVED
        if not is_received_htlc and not is_revocation:
            if not chan.lnworker.is_accepted_mpp(htlc.payment_hash):
                # do not redeem this, it might publish the preimage of an incomplete MPP
                continue
            preimage = chan.lnworker.get_preimage(htlc.payment_hash)
            if not preimage:
                # we might not have the preimage if this is a hold invoice
                continue
        else:
            preimage = None
        tx_htlc(
            htlc=htlc,
            is_received_htlc=is_received_htlc,
            ctx_output_idx=ctx_output_idx,
            preimage=preimage)
    return txs
Handle the case when the remote force-closes with their ctx.
    Sweep outputs that do not have a CSV delay ('to_remote' and first-stage HTLCs).
    Outputs with CSV delay ('to_local' and second-stage HTLCs) are redeemed by LNWatcher.

    We sweep:
        to_local: if revoked
        to_remote: CSV delay with anchors, otherwise sweeping not needed
        htlc success: CSV delay with anchors, no delay otherwise, or revoked
        htlc timeout: CSV delay with anchors, CLTV locktime, or revoked
        second-stage htlc transactions: CSV delay

    Outputs with CSV/CLTV are redeemed by LNWatcher.
    
electrum/lnsweep.py