test_lnutil.py (54929B)
1 import unittest 2 import json 3 4 from electrum import bitcoin 5 from electrum.json_db import StoredDict 6 from electrum.lnutil import (RevocationStore, get_per_commitment_secret_from_seed, make_offered_htlc, 7 make_received_htlc, make_commitment, make_htlc_tx_witness, make_htlc_tx_output, 8 make_htlc_tx_inputs, secret_to_pubkey, derive_blinded_pubkey, derive_privkey, 9 derive_pubkey, make_htlc_tx, extract_ctn_from_tx, UnableToDeriveSecret, 10 get_compressed_pubkey_from_bech32, split_host_port, ConnStringFormatError, 11 ScriptHtlc, extract_nodeid, calc_fees_for_commitment_tx, UpdateAddHtlc, LnFeatures, 12 ln_compare_features, IncompatibleLightningFeatures) 13 from electrum.util import bh2u, bfh, MyEncoder 14 from electrum.transaction import Transaction, PartialTransaction 15 from electrum.lnworker import LNWallet 16 17 from . import ElectrumTestCase 18 19 20 funding_tx_id = '8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be' 21 funding_output_index = 0 22 funding_amount_satoshi = 10000000 23 commitment_number = 42 24 local_delay = 144 25 local_dust_limit_satoshi = 546 26 27 local_payment_basepoint = bytes.fromhex('034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa') 28 remote_payment_basepoint = bytes.fromhex('032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991') 29 # obs = get_obscured_ctn(42, local_payment_basepoint, remote_payment_basepoint) 30 local_funding_privkey = bytes.fromhex('30ff4956bbdd3222d44cc5e8a1261dab1e07957bdac5ae88fe3261ef321f374901') 31 local_funding_pubkey = bytes.fromhex('023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb') 32 remote_funding_pubkey = bytes.fromhex('030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c1') 33 local_privkey = bytes.fromhex('bb13b121cdc357cd2e608b0aea294afca36e2b34cf958e2e6451a2f27469449101') 34 localpubkey = bytes.fromhex('030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e7') 35 remotepubkey = bytes.fromhex('0394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b') 36 local_delayedpubkey = bytes.fromhex('03fd5960528dc152014952efdb702a88f71e3c1653b2314431701ec77e57fde83c') 37 local_revocation_pubkey = bytes.fromhex('0212a140cd0c6539d07cd08dfe09984dec3251ea808b892efeac3ede9402bf2b19') 38 # funding wscript = 5221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae 39 40 41 class TestLNUtil(ElectrumTestCase): 42 def test_shachain_store(self): 43 tests = [ 44 { 45 "name": "insert_secret correct sequence", 46 "inserts": [ 47 { 48 "index": 281474976710655, 49 "secret": "7cc854b54e3e0dcdb010d7a3fee464a9687b" +\ 50 "e6e8db3be6854c475621e007a5dc", 51 "successful": True 52 }, 53 { 54 "index": 281474976710654, 55 "secret": "c7518c8ae4660ed02894df8976fa1a3659c1" +\ 56 "a8b4b5bec0c4b872abeba4cb8964", 57 "successful": True 58 }, 59 { 60 "index": 281474976710653, 61 "secret": "2273e227a5b7449b6e70f1fb4652864038b1" +\ 62 "cbf9cd7c043a7d6456b7fc275ad8", 63 "successful": True 64 }, 65 { 66 "index": 281474976710652, 67 "secret": "27cddaa5624534cb6cb9d7da077cf2b22ab2" +\ 68 "1e9b506fd4998a51d54502e99116", 69 "successful": True 70 }, 71 { 72 "index": 281474976710651, 73 "secret": "c65716add7aa98ba7acb236352d665cab173" +\ 74 "45fe45b55fb879ff80e6bd0c41dd", 75 "successful": True 76 }, 77 { 78 "index": 281474976710650, 79 "secret": "969660042a28f32d9be17344e09374b37996" +\ 80 "2d03db1574df5a8a5a47e19ce3f2", 81 "successful": True 82 }, 83 { 84 "index": 281474976710649, 85 "secret": "a5a64476122ca0925fb344bdc1854c1c0a59" +\ 86 "fc614298e50a33e331980a220f32", 87 "successful": True 88 }, 89 { 90 "index": 281474976710648, 91 "secret": "05cde6323d949933f7f7b78776bcc1ea6d9b" +\ 92 "31447732e3802e1f7ac44b650e17", 93 "successful": True 94 } 95 ] 96 }, 97 { 98 "name": "insert_secret #1 incorrect", 99 "inserts": [ 100 { 101 "index": 281474976710655, 102 "secret": "02a40c85b6f28da08dfdbe0926c53fab2d" +\ 103 "e6d28c10301f8f7c4073d5e42e3148", 104 "successful": True 105 }, 106 { 107 "index": 281474976710654, 108 "secret": "c7518c8ae4660ed02894df8976fa1a3659" +\ 109 "c1a8b4b5bec0c4b872abeba4cb8964", 110 "successful": False 111 } 112 ] 113 }, 114 { 115 "name": "insert_secret #2 incorrect (#1 derived from incorrect)", 116 "inserts": [ 117 { 118 "index": 281474976710655, 119 "secret": "02a40c85b6f28da08dfdbe0926c53fab2de6" +\ 120 "d28c10301f8f7c4073d5e42e3148", 121 "successful": True 122 }, 123 { 124 "index": 281474976710654, 125 "secret": "dddc3a8d14fddf2b68fa8c7fbad274827493" +\ 126 "7479dd0f8930d5ebb4ab6bd866a3", 127 "successful": True 128 }, 129 { 130 "index": 281474976710653, 131 "secret": "2273e227a5b7449b6e70f1fb4652864038b1" +\ 132 "cbf9cd7c043a7d6456b7fc275ad8", 133 "successful": True 134 }, 135 { 136 "index": 281474976710652, 137 "secret": "27cddaa5624534cb6cb9d7da077cf2b22a" +\ 138 "b21e9b506fd4998a51d54502e99116", 139 "successful": False 140 } 141 ] 142 }, 143 { 144 "name": "insert_secret #3 incorrect", 145 "inserts": [ 146 { 147 "index": 281474976710655, 148 "secret": "7cc854b54e3e0dcdb010d7a3fee464a9687b" +\ 149 "e6e8db3be6854c475621e007a5dc", 150 "successful": True 151 }, 152 { 153 "index": 281474976710654, 154 "secret": "c7518c8ae4660ed02894df8976fa1a3659c1" +\ 155 "a8b4b5bec0c4b872abeba4cb8964", 156 "successful": True 157 }, 158 { 159 "index": 281474976710653, 160 "secret": "c51a18b13e8527e579ec56365482c62f180b" +\ 161 "7d5760b46e9477dae59e87ed423a", 162 "successful": True 163 }, 164 { 165 "index": 281474976710652, 166 "secret": "27cddaa5624534cb6cb9d7da077cf2b22ab2" +\ 167 "1e9b506fd4998a51d54502e99116", 168 "successful": False 169 } 170 ] 171 }, 172 { 173 "name": "insert_secret #4 incorrect (1,2,3 derived from incorrect)", 174 "inserts": [ 175 { 176 "index": 281474976710655, 177 "secret": "02a40c85b6f28da08dfdbe0926c53fab2de6" +\ 178 "d28c10301f8f7c4073d5e42e3148", 179 "successful": True 180 }, 181 { 182 "index": 281474976710654, 183 "secret": "dddc3a8d14fddf2b68fa8c7fbad274827493" +\ 184 "7479dd0f8930d5ebb4ab6bd866a3", 185 "successful": True 186 }, 187 { 188 "index": 281474976710653, 189 "secret": "c51a18b13e8527e579ec56365482c62f18" +\ 190 "0b7d5760b46e9477dae59e87ed423a", 191 "successful": True 192 }, 193 { 194 "index": 281474976710652, 195 "secret": "ba65d7b0ef55a3ba300d4e87af29868f39" +\ 196 "4f8f138d78a7011669c79b37b936f4", 197 "successful": True 198 }, 199 { 200 "index": 281474976710651, 201 "secret": "c65716add7aa98ba7acb236352d665cab1" +\ 202 "7345fe45b55fb879ff80e6bd0c41dd", 203 "successful": True 204 }, 205 { 206 "index": 281474976710650, 207 "secret": "969660042a28f32d9be17344e09374b379" +\ 208 "962d03db1574df5a8a5a47e19ce3f2", 209 "successful": True 210 }, 211 { 212 "index": 281474976710649, 213 "secret": "a5a64476122ca0925fb344bdc1854c1c0a" +\ 214 "59fc614298e50a33e331980a220f32", 215 "successful": True 216 }, 217 { 218 "index": 281474976710649, 219 "secret": "05cde6323d949933f7f7b78776bcc1ea6d9b" +\ 220 "31447732e3802e1f7ac44b650e17", 221 "successful": False 222 } 223 ] 224 }, 225 { 226 "name": "insert_secret #5 incorrect", 227 "inserts": [ 228 { 229 "index": 281474976710655, 230 "secret": "7cc854b54e3e0dcdb010d7a3fee464a9687b" +\ 231 "e6e8db3be6854c475621e007a5dc", 232 "successful": True 233 }, 234 { 235 "index": 281474976710654, 236 "secret": "c7518c8ae4660ed02894df8976fa1a3659c1a" +\ 237 "8b4b5bec0c4b872abeba4cb8964", 238 "successful": True 239 }, 240 { 241 "index": 281474976710653, 242 "secret": "2273e227a5b7449b6e70f1fb4652864038b1" +\ 243 "cbf9cd7c043a7d6456b7fc275ad8", 244 "successful": True 245 }, 246 { 247 "index": 281474976710652, 248 "secret": "27cddaa5624534cb6cb9d7da077cf2b22ab21" +\ 249 "e9b506fd4998a51d54502e99116", 250 "successful": True 251 }, 252 { 253 "index": 281474976710651, 254 "secret": "631373ad5f9ef654bb3dade742d09504c567" +\ 255 "edd24320d2fcd68e3cc47e2ff6a6", 256 "successful": True 257 }, 258 { 259 "index": 281474976710650, 260 "secret": "969660042a28f32d9be17344e09374b37996" +\ 261 "2d03db1574df5a8a5a47e19ce3f2", 262 "successful": False 263 } 264 ] 265 }, 266 { 267 "name": "insert_secret #6 incorrect (5 derived from incorrect)", 268 "inserts": [ 269 { 270 "index": 281474976710655, 271 "secret": "7cc854b54e3e0dcdb010d7a3fee464a9687b" +\ 272 "e6e8db3be6854c475621e007a5dc", 273 "successful": True 274 }, 275 { 276 "index": 281474976710654, 277 "secret": "c7518c8ae4660ed02894df8976fa1a3659c1a" +\ 278 "8b4b5bec0c4b872abeba4cb8964", 279 "successful": True 280 }, 281 { 282 "index": 281474976710653, 283 "secret": "2273e227a5b7449b6e70f1fb4652864038b1" +\ 284 "cbf9cd7c043a7d6456b7fc275ad8", 285 "successful": True 286 }, 287 { 288 "index": 281474976710652, 289 "secret": "27cddaa5624534cb6cb9d7da077cf2b22ab21" +\ 290 "e9b506fd4998a51d54502e99116", 291 "successful": True 292 }, 293 { 294 "index": 281474976710651, 295 "secret": "631373ad5f9ef654bb3dade742d09504c567" +\ 296 "edd24320d2fcd68e3cc47e2ff6a6", 297 "successful": True 298 }, 299 { 300 "index": 281474976710650, 301 "secret": "b7e76a83668bde38b373970155c868a65330" +\ 302 "4308f9896692f904a23731224bb1", 303 "successful": True 304 }, 305 { 306 "index": 281474976710649, 307 "secret": "a5a64476122ca0925fb344bdc1854c1c0a59f" +\ 308 "c614298e50a33e331980a220f32", 309 "successful": True 310 }, 311 { 312 "index": 281474976710648, 313 "secret": "05cde6323d949933f7f7b78776bcc1ea6d9b" +\ 314 "31447732e3802e1f7ac44b650e17", 315 "successful": False 316 } 317 ] 318 }, 319 { 320 "name": "insert_secret #7 incorrect", 321 "inserts": [ 322 { 323 "index": 281474976710655, 324 "secret": "7cc854b54e3e0dcdb010d7a3fee464a9687b" +\ 325 "e6e8db3be6854c475621e007a5dc", 326 "successful": True 327 }, 328 { 329 "index": 281474976710654, 330 "secret": "c7518c8ae4660ed02894df8976fa1a3659c1a" +\ 331 "8b4b5bec0c4b872abeba4cb8964", 332 "successful": True 333 }, 334 { 335 "index": 281474976710653, 336 "secret": "2273e227a5b7449b6e70f1fb4652864038b1" +\ 337 "cbf9cd7c043a7d6456b7fc275ad8", 338 "successful": True 339 }, 340 { 341 "index": 281474976710652, 342 "secret": "27cddaa5624534cb6cb9d7da077cf2b22ab21" +\ 343 "e9b506fd4998a51d54502e99116", 344 "successful": True 345 }, 346 { 347 "index": 281474976710651, 348 "secret": "c65716add7aa98ba7acb236352d665cab173" +\ 349 "45fe45b55fb879ff80e6bd0c41dd", 350 "successful": True 351 }, 352 { 353 "index": 281474976710650, 354 "secret": "969660042a28f32d9be17344e09374b37996" +\ 355 "2d03db1574df5a8a5a47e19ce3f2", 356 "successful": True 357 }, 358 { 359 "index": 281474976710649, 360 "secret": "e7971de736e01da8ed58b94c2fc216cb1d" +\ 361 "ca9e326f3a96e7194fe8ea8af6c0a3", 362 "successful": True 363 }, 364 { 365 "index": 281474976710648, 366 "secret": "05cde6323d949933f7f7b78776bcc1ea6d" +\ 367 "9b31447732e3802e1f7ac44b650e17", 368 "successful": False 369 } 370 ] 371 }, 372 { 373 "name": "insert_secret #8 incorrect", 374 "inserts": [ 375 { 376 "index": 281474976710655, 377 "secret": "7cc854b54e3e0dcdb010d7a3fee464a9687b" +\ 378 "e6e8db3be6854c475621e007a5dc", 379 "successful": True 380 }, 381 { 382 "index": 281474976710654, 383 "secret": "c7518c8ae4660ed02894df8976fa1a3659c1a" +\ 384 "8b4b5bec0c4b872abeba4cb8964", 385 "successful": True 386 }, 387 { 388 "index": 281474976710653, 389 "secret": "2273e227a5b7449b6e70f1fb4652864038b1" +\ 390 "cbf9cd7c043a7d6456b7fc275ad8", 391 "successful": True 392 }, 393 { 394 "index": 281474976710652, 395 "secret": "27cddaa5624534cb6cb9d7da077cf2b22ab21" +\ 396 "e9b506fd4998a51d54502e99116", 397 "successful": True 398 }, 399 { 400 "index": 281474976710651, 401 "secret": "c65716add7aa98ba7acb236352d665cab173" +\ 402 "45fe45b55fb879ff80e6bd0c41dd", 403 "successful": True 404 }, 405 { 406 "index": 281474976710650, 407 "secret": "969660042a28f32d9be17344e09374b37996" +\ 408 "2d03db1574df5a8a5a47e19ce3f2", 409 "successful": True 410 }, 411 { 412 "index": 281474976710649, 413 "secret": "a5a64476122ca0925fb344bdc1854c1c0a" +\ 414 "59fc614298e50a33e331980a220f32", 415 "successful": True 416 }, 417 { 418 "index": 281474976710648, 419 "secret": "a7efbc61aac46d34f77778bac22c8a20c6" +\ 420 "a46ca460addc49009bda875ec88fa4", 421 "successful": False 422 } 423 ] 424 } 425 ] 426 427 for test in tests: 428 receiver = RevocationStore(StoredDict({}, None, [])) 429 for insert in test["inserts"]: 430 secret = bytes.fromhex(insert["secret"]) 431 432 try: 433 receiver.add_next_entry(secret) 434 except Exception as e: 435 if insert["successful"]: 436 raise Exception("Failed ({}): error was received but it shouldn't: {}".format(test["name"], e)) 437 else: 438 if not insert["successful"]: 439 raise Exception("Failed ({}): error wasn't received".format(test["name"])) 440 441 for insert in test["inserts"]: 442 secret = bytes.fromhex(insert["secret"]) 443 index = insert["index"] 444 if insert["successful"]: 445 self.assertEqual(secret, receiver.retrieve_secret(index)) 446 447 print("Passed ({})".format(test["name"])) 448 449 def test_shachain_produce_consume(self): 450 seed = bitcoin.sha256(b"shachaintest") 451 consumer = RevocationStore(StoredDict({}, None, [])) 452 for i in range(10000): 453 secret = get_per_commitment_secret_from_seed(seed, RevocationStore.START_INDEX - i) 454 try: 455 consumer.add_next_entry(secret) 456 except Exception as e: 457 raise Exception("iteration " + str(i) + ": " + str(e)) 458 if i % 1000 == 0: 459 c1 = consumer 460 s1 = json.dumps(c1.storage, cls=MyEncoder) 461 c2 = RevocationStore(StoredDict(json.loads(s1), None, [])) 462 s2 = json.dumps(c2.storage, cls=MyEncoder) 463 self.assertEqual(s1, s2) 464 465 def test_commitment_tx_with_all_five_HTLCs_untrimmed_minimum_feerate(self): 466 to_local_msat = 6988000000 467 to_remote_msat = 3000000000 468 local_feerate_per_kw = 0 469 # base commitment transaction fee = 0 470 # actual commitment transaction fee = 0 471 472 per_commitment_secret = 0x1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100 473 per_commitment_point = secret_to_pubkey(per_commitment_secret) 474 475 remote_htlcpubkey = remotepubkey 476 local_htlcpubkey = localpubkey 477 478 htlc_cltv_timeout = {} 479 htlc_payment_preimage = {} 480 htlc = {} 481 482 htlc_cltv_timeout[2] = 502 483 htlc_payment_preimage[2] = b"\x02" * 32 484 htlc[2] = make_offered_htlc(local_revocation_pubkey, remote_htlcpubkey, local_htlcpubkey, bitcoin.sha256(htlc_payment_preimage[2])) 485 486 htlc_cltv_timeout[3] = 503 487 htlc_payment_preimage[3] = b"\x03" * 32 488 htlc[3] = make_offered_htlc(local_revocation_pubkey, remote_htlcpubkey, local_htlcpubkey, bitcoin.sha256(htlc_payment_preimage[3])) 489 490 htlc_cltv_timeout[0] = 500 491 htlc_payment_preimage[0] = b"\x00" * 32 492 htlc[0] = make_received_htlc(local_revocation_pubkey, remote_htlcpubkey, local_htlcpubkey, bitcoin.sha256(htlc_payment_preimage[0]), htlc_cltv_timeout[0]) 493 494 htlc_cltv_timeout[1] = 501 495 htlc_payment_preimage[1] = b"\x01" * 32 496 htlc[1] = make_received_htlc(local_revocation_pubkey, remote_htlcpubkey, local_htlcpubkey, bitcoin.sha256(htlc_payment_preimage[1]), htlc_cltv_timeout[1]) 497 498 htlc_cltv_timeout[4] = 504 499 htlc_payment_preimage[4] = b"\x04" * 32 500 htlc[4] = make_received_htlc(local_revocation_pubkey, remote_htlcpubkey, local_htlcpubkey, bitcoin.sha256(htlc_payment_preimage[4]), htlc_cltv_timeout[4]) 501 502 remote_signature = "304402204fd4928835db1ccdfc40f5c78ce9bd65249b16348df81f0c44328dcdefc97d630220194d3869c38bc732dd87d13d2958015e2fc16829e74cd4377f84d215c0b70606" 503 output_commit_tx = "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8007e80300000000000022002052bfef0479d7b293c27e0f1eb294bea154c63a3294ef092c19af51409bce0e2ad007000000000000220020403d394747cae42e98ff01734ad5c08f82ba123d3d9a620abda88989651e2ab5d007000000000000220020748eba944fedc8827f6b06bc44678f93c0f9e6078b35c6331ed31e75f8ce0c2db80b000000000000220020c20b5d1f8584fd90443e7b7b720136174fa4b9333c261d04dbbd012635c0f419a00f0000000000002200208c48d15160397c9731df9bc3b236656efb6665fbfe92b4a6878e88a499f741c4c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de843110e0a06a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e04004730440220275b0c325a5e9355650dc30c0eccfbc7efb23987c24b556b9dfdd40effca18d202206caceb2c067836c51f296740c7ae807ffcbfbf1dd3a0d56b6de9a5b247985f060147304402204fd4928835db1ccdfc40f5c78ce9bd65249b16348df81f0c44328dcdefc97d630220194d3869c38bc732dd87d13d2958015e2fc16829e74cd4377f84d215c0b7060601475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220" 504 505 htlc_obj = {} 506 for num, msat in [(0, 1000 * 1000), 507 (2, 2000 * 1000), 508 (1, 2000 * 1000), 509 (3, 3000 * 1000), 510 (4, 4000 * 1000)]: 511 htlc_obj[num] = UpdateAddHtlc(amount_msat=msat, payment_hash=bitcoin.sha256(htlc_payment_preimage[num]), cltv_expiry=0, htlc_id=None, timestamp=0) 512 htlcs = [ScriptHtlc(htlc[x], htlc_obj[x]) for x in range(5)] 513 514 our_commit_tx = make_commitment( 515 ctn=commitment_number, 516 local_funding_pubkey=local_funding_pubkey, 517 remote_funding_pubkey=remote_funding_pubkey, 518 remote_payment_pubkey=remotepubkey, 519 funder_payment_basepoint=local_payment_basepoint, 520 fundee_payment_basepoint=remote_payment_basepoint, 521 revocation_pubkey=local_revocation_pubkey, 522 delayed_pubkey=local_delayedpubkey, 523 to_self_delay=local_delay, 524 funding_txid=funding_tx_id, 525 funding_pos=funding_output_index, 526 funding_sat=funding_amount_satoshi, 527 local_amount=to_local_msat, 528 remote_amount=to_remote_msat, 529 dust_limit_sat=local_dust_limit_satoshi, 530 fees_per_participant=calc_fees_for_commitment_tx(num_htlcs=len(htlcs), feerate=local_feerate_per_kw, is_local_initiator=True), 531 htlcs=htlcs) 532 self.sign_and_insert_remote_sig(our_commit_tx, remote_funding_pubkey, remote_signature, local_funding_pubkey, local_funding_privkey) 533 self.assertEqual(str(our_commit_tx), output_commit_tx) 534 535 signature_for_output_remote_htlc = {} 536 signature_for_output_remote_htlc[0] = "304402206a6e59f18764a5bf8d4fa45eebc591566689441229c918b480fb2af8cc6a4aeb02205248f273be447684b33e3c8d1d85a8e0ca9fa0bae9ae33f0527ada9c162919a6" 537 signature_for_output_remote_htlc[2] = "3045022100d5275b3619953cb0c3b5aa577f04bc512380e60fa551762ce3d7a1bb7401cff9022037237ab0dac3fe100cde094e82e2bed9ba0ed1bb40154b48e56aa70f259e608b" 538 signature_for_output_remote_htlc[1] = "304402201b63ec807771baf4fdff523c644080de17f1da478989308ad13a58b51db91d360220568939d38c9ce295adba15665fa68f51d967e8ed14a007b751540a80b325f202" 539 signature_for_output_remote_htlc[3] = "3045022100daee1808f9861b6c3ecd14f7b707eca02dd6bdfc714ba2f33bc8cdba507bb182022026654bf8863af77d74f51f4e0b62d461a019561bb12acb120d3f7195d148a554" 540 signature_for_output_remote_htlc[4] = "304402207e0410e45454b0978a623f36a10626ef17b27d9ad44e2760f98cfa3efb37924f0220220bd8acd43ecaa916a80bd4f919c495a2c58982ce7c8625153f8596692a801d" 541 542 output_htlc_tx = {} 543 SUCCESS = True 544 TIMEOUT = False 545 output_htlc_tx[0] = (SUCCESS, "020000000001018154ecccf11a5fb56c39654c4deb4d2296f83c69268280b94d021370c94e219700000000000000000001e8030000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402206a6e59f18764a5bf8d4fa45eebc591566689441229c918b480fb2af8cc6a4aeb02205248f273be447684b33e3c8d1d85a8e0ca9fa0bae9ae33f0527ada9c162919a60147304402207cb324fa0de88f452ffa9389678127ebcf4cabe1dd848b8e076c1a1962bf34720220116ed922b12311bd602d67e60d2529917f21c5b82f25ff6506c0f87886b4dfd5012000000000000000000000000000000000000000000000000000000000000000008a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a914b8bcb07f6344b42ab04250c86a6e8b75d3fdbbc688527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f401b175ac686800000000") 546 547 output_htlc_tx[2] = (TIMEOUT, "020000000001018154ecccf11a5fb56c39654c4deb4d2296f83c69268280b94d021370c94e219701000000000000000001d0070000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100d5275b3619953cb0c3b5aa577f04bc512380e60fa551762ce3d7a1bb7401cff9022037237ab0dac3fe100cde094e82e2bed9ba0ed1bb40154b48e56aa70f259e608b0147304402205735e9f335dfd123f730ac5bf184fd7d5b672e4d84c51a3f0478cc229bb44936022018b1cec3e3b29e5cc335d7e326bc29d75a7e063216427d081cb83ebdbd828b4d01008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a914b43e1b38138a41b37f7cd9a1d274bc63e3a9b5d188ac6868f6010000") 548 549 output_htlc_tx[1] = (SUCCESS, "020000000001018154ecccf11a5fb56c39654c4deb4d2296f83c69268280b94d021370c94e219702000000000000000001d0070000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402201b63ec807771baf4fdff523c644080de17f1da478989308ad13a58b51db91d360220568939d38c9ce295adba15665fa68f51d967e8ed14a007b751540a80b325f202014730440220481a48f83c358ae0f220e37f88e56b3d434cefaded82065b8e7a9fd78fee7a26022022674ab37a4c39e6efba302f760ca05931d8add8d65231c5bf34a6c2a76b15bf012001010101010101010101010101010101010101010101010101010101010101018a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a9144b6b2e5444c2639cc0fb7bcea5afba3f3cdce23988527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f501b175ac686800000000") 550 551 output_htlc_tx[3] = (TIMEOUT, "020000000001018154ecccf11a5fb56c39654c4deb4d2296f83c69268280b94d021370c94e219703000000000000000001b80b0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0500483045022100daee1808f9861b6c3ecd14f7b707eca02dd6bdfc714ba2f33bc8cdba507bb182022026654bf8863af77d74f51f4e0b62d461a019561bb12acb120d3f7195d148a554014730440220643aacb19bbb72bd2b635bc3f7375481f5981bace78cdd8319b2988ffcc6704202203d27784ec8ad51ed3bd517a05525a5139bb0b755dd719e0054332d186ac0872701008576a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c820120876475527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae67a9148a486ff2e31d6158bf39e2608864d63fefd09d5b88ac6868f7010000") 552 553 output_htlc_tx[4] = (SUCCESS, "020000000001018154ecccf11a5fb56c39654c4deb4d2296f83c69268280b94d021370c94e219704000000000000000001a00f0000000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e050047304402207e0410e45454b0978a623f36a10626ef17b27d9ad44e2760f98cfa3efb37924f0220220bd8acd43ecaa916a80bd4f919c495a2c58982ce7c8625153f8596692a801d014730440220549e80b4496803cbc4a1d09d46df50109f546d43fbbf86cd90b174b1484acd5402205f12a4f995cb9bded597eabfee195a285986aa6d93ae5bb72507ebc6a4e2349e012004040404040404040404040404040404040404040404040404040404040404048a76a91414011f7254d96b819c76986c277d115efce6f7b58763ac67210394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b7c8201208763a91418bc1a114ccf9c052d3d23e28d3b0a9d1227434288527c21030d417a46946384f88d5f3337267c5e579765875dc4daca813e21734b140639e752ae677502f801b175ac686800000000") 554 555 htlc_output_index = {0: 0, 1: 2, 2: 1, 3: 3, 4: 4} 556 557 for i in range(5): 558 self.assertEqual(output_htlc_tx[i][1], self.htlc_tx(htlc[i], htlc_output_index[i], 559 htlcs[i].htlc.amount_msat, 560 htlc_payment_preimage[i], 561 signature_for_output_remote_htlc[i], 562 output_htlc_tx[i][0], htlc_cltv_timeout[i] if not output_htlc_tx[i][0] else 0, 563 local_feerate_per_kw, 564 our_commit_tx)) 565 566 def htlc_tx(self, htlc, htlc_output_index, amount_msat, htlc_payment_preimage, remote_htlc_sig, success, cltv_timeout, local_feerate_per_kw, our_commit_tx): 567 _script, our_htlc_tx_output = make_htlc_tx_output( 568 amount_msat=amount_msat, 569 local_feerate=local_feerate_per_kw, 570 revocationpubkey=local_revocation_pubkey, 571 local_delayedpubkey=local_delayedpubkey, 572 success=success, 573 to_self_delay=local_delay) 574 our_htlc_tx_inputs = make_htlc_tx_inputs( 575 htlc_output_txid=our_commit_tx.txid(), 576 htlc_output_index=htlc_output_index, 577 amount_msat=amount_msat, 578 witness_script=bh2u(htlc)) 579 our_htlc_tx = make_htlc_tx( 580 cltv_expiry=cltv_timeout, 581 inputs=our_htlc_tx_inputs, 582 output=our_htlc_tx_output) 583 584 local_sig = our_htlc_tx.sign_txin(0, local_privkey[:-1]) 585 586 our_htlc_tx_witness = make_htlc_tx_witness( 587 remotehtlcsig=bfh(remote_htlc_sig) + b"\x01", # 0x01 is SIGHASH_ALL 588 localhtlcsig=bfh(local_sig), 589 payment_preimage=htlc_payment_preimage if success else b'', # will put 00 on witness if timeout 590 witness_script=htlc) 591 our_htlc_tx._inputs[0].witness = our_htlc_tx_witness 592 return str(our_htlc_tx) 593 594 def test_commitment_tx_with_one_output(self): 595 to_local_msat= 6988000000 596 to_remote_msat= 3000000000 597 local_feerate_per_kw= 9651181 598 remote_signature = "3044022064901950be922e62cbe3f2ab93de2b99f37cff9fc473e73e394b27f88ef0731d02206d1dfa227527b4df44a07599289e207d6fd9cca60c0365682dcd3deaf739567e" 599 output_commit_tx= "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8001c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de8431100400473044022031a82b51bd014915fe68928d1abf4b9885353fb896cac10c3fdd88d7f9c7f2e00220716bda819641d2c63e65d3549b6120112e1aeaf1742eed94a471488e79e206b101473044022064901950be922e62cbe3f2ab93de2b99f37cff9fc473e73e394b27f88ef0731d02206d1dfa227527b4df44a07599289e207d6fd9cca60c0365682dcd3deaf739567e01475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220" 600 601 our_commit_tx = make_commitment( 602 ctn=commitment_number, 603 local_funding_pubkey=local_funding_pubkey, 604 remote_funding_pubkey=remote_funding_pubkey, 605 remote_payment_pubkey=remotepubkey, 606 funder_payment_basepoint=local_payment_basepoint, 607 fundee_payment_basepoint=remote_payment_basepoint, 608 revocation_pubkey=local_revocation_pubkey, 609 delayed_pubkey=local_delayedpubkey, 610 to_self_delay=local_delay, 611 funding_txid=funding_tx_id, 612 funding_pos=funding_output_index, 613 funding_sat=funding_amount_satoshi, 614 local_amount=to_local_msat, 615 remote_amount=to_remote_msat, 616 dust_limit_sat=local_dust_limit_satoshi, 617 fees_per_participant=calc_fees_for_commitment_tx(num_htlcs=0, feerate=local_feerate_per_kw, is_local_initiator=True), 618 htlcs=[]) 619 self.sign_and_insert_remote_sig(our_commit_tx, remote_funding_pubkey, remote_signature, local_funding_pubkey, local_funding_privkey) 620 621 self.assertEqual(str(our_commit_tx), output_commit_tx) 622 623 def test_commitment_tx_with_fee_greater_than_funder_amount(self): 624 to_local_msat= 6988000000 625 to_remote_msat= 3000000000 626 local_feerate_per_kw= 9651936 627 remote_signature = "3044022064901950be922e62cbe3f2ab93de2b99f37cff9fc473e73e394b27f88ef0731d02206d1dfa227527b4df44a07599289e207d6fd9cca60c0365682dcd3deaf739567e" 628 output_commit_tx= "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8001c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de8431100400473044022031a82b51bd014915fe68928d1abf4b9885353fb896cac10c3fdd88d7f9c7f2e00220716bda819641d2c63e65d3549b6120112e1aeaf1742eed94a471488e79e206b101473044022064901950be922e62cbe3f2ab93de2b99f37cff9fc473e73e394b27f88ef0731d02206d1dfa227527b4df44a07599289e207d6fd9cca60c0365682dcd3deaf739567e01475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220" 629 630 our_commit_tx = make_commitment( 631 ctn=commitment_number, 632 local_funding_pubkey=local_funding_pubkey, 633 remote_funding_pubkey=remote_funding_pubkey, 634 remote_payment_pubkey=remotepubkey, 635 funder_payment_basepoint=local_payment_basepoint, 636 fundee_payment_basepoint=remote_payment_basepoint, 637 revocation_pubkey=local_revocation_pubkey, 638 delayed_pubkey=local_delayedpubkey, 639 to_self_delay=local_delay, 640 funding_txid=funding_tx_id, 641 funding_pos=funding_output_index, 642 funding_sat=funding_amount_satoshi, 643 local_amount=to_local_msat, 644 remote_amount=to_remote_msat, 645 dust_limit_sat=local_dust_limit_satoshi, 646 fees_per_participant=calc_fees_for_commitment_tx(num_htlcs=0, feerate=local_feerate_per_kw, is_local_initiator=True), 647 htlcs=[]) 648 self.sign_and_insert_remote_sig(our_commit_tx, remote_funding_pubkey, remote_signature, local_funding_pubkey, local_funding_privkey) 649 650 self.assertEqual(str(our_commit_tx), output_commit_tx) 651 652 def test_extract_commitment_number_from_tx(self): 653 raw_tx = "02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8007e80300000000000022002052bfef0479d7b293c27e0f1eb294bea154c63a3294ef092c19af51409bce0e2ad007000000000000220020403d394747cae42e98ff01734ad5c08f82ba123d3d9a620abda88989651e2ab5d007000000000000220020748eba944fedc8827f6b06bc44678f93c0f9e6078b35c6331ed31e75f8ce0c2db80b000000000000220020c20b5d1f8584fd90443e7b7b720136174fa4b9333c261d04dbbd012635c0f419a00f0000000000002200208c48d15160397c9731df9bc3b236656efb6665fbfe92b4a6878e88a499f741c4c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de843110e0a06a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e04004730440220275b0c325a5e9355650dc30c0eccfbc7efb23987c24b556b9dfdd40effca18d202206caceb2c067836c51f296740c7ae807ffcbfbf1dd3a0d56b6de9a5b247985f060147304402204fd4928835db1ccdfc40f5c78ce9bd65249b16348df81f0c44328dcdefc97d630220194d3869c38bc732dd87d13d2958015e2fc16829e74cd4377f84d215c0b7060601475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220" 654 tx = Transaction(raw_tx) 655 self.assertEqual(commitment_number, extract_ctn_from_tx(tx, 0, local_payment_basepoint, remote_payment_basepoint)) 656 657 def test_per_commitment_secret_from_seed(self): 658 self.assertEqual(0x02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148.to_bytes(byteorder="big", length=32), 659 get_per_commitment_secret_from_seed(0x0000000000000000000000000000000000000000000000000000000000000000.to_bytes(byteorder="big", length=32), 281474976710655)) 660 self.assertEqual(0x7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc.to_bytes(byteorder="big", length=32), 661 get_per_commitment_secret_from_seed(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF.to_bytes(byteorder="big", length=32), 281474976710655)) 662 self.assertEqual(0x56f4008fb007ca9acf0e15b054d5c9fd12ee06cea347914ddbaed70d1c13a528.to_bytes(byteorder="big", length=32), 663 get_per_commitment_secret_from_seed(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF.to_bytes(byteorder="big", length=32), 0xaaaaaaaaaaa)) 664 self.assertEqual(0x9015daaeb06dba4ccc05b91b2f73bd54405f2be9f217fbacd3c5ac2e62327d31.to_bytes(byteorder="big", length=32), 665 get_per_commitment_secret_from_seed(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF.to_bytes(byteorder="big", length=32), 0x555555555555)) 666 self.assertEqual(0x915c75942a26bb3a433a8ce2cb0427c29ec6c1775cfc78328b57f6ba7bfeaa9c.to_bytes(byteorder="big", length=32), 667 get_per_commitment_secret_from_seed(0x0101010101010101010101010101010101010101010101010101010101010101.to_bytes(byteorder="big", length=32), 1)) 668 669 def test_key_derivation(self): 670 # BOLT3, Appendix E 671 base_secret = 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 672 per_commitment_secret = 0x1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100 673 revocation_basepoint_secret = 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 674 base_point = secret_to_pubkey(base_secret) 675 self.assertEqual(base_point, bfh('036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2')) 676 per_commitment_point = secret_to_pubkey(per_commitment_secret) 677 self.assertEqual(per_commitment_point, bfh('025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486')) 678 localpubkey = derive_pubkey(base_point, per_commitment_point) 679 self.assertEqual(localpubkey, bfh('0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5')) 680 localprivkey = derive_privkey(base_secret, per_commitment_point) 681 self.assertEqual(localprivkey, 0xcbced912d3b21bf196a766651e436aff192362621ce317704ea2f75d87e7be0f) 682 revocation_basepoint = secret_to_pubkey(revocation_basepoint_secret) 683 self.assertEqual(revocation_basepoint, bfh('036d6caac248af96f6afa7f904f550253a0f3ef3f5aa2fe6838a95b216691468e2')) 684 revocationpubkey = derive_blinded_pubkey(revocation_basepoint, per_commitment_point) 685 self.assertEqual(revocationpubkey, bfh('02916e326636d19c33f13e8c0c3a03dd157f332f3e99c317c141dd865eb01f8ff0')) 686 687 def test_simple_commitment_tx_with_no_HTLCs(self): 688 to_local_msat = 7000000000 689 to_remote_msat = 3000000000 690 local_feerate_per_kw = 15000 691 # base commitment transaction fee = 10860 692 # actual commitment transaction fee = 10860 693 # to_local amount 6989140 wscript 63210212a140cd0c6539d07cd08dfe09984dec3251ea808b892efeac3ede9402bf2b1967029000b2752103fd5960528dc152014952efdb702a88f71e3c1653b2314431701ec77e57fde83c68ac 694 # to_remote amount 3000000 P2WPKH(0394854aa6eab5b2a8122cc726e9dded053a2184d88256816826d6231c068d4a5b) 695 remote_signature = "3045022100f51d2e566a70ba740fc5d8c0f07b9b93d2ed741c3c0860c613173de7d39e7968022041376d520e9c0e1ad52248ddf4b22e12be8763007df977253ef45a4ca3bdb7c0" 696 # local_signature = 3044022051b75c73198c6deee1a875871c3961832909acd297c6b908d59e3319e5185a46022055c419379c5051a78d00dbbce11b5b664a0c22815fbcc6fcef6b1937c3836939 697 our_commit_tx = make_commitment( 698 ctn=commitment_number, 699 local_funding_pubkey=local_funding_pubkey, 700 remote_funding_pubkey=remote_funding_pubkey, 701 remote_payment_pubkey=remotepubkey, 702 funder_payment_basepoint=local_payment_basepoint, 703 fundee_payment_basepoint=remote_payment_basepoint, 704 revocation_pubkey=local_revocation_pubkey, 705 delayed_pubkey=local_delayedpubkey, 706 to_self_delay=local_delay, 707 funding_txid=funding_tx_id, 708 funding_pos=funding_output_index, 709 funding_sat=funding_amount_satoshi, 710 local_amount=to_local_msat, 711 remote_amount=to_remote_msat, 712 dust_limit_sat=local_dust_limit_satoshi, 713 fees_per_participant=calc_fees_for_commitment_tx(num_htlcs=0, feerate=local_feerate_per_kw, is_local_initiator=True), 714 htlcs=[]) 715 self.sign_and_insert_remote_sig(our_commit_tx, remote_funding_pubkey, remote_signature, local_funding_pubkey, local_funding_privkey) 716 ref_commit_tx_str = '02000000000101bef67e4e2fb9ddeeb3461973cd4c62abb35050b1add772995b820b584a488489000000000038b02b8002c0c62d0000000000160014ccf1af2f2aabee14bb40fa3851ab2301de84311054a56a00000000002200204adb4e2f00643db396dd120d4e7dc17625f5f2c11a40d857accc862d6b7dd80e0400473044022051b75c73198c6deee1a875871c3961832909acd297c6b908d59e3319e5185a46022055c419379c5051a78d00dbbce11b5b664a0c22815fbcc6fcef6b1937c383693901483045022100f51d2e566a70ba740fc5d8c0f07b9b93d2ed741c3c0860c613173de7d39e7968022041376d520e9c0e1ad52248ddf4b22e12be8763007df977253ef45a4ca3bdb7c001475221023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb21030e9f7b623d2ccc7c9bd44d66d5ce21ce504c0acf6385a132cec6d3c39fa711c152ae3e195220' 717 self.assertEqual(str(our_commit_tx), ref_commit_tx_str) 718 719 def sign_and_insert_remote_sig(self, tx: PartialTransaction, remote_pubkey, remote_signature, pubkey, privkey): 720 assert type(remote_pubkey) is bytes 721 assert len(remote_pubkey) == 33 722 assert type(remote_signature) is str 723 assert type(pubkey) is bytes 724 assert type(privkey) is bytes 725 assert len(pubkey) == 33 726 assert len(privkey) == 33 727 tx.sign({bh2u(pubkey): (privkey[:-1], True)}) 728 tx.add_signature_to_txin(txin_idx=0, signing_pubkey=remote_pubkey.hex(), sig=remote_signature + "01") 729 730 def test_get_compressed_pubkey_from_bech32(self): 731 self.assertEqual(b'\x03\x84\xef\x87\xd9d\xa2\xaaa7=\xff\xb8\xfe=t8[}>;\n\x13\xa8e\x8eo:\xf5Mi\xb5H', 732 get_compressed_pubkey_from_bech32('ln1qwzwlp7evj325cfh8hlm3l3awsu9klf78v9p82r93ehn4a2ddx65s66awg5')) 733 734 def test_split_host_port(self): 735 self.assertEqual(split_host_port("[::1]:8000"), ("::1", "8000")) 736 self.assertEqual(split_host_port("[::1]"), ("::1", "9735")) 737 self.assertEqual(split_host_port("[2601:602:8800:9a:dc59:a4ff:fede:24a9]:9735"), ("2601:602:8800:9a:dc59:a4ff:fede:24a9", "9735")) 738 self.assertEqual(split_host_port("[2601:602:8800::a4ff:fede:24a9]:9735"), ("2601:602:8800::a4ff:fede:24a9", "9735")) 739 self.assertEqual(split_host_port("kæn.guru:8000"), ("kæn.guru", "8000")) 740 self.assertEqual(split_host_port("kæn.guru"), ("kæn.guru", "9735")) 741 self.assertEqual(split_host_port("127.0.0.1:8000"), ("127.0.0.1", "8000")) 742 self.assertEqual(split_host_port("127.0.0.1"), ("127.0.0.1", "9735")) 743 # accepted by getaddrinfo but not ipaddress.ip_address 744 self.assertEqual(split_host_port("127.0.0:8000"), ("127.0.0", "8000")) 745 self.assertEqual(split_host_port("127.0.0"), ("127.0.0", "9735")) 746 self.assertEqual(split_host_port("electrum.org:8000"), ("electrum.org", "8000")) 747 self.assertEqual(split_host_port("electrum.org"), ("electrum.org", "9735")) 748 749 with self.assertRaises(ConnStringFormatError): 750 split_host_port("electrum.org:8000:") 751 with self.assertRaises(ConnStringFormatError): 752 split_host_port("electrum.org:") 753 754 def test_extract_nodeid(self): 755 with self.assertRaises(ConnStringFormatError): 756 extract_nodeid("00" * 32 + "@localhost") 757 with self.assertRaises(ConnStringFormatError): 758 extract_nodeid("00" * 33 + "@") 759 self.assertEqual(extract_nodeid("00" * 33 + "@localhost"), (b"\x00" * 33, "localhost")) 760 761 def test_ln_features_validate_transitive_dependencies(self): 762 features = LnFeatures.OPTION_DATA_LOSS_PROTECT_REQ 763 self.assertTrue(features.validate_transitive_dependencies()) 764 features = LnFeatures.PAYMENT_SECRET_OPT 765 self.assertFalse(features.validate_transitive_dependencies()) 766 features = LnFeatures.PAYMENT_SECRET_REQ 767 self.assertFalse(features.validate_transitive_dependencies()) 768 features = LnFeatures.PAYMENT_SECRET_REQ | LnFeatures.VAR_ONION_REQ 769 self.assertTrue(features.validate_transitive_dependencies()) 770 features = LnFeatures.BASIC_MPP_OPT | LnFeatures.PAYMENT_SECRET_REQ 771 self.assertFalse(features.validate_transitive_dependencies()) 772 features = LnFeatures.BASIC_MPP_OPT | LnFeatures.PAYMENT_SECRET_REQ | LnFeatures.VAR_ONION_OPT 773 self.assertTrue(features.validate_transitive_dependencies()) 774 features = LnFeatures.BASIC_MPP_OPT | LnFeatures.PAYMENT_SECRET_REQ | LnFeatures.VAR_ONION_REQ 775 self.assertTrue(features.validate_transitive_dependencies()) 776 777 def test_ln_features_for_init_message(self): 778 features = LnFeatures.OPTION_DATA_LOSS_PROTECT_REQ 779 self.assertEqual(features, features.for_init_message()) 780 features = LnFeatures.PAYMENT_SECRET_OPT 781 self.assertEqual(features, features.for_init_message()) 782 features = LnFeatures.PAYMENT_SECRET_REQ 783 self.assertEqual(features, features.for_init_message()) 784 features = LnFeatures.PAYMENT_SECRET_REQ | LnFeatures.VAR_ONION_REQ 785 self.assertEqual(features, features.for_init_message()) 786 features = LnFeatures.BASIC_MPP_OPT | LnFeatures.PAYMENT_SECRET_REQ 787 self.assertEqual(features, features.for_init_message()) 788 features = LnFeatures.BASIC_MPP_OPT | LnFeatures.PAYMENT_SECRET_REQ | LnFeatures.VAR_ONION_OPT 789 self.assertEqual(features, features.for_init_message()) 790 features = LnFeatures.BASIC_MPP_OPT | LnFeatures.PAYMENT_SECRET_REQ | LnFeatures.VAR_ONION_REQ 791 self.assertEqual(features, features.for_init_message()) 792 793 def test_ln_features_for_invoice(self): 794 features = LnFeatures.OPTION_DATA_LOSS_PROTECT_REQ 795 self.assertEqual(LnFeatures(0), features.for_invoice()) 796 features = LnFeatures.PAYMENT_SECRET_OPT 797 self.assertEqual(features, features.for_invoice()) 798 features = LnFeatures.PAYMENT_SECRET_REQ 799 self.assertEqual(features, features.for_invoice()) 800 features = LnFeatures.PAYMENT_SECRET_REQ | LnFeatures.VAR_ONION_REQ 801 self.assertEqual(features, features.for_invoice()) 802 features = LnFeatures.BASIC_MPP_OPT | LnFeatures.PAYMENT_SECRET_REQ | LnFeatures.OPTION_DATA_LOSS_PROTECT_REQ 803 self.assertEqual(LnFeatures.BASIC_MPP_OPT | LnFeatures.PAYMENT_SECRET_REQ, 804 features.for_invoice()) 805 features = LnFeatures.BASIC_MPP_OPT | LnFeatures.PAYMENT_SECRET_REQ | LnFeatures.VAR_ONION_OPT | LnFeatures.OPTION_DATA_LOSS_PROTECT_REQ 806 self.assertEqual(LnFeatures.BASIC_MPP_OPT | LnFeatures.PAYMENT_SECRET_REQ | LnFeatures.VAR_ONION_OPT, 807 features.for_invoice()) 808 features = LnFeatures.BASIC_MPP_OPT | LnFeatures.PAYMENT_SECRET_REQ | LnFeatures.VAR_ONION_REQ 809 self.assertEqual(features, features.for_invoice()) 810 811 def test_ln_compare_features(self): 812 f1 = LnFeatures.OPTION_DATA_LOSS_PROTECT_REQ | LnFeatures.OPTION_DATA_LOSS_PROTECT_OPT 813 f2 = LnFeatures.OPTION_DATA_LOSS_PROTECT_REQ 814 self.assertEqual(LnFeatures.OPTION_DATA_LOSS_PROTECT_REQ | LnFeatures.OPTION_DATA_LOSS_PROTECT_OPT, 815 ln_compare_features(f1, f2)) 816 self.assertEqual(LnFeatures.OPTION_DATA_LOSS_PROTECT_REQ | LnFeatures.OPTION_DATA_LOSS_PROTECT_OPT, 817 ln_compare_features(f2, f1)) 818 # note that the args are not commutative; if we (first arg) REQ a feature, OPT will get auto-set 819 f1 = LnFeatures.OPTION_DATA_LOSS_PROTECT_OPT 820 f2 = LnFeatures.OPTION_DATA_LOSS_PROTECT_REQ 821 self.assertEqual(LnFeatures.OPTION_DATA_LOSS_PROTECT_OPT, 822 ln_compare_features(f1, f2)) 823 self.assertEqual(LnFeatures.OPTION_DATA_LOSS_PROTECT_REQ | LnFeatures.OPTION_DATA_LOSS_PROTECT_OPT, 824 ln_compare_features(f2, f1)) 825 826 f1 = LnFeatures(0) 827 f2 = LnFeatures.OPTION_DATA_LOSS_PROTECT_OPT 828 self.assertEqual(LnFeatures(0), ln_compare_features(f1, f2)) 829 self.assertEqual(LnFeatures(0), ln_compare_features(f2, f1)) 830 831 f1 = LnFeatures(0) 832 f2 = LnFeatures.OPTION_DATA_LOSS_PROTECT_REQ 833 with self.assertRaises(IncompatibleLightningFeatures): 834 ln_compare_features(f1, f2) 835 with self.assertRaises(IncompatibleLightningFeatures): 836 ln_compare_features(f2, f1) 837 838 f1 = LnFeatures.BASIC_MPP_OPT | LnFeatures.PAYMENT_SECRET_REQ | LnFeatures.OPTION_DATA_LOSS_PROTECT_OPT | LnFeatures.VAR_ONION_OPT 839 f2 = LnFeatures.PAYMENT_SECRET_OPT | LnFeatures.OPTION_DATA_LOSS_PROTECT_REQ | LnFeatures.VAR_ONION_OPT 840 self.assertEqual(LnFeatures.PAYMENT_SECRET_OPT | 841 LnFeatures.PAYMENT_SECRET_REQ | 842 LnFeatures.OPTION_DATA_LOSS_PROTECT_OPT | 843 LnFeatures.VAR_ONION_OPT, 844 ln_compare_features(f1, f2)) 845 self.assertEqual(LnFeatures.PAYMENT_SECRET_OPT | 846 LnFeatures.OPTION_DATA_LOSS_PROTECT_OPT | 847 LnFeatures.OPTION_DATA_LOSS_PROTECT_REQ | 848 LnFeatures.VAR_ONION_OPT, 849 ln_compare_features(f2, f1)) 850 851 def test_ln_features_supports(self): 852 f_null = LnFeatures(0) 853 f_opt = LnFeatures.OPTION_DATA_LOSS_PROTECT_OPT 854 f_req = LnFeatures.OPTION_DATA_LOSS_PROTECT_REQ 855 f_optreq = LnFeatures.OPTION_DATA_LOSS_PROTECT_REQ | LnFeatures.OPTION_DATA_LOSS_PROTECT_OPT 856 self.assertFalse(f_null.supports(LnFeatures.OPTION_DATA_LOSS_PROTECT_OPT)) 857 self.assertFalse(f_null.supports(LnFeatures.OPTION_DATA_LOSS_PROTECT_REQ)) 858 self.assertTrue(f_opt.supports(LnFeatures.OPTION_DATA_LOSS_PROTECT_OPT)) 859 self.assertTrue(f_opt.supports(LnFeatures.OPTION_DATA_LOSS_PROTECT_REQ)) 860 self.assertTrue(f_req.supports(LnFeatures.OPTION_DATA_LOSS_PROTECT_OPT)) 861 self.assertTrue(f_req.supports(LnFeatures.OPTION_DATA_LOSS_PROTECT_REQ)) 862 self.assertTrue(f_optreq.supports(LnFeatures.OPTION_DATA_LOSS_PROTECT_OPT)) 863 self.assertTrue(f_optreq.supports(LnFeatures.OPTION_DATA_LOSS_PROTECT_REQ)) 864 with self.assertRaises(ValueError): 865 f_opt.supports(f_optreq) 866 with self.assertRaises(ValueError): 867 f_optreq.supports(f_optreq) 868 f1 = LnFeatures.BASIC_MPP_OPT | LnFeatures.PAYMENT_SECRET_REQ | LnFeatures.OPTION_DATA_LOSS_PROTECT_OPT | LnFeatures.VAR_ONION_OPT 869 self.assertTrue(f1.supports(LnFeatures.PAYMENT_SECRET_OPT)) 870 self.assertTrue(f1.supports(LnFeatures.BASIC_MPP_REQ)) 871 self.assertFalse(f1.supports(LnFeatures.OPTION_STATIC_REMOTEKEY_OPT)) 872 self.assertFalse(f1.supports(LnFeatures.OPTION_TRAMPOLINE_ROUTING_REQ)) 873 874 def test_lnworker_decode_channel_update_msg(self): 875 msg_without_prefix = bytes.fromhex("439b71c8ddeff63004e4ff1f9764a57dcf20232b79d9d669aef0e31c42be8e44208f7d868d0133acb334047f30e9399dece226ccd98e5df5330adf7f356290516fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d619000000000008762700054a00005ef2cf9c0101009000000000000003e80000000000000001000000002367b880") 876 # good messages 877 self.assertNotEqual( 878 None, 879 LNWallet._decode_channel_update_msg(msg_without_prefix)) 880 self.assertNotEqual( 881 None, 882 LNWallet._decode_channel_update_msg(bytes.fromhex("0102") + msg_without_prefix)) 883 # bad messages 884 self.assertEqual( 885 None, 886 LNWallet._decode_channel_update_msg(bytes.fromhex("0102030405"))) 887 self.assertEqual( 888 None, 889 LNWallet._decode_channel_update_msg(bytes.fromhex("ffff") + msg_without_prefix)) 890 self.assertEqual( 891 None, 892 LNWallet._decode_channel_update_msg(bytes.fromhex("0101") + msg_without_prefix))