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