URI: 
       thandle_error_code_from_failed_htlc: omg brainfart :( - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 10c21834613318f15bd30213fa52eaada50d1285
   DIR parent c2111a2616d2e9b759ce84304ad61d4b90f3db8f
  HTML Author: SomberNight <somber.night@protonmail.com>
       Date:   Wed, 24 Jun 2020 21:33:44 +0200
       
       handle_error_code_from_failed_htlc: omg brainfart :(
       
       follow-up 85841ba20de7cb6459066538474d3f13e010031e
       
       Diffstat:
         M electrum/lnworker.py                |      41 +++++++++++++++++++------------
         M electrum/tests/test_lnutil.py       |      21 +++++++++++++++++++++
       
       2 files changed, 46 insertions(+), 16 deletions(-)
       ---
   DIR diff --git a/electrum/lnworker.py b/electrum/lnworker.py
       t@@ -7,7 +7,7 @@ import os
        from decimal import Decimal
        import random
        import time
       -from typing import Optional, Sequence, Tuple, List, Dict, TYPE_CHECKING, NamedTuple, Union, Mapping
       +from typing import Optional, Sequence, Tuple, List, Dict, TYPE_CHECKING, NamedTuple, Union, Mapping, Any
        import threading
        import socket
        import aiohttp
       t@@ -968,21 +968,10 @@ class LNWallet(LNWorker):
                    offset = failure_codes[code]
                    channel_update_len = int.from_bytes(data[offset:offset+2], byteorder="big")
                    channel_update_as_received = data[offset+2: offset+2+channel_update_len]
       -            channel_update_typed = (258).to_bytes(length=2, byteorder="big") + channel_update_as_received
       -            # note: some nodes put channel updates in error msgs with the leading msg_type already there.
       -            #       we try decoding both ways here.
       -            try:
       -                message_type, payload = decode_msg(channel_update_typed)
       -                if not payload['chain_hash'] != constants.net.rev_genesis_bytes(): raise Exception()
       -                payload['raw'] = channel_update_typed
       -            except:  # FIXME: too broad
       -                try:
       -                    message_type, payload = decode_msg(channel_update_as_received)
       -                    if not payload['chain_hash'] != constants.net.rev_genesis_bytes(): raise Exception()
       -                    payload['raw'] = channel_update_as_received
       -                except:
       -                    self.logger.info(f'could not decode channel_update for failed htlc: {channel_update_as_received.hex()}')
       -                    return True
       +            payload = self._decode_channel_update_msg(channel_update_as_received)
       +            if payload is None:
       +                self.logger.info(f'could not decode channel_update for failed htlc: {channel_update_as_received.hex()}')
       +                return True
                    r = self.channel_db.add_channel_update(payload)
                    blacklist = False
                    short_channel_id = ShortChannelID(payload['short_channel_id'])
       t@@ -1005,6 +994,26 @@ class LNWallet(LNWorker):
                    blacklist = True
                return blacklist
        
       +    @classmethod
       +    def _decode_channel_update_msg(cls, chan_upd_msg: bytes) -> Optional[Dict[str, Any]]:
       +        channel_update_as_received = chan_upd_msg
       +        channel_update_typed = (258).to_bytes(length=2, byteorder="big") + channel_update_as_received
       +        # note: some nodes put channel updates in error msgs with the leading msg_type already there.
       +        #       we try decoding both ways here.
       +        try:
       +            message_type, payload = decode_msg(channel_update_typed)
       +            if payload['chain_hash'] != constants.net.rev_genesis_bytes(): raise Exception()
       +            payload['raw'] = channel_update_typed
       +            return payload
       +        except:  # FIXME: too broad
       +            try:
       +                message_type, payload = decode_msg(channel_update_as_received)
       +                if payload['chain_hash'] != constants.net.rev_genesis_bytes(): raise Exception()
       +                payload['raw'] = channel_update_as_received
       +                return payload
       +            except:
       +                return None
       +
            @staticmethod
            def _check_invoice(invoice: str, *, amount_msat: int = None) -> LnAddr:
                addr = lndecode(invoice, expected_hrp=constants.net.SEGWIT_HRP)
   DIR diff --git a/electrum/tests/test_lnutil.py b/electrum/tests/test_lnutil.py
       t@@ -11,6 +11,7 @@ from electrum.lnutil import (RevocationStore, get_per_commitment_secret_from_see
                                     ScriptHtlc, extract_nodeid, calc_fees_for_commitment_tx, UpdateAddHtlc, LnFeatures)
        from electrum.util import bh2u, bfh, MyEncoder
        from electrum.transaction import Transaction, PartialTransaction
       +from electrum.lnworker import LNWallet
        
        from . import ElectrumTestCase
        
       t@@ -805,3 +806,23 @@ class TestLNUtil(ElectrumTestCase):
                                 features.for_invoice())
                features = LnFeatures.BASIC_MPP_OPT | LnFeatures.PAYMENT_SECRET_REQ | LnFeatures.VAR_ONION_REQ
                self.assertEqual(features, features.for_invoice())
       +
       +    def test_lnworker_decode_channel_update_msg(self):
       +        msg_without_prefix = bytes.fromhex("439b71c8ddeff63004e4ff1f9764a57dcf20232b79d9d669aef0e31c42be8e44208f7d868d0133acb334047f30e9399dece226ccd98e5df5330adf7f356290516fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d619000000000008762700054a00005ef2cf9c0101009000000000000003e80000000000000001000000002367b880")
       +        # good messages
       +        self.assertNotEqual(
       +            None,
       +            LNWallet._decode_channel_update_msg(msg_without_prefix))
       +        self.assertNotEqual(
       +            None,
       +            LNWallet._decode_channel_update_msg(bytes.fromhex("0102") + msg_without_prefix))
       +        # bad messages
       +        self.assertEqual(
       +            None,
       +            LNWallet._decode_channel_update_msg(bytes.fromhex("0102030405")))
       +        self.assertEqual(
       +            None,
       +            LNWallet._decode_channel_update_msg(bytes.fromhex("ffff") + msg_without_prefix))
       +        self.assertEqual(
       +            None,
       +            LNWallet._decode_channel_update_msg(bytes.fromhex("0101") + msg_without_prefix))