electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

test_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())