URI: 
       tln: avoid code duplication - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 399fe08047afaa15f33e95d424f1647ffc9fbd45
   DIR parent d1769472bd9ce43c81fbf9d34e7c7e3cec3bb1b0
  HTML Author: Janus <ysangkok@gmail.com>
       Date:   Fri, 15 Jun 2018 16:35:29 +0200
       
       ln: avoid code duplication
       
       Diffstat:
         M lib/lnbase.py                       |     149 +++++++++----------------------
         M lib/lnhtlc.py                       |      24 +++++++++++++++++++-----
         M lib/tests/test_lnhtlc.py            |       2 +-
       
       3 files changed, 63 insertions(+), 112 deletions(-)
       ---
   DIR diff --git a/lib/lnbase.py b/lib/lnbase.py
       t@@ -984,28 +984,11 @@ class Peer(PrintError):
            def on_update_fail_htlc(self, payload):
                print("UPDATE_FAIL_HTLC", decode_onion_error(payload["reason"], self.node_keys, self.secret_key))
        
       -    def derive_and_incr(self, chan):
       -        last_small_num = chan.local_state.ctn
       -        next_small_num = last_small_num + 2
       -        this_small_num = last_small_num + 1
       -        last_secret = get_per_commitment_secret_from_seed(chan.local_state.per_commitment_secret_seed, 2**48-last_small_num-1)
       -        this_secret = get_per_commitment_secret_from_seed(chan.local_state.per_commitment_secret_seed, 2**48-this_small_num-1)
       -        this_point = secret_to_pubkey(int.from_bytes(this_secret, 'big'))
       -        next_secret = get_per_commitment_secret_from_seed(chan.local_state.per_commitment_secret_seed, 2**48-next_small_num-1)
       -        next_point = secret_to_pubkey(int.from_bytes(next_secret, 'big'))
       -        chan = chan._replace(
       -            local_state=chan.local_state._replace(
       -                ctn=chan.local_state.ctn + 1
       -            )
       -        )
       -        return chan, last_secret, this_point, next_point
       -
            @aiosafe
            async def pay(self, path, chan, amount_msat, payment_hash, pubkey_in_invoice, min_final_cltv_expiry):
                assert self.channel_state[chan.channel_id] == "OPEN"
                assert amount_msat > 0, "amount_msat is not greater zero"
                height = self.network.get_local_height()
       -        their_revstore = chan.remote_state.revocation_store
                route = self.lnworker.path_finder.create_route_from_path(path, self.lnworker.pubkey)
                hops_data = []
                sum_of_deltas = sum(route_edge.channel_policy.cltv_expiry_delta for route_edge in route[1:])
       t@@ -1035,69 +1018,53 @@ class Peer(PrintError):
        
                self.send_message(gen_msg("commitment_signed", channel_id=chan.channel_id, signature=sig_64, num_htlcs=1, htlc_signature=htlc_sig))
        
       -        revoke_and_ack_msg = await self.revoke_and_ack[chan.channel_id].get()
       -        m.receive_revocation(RevokeAndAck(revoke_and_ack_msg["per_commitment_secret"], revoke_and_ack_msg["next_per_commitment_point"]))
       +        await self.receive_revoke(m)
        
       -        rev, _ = m.revoke_current_commitment()
       -        self.send_message(gen_msg("revoke_and_ack",
       -            channel_id=chan.channel_id,
       -            per_commitment_secret=rev.per_commitment_secret,
       -            next_per_commitment_point=rev.next_per_commitment_point))
       -
       -        chan = m.state
       -
       -        print("waiting for update_fulfill")
       +        self.revoke(m)
        
                update_fulfill_htlc_msg = await self.update_fulfill_htlc[chan.channel_id].get()
       +        m.receive_htlc_settle(update_fulfill_htlc_msg["payment_preimage"], int.from_bytes(update_fulfill_htlc_msg["id"], "big"))
        
       -        print("waiting for commitment_signed")
       -        commitment_signed_msg = await self.commitment_signed[chan.channel_id].get()
       -
       -        chan, last_secret, _, next_point = self.derive_and_incr(chan)
       -        self.send_message(gen_msg("revoke_and_ack",
       -            channel_id=chan.channel_id,
       -            per_commitment_secret=last_secret,
       -            next_per_commitment_point=next_point))
       +        self.revoke(m)
        
       -        next_per_commitment_point = revoke_and_ack_msg["next_per_commitment_point"]
       +        while (await self.commitment_signed[chan.channel_id].get())["htlc_signature"] == b"":
       +            pass
       +        # TODO process above commitment transactions
        
       -        bare_ctx = make_commitment_using_open_channel(chan, chan.remote_state.ctn + 1, False, next_per_commitment_point,
       +        bare_ctx = make_commitment_using_open_channel(m.state, m.state.remote_state.ctn + 1, False, m.state.remote_state.next_per_commitment_point,
                    msat_remote, msat_local)
        
                sig_64 = sign_and_get_sig_string(bare_ctx, chan.local_config, chan.remote_config)
       -
                self.send_message(gen_msg("commitment_signed", channel_id=chan.channel_id, signature=sig_64, num_htlcs=0))
       +        m.state = m.state._replace(remote_state=m.state.remote_state._replace(ctn=m.state.remote_state.ctn + 1))
        
       -        revoke_and_ack_msg = await self.revoke_and_ack[chan.channel_id].get()
       -        # TODO check revoke_and_ack results
       +        await self.receive_revoke(m)
        
       -        chan = chan._replace(
       -            local_state=chan.local_state._replace(
       -                amount_msat=msat_local,
       -                next_htlc_id=chan.local_state.next_htlc_id + 1
       -            ),
       -            remote_state=chan.remote_state._replace(
       -                ctn=chan.remote_state.ctn + 1,
       -                revocation_store=their_revstore,
       -                last_per_commitment_point=next_per_commitment_point,
       -                next_per_commitment_point=revoke_and_ack_msg["next_per_commitment_point"],
       -                amount_msat=msat_remote
       -            )
       -        )
       -        self.lnworker.save_channel(chan)
       +        self.lnworker.save_channel(m.state)
       +
       +    async def receive_revoke(self, m):
       +        revoke_and_ack_msg = await self.revoke_and_ack[m.state.channel_id].get()
       +        m.receive_revocation(RevokeAndAck(revoke_and_ack_msg["per_commitment_secret"], revoke_and_ack_msg["next_per_commitment_point"]))
       +
       +    def revoke(self, m):
       +        rev, _ = m.revoke_current_commitment()
       +        self.send_message(gen_msg("revoke_and_ack",
       +            channel_id=m.state.channel_id,
       +            per_commitment_secret=rev.per_commitment_secret,
       +            next_per_commitment_point=rev.next_per_commitment_point))
       +
       +    async def receive_commitment(self, m):
       +        commitment_signed_msg = await self.commitment_signed[m.state.channel_id].get()
       +        data = commitment_signed_msg["htlc_signature"]
       +        htlc_sigs = [data[i:i+64] for i in range(0, len(data), 64)]
       +        m.receive_new_commitment(commitment_signed_msg["signature"], htlc_sigs)
       +        return len(htlc_sigs)
        
            @aiosafe
            async def receive_commitment_revoke_ack(self, htlc, decoded, payment_preimage):
                chan = self.channels[htlc['channel_id']]
                channel_id = chan.channel_id
                expected_received_msat = int(decoded.amount * COIN * 1000)
       -        while True:
       -            self.print_error("receiving commitment")
       -            commitment_signed_msg = await self.commitment_signed[channel_id].get()
       -            num_htlcs = int.from_bytes(commitment_signed_msg["num_htlcs"], "big")
       -            print("num_htlcs", num_htlcs)
       -            if num_htlcs == 1:
       -                break
                htlc_id = int.from_bytes(htlc["id"], 'big')
                assert htlc_id == chan.remote_state.next_htlc_id, (htlc_id, chan.remote_state.next_htlc_id)
        
       t@@ -1112,67 +1079,36 @@ class Peer(PrintError):
                htlc = UpdateAddHtlc(amount_msat, payment_hash, cltv_expiry, 0)
        
                m = HTLCStateMachine(chan)
       +
                m.receive_htlc(htlc)
        
       -        data = commitment_signed_msg["htlc_signature"]
       -        htlc_sigs = [data[i:i+64] for i in range(0, len(data), 64)]
       -        m.receive_new_commitment(commitment_signed_msg["signature"], htlc_sigs)
       +        assert (await self.receive_commitment(m)) == 1
        
       -        rev, _ = m.revoke_current_commitment()
       -        self.send_message(gen_msg("revoke_and_ack",
       -            channel_id=channel_id,
       -            per_commitment_secret=rev.per_commitment_secret,
       -            next_per_commitment_point=rev.next_per_commitment_point))
       +        self.revoke(m)
        
                sig_64, htlc_sigs = m.sign_next_commitment()
       -        chan = m.state
                htlc_sig = htlc_sigs[0]
                self.send_message(gen_msg("commitment_signed", channel_id=channel_id, signature=sig_64, num_htlcs=1, htlc_signature=htlc_sig))
        
       -        revoke_and_ack_msg = await self.revoke_and_ack[channel_id].get()
       -
       -        # TODO check revoke_and_ack_msg contents
       +        await self.receive_revoke(m)
        
       +        m.settle_htlc(payment_preimage, htlc_id)
                self.send_message(gen_msg("update_fulfill_htlc", channel_id=channel_id, id=htlc_id, payment_preimage=payment_preimage))
        
       -        remote_next_commitment_point = revoke_and_ack_msg["next_per_commitment_point"]
       -
                # remote commitment transaction without htlcs
       -        bare_ctx = make_commitment_using_open_channel(chan, chan.remote_state.ctn + 2, False, remote_next_commitment_point,
       -            chan.remote_state.amount_msat - expected_received_msat, chan.local_state.amount_msat + expected_received_msat)
       -
       -        sig_64 = sign_and_get_sig_string(bare_ctx, chan.local_config, chan.remote_config)
       -
       +        bare_ctx = make_commitment_using_open_channel(m.state, m.state.remote_state.ctn + 1, False, m.state.remote_state.next_per_commitment_point,
       +            m.state.remote_state.amount_msat - expected_received_msat, m.state.local_state.amount_msat + expected_received_msat)
       +        sig_64 = sign_and_get_sig_string(bare_ctx, m.state.local_config, m.state.remote_config)
                self.send_message(gen_msg("commitment_signed", channel_id=channel_id, signature=sig_64, num_htlcs=0))
       +        m.state = m.state._replace(remote_state=m.state.remote_state._replace(ctn=m.state.remote_state.ctn + 1))
        
       -        revoke_and_ack_msg = await self.revoke_and_ack[channel_id].get()
       -
       -        # TODO check revoke_and_ack results
       -
       -        commitment_signed_msg = await self.commitment_signed[channel_id].get()
       +        await self.receive_revoke(m)
        
       -        # TODO check commitment_signed results
       +        assert (await self.receive_commitment(m)) == 0
        
       -        chan, last_secret, _, next_point = self.derive_and_incr(chan)
       +        self.revoke(m)
        
       -        self.send_message(gen_msg("revoke_and_ack",
       -            channel_id=channel_id,
       -            per_commitment_secret=last_secret,
       -            next_per_commitment_point=next_point))
       -
       -        new_chan = chan._replace(
       -            local_state=chan.local_state._replace(
       -                amount_msat=chan.local_state.amount_msat + expected_received_msat
       -            ),
       -            remote_state=chan.remote_state._replace(
       -                ctn=chan.remote_state.ctn + 2,
       -                last_per_commitment_point=remote_next_commitment_point,
       -                next_per_commitment_point=revoke_and_ack_msg["next_per_commitment_point"],
       -                amount_msat=chan.remote_state.amount_msat - expected_received_msat,
       -                next_htlc_id=htlc_id + 1
       -            )
       -        )
       -        self.lnworker.save_channel(new_chan)
       +        self.lnworker.save_channel(m.state)
        
            def on_commitment_signed(self, payload):
                self.print_error("commitment_signed", payload)
       t@@ -1203,6 +1139,7 @@ class Peer(PrintError):
                    assert False
        
            def on_revoke_and_ack(self, payload):
       +        print("got revoke_and_ack")
                channel_id = payload["channel_id"]
                self.revoke_and_ack[channel_id].put_nowait(payload)
        
   DIR diff --git a/lib/lnhtlc.py b/lib/lnhtlc.py
       t@@ -66,7 +66,8 @@ class HTLCStateMachine(PrintError):
                assert type(htlc) is UpdateAddHtlc
                self.local_update_log.append(htlc)
                self.print_error("add_htlc")
       -        htlc_id = len(self.local_update_log)-1
       +        htlc_id = self.state.local_state.next_htlc_id
       +        self.state = self.state._replace(local_state=self.state.local_state._replace(next_htlc_id=htlc_id + 1))
                htlc.htlc_id = htlc_id
                return htlc_id
        
       t@@ -79,7 +80,8 @@ class HTLCStateMachine(PrintError):
                assert type(htlc) is UpdateAddHtlc
                self.remote_update_log.append(htlc)
                self.print_error("receive_htlc")
       -        htlc_id = len(self.remote_update_log)-1
       +        htlc_id = self.state.remote_state.next_htlc_id
       +        self.state = self.state._replace(remote_state=self.state.remote_state._replace(next_htlc_id=htlc_id + 1))
                htlc.htlc_id = htlc_id
                return htlc_id
        
       t@@ -226,15 +228,23 @@ class HTLCStateMachine(PrintError):
                        continue
                    settle_fails2.append(x)
        
       +        sent_this_batch = 0
       +        received_this_batch = 0
       +
                for x in settle_fails2:
       -            self.total_msat_sent += self.lookup_htlc(self.local_update_log, x.htlc_id).amount_msat
       +            htlc = self.lookup_htlc(self.local_update_log, x.htlc_id)
       +            sent_this_batch += htlc.amount_msat + htlc.total_fee
       +
       +        self.total_msat_sent += sent_this_batch
        
                # increase received_msat counter for htlc's that have been settled
                adds2 = self.gen_htlc_indices("remote")
                for htlc in adds2:
                    htlc_id = htlc.htlc_id
                    if SettleHtlc(htlc_id) in self.local_update_log:
       -                self.total_msat_received += self.lookup_htlc(self.remote_update_log, htlc_id).amount_msat
       +                htlc = self.lookup_htlc(self.remote_update_log, htlc_id)
       +                received_this_batch += htlc.amount_msat + htlc.total_fee
       +        self.total_msat_received += received_this_batch
        
                # log compaction (remove entries relating to htlc's that have been settled)
        
       t@@ -269,6 +279,10 @@ class HTLCStateMachine(PrintError):
                        ctn=self.state.remote_state.ctn + 1,
                        last_per_commitment_point=next_point,
                        next_per_commitment_point=revocation.next_per_commitment_point,
       +                amount_msat=self.state.remote_state.amount_msat + (sent_this_batch - received_this_batch)
       +            ),
       +            local_state=self.state.local_state._replace(
       +                amount_msat = self.state.local_state.amount_msat + (received_this_batch - sent_this_batch)
                    )
                )
        
       t@@ -368,7 +382,7 @@ class HTLCStateMachine(PrintError):
            def htlcs_in_remote(self):
                return self.gen_htlc_indices("remote")
        
       -    def settle_htlc(self, preimage, htlc_id, source_ref, dest_ref, close_key):
       +    def settle_htlc(self, preimage, htlc_id):
                """
                SettleHTLC attempts to settle an existing outstanding received HTLC.
                """
   DIR diff --git a/lib/tests/test_lnhtlc.py b/lib/tests/test_lnhtlc.py
       t@@ -193,7 +193,7 @@ class TestLNBaseHTLCStateMachine(unittest.TestCase):
                # Now we'll repeat a similar exchange, this time with Bob settling the
                # HTLC once he learns of the preimage.
                preimage = paymentPreimage
       -        bob_channel.settle_htlc(preimage, bobHtlcIndex, None, None, None)
       +        bob_channel.settle_htlc(preimage, bobHtlcIndex)
        
                alice_channel.receive_htlc_settle(preimage, aliceHtlcIndex)