URI: 
       tchannel_db: add verbose option to add_channel_update - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 2d0ef78a11f99f198b8b6d3802a98b60a319583a
   DIR parent 64733a39dcf702d271236eb044fa23263e9948f2
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Fri, 24 Apr 2020 11:45:39 +0200
       
       channel_db: add verbose option to add_channel_update
       
       Diffstat:
         M electrum/channel_db.py              |      94 ++++++++++++++++---------------
         M electrum/lnworker.py                |      11 ++++++-----
       
       2 files changed, 55 insertions(+), 50 deletions(-)
       ---
   DIR diff --git a/electrum/channel_db.py b/electrum/channel_db.py
       t@@ -32,6 +32,7 @@ import binascii
        import base64
        import asyncio
        import threading
       +from enum import IntEnum
        
        
        from .sql_db import SqlDB, sql
       t@@ -196,13 +197,17 @@ class NodeInfo(NamedTuple):
                return addresses
        
        
       +class UpdateStatus(IntEnum):
       +    ORPHANED   = 0
       +    EXPIRED    = 1
       +    DEPRECATED = 2
       +    GOOD       = 3
       +
        class CategorizedChannelUpdates(NamedTuple):
            orphaned: List    # no channel announcement for channel update
            expired: List     # update older than two weeks
            deprecated: List  # update older than database entry
            good: List        # good updates
       -    to_delete: List   # database entries to delete
       -
        
        
        create_channel_info = """
       t@@ -374,62 +379,61 @@ class ChannelDB(SqlDB):
                if old_policy.message_flags != new_policy.message_flags:
                    self.logger.info(f'message_flags: {old_policy.message_flags} -> {new_policy.message_flags}')
        
       -    def add_channel_updates(self, payloads, max_age=None, verify=True) -> CategorizedChannelUpdates:
       +    def add_channel_update(self, payload, max_age=None, verify=False, verbose=True):
       +        now = int(time.time())
       +        short_channel_id = ShortChannelID(payload['short_channel_id'])
       +        timestamp = payload['timestamp']
       +        if max_age and now - timestamp > max_age:
       +            return UpdateStatus.EXPIRED
       +        channel_info = self._channels.get(short_channel_id)
       +        if not channel_info:
       +            return UpdateStatus.ORPHANED
       +        flags = int.from_bytes(payload['channel_flags'], 'big')
       +        direction = flags & FLAG_DIRECTION
       +        start_node = channel_info.node1_id if direction == 0 else channel_info.node2_id
       +        payload['start_node'] = start_node
       +        # compare updates to existing database entries
       +        timestamp = payload['timestamp']
       +        start_node = payload['start_node']
       +        short_channel_id = ShortChannelID(payload['short_channel_id'])
       +        key = (start_node, short_channel_id)
       +        old_policy = self._policies.get(key)
       +        if old_policy and timestamp <= old_policy.timestamp:
       +            return UpdateStatus.DEPRECATED
       +        if verify:
       +            self.verify_channel_update(payload)
       +        policy = Policy.from_msg(payload)
       +        with self.lock:
       +            self._policies[key] = policy
       +        self._update_num_policies_for_chan(short_channel_id)
       +        if 'raw' in payload:
       +            self._db_save_policy(policy.key, payload['raw'])
       +        if old_policy and verbose:
       +            self.print_change(old_policy, policy)
       +        return UpdateStatus.GOOD
       +
       +    def add_channel_updates(self, payloads, max_age=None) -> CategorizedChannelUpdates:
                orphaned = []
                expired = []
                deprecated = []
                good = []
       -        to_delete = []
       -        # filter orphaned and expired first
       -        known = []
       -        now = int(time.time())
                for payload in payloads:
       -            short_channel_id = ShortChannelID(payload['short_channel_id'])
       -            timestamp = payload['timestamp']
       -            if max_age and now - timestamp > max_age:
       -                expired.append(payload)
       -                continue
       -            channel_info = self._channels.get(short_channel_id)
       -            if not channel_info:
       +            r = self.add_channel_update(payload, max_age=max_age, verbose=False)
       +            if r == UpdateStatus.ORPHANED:
                        orphaned.append(payload)
       -                continue
       -            flags = int.from_bytes(payload['channel_flags'], 'big')
       -            direction = flags & FLAG_DIRECTION
       -            start_node = channel_info.node1_id if direction == 0 else channel_info.node2_id
       -            payload['start_node'] = start_node
       -            known.append(payload)
       -        # compare updates to existing database entries
       -        for payload in known:
       -            timestamp = payload['timestamp']
       -            start_node = payload['start_node']
       -            short_channel_id = ShortChannelID(payload['short_channel_id'])
       -            key = (start_node, short_channel_id)
       -            old_policy = self._policies.get(key)
       -            if old_policy and timestamp <= old_policy.timestamp:
       +            elif r == UpdateStatus.EXPIRED:
       +                expired.append(payload)
       +            elif r == UpdateStatus.DEPRECATED:
                        deprecated.append(payload)
       -                continue
       -            good.append(payload)
       -            if verify:
       -                self.verify_channel_update(payload)
       -            policy = Policy.from_msg(payload)
       -            with self.lock:
       -                self._policies[key] = policy
       -            self._update_num_policies_for_chan(short_channel_id)
       -            if 'raw' in payload:
       -                self._db_save_policy(policy.key, payload['raw'])
       -        #
       +            elif r == UpdateStatus.GOOD:
       +                good.append(payload)
                self.update_counts()
                return CategorizedChannelUpdates(
                    orphaned=orphaned,
                    expired=expired,
                    deprecated=deprecated,
       -            good=good,
       -            to_delete=to_delete,
       -        )
       +            good=good)
        
       -    def add_channel_update(self, payload):
       -        # called from tests
       -        self.add_channel_updates([payload], verify=False)
        
            def create_database(self):
                c = self.conn.cursor()
   DIR diff --git a/electrum/lnworker.py b/electrum/lnworker.py
       t@@ -67,6 +67,7 @@ from .lnwatcher import LNWalletWatcher
        from .crypto import pw_encode_bytes, pw_decode_bytes, PW_HASH_VERSION_LATEST
        from .lnutil import ChannelBackupStorage
        from .lnchannel import ChannelBackup
       +from .channel_db import UpdateStatus
        
        if TYPE_CHECKING:
            from .network import Network
       t@@ -930,20 +931,20 @@ class LNWallet(LNWorker):
                    if payload['chain_hash'] != constants.net.rev_genesis_bytes():
                        self.logger.info(f'could not decode channel_update for failed htlc: {channel_update_as_received.hex()}')
                        return True
       -            categorized_chan_upds = self.channel_db.add_channel_updates([payload])
       +            r = self.channel_db.add_channel_update(payload)
                    blacklist = False
                    short_channel_id = ShortChannelID(payload['short_channel_id'])
       -            if categorized_chan_upds.good:
       +            if r == UpdateStatus.GOOD:
                        self.logger.info(f"applied channel update to {short_channel_id}")
                        peer.maybe_save_remote_update(payload)
       -            elif categorized_chan_upds.orphaned:
       +            elif r == UpdateStatus.ORPHANED:
                        # maybe it is a private channel (and data in invoice was outdated)
                        self.logger.info(f"Could not find {short_channel_id}. maybe update is for private channel?")
                        start_node_id = route[sender_idx].node_id
                        self.channel_db.add_channel_update_for_private_channel(payload, start_node_id)
       -            elif categorized_chan_upds.expired:
       +            elif r == UpdateStatus.EXPIRED:
                        blacklist = True
       -            elif categorized_chan_upds.deprecated:
       +            elif r == UpdateStatus.DEPRECATED:
                        self.logger.info(f'channel update is not more recent.')
                        blacklist = True
                else: