URI: 
       trework on_channel_closed in LNWorker: - use detect_who_closed; this allows us to redeem to_remote of breach ctx - do not redeem to_local of breach ctx, because it is redundant with lnwatcher - rename a few methods - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 6bbdbf75961dbda5bac4566c3447e4d7d5beccaa
   DIR parent 930d21c31c5240fe57ed5f53335637e4f3ac5335
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Sat, 25 May 2019 06:02:23 +0200
       
       rework on_channel_closed in LNWorker:
        - use detect_who_closed; this allows us to redeem to_remote of breach ctx
        - do not redeem to_local of breach ctx, because it is redundant with lnwatcher
        - rename a few methods
       
       Diffstat:
         M electrum/lnchannel.py               |      10 +++-------
         M electrum/lnsweep.py                 |      37 +++++++++----------------------
         M electrum/lnworker.py                |      37 ++++++++++++++++---------------
       
       3 files changed, 33 insertions(+), 51 deletions(-)
       ---
   DIR diff --git a/electrum/lnchannel.py b/electrum/lnchannel.py
       t@@ -46,8 +46,7 @@ from .lnutil import (Outpoint, LocalConfig, RemoteConfig, Keypair, OnlyPubkeyKey
                            HTLC_TIMEOUT_WEIGHT, HTLC_SUCCESS_WEIGHT, extract_ctn_from_tx_and_chan, UpdateAddHtlc,
                            funding_output_script, SENT, RECEIVED, LOCAL, REMOTE, HTLCOwner, make_commitment_outputs,
                            ScriptHtlc, PaymentFailure, calc_onchain_fees, RemoteMisbehaving, make_htlc_output_witness_script)
       -from .lnsweep import create_sweeptxs_for_their_just_revoked_ctx
       -from .lnsweep import create_sweeptxs_for_our_latest_ctx, create_sweeptxs_for_their_latest_ctx
       +from .lnsweep import create_sweeptxs_for_their_revoked_ctx
        from .lnhtlc import HTLCManager
        
        
       t@@ -168,6 +167,7 @@ class Channel(Logger):
        
                self.local_commitment = None
                self.remote_commitment = None
       +        self.sweep_info = None
        
            def get_payments(self):
                out = {}
       t@@ -186,13 +186,9 @@ class Channel(Logger):
                ctn = extract_ctn_from_tx_and_chan(ctx, self)
                assert self.signature_fits(ctx), (self.hm.log[LOCAL])
                self.local_commitment = ctx
       -        if self.sweep_address is not None:
       -            self.local_sweeptxs = create_sweeptxs_for_our_latest_ctx(self, self.local_commitment, self.sweep_address)
        
            def set_remote_commitment(self):
                self.remote_commitment = self.current_commitment(REMOTE)
       -        if self.sweep_address is not None:
       -            self.remote_sweeptxs = create_sweeptxs_for_their_latest_ctx(self, self.remote_commitment, self.sweep_address)
        
            def open_with_first_pcp(self, remote_pcp, remote_sig):
                self.remote_commitment_to_be_revoked = self.pending_commitment(REMOTE)
       t@@ -460,7 +456,7 @@ class Channel(Logger):
                    return
                outpoint = self.funding_outpoint.to_str()
                ctx = self.remote_commitment_to_be_revoked  # FIXME can't we just reconstruct it?
       -        sweeptxs = create_sweeptxs_for_their_just_revoked_ctx(self, ctx, per_commitment_secret, self.sweep_address)
       +        sweeptxs = create_sweeptxs_for_their_revoked_ctx(self, ctx, per_commitment_secret, self.sweep_address)
                for prev_txid, tx in sweeptxs.items():
                    if tx is not None:
                        self.lnwatcher.add_sweep_tx(outpoint, prev_txid, str(tx))
   DIR diff --git a/electrum/lnsweep.py b/electrum/lnsweep.py
       t@@ -56,8 +56,8 @@ def maybe_create_sweeptx_for_their_ctx_to_local(ctx: Transaction, revocation_pri
            return sweep_tx
        
        
       -def create_sweeptxs_for_their_just_revoked_ctx(chan: 'Channel', ctx: Transaction, per_commitment_secret: bytes,
       -                                               sweep_address: str) -> Dict[str,Transaction]:
       +def create_sweeptxs_for_their_revoked_ctx(chan: 'Channel', ctx: Transaction, per_commitment_secret: bytes,
       +                                          sweep_address: str) -> Dict[str,Transaction]:
            """Presign sweeping transactions using the just received revoked pcs.
            These will only be utilised if the remote breaches.
            Sweep 'to_local', and all the HTLCs (two cases: directly from ctx, or from HTLC tx).
       t@@ -135,12 +135,8 @@ class ChannelClosedBy(Enum):
            UNKNOWN = auto()
        
        
       -class ChannelCloseSituationReport(NamedTuple):
       -    closed_by: ChannelClosedBy
       -    is_breach: Optional[bool]
        
       -
       -def detect_how_channel_was_closed(chan: 'Channel', ctx: Transaction) -> ChannelCloseSituationReport:
       +def detect_who_closed(chan: 'Channel', ctx: Transaction) -> ChannelClosedBy:
            ctn = extract_ctn_from_tx_and_chan(ctx, chan)
            our_conf, their_conf = get_ordered_channel_configs(chan=chan, for_us=True)
        
       t@@ -193,19 +189,19 @@ def detect_how_channel_was_closed(chan: 'Channel', ctx: Transaction) -> ChannelC
            to_local_address, to_remote_address, is_breach = get_to_local_and_to_remote_addresses_for_our_ctx()
            if (to_local_address and ctx.get_output_idx_from_address(to_local_address) is not None
                    or to_remote_address and ctx.get_output_idx_from_address(to_remote_address) is not None):
       -        return ChannelCloseSituationReport(closed_by=ChannelClosedBy.US, is_breach=is_breach)
       +        return ChannelClosedBy.US
        
            # their ctx?
            to_local_address, to_remote_address, is_breach = get_to_local_and_to_remote_addresses_for_their_ctx()
            if (to_local_address and ctx.get_output_idx_from_address(to_local_address) is not None
                    or to_remote_address and ctx.get_output_idx_from_address(to_remote_address) is not None):
       -        return ChannelCloseSituationReport(closed_by=ChannelClosedBy.THEM, is_breach=is_breach)
       +        return ChannelClosedBy.THEM
        
       -    return ChannelCloseSituationReport(closed_by=ChannelClosedBy.UNKNOWN, is_breach=None)
       +    return ChannelClosedBy.UNKNOWN
        
        
       -def create_sweeptxs_for_our_latest_ctx(chan: 'Channel', ctx: Transaction,
       -                                       sweep_address: str) -> Dict[str,Transaction]:
       +def create_sweeptxs_for_our_ctx(chan: 'Channel', ctx: Transaction,
       +                                sweep_address: str) -> Dict[str,Transaction]:
            """Handle the case where we force close unilaterally with our latest ctx.
            Construct sweep txns for 'to_local', and for all HTLCs (2 txns each).
            'to_local' can be swept even if this is a breach (by us),
       t@@ -277,8 +273,8 @@ def create_sweeptxs_for_our_latest_ctx(chan: 'Channel', ctx: Transaction,
            return txs
        
        
       -def create_sweeptxs_for_their_latest_ctx(chan: 'Channel', ctx: Transaction,
       -                                         sweep_address: str) -> Dict[str,Transaction]:
       +def create_sweeptxs_for_their_ctx(chan: 'Channel', ctx: Transaction,
       +                                  sweep_address: str) -> Dict[str,Transaction]:
            """Handle the case when the remote force-closes with their ctx.
            Regardless of it is a breach or not, construct sweep tx for 'to_remote'.
            If it is a breach, also construct sweep tx for 'to_local'.
       t@@ -313,18 +309,7 @@ def create_sweeptxs_for_their_latest_ctx(chan: 'Channel', ctx: Transaction,
            other_payment_privkey = ecc.ECPrivkey.from_secret_scalar(other_payment_privkey)
        
            txs = {}
       -    if per_commitment_secret:  # breach
       -        # to_local
       -        other_revocation_privkey = derive_blinded_privkey(other_conf.revocation_basepoint.privkey,
       -                                                          per_commitment_secret)
       -        this_delayed_pubkey = derive_pubkey(this_conf.delayed_basepoint.pubkey, their_pcp)
       -        sweep_tx = maybe_create_sweeptx_for_their_ctx_to_local(ctx=ctx,
       -                                                               revocation_privkey=other_revocation_privkey,
       -                                                               to_self_delay=other_conf.to_self_delay,
       -                                                               delayed_pubkey=this_delayed_pubkey,
       -                                                               sweep_address=sweep_address)
       -        if sweep_tx:
       -            txs[sweep_tx.prevout(0)] = sweep_tx
       +    # to_local is handled by lnwatcher
            # to_remote
            sweep_tx = maybe_create_sweeptx_for_their_ctx_to_remote(ctx=ctx,
                                                                    sweep_address=sweep_address,
   DIR diff --git a/electrum/lnworker.py b/electrum/lnworker.py
       t@@ -46,6 +46,7 @@ from .lnrouter import RouteEdge, is_route_sane_to_use
        from .address_synchronizer import TX_HEIGHT_LOCAL
        from . import lnsweep
        from .lnsweep import ChannelClosedBy
       +from .lnsweep import create_sweeptxs_for_their_ctx, create_sweeptxs_for_our_ctx
        
        if TYPE_CHECKING:
            from .network import Network
       t@@ -511,24 +512,24 @@ class LNWallet(LNWorker):
                # remove from channel_db
                if chan.short_channel_id is not None:
                    self.channel_db.remove_channel(chan.short_channel_id)
       -        # detect who closed
       -        assert closing_tx, f"no closing tx... {repr(closing_tx)}"
       -        sitrep = lnsweep.detect_how_channel_was_closed(chan, closing_tx)
       -        if sitrep.closed_by == ChannelClosedBy.US:
       -            self.logger.info(f'we force closed {funding_outpoint}. sitrep: {repr(sitrep)}')
       -            encumbered_sweeptxs = chan.local_sweeptxs
       -        elif sitrep.closed_by == ChannelClosedBy.THEM and sitrep.is_breach is False:
       -            self.logger.info(f'they force closed {funding_outpoint}. sitrep: {repr(sitrep)}')
       -            encumbered_sweeptxs = chan.remote_sweeptxs
       -        else:
       -            self.logger.info(f'not sure who closed {funding_outpoint} {closing_txid}. sitrep: {repr(sitrep)}')
       -            return
       -        # sweep
       -        for prevout, spender in spenders.items():
       -            e_tx = encumbered_sweeptxs.get(prevout)
       -            if e_tx is None:
       -                continue
       -            if spender is not None:
       +
       +        # detect who closed and set sweep_info
       +        if chan.sweep_info is None:
       +            closed_by = lnsweep.detect_who_closed(chan, closing_tx)
       +            if closed_by == ChannelClosedBy.US:
       +                self.logger.info(f'we force closed {funding_outpoint}.')
       +                chan.sweep_info = create_sweeptxs_for_our_ctx(chan, closing_tx, chan.sweep_address)
       +            elif closed_by == ChannelClosedBy.THEM:
       +                self.logger.info(f'they force closed {funding_outpoint}.')
       +                chan.sweep_info = create_sweeptxs_for_their_ctx(chan, closing_tx, chan.sweep_address)
       +            else:
       +                self.logger.info(f'not sure who closed {funding_outpoint} {closing_txid}.')
       +                chan.sweep_info = {}
       +            self.logger.info(f'{repr(chan.sweep_info)}')
       +
       +        # create and broadcast transaction
       +        for prevout, e_tx in chan.sweep_info.items():
       +            if spenders.get(prevout) is not None:
                        self.logger.info(f'outpoint already spent {prevout}')
                        continue
                    prev_txid, prev_index = prevout.split(':')