electrum

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

commit a8ace7ef4fa88a7977740f87d544cd8542a4fd3c
parent 864efa029bb695f98beeeaa46f1b22c98241eee2
Author: SomberNight <somber.night@protonmail.com>
Date:   Tue,  9 Oct 2018 21:23:22 +0200

lnonion: use IntEnum and IntFlag for failure codes

Diffstat:
Melectrum/lnbase.py | 11++++++-----
Melectrum/lnonion.py | 70++++++++++++++++++++++++++++++++++++++++++----------------------------
2 files changed, 48 insertions(+), 33 deletions(-)

diff --git a/electrum/lnbase.py b/electrum/lnbase.py @@ -25,7 +25,7 @@ from .crypto import sha256 from . import constants from .util import PrintError, bh2u, print_error, bfh, log_exceptions from .transaction import Transaction, TxOutput -from .lnonion import new_onion_packet, OnionHopsDataSingle, OnionPerHop, decode_onion_error, ONION_FAILURE_CODE_MAP +from .lnonion import new_onion_packet, OnionHopsDataSingle, OnionPerHop, decode_onion_error, OnionFailureCode from .lnaddr import lndecode from .lnhtlc import HTLCStateMachine, RevokeAndAck from .lnutil import (Outpoint, ChannelConfig, LocalState, @@ -467,9 +467,12 @@ class Peer(PrintError): # Note that this is prone to a race.. we might not have a short_channel_id # associated with the channel in some cases short_channel_id = payload['short_channel_id'] + self.print_error("not found channel announce for channel update in db", bh2u(short_channel_id)) for chan in self.channels.values(): if chan.short_channel_id_predicted == short_channel_id: chan.pending_channel_update_message = payload + self.print_error("channel update is for our own private channel", bh2u(short_channel_id)) + break def on_channel_announcement(self, payload): self.channel_db.on_channel_announcement(payload) @@ -1022,10 +1025,9 @@ class Peer(PrintError): self.print_error("UPDATE_FAIL_HTLC. cannot decode! attempted route is MISSING. {}".format(key)) else: failure_msg, sender_idx = decode_onion_error(payload["reason"], [x.node_id for x in route], chan.onion_keys[htlc_id]) - code = failure_msg.code - code_name = ONION_FAILURE_CODE_MAP.get(code, 'unknown_error??') + code = OnionFailureCode(failure_msg.code) data = failure_msg.data - self.print_error("UPDATE_FAIL_HTLC", code_name, code, data) + self.print_error("UPDATE_FAIL_HTLC", repr(code), data) try: short_chan_id = route[sender_idx + 1].short_channel_id except IndexError: @@ -1034,7 +1036,6 @@ class Peer(PrintError): # TODO this should depend on the error # also, we need finer blacklisting (directed edges; nodes) self.network.path_finder.blacklist.add(short_chan_id) - self.print_error("HTLC failure with code {} ({})".format(code, code_name)) # process update_fail_htlc on channel chan = self.channels[channel_id] chan.receive_fail_htlc(htlc_id) diff --git a/electrum/lnonion.py b/electrum/lnonion.py @@ -27,6 +27,7 @@ import hashlib import hmac from collections import namedtuple from typing import Sequence +from enum import IntEnum, IntFlag from cryptography.hazmat.primitives.ciphers import Cipher, algorithms from cryptography.hazmat.backends import default_backend @@ -299,33 +300,46 @@ def get_failure_msg_from_onion_error(decrypted_error_packet: bytes) -> OnionRout return OnionRoutingFailureMessage(failure_code, failure_data) -ONION_FC_BADONION = BADONION = 0x8000 -ONION_FC_PERM = PERM = 0x4000 -ONION_FC_NODE = NODE = 0x2000 -ONION_FC_UPDATE = UPDATE = 0x1000 -ONION_FAILURE_CODE_MAP = { - PERM | 1 : 'invalid_realm', - NODE | 2 : 'temporary_node_failure', - PERM | NODE | 2 : 'permanent_node_failure', - PERM | NODE | 3 : 'required_node_feature_missing', - BADONION | PERM | 4 : 'invalid_onion_version', - BADONION | PERM | 5 : 'invalid_onion_hmac', - BADONION | PERM | 6 : 'invalid_onion_key', - UPDATE | 7 : 'temporary_channel_failure', - PERM | 8 : 'permanent_channel_failure', - PERM | 9 : 'required_channel_feature_missing', - PERM | 10 : 'unknown_next_peer', - UPDATE | 11 : 'amount_below_minimum', - UPDATE | 12 : 'fee_insufficient', - UPDATE | 13 : 'incorrect_cltv_expiry', - UPDATE | 14 : 'expiry_too_soon', - PERM | 15 : 'unknown_payment_hash', - PERM | 16 : 'incorrect_payment_amount', - 17 : 'final_expiry_too_soon', - 18 : 'final_incorrect_cltv_expiry', - 19 : 'final_incorrect_htlc_amount', - UPDATE | 20 : 'channel_disabled', - 21 : 'expiry_too_far', -} +class OnionFailureCodeMetaFlag(IntFlag): + BADONION = 0x8000 + PERM = 0x4000 + NODE = 0x2000 + UPDATE = 0x1000 + +BADONION = OnionFailureCodeMetaFlag.BADONION +PERM = OnionFailureCodeMetaFlag.PERM +NODE = OnionFailureCodeMetaFlag.NODE +UPDATE = OnionFailureCodeMetaFlag.UPDATE +class OnionFailureCode(IntEnum): + INVALID_REALM = PERM | 1 + TEMPORARY_NODE_FAILURE = NODE | 2 + PERMANENT_NODE_FAILURE = PERM | NODE | 2 + REQUIRED_NODE_FEATURE_MISSING = PERM | NODE | 3 + INVALID_ONION_VERSION = BADONION | PERM | 4 + INVALID_ONION_HMAC = BADONION | PERM | 5 + INVALID_ONION_KEY = BADONION | PERM | 6 + TEMPORARY_CHANNEL_FAILURE = UPDATE | 7 + PERMANENT_CHANNEL_FAILURE = PERM | 8 + REQUIRED_CHANNEL_FEATURE_MISSING = PERM | 9 + UNKNOWN_NEXT_PEER = PERM | 10 + AMOUNT_BELOW_MINIMUM = UPDATE | 11 + FEE_INSUFFICIENT = UPDATE | 12 + INCORRECT_CLTV_EXPIRY = UPDATE | 13 + EXPIRY_TOO_SOON = UPDATE | 14 + UNKNOWN_PAYMENT_HASH = PERM | 15 + INCORRECT_PAYMENT_AMOUNT = PERM | 16 + FINAL_EXPIRY_TOO_SOON = 17 + FINAL_INCORRECT_CLTV_EXPIRY = 18 + FINAL_INCORRECT_HTLC_AMOUNT = 19 + CHANNEL_DISABLED = UPDATE | 20 + EXPIRY_TOO_FAR = 21 + + @classmethod + def _missing_(cls, value: int) -> int: + # note that for unknown error codes, we return an int, + # not an instance of cls + return value + + # don't use these elsewhere, the names are ambiguous without context del BADONION; del PERM; del NODE; del UPDATE