URI: 
       ttest_lnhtlc.py - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
       ttest_lnhtlc.py (11810B)
       ---
            1 from pprint import pprint
            2 import unittest
            3 from typing import NamedTuple
            4 
            5 from electrum.lnutil import RECEIVED, LOCAL, REMOTE, SENT, HTLCOwner, Direction
            6 from electrum.lnhtlc import HTLCManager
            7 from electrum.json_db import StoredDict
            8 
            9 from . import ElectrumTestCase
           10 
           11 class H(NamedTuple):
           12     owner : str
           13     htlc_id : int
           14 
           15 class TestHTLCManager(ElectrumTestCase):
           16     def test_adding_htlcs_race(self):
           17         A = HTLCManager(StoredDict({}, None, []))
           18         B = HTLCManager(StoredDict({}, None, []))
           19         A.channel_open_finished()
           20         B.channel_open_finished()
           21         ah0, bh0 = H('A', 0), H('B', 0)
           22         B.recv_htlc(A.send_htlc(ah0))
           23         self.assertEqual(B.log[REMOTE]['locked_in'][0][LOCAL], 1)
           24         A.recv_htlc(B.send_htlc(bh0))
           25         self.assertEqual(B.get_htlcs_in_latest_ctx(LOCAL), [])
           26         self.assertEqual(A.get_htlcs_in_latest_ctx(LOCAL), [])
           27         self.assertEqual(B.get_htlcs_in_next_ctx(LOCAL), [(RECEIVED, ah0)])
           28         self.assertEqual(A.get_htlcs_in_next_ctx(LOCAL), [(RECEIVED, bh0)])
           29         A.send_ctx()
           30         B.recv_ctx()
           31         B.send_ctx()
           32         A.recv_ctx()
           33         self.assertEqual(B.get_htlcs_in_oldest_unrevoked_ctx(LOCAL), [])
           34         self.assertEqual(A.get_htlcs_in_oldest_unrevoked_ctx(LOCAL), [])
           35         self.assertEqual(B.get_htlcs_in_latest_ctx(LOCAL), [(RECEIVED, ah0)])
           36         self.assertEqual(A.get_htlcs_in_latest_ctx(LOCAL), [(RECEIVED, bh0)])
           37         B.send_rev()
           38         A.recv_rev()
           39         A.send_rev()
           40         B.recv_rev()
           41         self.assertEqual(B.get_htlcs_in_oldest_unrevoked_ctx(LOCAL), [(RECEIVED, ah0)])
           42         self.assertEqual(A.get_htlcs_in_oldest_unrevoked_ctx(LOCAL), [(RECEIVED, bh0)])
           43         self.assertEqual(B.get_htlcs_in_latest_ctx(LOCAL), [(RECEIVED, ah0)])
           44         self.assertEqual(A.get_htlcs_in_latest_ctx(LOCAL), [(RECEIVED, bh0)])
           45         A.send_ctx()
           46         B.recv_ctx()
           47         B.send_ctx()
           48         A.recv_ctx()
           49         self.assertEqual(B.get_htlcs_in_oldest_unrevoked_ctx(LOCAL), [(RECEIVED, ah0)])
           50         self.assertEqual(A.get_htlcs_in_oldest_unrevoked_ctx(LOCAL), [(RECEIVED, bh0)])
           51         self.assertEqual(B.get_htlcs_in_latest_ctx(LOCAL), [(RECEIVED, ah0), (SENT, bh0)][::-1])
           52         self.assertEqual(A.get_htlcs_in_latest_ctx(LOCAL), [(RECEIVED, bh0), (SENT, ah0)][::-1])
           53         B.send_rev()
           54         A.recv_rev()
           55         A.send_rev()
           56         B.recv_rev()
           57         self.assertEqual(B.get_htlcs_in_oldest_unrevoked_ctx(LOCAL), [(RECEIVED, ah0), (SENT, bh0)][::-1])
           58         self.assertEqual(A.get_htlcs_in_oldest_unrevoked_ctx(LOCAL), [(RECEIVED, bh0), (SENT, ah0)][::-1])
           59         self.assertEqual(B.get_htlcs_in_latest_ctx(LOCAL), [(RECEIVED, ah0), (SENT, bh0)][::-1])
           60         self.assertEqual(A.get_htlcs_in_latest_ctx(LOCAL), [(RECEIVED, bh0), (SENT, ah0)][::-1])
           61 
           62     def test_single_htlc_full_lifecycle(self):
           63         def htlc_lifecycle(htlc_success: bool):
           64             A = HTLCManager(StoredDict({}, None, []))
           65             B = HTLCManager(StoredDict({}, None, []))
           66             A.channel_open_finished()
           67             B.channel_open_finished()
           68             B.recv_htlc(A.send_htlc(H('A', 0)))
           69             self.assertEqual(len(B.get_htlcs_in_next_ctx(REMOTE)), 0)
           70             self.assertEqual(len(A.get_htlcs_in_next_ctx(REMOTE)), 1)
           71             self.assertEqual(len(B.get_htlcs_in_next_ctx(LOCAL)), 1)
           72             self.assertEqual(len(A.get_htlcs_in_next_ctx(LOCAL)), 0)
           73             A.send_ctx()
           74             B.recv_ctx()
           75             B.send_rev()
           76             A.recv_rev()
           77             B.send_ctx()
           78             A.recv_ctx()
           79             A.send_rev()
           80             B.recv_rev()
           81             self.assertEqual(len(A.get_htlcs_in_latest_ctx(LOCAL)), 1)
           82             self.assertEqual(len(B.get_htlcs_in_latest_ctx(LOCAL)), 1)
           83             if htlc_success:
           84                 B.send_settle(0)
           85                 A.recv_settle(0)
           86             else:
           87                 B.send_fail(0)
           88                 A.recv_fail(0)
           89             self.assertEqual(list(A.htlcs_by_direction(REMOTE, RECEIVED).values()), [H('A', 0)])
           90             self.assertNotEqual(A.get_htlcs_in_latest_ctx(LOCAL), [])
           91             self.assertNotEqual(B.get_htlcs_in_latest_ctx(REMOTE), [])
           92 
           93             self.assertEqual(A.get_htlcs_in_next_ctx(LOCAL), [])
           94             self.assertNotEqual(A.get_htlcs_in_next_ctx(REMOTE), [])
           95             self.assertEqual(A.get_htlcs_in_next_ctx(REMOTE), A.get_htlcs_in_latest_ctx(REMOTE))
           96 
           97             self.assertEqual(B.get_htlcs_in_next_ctx(REMOTE), [])
           98             B.send_ctx()
           99             A.recv_ctx()
          100             A.send_rev() # here pending_htlcs(REMOTE) should become empty
          101             self.assertEqual(A.get_htlcs_in_next_ctx(REMOTE), [])
          102 
          103             B.recv_rev()
          104             A.send_ctx()
          105             B.recv_ctx()
          106             B.send_rev()
          107             A.recv_rev()
          108             self.assertEqual(B.get_htlcs_in_latest_ctx(LOCAL), [])
          109             self.assertEqual(A.get_htlcs_in_latest_ctx(LOCAL), [])
          110             self.assertEqual(A.get_htlcs_in_latest_ctx(REMOTE), [])
          111             self.assertEqual(B.get_htlcs_in_latest_ctx(REMOTE), [])
          112             self.assertEqual(len(A.all_settled_htlcs_ever(LOCAL)), int(htlc_success))
          113             self.assertEqual(len(A.sent_in_ctn(2)), int(htlc_success))
          114             self.assertEqual(len(B.received_in_ctn(2)), int(htlc_success))
          115 
          116             A.recv_htlc(B.send_htlc(H('B', 0)))
          117             self.assertEqual(A.get_htlcs_in_next_ctx(REMOTE), [])
          118             self.assertNotEqual(A.get_htlcs_in_next_ctx(LOCAL), [])
          119             self.assertNotEqual(B.get_htlcs_in_next_ctx(REMOTE), [])
          120             self.assertEqual(B.get_htlcs_in_next_ctx(LOCAL), [])
          121 
          122             B.send_ctx()
          123             A.recv_ctx()
          124             A.send_rev()
          125             B.recv_rev()
          126 
          127             self.assertNotEqual(A.get_htlcs_in_next_ctx(REMOTE), A.get_htlcs_in_latest_ctx(REMOTE))
          128             self.assertEqual(A.get_htlcs_in_next_ctx(LOCAL), A.get_htlcs_in_latest_ctx(LOCAL))
          129             self.assertEqual(B.get_htlcs_in_next_ctx(REMOTE), B.get_htlcs_in_latest_ctx(REMOTE))
          130             self.assertNotEqual(B.get_htlcs_in_next_ctx(LOCAL), B.get_htlcs_in_next_ctx(REMOTE))
          131 
          132         htlc_lifecycle(htlc_success=True)
          133         htlc_lifecycle(htlc_success=False)
          134 
          135     def test_remove_htlc_while_owing_commitment(self):
          136         def htlc_lifecycle(htlc_success: bool):
          137             A = HTLCManager(StoredDict({}, None, []))
          138             B = HTLCManager(StoredDict({}, None, []))
          139             A.channel_open_finished()
          140             B.channel_open_finished()
          141             ah0 = H('A', 0)
          142             B.recv_htlc(A.send_htlc(ah0))
          143             A.send_ctx()
          144             B.recv_ctx()
          145             B.send_rev()
          146             A.recv_rev()
          147             if htlc_success:
          148                 B.send_settle(0)
          149                 A.recv_settle(0)
          150             else:
          151                 B.send_fail(0)
          152                 A.recv_fail(0)
          153             self.assertEqual([], A.get_htlcs_in_oldest_unrevoked_ctx(LOCAL))
          154             self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_oldest_unrevoked_ctx(REMOTE))
          155             self.assertEqual([], A.get_htlcs_in_latest_ctx(LOCAL))
          156             self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_latest_ctx(REMOTE))
          157             self.assertEqual([], A.get_htlcs_in_next_ctx(LOCAL))
          158             self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_next_ctx(REMOTE))
          159             B.send_ctx()
          160             A.recv_ctx()
          161             A.send_rev()
          162             B.recv_rev()
          163             self.assertEqual([], A.get_htlcs_in_oldest_unrevoked_ctx(LOCAL))
          164             self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_oldest_unrevoked_ctx(REMOTE))
          165             self.assertEqual([], A.get_htlcs_in_latest_ctx(LOCAL))
          166             self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_latest_ctx(REMOTE))
          167             self.assertEqual([], A.get_htlcs_in_next_ctx(LOCAL))
          168             self.assertEqual([], A.get_htlcs_in_next_ctx(REMOTE))
          169 
          170         htlc_lifecycle(htlc_success=True)
          171         htlc_lifecycle(htlc_success=False)
          172 
          173     def test_adding_htlc_between_send_ctx_and_recv_rev(self):
          174         A = HTLCManager(StoredDict({}, None, []))
          175         B = HTLCManager(StoredDict({}, None, []))
          176         A.channel_open_finished()
          177         B.channel_open_finished()
          178         A.send_ctx()
          179         B.recv_ctx()
          180         B.send_rev()
          181         ah0 = H('A', 0)
          182         B.recv_htlc(A.send_htlc(ah0))
          183         self.assertEqual([], A.get_htlcs_in_latest_ctx(LOCAL))
          184         self.assertEqual([], A.get_htlcs_in_latest_ctx(REMOTE))
          185         self.assertEqual([], A.get_htlcs_in_next_ctx(LOCAL))
          186         self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_next_ctx(REMOTE))
          187         A.recv_rev()
          188         self.assertEqual([], A.get_htlcs_in_latest_ctx(LOCAL))
          189         self.assertEqual([], A.get_htlcs_in_latest_ctx(REMOTE))
          190         self.assertEqual([], A.get_htlcs_in_next_ctx(LOCAL))
          191         self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_next_ctx(REMOTE))
          192         A.send_ctx()
          193         B.recv_ctx()
          194         self.assertEqual([], A.get_htlcs_in_latest_ctx(LOCAL))
          195         self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_latest_ctx(REMOTE))
          196         self.assertEqual([], A.get_htlcs_in_next_ctx(LOCAL))
          197         self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_next_ctx(REMOTE))
          198         B.send_rev()
          199         A.recv_rev()
          200         self.assertEqual([], A.get_htlcs_in_latest_ctx(LOCAL))
          201         self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_latest_ctx(REMOTE))
          202         self.assertEqual([(Direction.SENT, ah0)], A.get_htlcs_in_next_ctx(LOCAL))
          203         self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_next_ctx(REMOTE))
          204         B.send_ctx()
          205         A.recv_ctx()
          206         self.assertEqual([], A.get_htlcs_in_oldest_unrevoked_ctx(LOCAL))
          207         self.assertEqual([(Direction.SENT, ah0)], A.get_htlcs_in_latest_ctx(LOCAL))
          208         self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_latest_ctx(REMOTE))
          209         self.assertEqual([(Direction.SENT, ah0)], A.get_htlcs_in_next_ctx(LOCAL))
          210         self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_next_ctx(REMOTE))
          211         A.send_rev()
          212         B.recv_rev()
          213         self.assertEqual([(Direction.SENT, ah0)], A.get_htlcs_in_oldest_unrevoked_ctx(LOCAL))
          214         self.assertEqual([(Direction.SENT, ah0)], A.get_htlcs_in_latest_ctx(LOCAL))
          215         self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_latest_ctx(REMOTE))
          216         self.assertEqual([(Direction.SENT, ah0)], A.get_htlcs_in_next_ctx(LOCAL))
          217         self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_next_ctx(REMOTE))
          218 
          219     def test_unacked_local_updates(self):
          220         A = HTLCManager(StoredDict({}, None, []))
          221         B = HTLCManager(StoredDict({}, None, []))
          222         A.channel_open_finished()
          223         B.channel_open_finished()
          224         self.assertEqual({}, A.get_unacked_local_updates())
          225 
          226         ah0 = H('A', 0)
          227         B.recv_htlc(A.send_htlc(ah0))
          228         A.store_local_update_raw_msg(b"upd_msg0", is_commitment_signed=False)
          229         self.assertEqual({1: [b"upd_msg0"]}, A.get_unacked_local_updates())
          230 
          231         ah1 = H('A', 1)
          232         B.recv_htlc(A.send_htlc(ah1))
          233         A.store_local_update_raw_msg(b"upd_msg1", is_commitment_signed=False)
          234         self.assertEqual({1: [b"upd_msg0", b"upd_msg1"]}, A.get_unacked_local_updates())
          235 
          236         A.send_ctx()
          237         B.recv_ctx()
          238         A.store_local_update_raw_msg(b"ctx1", is_commitment_signed=True)
          239         self.assertEqual({1: [b"upd_msg0", b"upd_msg1", b"ctx1"]}, A.get_unacked_local_updates())
          240 
          241         ah2 = H('A', 2)
          242         B.recv_htlc(A.send_htlc(ah2))
          243         A.store_local_update_raw_msg(b"upd_msg2", is_commitment_signed=False)
          244         self.assertEqual({1: [b"upd_msg0", b"upd_msg1", b"ctx1"], 2: [b"upd_msg2"]}, A.get_unacked_local_updates())
          245 
          246         B.send_rev()
          247         A.recv_rev()
          248         self.assertEqual({2: [b"upd_msg2"]}, A.get_unacked_local_updates())