tlnpeer.maybe_fulfill_htlc: follow BOLTs re some errors - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit 31bdb5c344f9bd2dc1f0885513302756f79b040f DIR parent 61e7f7e75ec491a7d05d15fe9aa0ff6bf736862f HTML Author: SomberNight <somber.night@protonmail.com> Date: Thu, 25 Feb 2021 12:12:44 +0100 lnpeer.maybe_fulfill_htlc: follow BOLTs re some errors related: https://github.com/lightningnetwork/lightning-rfc/pull/608 Diffstat: M electrum/lnpeer.py | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) --- DIR diff --git a/electrum/lnpeer.py b/electrum/lnpeer.py t@@ -1507,13 +1507,21 @@ class Peer(Logger): asyncio.ensure_future(forward_trampoline_payment()) - def maybe_fulfill_htlc( self, *, chan: Channel, htlc: UpdateAddHtlc, processed_onion: ProcessedOnionPacket, - is_trampoline:bool = False) -> Optional[bytes]: + is_trampoline: bool = False, + ) -> Optional[bytes]: + """As a final recipient of an HTLC, decide if we should fulfill it. + Returns the preimage if yes, or None. + """ + + try: + amt_to_forward = processed_onion.hop_data.payload["amt_to_forward"]["amt_to_forward"] + except: + raise OnionRoutingFailure(code=OnionFailureCode.INVALID_ONION_PAYLOAD, data=b'\x00\x00\x00') # Check that our blockchain tip is sufficiently recent so that we have an approx idea of the height. # We should not release the preimage for an HTLC that its sender could already time out as t@@ -1522,8 +1530,11 @@ class Peer(Logger): if chain.is_tip_stale(): raise OnionRoutingFailure(code=OnionFailureCode.TEMPORARY_NODE_FAILURE, data=b'') local_height = chain.height() + exc_incorrect_or_unknown_pd = OnionRoutingFailure( + code=OnionFailureCode.INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS, + data=amt_to_forward.to_bytes(8, byteorder="big") + local_height.to_bytes(4, byteorder="big")) if local_height + MIN_FINAL_CLTV_EXPIRY_ACCEPTED > htlc.cltv_expiry: - raise OnionRoutingFailure(code=OnionFailureCode.FINAL_EXPIRY_TOO_SOON, data=b'') + raise exc_incorrect_or_unknown_pd try: cltv_from_onion = processed_onion.hop_data.payload["outgoing_cltv_value"]["outgoing_cltv_value"] except: t@@ -1535,10 +1546,6 @@ class Peer(Logger): code=OnionFailureCode.FINAL_INCORRECT_CLTV_EXPIRY, data=htlc.cltv_expiry.to_bytes(4, byteorder="big")) try: - amt_to_forward = processed_onion.hop_data.payload["amt_to_forward"]["amt_to_forward"] - except: - raise OnionRoutingFailure(code=OnionFailureCode.INVALID_ONION_PAYLOAD, data=b'\x00\x00\x00') - try: total_msat = processed_onion.hop_data.payload["payment_data"]["total_msat"] except: total_msat = amt_to_forward # fall back to "amt_to_forward" t@@ -1554,21 +1561,21 @@ class Peer(Logger): info = self.lnworker.get_payment_info(htlc.payment_hash) if info is None: - raise OnionRoutingFailure(code=OnionFailureCode.INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS, data=b'') + raise exc_incorrect_or_unknown_pd preimage = self.lnworker.get_preimage(htlc.payment_hash) try: payment_secret_from_onion = processed_onion.hop_data.payload["payment_data"]["payment_secret"] except: if total_msat > amt_to_forward: # payment_secret is required for MPP - raise OnionRoutingFailure(code=OnionFailureCode.INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS, data=b'') + raise exc_incorrect_or_unknown_pd # TODO fail here if invoice has set PAYMENT_SECRET_REQ else: if payment_secret_from_onion != derive_payment_secret_from_payment_preimage(preimage): - raise OnionRoutingFailure(code=OnionFailureCode.INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS, data=b'') + raise exc_incorrect_or_unknown_pd invoice_msat = info.amount_msat if not (invoice_msat is None or invoice_msat <= total_msat <= 2 * invoice_msat): - raise OnionRoutingFailure(code=OnionFailureCode.INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS, data=b'') + raise exc_incorrect_or_unknown_pd accepted, expired = self.lnworker.htlc_received(chan.short_channel_id, htlc, total_msat) if accepted: return preimage