electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit 2d0ef78a11f99f198b8b6d3802a98b60a319583a
parent 64733a39dcf702d271236eb044fa23263e9948f2
Author: ThomasV <thomasv@electrum.org>
Date:   Fri, 24 Apr 2020 11:45:39 +0200

channel_db: add verbose option to add_channel_update

Diffstat:
Melectrum/channel_db.py | 94+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Melectrum/lnworker.py | 11++++++-----
2 files changed, 55 insertions(+), 50 deletions(-)

diff --git a/electrum/channel_db.py b/electrum/channel_db.py @@ -32,6 +32,7 @@ import binascii import base64 import asyncio import threading +from enum import IntEnum from .sql_db import SqlDB, sql @@ -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 = """ @@ -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() diff --git a/electrum/lnworker.py b/electrum/lnworker.py @@ -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 @@ -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: