def test_adding_htlcs_race(self): A = HTLCManager(StoredDict({}, None, [])) B = HTLCManager(StoredDict({}, None, [])) A.channel_open_finished() B.channel_open_finished() ah0, bh0 = H('A', 0), H('B', 0) B.recv_htlc(A.send_htlc(ah0)) self.assertEqual(B.log[REMOTE]['locked_in'][0][LOCAL], 1) A.recv_htlc(B.send_htlc(bh0)) self.assertEqual(B.get_htlcs_in_latest_ctx(LOCAL), []) self.assertEqual(A.get_htlcs_in_latest_ctx(LOCAL), []) self.assertEqual(B.get_htlcs_in_next_ctx(LOCAL), [(RECEIVED, ah0)]) self.assertEqual(A.get_htlcs_in_next_ctx(LOCAL), [(RECEIVED, bh0)]) A.send_ctx() B.recv_ctx() B.send_ctx() A.recv_ctx() self.assertEqual(B.get_htlcs_in_oldest_unrevoked_ctx(LOCAL), []) self.assertEqual(A.get_htlcs_in_oldest_unrevoked_ctx(LOCAL), []) self.assertEqual(B.get_htlcs_in_latest_ctx(LOCAL), [(RECEIVED, ah0)]) self.assertEqual(A.get_htlcs_in_latest_ctx(LOCAL), [(RECEIVED, bh0)]) B.send_rev() A.recv_rev() A.send_rev() B.recv_rev() self.assertEqual(B.get_htlcs_in_oldest_unrevoked_ctx(LOCAL), [(RECEIVED, ah0)]) self.assertEqual(A.get_htlcs_in_oldest_unrevoked_ctx(LOCAL), [(RECEIVED, bh0)]) self.assertEqual(B.get_htlcs_in_latest_ctx(LOCAL), [(RECEIVED, ah0)]) self.assertEqual(A.get_htlcs_in_latest_ctx(LOCAL), [(RECEIVED, bh0)]) A.send_ctx() B.recv_ctx() B.send_ctx() A.recv_ctx() self.assertEqual(B.get_htlcs_in_oldest_unrevoked_ctx(LOCAL), [(RECEIVED, ah0)]) self.assertEqual(A.get_htlcs_in_oldest_unrevoked_ctx(LOCAL), [(RECEIVED, bh0)]) self.assertEqual(B.get_htlcs_in_latest_ctx(LOCAL), [(RECEIVED, ah0), (SENT, bh0)][::-1]) self.assertEqual(A.get_htlcs_in_latest_ctx(LOCAL), [(RECEIVED, bh0), (SENT, ah0)][::-1]) B.send_rev() A.recv_rev() A.send_rev() B.recv_rev() self.assertEqual(B.get_htlcs_in_oldest_unrevoked_ctx(LOCAL), [(RECEIVED, ah0), (SENT, bh0)][::-1]) self.assertEqual(A.get_htlcs_in_oldest_unrevoked_ctx(LOCAL), [(RECEIVED, bh0), (SENT, ah0)][::-1]) self.assertEqual(B.get_htlcs_in_latest_ctx(LOCAL), [(RECEIVED, ah0), (SENT, bh0)][::-1]) self.assertEqual(A.get_htlcs_in_latest_ctx(LOCAL), [(RECEIVED, bh0), (SENT, ah0)][::-1])
def test_shachain_produce_consume(self): seed = bitcoin.sha256(b"shachaintest") consumer = RevocationStore(StoredDict({}, None, [])) for i in range(10000): secret = get_per_commitment_secret_from_seed(seed, RevocationStore.START_INDEX - i) try: consumer.add_next_entry(secret) except Exception as e: raise Exception("iteration " + str(i) + ": " + str(e)) if i % 1000 == 0: c1 = consumer s1 = json.dumps(c1.storage, cls=MyEncoder) c2 = RevocationStore(StoredDict(json.loads(s1), None, [])) s2 = json.dumps(c2.storage, cls=MyEncoder) self.assertEqual(s1, s2)
def create_channel_state(funding_txid, funding_index, funding_sat, is_initiator, local_amount, remote_amount, privkeys, other_pubkeys, seed, cur, nex, other_node_id, l_dust, r_dust, l_csv, r_csv): assert local_amount > 0 assert remote_amount > 0 channel_id, _ = lnpeer.channel_id_from_funding_tx(funding_txid, funding_index) state = { "channel_id":channel_id.hex(), "short_channel_id":channel_id[:8], "funding_outpoint":lnpeer.Outpoint(funding_txid, funding_index), "remote_config":lnpeer.RemoteConfig( payment_basepoint=other_pubkeys[0], multisig_key=other_pubkeys[1], htlc_basepoint=other_pubkeys[2], delayed_basepoint=other_pubkeys[3], revocation_basepoint=other_pubkeys[4], to_self_delay=r_csv, dust_limit_sat=r_dust, max_htlc_value_in_flight_msat=one_bitcoin_in_msat * 5, max_accepted_htlcs=5, initial_msat=remote_amount, reserve_sat=0, htlc_minimum_msat=1, next_per_commitment_point=nex, current_per_commitment_point=cur, ), "local_config":lnpeer.LocalConfig( channel_seed = None, payment_basepoint=privkeys[0], multisig_key=privkeys[1], htlc_basepoint=privkeys[2], delayed_basepoint=privkeys[3], revocation_basepoint=privkeys[4], to_self_delay=l_csv, dust_limit_sat=l_dust, max_htlc_value_in_flight_msat=one_bitcoin_in_msat * 5, max_accepted_htlcs=5, initial_msat=local_amount, reserve_sat=0, per_commitment_secret_seed=seed, funding_locked_received=True, was_announced=False, current_commitment_signature=None, current_htlc_signatures=None, htlc_minimum_msat=1, ), "constraints":lnpeer.ChannelConstraints( capacity=funding_sat, is_initiator=is_initiator, funding_txn_minimum_depth=3, ), "node_id":other_node_id.hex(), 'onion_keys': {}, 'data_loss_protect_remote_pcp': {}, 'state': 'PREOPENING', 'log': {}, 'revocation_store': {}, } return StoredDict(state, None, [])
def htlc_lifecycle(htlc_success: bool): A = HTLCManager(StoredDict({}, None, [])) B = HTLCManager(StoredDict({}, None, [])) A.channel_open_finished() B.channel_open_finished() ah0 = H('A', 0) B.recv_htlc(A.send_htlc(ah0)) A.send_ctx() B.recv_ctx() B.send_rev() A.recv_rev() if htlc_success: B.send_settle(0) A.recv_settle(0) else: B.send_fail(0) A.recv_fail(0) self.assertEqual([], A.get_htlcs_in_oldest_unrevoked_ctx(LOCAL)) self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_oldest_unrevoked_ctx(REMOTE)) self.assertEqual([], A.get_htlcs_in_latest_ctx(LOCAL)) self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_latest_ctx(REMOTE)) self.assertEqual([], A.get_htlcs_in_next_ctx(LOCAL)) self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_next_ctx(REMOTE)) B.send_ctx() A.recv_ctx() A.send_rev() B.recv_rev() self.assertEqual([], A.get_htlcs_in_oldest_unrevoked_ctx(LOCAL)) self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_oldest_unrevoked_ctx(REMOTE)) self.assertEqual([], A.get_htlcs_in_latest_ctx(LOCAL)) self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_latest_ctx(REMOTE)) self.assertEqual([], A.get_htlcs_in_next_ctx(LOCAL)) self.assertEqual([], A.get_htlcs_in_next_ctx(REMOTE))
def test_unacked_local_updates(self): A = HTLCManager(StoredDict({}, None, [])) B = HTLCManager(StoredDict({}, None, [])) A.channel_open_finished() B.channel_open_finished() self.assertEqual({}, A.get_unacked_local_updates()) ah0 = H('A', 0) B.recv_htlc(A.send_htlc(ah0)) A.store_local_update_raw_msg(b"upd_msg0", is_commitment_signed=False) self.assertEqual({1: [b"upd_msg0"]}, A.get_unacked_local_updates()) ah1 = H('A', 1) B.recv_htlc(A.send_htlc(ah1)) A.store_local_update_raw_msg(b"upd_msg1", is_commitment_signed=False) self.assertEqual({1: [b"upd_msg0", b"upd_msg1"]}, A.get_unacked_local_updates()) A.send_ctx() B.recv_ctx() A.store_local_update_raw_msg(b"ctx1", is_commitment_signed=True) self.assertEqual({1: [b"upd_msg0", b"upd_msg1", b"ctx1"]}, A.get_unacked_local_updates()) ah2 = H('A', 2) B.recv_htlc(A.send_htlc(ah2)) A.store_local_update_raw_msg(b"upd_msg2", is_commitment_signed=False) self.assertEqual( { 1: [b"upd_msg0", b"upd_msg1", b"ctx1"], 2: [b"upd_msg2"] }, A.get_unacked_local_updates()) B.send_rev() A.recv_rev() self.assertEqual({2: [b"upd_msg2"]}, A.get_unacked_local_updates())
def test_shachain_store(self): tests = [ { "name": "insert_secret correct sequence", "inserts": [ { "index": 281474976710655, "secret": "7cc854b54e3e0dcdb010d7a3fee464a9687b" +\ "e6e8db3be6854c475621e007a5dc", "successful": True }, { "index": 281474976710654, "secret": "c7518c8ae4660ed02894df8976fa1a3659c1" +\ "a8b4b5bec0c4b872abeba4cb8964", "successful": True }, { "index": 281474976710653, "secret": "2273e227a5b7449b6e70f1fb4652864038b1" +\ "cbf9cd7c043a7d6456b7fc275ad8", "successful": True }, { "index": 281474976710652, "secret": "27cddaa5624534cb6cb9d7da077cf2b22ab2" +\ "1e9b506fd4998a51d54502e99116", "successful": True }, { "index": 281474976710651, "secret": "c65716add7aa98ba7acb236352d665cab173" +\ "45fe45b55fb879ff80e6bd0c41dd", "successful": True }, { "index": 281474976710650, "secret": "969660042a28f32d9be17344e09374b37996" +\ "2d03db1574df5a8a5a47e19ce3f2", "successful": True }, { "index": 281474976710649, "secret": "a5a64476122ca0925fb344bdc1854c1c0a59" +\ "fc614298e50a33e331980a220f32", "successful": True }, { "index": 281474976710648, "secret": "05cde6323d949933f7f7b78776bcc1ea6d9b" +\ "31447732e3802e1f7ac44b650e17", "successful": True } ] }, { "name": "insert_secret #1 incorrect", "inserts": [ { "index": 281474976710655, "secret": "02a40c85b6f28da08dfdbe0926c53fab2d" +\ "e6d28c10301f8f7c4073d5e42e3148", "successful": True }, { "index": 281474976710654, "secret": "c7518c8ae4660ed02894df8976fa1a3659" +\ "c1a8b4b5bec0c4b872abeba4cb8964", "successful": False } ] }, { "name": "insert_secret #2 incorrect (#1 derived from incorrect)", "inserts": [ { "index": 281474976710655, "secret": "02a40c85b6f28da08dfdbe0926c53fab2de6" +\ "d28c10301f8f7c4073d5e42e3148", "successful": True }, { "index": 281474976710654, "secret": "dddc3a8d14fddf2b68fa8c7fbad274827493" +\ "7479dd0f8930d5ebb4ab6bd866a3", "successful": True }, { "index": 281474976710653, "secret": "2273e227a5b7449b6e70f1fb4652864038b1" +\ "cbf9cd7c043a7d6456b7fc275ad8", "successful": True }, { "index": 281474976710652, "secret": "27cddaa5624534cb6cb9d7da077cf2b22a" +\ "b21e9b506fd4998a51d54502e99116", "successful": False } ] }, { "name": "insert_secret #3 incorrect", "inserts": [ { "index": 281474976710655, "secret": "7cc854b54e3e0dcdb010d7a3fee464a9687b" +\ "e6e8db3be6854c475621e007a5dc", "successful": True }, { "index": 281474976710654, "secret": "c7518c8ae4660ed02894df8976fa1a3659c1" +\ "a8b4b5bec0c4b872abeba4cb8964", "successful": True }, { "index": 281474976710653, "secret": "c51a18b13e8527e579ec56365482c62f180b" +\ "7d5760b46e9477dae59e87ed423a", "successful": True }, { "index": 281474976710652, "secret": "27cddaa5624534cb6cb9d7da077cf2b22ab2" +\ "1e9b506fd4998a51d54502e99116", "successful": False } ] }, { "name": "insert_secret #4 incorrect (1,2,3 derived from incorrect)", "inserts": [ { "index": 281474976710655, "secret": "02a40c85b6f28da08dfdbe0926c53fab2de6" +\ "d28c10301f8f7c4073d5e42e3148", "successful": True }, { "index": 281474976710654, "secret": "dddc3a8d14fddf2b68fa8c7fbad274827493" +\ "7479dd0f8930d5ebb4ab6bd866a3", "successful": True }, { "index": 281474976710653, "secret": "c51a18b13e8527e579ec56365482c62f18" +\ "0b7d5760b46e9477dae59e87ed423a", "successful": True }, { "index": 281474976710652, "secret": "ba65d7b0ef55a3ba300d4e87af29868f39" +\ "4f8f138d78a7011669c79b37b936f4", "successful": True }, { "index": 281474976710651, "secret": "c65716add7aa98ba7acb236352d665cab1" +\ "7345fe45b55fb879ff80e6bd0c41dd", "successful": True }, { "index": 281474976710650, "secret": "969660042a28f32d9be17344e09374b379" +\ "962d03db1574df5a8a5a47e19ce3f2", "successful": True }, { "index": 281474976710649, "secret": "a5a64476122ca0925fb344bdc1854c1c0a" +\ "59fc614298e50a33e331980a220f32", "successful": True }, { "index": 281474976710649, "secret": "05cde6323d949933f7f7b78776bcc1ea6d9b" +\ "31447732e3802e1f7ac44b650e17", "successful": False } ] }, { "name": "insert_secret #5 incorrect", "inserts": [ { "index": 281474976710655, "secret": "7cc854b54e3e0dcdb010d7a3fee464a9687b" +\ "e6e8db3be6854c475621e007a5dc", "successful": True }, { "index": 281474976710654, "secret": "c7518c8ae4660ed02894df8976fa1a3659c1a" +\ "8b4b5bec0c4b872abeba4cb8964", "successful": True }, { "index": 281474976710653, "secret": "2273e227a5b7449b6e70f1fb4652864038b1" +\ "cbf9cd7c043a7d6456b7fc275ad8", "successful": True }, { "index": 281474976710652, "secret": "27cddaa5624534cb6cb9d7da077cf2b22ab21" +\ "e9b506fd4998a51d54502e99116", "successful": True }, { "index": 281474976710651, "secret": "631373ad5f9ef654bb3dade742d09504c567" +\ "edd24320d2fcd68e3cc47e2ff6a6", "successful": True }, { "index": 281474976710650, "secret": "969660042a28f32d9be17344e09374b37996" +\ "2d03db1574df5a8a5a47e19ce3f2", "successful": False } ] }, { "name": "insert_secret #6 incorrect (5 derived from incorrect)", "inserts": [ { "index": 281474976710655, "secret": "7cc854b54e3e0dcdb010d7a3fee464a9687b" +\ "e6e8db3be6854c475621e007a5dc", "successful": True }, { "index": 281474976710654, "secret": "c7518c8ae4660ed02894df8976fa1a3659c1a" +\ "8b4b5bec0c4b872abeba4cb8964", "successful": True }, { "index": 281474976710653, "secret": "2273e227a5b7449b6e70f1fb4652864038b1" +\ "cbf9cd7c043a7d6456b7fc275ad8", "successful": True }, { "index": 281474976710652, "secret": "27cddaa5624534cb6cb9d7da077cf2b22ab21" +\ "e9b506fd4998a51d54502e99116", "successful": True }, { "index": 281474976710651, "secret": "631373ad5f9ef654bb3dade742d09504c567" +\ "edd24320d2fcd68e3cc47e2ff6a6", "successful": True }, { "index": 281474976710650, "secret": "b7e76a83668bde38b373970155c868a65330" +\ "4308f9896692f904a23731224bb1", "successful": True }, { "index": 281474976710649, "secret": "a5a64476122ca0925fb344bdc1854c1c0a59f" +\ "c614298e50a33e331980a220f32", "successful": True }, { "index": 281474976710648, "secret": "05cde6323d949933f7f7b78776bcc1ea6d9b" +\ "31447732e3802e1f7ac44b650e17", "successful": False } ] }, { "name": "insert_secret #7 incorrect", "inserts": [ { "index": 281474976710655, "secret": "7cc854b54e3e0dcdb010d7a3fee464a9687b" +\ "e6e8db3be6854c475621e007a5dc", "successful": True }, { "index": 281474976710654, "secret": "c7518c8ae4660ed02894df8976fa1a3659c1a" +\ "8b4b5bec0c4b872abeba4cb8964", "successful": True }, { "index": 281474976710653, "secret": "2273e227a5b7449b6e70f1fb4652864038b1" +\ "cbf9cd7c043a7d6456b7fc275ad8", "successful": True }, { "index": 281474976710652, "secret": "27cddaa5624534cb6cb9d7da077cf2b22ab21" +\ "e9b506fd4998a51d54502e99116", "successful": True }, { "index": 281474976710651, "secret": "c65716add7aa98ba7acb236352d665cab173" +\ "45fe45b55fb879ff80e6bd0c41dd", "successful": True }, { "index": 281474976710650, "secret": "969660042a28f32d9be17344e09374b37996" +\ "2d03db1574df5a8a5a47e19ce3f2", "successful": True }, { "index": 281474976710649, "secret": "e7971de736e01da8ed58b94c2fc216cb1d" +\ "ca9e326f3a96e7194fe8ea8af6c0a3", "successful": True }, { "index": 281474976710648, "secret": "05cde6323d949933f7f7b78776bcc1ea6d" +\ "9b31447732e3802e1f7ac44b650e17", "successful": False } ] }, { "name": "insert_secret #8 incorrect", "inserts": [ { "index": 281474976710655, "secret": "7cc854b54e3e0dcdb010d7a3fee464a9687b" +\ "e6e8db3be6854c475621e007a5dc", "successful": True }, { "index": 281474976710654, "secret": "c7518c8ae4660ed02894df8976fa1a3659c1a" +\ "8b4b5bec0c4b872abeba4cb8964", "successful": True }, { "index": 281474976710653, "secret": "2273e227a5b7449b6e70f1fb4652864038b1" +\ "cbf9cd7c043a7d6456b7fc275ad8", "successful": True }, { "index": 281474976710652, "secret": "27cddaa5624534cb6cb9d7da077cf2b22ab21" +\ "e9b506fd4998a51d54502e99116", "successful": True }, { "index": 281474976710651, "secret": "c65716add7aa98ba7acb236352d665cab173" +\ "45fe45b55fb879ff80e6bd0c41dd", "successful": True }, { "index": 281474976710650, "secret": "969660042a28f32d9be17344e09374b37996" +\ "2d03db1574df5a8a5a47e19ce3f2", "successful": True }, { "index": 281474976710649, "secret": "a5a64476122ca0925fb344bdc1854c1c0a" +\ "59fc614298e50a33e331980a220f32", "successful": True }, { "index": 281474976710648, "secret": "a7efbc61aac46d34f77778bac22c8a20c6" +\ "a46ca460addc49009bda875ec88fa4", "successful": False } ] } ] for test in tests: receiver = RevocationStore(StoredDict({}, None, [])) for insert in test["inserts"]: secret = bytes.fromhex(insert["secret"]) try: receiver.add_next_entry(secret) except Exception as e: if insert["successful"]: raise Exception("Failed ({}): error was received but it shouldn't: {}".format(test["name"], e)) else: if not insert["successful"]: raise Exception("Failed ({}): error wasn't received".format(test["name"])) for insert in test["inserts"]: secret = bytes.fromhex(insert["secret"]) index = insert["index"] if insert["successful"]: self.assertEqual(secret, receiver.retrieve_secret(index)) print("Passed ({})".format(test["name"]))
def htlc_lifecycle(htlc_success: bool): A = HTLCManager(StoredDict({}, None, [])) B = HTLCManager(StoredDict({}, None, [])) A.channel_open_finished() B.channel_open_finished() B.recv_htlc(A.send_htlc(H('A', 0))) self.assertEqual(len(B.get_htlcs_in_next_ctx(REMOTE)), 0) self.assertEqual(len(A.get_htlcs_in_next_ctx(REMOTE)), 1) self.assertEqual(len(B.get_htlcs_in_next_ctx(LOCAL)), 1) self.assertEqual(len(A.get_htlcs_in_next_ctx(LOCAL)), 0) A.send_ctx() B.recv_ctx() B.send_rev() A.recv_rev() B.send_ctx() A.recv_ctx() A.send_rev() B.recv_rev() self.assertEqual(len(A.get_htlcs_in_latest_ctx(LOCAL)), 1) self.assertEqual(len(B.get_htlcs_in_latest_ctx(LOCAL)), 1) if htlc_success: B.send_settle(0) A.recv_settle(0) else: B.send_fail(0) A.recv_fail(0) self.assertEqual( list(A.htlcs_by_direction(REMOTE, RECEIVED).values()), [H('A', 0)]) self.assertNotEqual(A.get_htlcs_in_latest_ctx(LOCAL), []) self.assertNotEqual(B.get_htlcs_in_latest_ctx(REMOTE), []) self.assertEqual(A.get_htlcs_in_next_ctx(LOCAL), []) self.assertNotEqual(A.get_htlcs_in_next_ctx(REMOTE), []) self.assertEqual(A.get_htlcs_in_next_ctx(REMOTE), A.get_htlcs_in_latest_ctx(REMOTE)) self.assertEqual(B.get_htlcs_in_next_ctx(REMOTE), []) B.send_ctx() A.recv_ctx() A.send_rev() # here pending_htlcs(REMOTE) should become empty self.assertEqual(A.get_htlcs_in_next_ctx(REMOTE), []) B.recv_rev() A.send_ctx() B.recv_ctx() B.send_rev() A.recv_rev() self.assertEqual(B.get_htlcs_in_latest_ctx(LOCAL), []) self.assertEqual(A.get_htlcs_in_latest_ctx(LOCAL), []) self.assertEqual(A.get_htlcs_in_latest_ctx(REMOTE), []) self.assertEqual(B.get_htlcs_in_latest_ctx(REMOTE), []) self.assertEqual(len(A.all_settled_htlcs_ever(LOCAL)), int(htlc_success)) self.assertEqual(len(A.sent_in_ctn(2)), int(htlc_success)) self.assertEqual(len(B.received_in_ctn(2)), int(htlc_success)) A.recv_htlc(B.send_htlc(H('B', 0))) self.assertEqual(A.get_htlcs_in_next_ctx(REMOTE), []) self.assertNotEqual(A.get_htlcs_in_next_ctx(LOCAL), []) self.assertNotEqual(B.get_htlcs_in_next_ctx(REMOTE), []) self.assertEqual(B.get_htlcs_in_next_ctx(LOCAL), []) B.send_ctx() A.recv_ctx() A.send_rev() B.recv_rev() self.assertNotEqual(A.get_htlcs_in_next_ctx(REMOTE), A.get_htlcs_in_latest_ctx(REMOTE)) self.assertEqual(A.get_htlcs_in_next_ctx(LOCAL), A.get_htlcs_in_latest_ctx(LOCAL)) self.assertEqual(B.get_htlcs_in_next_ctx(REMOTE), B.get_htlcs_in_latest_ctx(REMOTE)) self.assertNotEqual(B.get_htlcs_in_next_ctx(LOCAL), B.get_htlcs_in_next_ctx(REMOTE))
def test_adding_htlc_between_send_ctx_and_recv_rev(self): A = HTLCManager(StoredDict({}, None, [])) B = HTLCManager(StoredDict({}, None, [])) A.channel_open_finished() B.channel_open_finished() A.send_ctx() B.recv_ctx() B.send_rev() ah0 = H('A', 0) B.recv_htlc(A.send_htlc(ah0)) self.assertEqual([], A.get_htlcs_in_latest_ctx(LOCAL)) self.assertEqual([], A.get_htlcs_in_latest_ctx(REMOTE)) self.assertEqual([], A.get_htlcs_in_next_ctx(LOCAL)) self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_next_ctx(REMOTE)) A.recv_rev() self.assertEqual([], A.get_htlcs_in_latest_ctx(LOCAL)) self.assertEqual([], A.get_htlcs_in_latest_ctx(REMOTE)) self.assertEqual([], A.get_htlcs_in_next_ctx(LOCAL)) self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_next_ctx(REMOTE)) A.send_ctx() B.recv_ctx() self.assertEqual([], A.get_htlcs_in_latest_ctx(LOCAL)) self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_latest_ctx(REMOTE)) self.assertEqual([], A.get_htlcs_in_next_ctx(LOCAL)) self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_next_ctx(REMOTE)) B.send_rev() A.recv_rev() self.assertEqual([], A.get_htlcs_in_latest_ctx(LOCAL)) self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_latest_ctx(REMOTE)) self.assertEqual([(Direction.SENT, ah0)], A.get_htlcs_in_next_ctx(LOCAL)) self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_next_ctx(REMOTE)) B.send_ctx() A.recv_ctx() self.assertEqual([], A.get_htlcs_in_oldest_unrevoked_ctx(LOCAL)) self.assertEqual([(Direction.SENT, ah0)], A.get_htlcs_in_latest_ctx(LOCAL)) self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_latest_ctx(REMOTE)) self.assertEqual([(Direction.SENT, ah0)], A.get_htlcs_in_next_ctx(LOCAL)) self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_next_ctx(REMOTE)) A.send_rev() B.recv_rev() self.assertEqual([(Direction.SENT, ah0)], A.get_htlcs_in_oldest_unrevoked_ctx(LOCAL)) self.assertEqual([(Direction.SENT, ah0)], A.get_htlcs_in_latest_ctx(LOCAL)) self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_latest_ctx(REMOTE)) self.assertEqual([(Direction.SENT, ah0)], A.get_htlcs_in_next_ctx(LOCAL)) self.assertEqual([(Direction.RECEIVED, ah0)], A.get_htlcs_in_next_ctx(REMOTE))