URI: 
       tlnonion: use IntEnum and IntFlag for failure codes - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit a8ace7ef4fa88a7977740f87d544cd8542a4fd3c
   DIR parent 864efa029bb695f98beeeaa46f1b22c98241eee2
  HTML Author: SomberNight <somber.night@protonmail.com>
       Date:   Tue,  9 Oct 2018 21:23:22 +0200
       
       lnonion: use IntEnum and IntFlag for failure codes
       
       Diffstat:
         M electrum/lnbase.py                  |      11 ++++++-----
         M electrum/lnonion.py                 |      70 +++++++++++++++++++-------------
       
       2 files changed, 48 insertions(+), 33 deletions(-)
       ---
   DIR diff --git a/electrum/lnbase.py b/electrum/lnbase.py
       t@@ -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,
       t@@ -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)
       t@@ -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:
       t@@ -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)
   DIR diff --git a/electrum/lnonion.py b/electrum/lnonion.py
       t@@ -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
       t@@ -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