From 6b43eac6fdba2d42a36291185c3c0337e98e0b43 Mon Sep 17 00:00:00 2001 From: SomberNight Date: Fri, 16 Jun 2023 20:01:56 +0000 Subject: [PATCH] lnonion: rm support for legacy (pre-TLV) onions see https://github.com/lightning/bolts/pull/962 --- electrum/lnonion.py | 110 +++++-------------- electrum/lnrouter.py | 6 ++ electrum/tests/test_lnrouter.py | 184 +++++++------------------------- 3 files changed, 70 insertions(+), 230 deletions(-) diff --git a/electrum/lnonion.py b/electrum/lnonion.py index 9dc687a1b..c7cd9d44e 100644 --- a/electrum/lnonion.py +++ b/electrum/lnonion.py @@ -42,7 +42,6 @@ if TYPE_CHECKING: HOPS_DATA_SIZE = 1300 # also sometimes called routingInfoSize in bolt-04 TRAMPOLINE_HOPS_DATA_SIZE = 400 -LEGACY_PER_HOP_FULL_SIZE = 65 PER_HOP_HMAC_SIZE = 32 @@ -51,53 +50,9 @@ class InvalidOnionMac(Exception): pass class InvalidOnionPubkey(Exception): pass -class LegacyHopDataPayload: - - def __init__(self, *, short_channel_id: bytes, amt_to_forward: int, outgoing_cltv_value: int): - self.short_channel_id = ShortChannelID(short_channel_id) - self.amt_to_forward = amt_to_forward - self.outgoing_cltv_value = outgoing_cltv_value - - def to_bytes(self) -> bytes: - ret = self.short_channel_id - ret += int.to_bytes(self.amt_to_forward, length=8, byteorder="big", signed=False) - ret += int.to_bytes(self.outgoing_cltv_value, length=4, byteorder="big", signed=False) - ret += bytes(12) # padding - if len(ret) != 32: - raise Exception('unexpected length {}'.format(len(ret))) - return ret - - def to_tlv_dict(self) -> dict: - d = { - "amt_to_forward": {"amt_to_forward": self.amt_to_forward}, - "outgoing_cltv_value": {"outgoing_cltv_value": self.outgoing_cltv_value}, - "short_channel_id": {"short_channel_id": self.short_channel_id}, - } - return d - - @classmethod - def from_bytes(cls, b: bytes) -> 'LegacyHopDataPayload': - if len(b) != 32: - raise Exception('unexpected length {}'.format(len(b))) - return LegacyHopDataPayload( - short_channel_id=b[:8], - amt_to_forward=int.from_bytes(b[8:16], byteorder="big", signed=False), - outgoing_cltv_value=int.from_bytes(b[16:20], byteorder="big", signed=False), - ) - - @classmethod - def from_tlv_dict(cls, d: dict) -> 'LegacyHopDataPayload': - return LegacyHopDataPayload( - short_channel_id=d["short_channel_id"]["short_channel_id"] if "short_channel_id" in d else b"\x00" * 8, - amt_to_forward=d["amt_to_forward"]["amt_to_forward"], - outgoing_cltv_value=d["outgoing_cltv_value"]["outgoing_cltv_value"], - ) - - class OnionHopsDataSingle: # called HopData in lnd - def __init__(self, *, is_tlv_payload: bool, payload: dict = None): - self.is_tlv_payload = is_tlv_payload + def __init__(self, *, payload: dict = None): if payload is None: payload = {} self.payload = payload @@ -107,29 +62,20 @@ class OnionHopsDataSingle: # called HopData in lnd def to_bytes(self) -> bytes: hmac_ = self.hmac if self.hmac is not None else bytes(PER_HOP_HMAC_SIZE) if self._raw_bytes_payload is not None: - ret = write_bigsize_int(len(self._raw_bytes_payload)) - ret += self._raw_bytes_payload - ret += hmac_ - return ret - if not self.is_tlv_payload: - ret = b"\x00" # realm==0 - legacy_payload = LegacyHopDataPayload.from_tlv_dict(self.payload) - ret += legacy_payload.to_bytes() + ret = self._raw_bytes_payload ret += hmac_ - if len(ret) != LEGACY_PER_HOP_FULL_SIZE: - raise Exception('unexpected length {}'.format(len(ret))) return ret - else: # tlv - payload_fd = io.BytesIO() - OnionWireSerializer.write_tlv_stream(fd=payload_fd, - tlv_stream_name="payload", - **self.payload) - payload_bytes = payload_fd.getvalue() - with io.BytesIO() as fd: - fd.write(write_bigsize_int(len(payload_bytes))) - fd.write(payload_bytes) - fd.write(hmac_) - return fd.getvalue() + # adding TLV payload. note: legacy hop data format no longer supported. + payload_fd = io.BytesIO() + OnionWireSerializer.write_tlv_stream(fd=payload_fd, + tlv_stream_name="payload", + **self.payload) + payload_bytes = payload_fd.getvalue() + with io.BytesIO() as fd: + fd.write(write_bigsize_int(len(payload_bytes))) + fd.write(payload_bytes) + fd.write(hmac_) + return fd.getvalue() @classmethod def from_fd(cls, fd: io.BytesIO) -> 'OnionHopsDataSingle': @@ -139,14 +85,7 @@ class OnionHopsDataSingle: # called HopData in lnd fd.seek(-1, io.SEEK_CUR) # undo read if first_byte == b'\x00': # legacy hop data format - b = fd.read(LEGACY_PER_HOP_FULL_SIZE) - if len(b) != LEGACY_PER_HOP_FULL_SIZE: - raise Exception(f'unexpected length {len(b)}') - ret = OnionHopsDataSingle(is_tlv_payload=False) - legacy_payload = LegacyHopDataPayload.from_bytes(b[1:33]) - ret.payload = legacy_payload.to_tlv_dict() - ret.hmac = b[33:] - return ret + raise Exception("legacy hop data format no longer supported") elif first_byte == b'\x01': # reserved for future use raise Exception("unsupported hop payload: length==1") @@ -155,7 +94,7 @@ class OnionHopsDataSingle: # called HopData in lnd hop_payload = fd.read(hop_payload_length) if hop_payload_length != len(hop_payload): raise Exception(f"unexpected EOF") - ret = OnionHopsDataSingle(is_tlv_payload=True) + ret = OnionHopsDataSingle() ret.payload = OnionWireSerializer.read_tlv_stream(fd=io.BytesIO(hop_payload), tlv_stream_name="payload") ret.hmac = fd.read(PER_HOP_HMAC_SIZE) @@ -163,7 +102,7 @@ class OnionHopsDataSingle: # called HopData in lnd return ret def __repr__(self): - return f"" + return f"" class OnionPacket: @@ -226,8 +165,14 @@ def get_shared_secrets_along_route(payment_path_pubkeys: Sequence[bytes], return hop_shared_secrets -def new_onion_packet(payment_path_pubkeys: Sequence[bytes], session_key: bytes, - hops_data: Sequence[OnionHopsDataSingle], associated_data: bytes, trampoline=False) -> OnionPacket: +def new_onion_packet( + payment_path_pubkeys: Sequence[bytes], + session_key: bytes, + hops_data: Sequence[OnionHopsDataSingle], + *, + associated_data: bytes, + trampoline: bool = False, +) -> OnionPacket: num_hops = len(payment_path_pubkeys) assert num_hops == len(hops_data) hop_shared_secrets = get_shared_secrets_along_route(payment_path_pubkeys, session_key) @@ -289,8 +234,7 @@ def calc_hops_data_for_payment( "total_msat": total_msat, "amount_msat": amt } - hops_data = [OnionHopsDataSingle( - is_tlv_payload=route[-1].has_feature_varonion(), payload=hop_payload)] + hops_data = [OnionHopsDataSingle(payload=hop_payload)] # payloads, backwards from last hop (but excluding the first edge): for edge_index in range(len(route) - 1, 0, -1): route_edge = route[edge_index] @@ -304,9 +248,7 @@ def calc_hops_data_for_payment( "short_channel_id": {"short_channel_id": route_edge.short_channel_id}, } hops_data.append( - OnionHopsDataSingle( - is_tlv_payload=route[edge_index-1].has_feature_varonion(), - payload=hop_payload)) + OnionHopsDataSingle(payload=hop_payload)) if not is_trampoline: amt += route_edge.fee_for_edge(amt) cltv += route_edge.cltv_expiry_delta diff --git a/electrum/lnrouter.py b/electrum/lnrouter.py index d6b8227f0..c89ba7f33 100644 --- a/electrum/lnrouter.py +++ b/electrum/lnrouter.py @@ -489,6 +489,12 @@ class LNPathFinder(Logger): route_edge = private_route_edges.get(short_channel_id, None) if route_edge is None: node_info = self.channel_db.get_node_info_for_node_id(node_id=end_node) + if node_info: + # it's ok if we are missing the node_announcement (node_info) for this node, + # but if we have it, we enforce that they support var_onion_optin + node_features = LnFeatures(node_info.features) + if not node_features.supports(LnFeatures.VAR_ONION_OPT): + return float('inf'), 0 route_edge = RouteEdge.from_channel_policy( channel_policy=channel_policy, short_channel_id=short_channel_id, diff --git a/electrum/tests/test_lnrouter.py b/electrum/tests/test_lnrouter.py index ff3aaefbd..8187934a2 100644 --- a/electrum/tests/test_lnrouter.py +++ b/electrum/tests/test_lnrouter.py @@ -298,7 +298,7 @@ class Test_LNRouter(ElectrumTestCase): self.assertEqual(1200, liquidity_hints.penalty(node_from, node_to, channel_id, 1_000_000)) @needs_test_with_all_chacha20_implementations - def test_new_onion_packet_legacy(self): + def test_new_onion_packet(self): # test vector from bolt-04 payment_path_pubkeys = [ bfh('02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619'), @@ -310,74 +310,26 @@ class Test_LNRouter(ElectrumTestCase): session_key = bfh('4141414141414141414141414141414141414141414141414141414141414141') associated_data = bfh('4242424242424242424242424242424242424242424242424242424242424242') hops_data = [ - OnionHopsDataSingle(is_tlv_payload=False, payload={ - "amt_to_forward": {"amt_to_forward": 0}, - "outgoing_cltv_value": {"outgoing_cltv_value": 0}, - "short_channel_id": {"short_channel_id": bfh('0000000000000000')}, - }), - OnionHopsDataSingle(is_tlv_payload=False, payload={ - "amt_to_forward": {"amt_to_forward": 1}, - "outgoing_cltv_value": {"outgoing_cltv_value": 1}, - "short_channel_id": {"short_channel_id": bfh('0101010101010101')}, - }), - OnionHopsDataSingle(is_tlv_payload=False, payload={ - "amt_to_forward": {"amt_to_forward": 2}, - "outgoing_cltv_value": {"outgoing_cltv_value": 2}, - "short_channel_id": {"short_channel_id": bfh('0202020202020202')}, - }), - OnionHopsDataSingle(is_tlv_payload=False, payload={ - "amt_to_forward": {"amt_to_forward": 3}, - "outgoing_cltv_value": {"outgoing_cltv_value": 3}, - "short_channel_id": {"short_channel_id": bfh('0303030303030303')}, - }), - OnionHopsDataSingle(is_tlv_payload=False, payload={ - "amt_to_forward": {"amt_to_forward": 4}, - "outgoing_cltv_value": {"outgoing_cltv_value": 4}, - "short_channel_id": {"short_channel_id": bfh('0404040404040404')}, - }), + OnionHopsDataSingle(), + OnionHopsDataSingle(), + OnionHopsDataSingle(), + OnionHopsDataSingle(), + OnionHopsDataSingle(), ] - packet = new_onion_packet(payment_path_pubkeys, session_key, hops_data, associated_data) - self.assertEqual(bfh('0002eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619e5f14350c2a76fc232b5e46d421e9615471ab9e0bc887beff8c95fdb878f7b3a71e87f9aab8f6378c6ff744c1f34b393ad28d065b535c1a8668d85d3b34a1b3befd10f7d61ab590531cf08000178a333a347f8b4072e216400406bdf3bf038659793a1f9e7abc789266cc861cabd95818c0fc8efbdfdc14e3f7c2bc7eb8d6a79ef75ce721caad69320c3a469a202f3e468c67eaf7a7cda226d0fd32f7b48084dca885d014698cf05d742557763d9cb743faeae65dcc79dddaecf27fe5942be5380d15e9a1ec866abe044a9ad635778ba61fc0776dc832b39451bd5d35072d2269cf9b040a2a2fba158a0d8085926dc2e44f0c88bf487da56e13ef2d5e676a8589881b4869ed4c7f0218ff8c6c7dd7221d189c65b3b9aaa71a01484b122846c7c7b57e02e679ea8469b70e14fe4f70fee4d87b910cf144be6fe48eef24da475c0b0bcc6565a9f99728426ce2380a9580e2a9442481ceae7679906c30b1a0e21a10f26150e0645ab6edfdab1ce8f8bea7b1dee511c5fd38ac0e702c1c15bb86b52bca1b71e15b96982d262a442024c33ceb7dd8f949063c2e5e613e873250e2f8708bd4e1924abd45f65c2fa5617bfb10ee9e4a42d6b5811acc8029c16274f937dac9e8817c7e579fdb767ffe277f26d413ced06b620ede8362081da21cf67c2ca9d6f15fe5bc05f82f5bb93f8916bad3d63338ca824f3bbc11b57ce94a5fa1bc239533679903d6fec92a8c792fd86e2960188c14f21e399cfd72a50c620e10aefc6249360b463df9a89bf6836f4f26359207b765578e5ed76ae9f31b1cc48324be576e3d8e44d217445dba466f9b6293fdf05448584eb64f61e02903f834518622b7d4732471c6e0e22e22d1f45e31f0509eab39cdea5980a492a1da2aaac55a98a01216cd4bfe7abaa682af0fbff2dfed030ba28f1285df750e4d3477190dd193f8643b61d8ac1c427d590badb1f61a05d480908fbdc7c6f0502dd0c4abb51d725e92f95da2a8facb79881a844e2026911adcc659d1fb20a2fce63787c8bb0d9f6789c4b231c76da81c3f0718eb7156565a081d2be6b4170c0e0bcebddd459f53db2590c974bca0d705c055dee8c629bf854a5d58edc85228499ec6dde80cce4c8910b81b1e9e8b0f43bd39c8d69c3a80672729b7dc952dd9448688b6bd06afc2d2819cda80b66c57b52ccf7ac1a86601410d18d0c732f69de792e0894a9541684ef174de766fd4ce55efea8f53812867be6a391ac865802dbc26d93959df327ec2667c7256aa5a1d3c45a69a6158f285d6c97c3b8eedb09527848500517995a9eae4cd911df531544c77f5a9a2f22313e3eb72ca7a07dba243476bc926992e0d1e58b4a2fc8c7b01e0cad726237933ea319bad7537d39f3ed635d1e6c1d29e97b3d2160a09e30ee2b65ac5bce00996a73c008bcf351cecb97b6833b6d121dcf4644260b2946ea204732ac9954b228f0beaa15071930fd9583dfc466d12b5f0eeeba6dcf23d5ce8ae62ee5796359d97a4a15955c778d868d0ef9991d9f2833b5bb66119c5f8b396fd108baed7906cbb3cc376d13551caed97fece6f42a4c908ee279f1127fda1dd3ee77d8de0a6f3c135fa3f1cffe38591b6738dc97b55f0acc52be9753ce53e64d7e497bb00ca6123758df3b68fad99e35c04389f7514a8e36039f541598a417275e77869989782325a15b5342ac5011ff07af698584b476b35d941a4981eac590a07a092bb50342da5d3341f901aa07964a8d02b623c7b106dd0ae50bfa007a22d46c8772fa55558176602946cb1d11ea5460db7586fb89c6d3bcd3ab6dd20df4a4db63d2e7d52380800ad812b8640887e027e946df96488b47fbc4a4fadaa8beda4abe446fafea5403fae2ef'), + hops_data[0]._raw_bytes_payload = bfh("1202023a98040205dc06080000000000000001") + hops_data[1]._raw_bytes_payload = bfh("52020236b00402057806080000000000000002fd02013c0102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f") + hops_data[2]._raw_bytes_payload = bfh("12020230d4040204e206080000000000000003") + hops_data[3]._raw_bytes_payload = bfh("1202022710040203e806080000000000000004") + hops_data[4]._raw_bytes_payload = bfh("fd011002022710040203e8082224a33562c54507a9334e79f0dc4f17d407e6d7c61f0e2f3d0d38599502f617042710fd012de02a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a") + packet = new_onion_packet(payment_path_pubkeys, session_key, hops_data, associated_data=associated_data) + self.assertEqual(bfh('0002eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619f7f3416a5aa36dc7eeb3ec6d421e9615471ab870a33ac07fa5d5a51df0a8823aabe3fea3f90d387529d4f72837f9e687230371ccd8d263072206dbed0234f6505e21e282abd8c0e4f5b9ff8042800bbab065036eadd0149b37f27dde664725a49866e052e809d2b0198ab9610faa656bbf4ec516763a59f8f42c171b179166ba38958d4f51b39b3e98706e2d14a2dafd6a5df808093abfca5aeaaca16eded5db7d21fb0294dd1a163edf0fb445d5c8d7d688d6dd9c541762bf5a5123bf9939d957fe648416e88f1b0928bfa034982b22548e1a4d922690eecf546275afb233acf4323974680779f1a964cfe687456035cc0fba8a5428430b390f0057b6d1fe9a8875bfa89693eeb838ce59f09d207a503ee6f6299c92d6361bc335fcbf9b5cd44747aadce2ce6069cfdc3d671daef9f8ae590cf93d957c9e873e9a1bc62d9640dc8fc39c14902d49a1c80239b6c5b7fd91d05878cbf5ffc7db2569f47c43d6c0d27c438abff276e87364deb8858a37e5a62c446af95d8b786eaf0b5fcf78d98b41496794f8dcaac4eef34b2acfb94c7e8c32a9e9866a8fa0b6f2a06f00a1ccde569f97eec05c803ba7500acc96691d8898d73d8e6a47b8f43c3d5de74458d20eda61474c426359677001fbd75a74d7d5db6cb4feb83122f133206203e4e2d293f838bf8c8b3a29acb321315100b87e80e0edb272ee80fda944e3fb6084ed4d7f7c7d21c69d9da43d31a90b70693f9b0cc3eac74c11ab8ff655905688916cfa4ef0bd04135f2e50b7c689a21d04e8e981e74c6058188b9b1f9dfc3eec6838e9ffbcf22ce738d8a177c19318dffef090cee67e12de1a3e2a39f61247547ba5257489cbc11d7d91ed34617fcc42f7a9da2e3cf31a94a210a1018143173913c38f60e62b24bf0d7518f38b5bab3e6a1f8aeb35e31d6442c8abb5178efc892d2e787d79c6ad9e2fc271792983fa9955ac4d1d84a36c024071bc6e431b625519d556af38185601f70e29035ea6a09c8b676c9d88cf7e05e0f17098b584c4168735940263f940033a220f40be4c85344128b14beb9e75696db37014107801a59b13e89cd9d2258c169d523be6d31552c44c82ff4bb18ec9f099f3bf0e5b1bb2ba9a87d7e26f98d294927b600b5529c47e04d98956677cbcee8fa2b60f49776d8b8c367465b7c626da53700684fb6c918ead0eab8360e4f60edd25b4f43816a75ecf70f909301825b512469f8389d79402311d8aecb7b3ef8599e79485a4388d87744d899f7c47ee644361e17040a7958c8911be6f463ab6a9b2afacd688ec55ef517b38f1339efc54487232798bb25522ff4572ff68567fe830f92f7b8113efce3e98c3fffbaedce4fd8b50e41da97c0c08e423a72689cc68e68f752a5e3a9003e64e35c957ca2e1c48bb6f64b05f56b70b575ad2f278d57850a7ad568c24a4d32a3d74b29f03dc125488bc7c637da582357f40b0a52d16b3b40bb2c2315d03360bc24209e20972c200566bcf3bbe5c5b0aedd83132a8a4d5b4242ba370b6d67d9b67eb01052d132c7866b9cb502e44796d9d356e4e3cb47cc527322cd24976fe7c9257a2864151a38e568ef7a79f10d6ef27cc04ce382347a2488b1f404fdbf407fe1ca1c9d0d5649e34800e25e18951c98cae9f43555eef65fee1ea8f15828807366c3b612cd5753bf9fb8fced08855f742cddd6f765f74254f03186683d646e6f09ac2805586c7cf11998357cafc5df3f285329366f475130c928b2dceba4aa383758e7a9d20705c4bb9db619e2992f608a1ba65db254bb389468741d0502e2588aeb54390ac600c19af5c8e61383fc1bebe0029e4474051e4ef908828db9cca13277ef65db3fd47ccc2179126aaefb627719f421e20'), packet.to_bytes()) @needs_test_with_all_chacha20_implementations - def test_new_onion_packet_mixed_payloads(self): - # test vector from bolt-04 - payment_path_pubkeys = [ - bfh('02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619'), - bfh('0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c'), - bfh('027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007'), - bfh('032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991'), - bfh('02edabbd16b41c8371b92ef2f04c1185b4f03b6dcd52ba9b78d9d7c89c8f221145'), - ] - session_key = bfh('4141414141414141414141414141414141414141414141414141414141414141') - associated_data = bfh('4242424242424242424242424242424242424242424242424242424242424242') - hops_data = [ - OnionHopsDataSingle(is_tlv_payload=False, payload={ - "amt_to_forward": {"amt_to_forward": 0}, - "outgoing_cltv_value": {"outgoing_cltv_value": 0}, - "short_channel_id": {"short_channel_id": bfh('0000000000000000')}, - }), - OnionHopsDataSingle(is_tlv_payload=True), - OnionHopsDataSingle(is_tlv_payload=True), - OnionHopsDataSingle(is_tlv_payload=True), - OnionHopsDataSingle(is_tlv_payload=False, payload={ - "amt_to_forward": {"amt_to_forward": 4}, - "outgoing_cltv_value": {"outgoing_cltv_value": 4}, - "short_channel_id": {"short_channel_id": bfh('0404040404040404')}, - }), - ] - hops_data[1]._raw_bytes_payload = bfh("0101010101010101000000000000000100000001") - hops_data[2]._raw_bytes_payload = bfh("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff") - hops_data[3]._raw_bytes_payload = bfh("0303030303030303000000000000000300000003") - packet = new_onion_packet(payment_path_pubkeys, session_key, hops_data, associated_data) - self.assertEqual(bfh('0002eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619e5f14350c2a76fc232b5e46d421e9615471ab9e0bc887beff8c95fdb878f7b3a710f8eaf9ccc768f66bb5dec1f7827f33c43fe2ddd05614c8283aa78e9e7573f87c50f7d61ab590531cf08000178a333a347f8b4072e1cea42da7552402b10765adae3f581408f35ff0a71a34b78b1d8ecae77df96c6404bae9a8e8d7178977d7094a1ae549f89338c0777551f874159eb42d3a59fb9285ad4e24883f27de23942ec966611e99bee1cee503455be9e8e642cef6cef7b9864130f692283f8a973d47a8f1c1726b6e59969385975c766e35737c8d76388b64f748ee7943ffb0e2ee45c57a1abc40762ae598723d21bd184e2b338f68ebff47219357bd19cd7e01e2337b806ef4d717888e129e59cd3dc31e6201ccb2fd6d7499836f37a993262468bcb3a4dcd03a22818aca49c6b7b9b8e9e870045631d8e039b066ff86e0d1b7291f71cefa7264c70404a8e538b566c17ccc5feab231401e6c08a01bd5edfc1aa8e3e533b96e82d1f91118d508924b923531929aea889fcdf057f5995d9731c4bf796fb0e41c885d488dcbc68eb742e27f44310b276edc6f652658149e7e9ced4edde5d38c9b8f92e16f6b4ab13d710ee5c193921909bdd75db331cd9d7581a39fca50814ed8d9d402b86e7f8f6ac2f3bca8e6fe47eb45fbdd3be21a8a8d200797eae3c9a0497132f92410d804977408494dff49dd3d8bce248e0b74fd9e6f0f7102c25ddfa02bd9ad9f746abbfa3379834bc2380d58e9d23237821475a1874484783a15d68f47d3dc339f38d9bf925655d5c946778680fd6d1f062f84128895aff09d35d6c92cca63d3f95a9ee8f2a84f383b4d6a087533e65de12fc8dcaf85777736a2088ff4b22462265028695b37e70963c10df8ef2458756c73007dc3e544340927f9e9f5ea4816a9fd9832c311d122e9512739a6b4714bba590e31caa143ce83cb84b36c738c60c3190ff70cd9ac286a9fd2ab619399b68f1f7447be376ce884b5913c8496d01cbf7a44a60b6e6747513f69dc538f340bc1388e0fde5d0c1db50a4dcb9cc0576e0e2474e4853af9623212578d502757ffb2e0e749695ed70f61c116560d0d4154b64dcf3cbf3c91d89fb6dd004dc19588e3479fcc63c394a4f9e8a3b8b961fce8a532304f1337f1a697a1bb14b94d2953f39b73b6a3125d24f27fcd4f60437881185370bde68a5454d816e7a70d4cea582effab9a4f1b730437e35f7a5c4b769c7b72f0346887c1e63576b2f1e2b3706142586883f8cf3a23595cc8e35a52ad290afd8d2f8bcd5b4c1b891583a4159af7110ecde092079209c6ec46d2bda60b04c519bb8bc6dffb5c87f310814ef2f3003671b3c90ddf5d0173a70504c2280d31f17c061f4bb12a978122c8a2a618bb7d1edcf14f84bf0fa181798b826a254fca8b6d7c81e0beb01bd77f6461be3c8647301d02b04753b0771105986aa0cbc13f7718d64e1b3437e8eef1d319359914a7932548c91570ef3ea741083ca5be5ff43c6d9444d29df06f76ec3dc936e3d180f4b6d0fbc495487c7d44d7c8fe4a70d5ff1461d0d9593f3f898c919c363fa18341ce9dae54f898ccf3fe792136682272941563387263c51b2a2f32363b804672cc158c9230472b554090a661aa81525d11876eefdcc45442249e61e07284592f1606491de5c0324d3af4be035d7ede75b957e879e9770cdde2e1bbc1ef75d45fe555f1ff6ac296a2f648eeee59c7c08260226ea333c285bcf37a9bbfa57ba2ab8083c4be6fc2ebe279537d22da96a07392908cf22b233337a74fe5c603b51712b43c3ee55010ee3d44dd9ba82bba3145ec358f863e04bbfa53799a7a9216718fd5859da2f0deb77b8e315ad6868fdec9400f45a48e6dc8ddbaeb3'), - packet.to_bytes()) - - @needs_test_with_all_chacha20_implementations - def test_process_onion_packet_mixed_payloads(self): + def test_process_onion_packet(self): # this test is not from bolt-04, but is based on the one there; - # here the TLV payloads are actually sane... + # here the TLV payloads are all known types. This allows testing + # decoding the onion and parsing hops_data into known TLV dicts. payment_path_pubkeys = [ bfh('02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619'), bfh('0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c'), @@ -395,89 +347,29 @@ class Test_LNRouter(ElectrumTestCase): session_key = bfh('4141414141414141414141414141414141414141414141414141414141414141') associated_data = bfh('4242424242424242424242424242424242424242424242424242424242424242') hops_data = [ - OnionHopsDataSingle(is_tlv_payload=False, payload={ - "amt_to_forward": {"amt_to_forward": 0}, - "outgoing_cltv_value": {"outgoing_cltv_value": 0}, - "short_channel_id": {"short_channel_id": bfh('0000000000000000')}, - }), - OnionHopsDataSingle(is_tlv_payload=True, payload={ - "amt_to_forward": {"amt_to_forward": 1}, - "outgoing_cltv_value": {"outgoing_cltv_value": 1}, - "short_channel_id": {"short_channel_id": bfh('0101010101010101')}, - }), - OnionHopsDataSingle(is_tlv_payload=True, payload={ - "amt_to_forward": {"amt_to_forward": 2}, - "outgoing_cltv_value": {"outgoing_cltv_value": 2}, - "short_channel_id": {"short_channel_id": bfh('0202020202020202')}, - }), - OnionHopsDataSingle(is_tlv_payload=True, payload={ - "amt_to_forward": {"amt_to_forward": 3}, - "outgoing_cltv_value": {"outgoing_cltv_value": 3}, - "short_channel_id": {"short_channel_id": bfh('0303030303030303')}, - }), - OnionHopsDataSingle(is_tlv_payload=False, payload={ - "amt_to_forward": {"amt_to_forward": 4}, - "outgoing_cltv_value": {"outgoing_cltv_value": 4}, - "short_channel_id": {"short_channel_id": bfh('0404040404040404')}, - }), - ] - packet = new_onion_packet(payment_path_pubkeys, session_key, hops_data, associated_data) - self.assertEqual(bfh('0002eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619e5f14350c2a76fc232b5e46d421e9615471ab9e0bc887beff8c95fdb878f7b3a71bde5adfa90b337f34616d8673d09dd055937273045566ce537ffbe3f9d1f263dc10c7d61ae590536c609010079a232a247922a5395359a63dfbefb85f40317e23254f3023f7d4a98f746c9ab06647645ce55c67308e3c77dc87a1caeac51b03b23c60f05e536e1d757c8c1093e34accfc4f97b5920f6dd2069d5b9ddbb384c3ac575e999a92a4434470ab0aa040c4c3cace3162a405842a88be783e64fad54bd6727c23fc446b7ec0dc3eec5a03eb6c70ec2784911c9e6d274322ec465f0972eb8e771b149f319582ba64dbc2b8e56a3ea79002801c09354f1541cf79bd1dccf5d6bd6b6bacc87a0f24ce497e14e8037e5a79fb4d9ca63fe47f17765963e8f17468a5eaec19a6cca2bfc4e4a366fea3a92112a945856be55e45197ecbab523025e7589529c30cc8addc8fa39d23ef64fa2e51a219c3bd4d3c484832f8e5af16bc46cdba0403991f4fc1b74beef857acf15fefed82ac8678ca66d26262c681beddfdb485aa498813b1a6c5833f1339c1a35244ab76baa0ccaf681ec1f54004e387063335648a77b65d90dde74f1c4b0a729ca25fa53256f7db6d35818b4e5910ba78ec69cf3646bf248ef46cf9cc33062662de2afe4dcf005951b85fd759429fa1ae490b78b14132ccb791232a6c680f03634c0136817f51bf9603a0dba405e7b347830be4327fceccd4734456842b82cf6275393b279bc6ac93d743e00a2d6042960089f70c782ce554b9f73eeeefeea50df7f6f80de1c4e869a7b502f9a5df30d1175402fa780812d35c6d489a30bb0cea53a1088669a238cccf416ecb37f8d8e6ea1327b64979d48e937db69a44a902923a75113685a4aca4a8d9c62b388b48d9c9e2ab9c2df4d529223144de6e16f2dd95a063da79163b3fe006a80263cde4410648f7c3e1f4a7707f82eb0e209002d972c7e57b4ff8ce063fa7b4140f52f569f0cc8793a97a170613efb6b27ba3a0370f8ea74fc0d6aabba54e0ee967abc70e87b580d2aac244236b7752db9d83b159afc1faf6b44b697643235bf59e99f43428caff409d26b9139538865b1f5cf4699f9296088aca461209024ad1dd00e3566e4fde2117b7b3ffced6696b735816a00199890056de86dcbb1b930228143dbf04f07c0eb34370089ea55c43b2c4546cbe1ff0c3a6217d994af9b4225f4b5acb1e3129f5f5b98d381a4692a8561c670b2ee95869f9614e76bb07f623c5194e1c9d26334026f8f5437ec1cde526f914fa094a465f0adcea32b79bfa44d2562536b0d8366da9ee577666c1d5e39615444ca5c900b8199fafac002b8235688eaa0c6887475a913b37d9a4ed43a894ea4576102e5d475ae0b962240ea95fc367b7ac214a4f8682448a9c0d2eea35727bdedc235a975ecc8148a5b03d6291a051dbefe19c8b344d2713c6664dd94ced53c6be39a837fbf1169cca6a12b0a2710f443ba1afeecb51e94236b2a6ed1c2f365b595443b1515de86dcb8c67282807789b47c331cde2fdd721262bef165fa96b7919d11bc5f2022f5affffdd747c7dbe3de8add829a0a8913519fdf7dba4e8a7a25456d2d559746d39ea6ffa31c7b904792fb734bba30f2e1adf7457a994513a1807785fe7b22bf419d1f407f8e2db8b22c0512b078c0cfdfd599e6c4a9d0cc624b9e24b87f30541c3248cd6643df15d251775cc457df4ea6b4e4c5990d87541028c6f0eb28502db1c11a92797168d0b68cb0a0d345b3a3ad05fc4016862f403c64670c41a2c0c6d4e384f5f7da6a204a24530a51182fd7164f120e74a78decb1ab6cda6b9cfc68ac0a35f7a57e750ead65a8e0429cc16e733b9e4feaea25d06c1a4768'), - packet.to_bytes()) - for i, privkey in enumerate(payment_path_privkeys): - processed_packet = process_onion_packet(packet, associated_data, privkey) - self.assertEqual(hops_data[i].to_bytes(), processed_packet.hop_data.to_bytes()) - packet = processed_packet.next_packet - - @needs_test_with_all_chacha20_implementations - def test_process_onion_packet_legacy(self): - # this test is not from bolt-04, but is based on the one there; - # except here we have the privkeys for these pubkeys - payment_path_pubkeys = [ - bfh('03d75c0ee70f68d73d7d13aeb6261d8ace11416800860c7e59407afe4e2e2d42bb'), - bfh('03960a0b830c7b8e76de745b819f252c62508346196b916f5e813cdb0773283cce'), - bfh('0385620e0a571cbc3552620f8bf1bdcdab2d1a4a59c36fa10b8249114ccbdda40d'), - bfh('02ee242cf6c38b7285f0152c33804ff777f5c51fd352ca8132e845e2cf23b3d8ba'), - bfh('025c585fd2e174bf8245b2b4a119e52a417688904228643ea3edaa1728bf2a258e'), - ] - payment_path_privkeys = [ - bfh('3463a278617b3dd83f79bda7f97673f12609c54386e1f0d2b67b1c6354fda14e'), - bfh('7e1255fddb52db1729fc3ceb21a46f95b8d9fe94cc83425e936a6c5223bb679d'), - bfh('c7ce8c1462c311eec24dff9e2532ac6241e50ae57e7d1833af21942136972f23'), - bfh('3d885f374d79a5e777459b083f7818cdc9493e5c4994ac9c7b843de8b70be661'), - bfh('dd72ab44729527b7942e195e7a835e7c71f9c0ff61844eb21274d9c26166a8f8'), - ] - session_key = bfh('4141414141414141414141414141414141414141414141414141414141414141') - associated_data = bfh('4242424242424242424242424242424242424242424242424242424242424242') - hops_data = [ - OnionHopsDataSingle(is_tlv_payload=False, payload={ - "amt_to_forward": {"amt_to_forward": 0}, - "outgoing_cltv_value": {"outgoing_cltv_value": 0}, - "short_channel_id": {"short_channel_id": bfh('0000000000000000')}, - }), - OnionHopsDataSingle(is_tlv_payload=False, payload={ - "amt_to_forward": {"amt_to_forward": 1}, - "outgoing_cltv_value": {"outgoing_cltv_value": 1}, - "short_channel_id": {"short_channel_id": bfh('0101010101010101')}, - }), - OnionHopsDataSingle(is_tlv_payload=False, payload={ - "amt_to_forward": {"amt_to_forward": 2}, - "outgoing_cltv_value": {"outgoing_cltv_value": 2}, - "short_channel_id": {"short_channel_id": bfh('0202020202020202')}, - }), - OnionHopsDataSingle(is_tlv_payload=False, payload={ - "amt_to_forward": {"amt_to_forward": 3}, - "outgoing_cltv_value": {"outgoing_cltv_value": 3}, - "short_channel_id": {"short_channel_id": bfh('0303030303030303')}, - }), - OnionHopsDataSingle(is_tlv_payload=False, payload={ - "amt_to_forward": {"amt_to_forward": 4}, - "outgoing_cltv_value": {"outgoing_cltv_value": 4}, - "short_channel_id": {"short_channel_id": bfh('0404040404040404')}, - }), + OnionHopsDataSingle(payload={ + 'amt_to_forward': {'amt_to_forward': 15000}, + 'outgoing_cltv_value': {'outgoing_cltv_value': 1500}, + 'short_channel_id': {'short_channel_id': bfh('0000000000000001')}}), + OnionHopsDataSingle(payload={ + 'amt_to_forward': {'amt_to_forward': 14000}, + 'outgoing_cltv_value': {'outgoing_cltv_value': 1400}, + 'short_channel_id': {'short_channel_id': bfh('0000000000000002')}}), + OnionHopsDataSingle(payload={ + 'amt_to_forward': {'amt_to_forward': 12500}, + 'outgoing_cltv_value': {'outgoing_cltv_value': 1250}, + 'short_channel_id': {'short_channel_id': bfh('0000000000000003')}}), + OnionHopsDataSingle(payload={ + 'amt_to_forward': {'amt_to_forward': 10000}, + 'outgoing_cltv_value': {'outgoing_cltv_value': 1000}, + 'short_channel_id': {'short_channel_id': bfh('0000000000000004')}}), + OnionHopsDataSingle(payload={ + 'amt_to_forward': {'amt_to_forward': 10000}, + 'outgoing_cltv_value': {'outgoing_cltv_value': 1000}, + 'payment_data': {'payment_secret': bfh('24a33562c54507a9334e79f0dc4f17d407e6d7c61f0e2f3d0d38599502f61704'), 'total_msat': 10000}}), ] - packet = new_onion_packet(payment_path_pubkeys, session_key, hops_data, associated_data) - self.assertEqual(bfh('0002eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f28368661954176cd9869da33d713aa219fcef1e5c806fef11e696bcc66844de8271c27974a049d041ffc5be934b8575c6ff4371f2f88d4edfd73e445534d3f6ae15b64b0d8308390bebf8d149002e31bdc283056477ba27c8054c248ad7306de31663a7c99ec65b251704041f7c4cc40a0016ba172fbf805ec59132a65a4c7eb1f41337931c5df0f840704535729262d30c6132d1b390f073edec8fa057176c6268b6ad06a82ff0229c3be444ee50b40686bc1306838b93c65771de1b6ca05dace1ff9814a6e58b2dd71e8244c83e28b2ed5a3b09e9e7df5c8c747e5765ba366a4f7407a6c6b0a32fb5521cce7cd668f7434c909c1be027d8595d85893e5f612c49a93eeeed80a78bab9c4a621ce0f6f5df7d64a9c8d435db19de192d9db522c7f7b4e201fc1b61a9bd3efd062ae24455d463818b01e2756c7d0691bc3ac4c017be34c9a8b2913bb1b94056bf7a21730afc3f254ffa41ca140a5d87ff470f536d08619e8004d50de2fe5954d6aa4a00570da397ba15ae9ea4d7d1f136256a9093f0a787a36cbb3520b6a3cf4d1b13b16bf399c4b0326da1382a90bd79cf92f4808c8c84eaa50a8ccf44acbde0e35b2e6b72858c8446d6a05f3ba70fb4adc70af27cea9bd1dc1ea35fb3cc236b8b9b69b614903db339b22ad5dc2ddda7ac65fd7de24e60b7dbba7aafc9d26c0f9fcb03f1bb85dfc21762f862620651db52ea703ae60aa7e07febf11caa95c4245a4b37eb9c233e1ab1604fb85849e7f49cb9f7c681c4d91b7c320eb4b89b9c6bcb636ceadda59f6ed47aa5b1ea0a946ea98f6ad2614e79e0d4ef96d6d65903adb0479709e03008bbdf3355dd87df7d68965fdf1ad5c68b6dc2761b96b10f8eb4c0329a646bf38cf4702002e61565231b4ac7a9cde63d23f7b24c9d42797b3c434558d71ed8bf9fcab2c2aee3e8b38c19f9edc3ad3dfe9ebba7387ce4764f97ed1c1a83552dff8315546761479a6f929c39bcca0891d4a967d1b77fa80feed6ae74ac82ed5fb7be225c3f2b0ebdc652afc2255c47bc318ac645bbf19c0819ff527ff6708a78e19c8ca3dc8087035e10d5ac976e84b71148586c8a5a7b26ed11b5b401ce7bb2ac532207eaa24d2f53aaa8024607da764d807c91489e82fcad04e6b8992a507119367f576ee5ffe6807d5723d60234d4c3f94adce0acfed9dba535ca375446a4e9b500b74ad2a66e1c6b0fc38933f282d3a4a877bceceeca52b46e731ca51a9534224a883c4a45587f973f73a22069a4154b1da03d307d8575c821bef0eef87165b9a1bbf902ecfca82ddd805d10fbb7147b496f6772f01e9bf542b00288f3a6efab32590c1f34535ece03a0587ca187d27a98d4c9aa7c044794baa43a81abbe307f51d0bda6e7b4cf62c4be553b176321777e7fd483d6cec16df137293aaf3ad53608e1c7831368675bb9608db04d5c859e7714edab3d2389837fa071f0795adfabc51507b1adbadc7f83e80bd4e4eb9ed1a89c9e0a6dc16f38d55181d5666b02150651961aab34faef97d80fa4e1960864dfec3b687fd4eadf7aa6c709cb4698ae86ae112f386f33731d996b9d41926a2e820c6ba483a61674a4bae03af37e872ffdc0a9a8a034327af17e13e9e7ac619c9188c2a5c12a6ebf887721455c0e2822e67a621ed49f1f50dfc38b71c29d0224954e84ced086c80de552cca3a14adbe43035901225bafc3db3b672c780e4fa12b59221f93690527efc16a28e7c63d1a99fc881f023b03a157076a7e999a715ed37521adb483e2477d75ba5a55d4abad22b024c5317334b6544f15971591c774d896229e4e668fc1c7958fbd76fa0b152a6f14c95692083badd066b6621367fd73d88ba8d860566e6d55b871d80c68296b80ae8847d'), + packet = new_onion_packet(payment_path_pubkeys, session_key, hops_data, associated_data=associated_data) + self.assertEqual(bfh('0002eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619f7f3416a5aa36dc7eeb3ec6d421e9615471ab858ba970cd3cceb768b44e692be2f390c0b7fe70122abae84d7801db070dfb1638cd8d263072206dbed0234f6505e21e282abd8587124c572aad8de04610a136d6c71a7648c0ef66f1b3655d8a9eea1f92349132c93befbd6c37dbfc55615814ae09e4cbef721c01b487007811bbbfdc1fc7bd869aeb70eb08b4140ff5f501394b3653ada2a3b36a263535ea421d26818afb278df46abcec093305b715cac22b0b03645f8f4797cf2987b1bf4bfdd9ed8648ed42ed1a831fc36ccd45416a132580281ddac4e7470e4d2afd675baad9282ec6335403a73e1391427e330996c834db93848b4ae29dd975f678b2f5155ad6865ca23190725d4b7238fb44f0e3762dd59091b45c97d45df8164a15d9ca0329ec76f957b0a0e49ae372154620708df5c0fa991f0dd12b6bff1ebaf9e2376bb64bc24713f7c57da569bcd9c43a50c088416564b786a87d1f40936a051a3dbfe023bd867a5e66148b61cdd24a79f8c18682150e55aa6969ce9becf51f7c69e72deafcd0659f6be4f78463eaef8716e56615c77b3fbea8190806359909dcbec13c1592523b3d2985ec3e83d42cb7286a66a22f58704ddf6979ceb6883ab4ad8ac99d30251035189ffd514e03ce1576844513d66965d4adfc2523f4eee0dede229ab96303e31348c72bc0c8c816c666a904e5ccbabadf5a919720438f4a14dbd4a802f8d4b942f0ca8572f59644c9ac1912c8c8efefc4afa7f19e27411d46b7541c55985e28ce5cd7620b335fea51de55fa00ef977e8522181ad19e5e04f93bcfc83a36edd7e96fe48e846f2e54fe7a7090fe8e46ba72123e1cdee0667777c38c4930e50401074d8ab31a9717457fcefaa46323003af553bee2b49ea7f907eb2ff3301463e64a8c53975c853bbdd2956b9001b5ce1562264963fce84201daaf752de6df7ca31291226969c9851d1fc4ea88ca67d38c38587c2cdd8bc4d3f7bdf705497a1e054246f684554b3b8dfac43194f1eadec7f83b711e663b5645bde6d7f8cefb59758303599fed25c3b4d2e4499d439c915910dd283b3e7118320f1c6e7385009fbcb9ae79bab72a85e644182b4dafc0a173241f2ae68ae6a504f17f102da1e91de4548c7f5bc1c107354519077a4e83407f0d6a8f0975b4ac0c2c7b30637a998dda27b56b56245371296b816876b859677bcf3473a07e0f300e788fdd60c51b1626b46050b182457c6d716994847aaef667ca45b2cede550c92d336ff29ce6effd933b875f81381cda6e59e9727e728a58c0b3e74035beeeb639ab7463744322bf40138b81895e9a8e8850c9513782dc7a79f04380c216cb177951d8940d576486b887a232fcd382adcbd639e70af0c1a08bcf1405496606fce4645aef10d769dc0c010a8a433d8cd24d5943843a89cdbc8d16531db027b312ab2c03a7f1fdb7f2bcb128639c49e86705c948137fd42d0080fda4be4e9ee812057c7974acbf0162730d3b647b355ac1a5adbb2993832eba443b7c9b5a0ae1fc00a6c0c2b0b65b9019690565739d6439bf602066a3a9bd9c67b83606de51792d25ae517cbbdf6e1827fa0e8b2b5c6023cbb1e9f0e10b786dc6fa154e282fd9c90b8d46ca685d0f4434760035073c92d131564b6845ef57457488add4f709073bbb41f5f31f8226904875a9fd9e1b7a2901e71426104d7a298a05af0d4ab549fbd69c539ebe64949a9b6088f16e2e4bc827c305cb8d64536b8364dc3d5f7519c3b431faa38b47a958cf0c6dcabf205280693abf747c262f44cd6ffa11b32fc38d4f9c3631d554d8b57389f1390ac65c06357843ee6d9f289bb054ef25de45c5149c090fe6ddcd4095696dcc9a5cfc09c8bdfd5b83a153'), packet.to_bytes()) for i, privkey in enumerate(payment_path_privkeys): processed_packet = process_onion_packet(packet, associated_data, privkey)