URI: 
       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