def check_accepted_htlc(
            self, *,
            chan: Channel,
            htlc: UpdateAddHtlc,
            processed_onion: ProcessedOnionPacket,
            log_fail_reason: Callable,
    ):
        """
        Perform checks that are invariant (results do not depend on height, network conditions, etc).
        May raise OnionRoutingFailure
        """
        try:
            amt_to_forward = processed_onion.hop_data.payload["amt_to_forward"]["amt_to_forward"]
        except Exception:
            log_fail_reason(f"'amt_to_forward' missing from onion")
            raise OnionRoutingFailure(code=OnionFailureCode.INVALID_ONION_PAYLOAD, data=b'\x00\x00\x00')

        exc_incorrect_or_unknown_pd = OnionRoutingFailure(
            code=OnionFailureCode.INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS,
            data=amt_to_forward.to_bytes(8, byteorder="big")) # height will be added later
        try:
            cltv_abs_from_onion = processed_onion.hop_data.payload["outgoing_cltv_value"]["outgoing_cltv_value"]
        except Exception:
            log_fail_reason(f"'outgoing_cltv_value' missing from onion")
            raise OnionRoutingFailure(code=OnionFailureCode.INVALID_ONION_PAYLOAD, data=b'\x00\x00\x00')

        if cltv_abs_from_onion > htlc.cltv_abs:
            log_fail_reason(f"cltv_abs_from_onion != htlc.cltv_abs")
            raise OnionRoutingFailure(
                code=OnionFailureCode.FINAL_INCORRECT_CLTV_EXPIRY,
                data=htlc.cltv_abs.to_bytes(4, byteorder="big"))
        try:
            total_msat = processed_onion.hop_data.payload["payment_data"]["total_msat"]
        except Exception:
            log_fail_reason(f"'total_msat' missing from onion")
            raise exc_incorrect_or_unknown_pd

        if chan.opening_fee:
            channel_opening_fee = chan.opening_fee['channel_opening_fee']
            total_msat -= channel_opening_fee
            amt_to_forward -= channel_opening_fee
        else:
            channel_opening_fee = 0

        if amt_to_forward > htlc.amount_msat:
            log_fail_reason(f"amt_to_forward != htlc.amount_msat")
            raise OnionRoutingFailure(
                code=OnionFailureCode.FINAL_INCORRECT_HTLC_AMOUNT,
                data=htlc.amount_msat.to_bytes(8, byteorder="big"))

        try:
            payment_secret_from_onion = processed_onion.hop_data.payload["payment_data"]["payment_secret"]  # type: bytes
        except Exception:
            log_fail_reason(f"'payment_secret' missing from onion")
            raise exc_incorrect_or_unknown_pd

        return payment_secret_from_onion, total_msat, channel_opening_fee, exc_incorrect_or_unknown_pd

        Perform checks that are invariant (results do not depend on height, network conditions, etc).
        May raise OnionRoutingFailure
        
electrum/lnpeer.py