electrum

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

commit bab9f163f7a7dcae2fbcf91675e7993ef8b55163
parent b85aea1541098d0284de5b92c1ca997c12c68cdc
Author: SomberNight <somber.night@protonmail.com>
Date:   Wed,  1 Aug 2018 19:06:43 +0200

decode onion errors to failure message type

Diffstat:
Melectrum/lnbase.py | 18++++++------------
Melectrum/lnonion.py | 32++++++++++++++++++++++++++++++++
2 files changed, 38 insertions(+), 12 deletions(-)

diff --git a/electrum/lnbase.py b/electrum/lnbase.py @@ -31,7 +31,7 @@ from . import constants from . import transaction from .util import PrintError, bh2u, print_error, bfh from .transaction import opcodes, Transaction -from .lnonion import new_onion_packet, OnionHopsDataSingle, OnionPerHop, decode_onion_error +from .lnonion import new_onion_packet, OnionHopsDataSingle, OnionPerHop, decode_onion_error, ONION_FAILURE_CODE_MAP from .lnaddr import lndecode from .lnhtlc import UpdateAddHtlc, HTLCStateMachine, RevokeAndAck, SettleHtlc @@ -817,25 +817,19 @@ class Peer(PrintError): route = self.attempted_route[key] failure_msg, sender_idx = decode_onion_error(payload["reason"], [x.node_id for x in route], self.secret_key) code = failure_msg.code + code_name = ONION_FAILURE_CODE_MAP.get(code, 'unknown_error!!') data = failure_msg.data - codes = [] - if code & 0x8000: - codes += ["BADONION"] - if code & 0x4000: - codes += ["PERM"] - if code & 0x2000: - codes += ["NODE"] - if code & 0x1000: - codes += ["UPDATE"] - print("UPDATE_FAIL_HTLC", codes, code, data) + print("UPDATE_FAIL_HTLC", code_name, code, data) try: short_chan_id = route[sender_idx + 1].short_channel_id except IndexError: print("payment destination reported error") else: + # 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.update_fail_htlc[payload["channel_id"]].put_nowait("HTLC failure with code {} (categories {})".format(code, codes)) + self.update_fail_htlc[payload["channel_id"]].put_nowait("HTLC failure with code {} ({})".format(code, code_name)) @aiosafe async def pay(self, path, chan, amount_msat, payment_hash, pubkey_in_invoice, min_final_cltv_expiry): diff --git a/electrum/lnonion.py b/electrum/lnonion.py @@ -297,3 +297,35 @@ def get_failure_msg_from_onion_error(decrypted_error_packet: bytes) -> OnionRout failure_code = int.from_bytes(failure_msg[:2], byteorder='big') failure_data = failure_msg[2:] 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', +} +# don't use these elsewhere, the names are ambiguous without context +del BADONION; del PERM; del NODE; del UPDATE