Browse Source

handle_error_code_from_failed_htlc: omg brainfart :(

follow-up 85841ba20d
bip39-recovery
SomberNight 5 years ago
parent
commit
10c2183461
No known key found for this signature in database GPG Key ID: B33B5F232C6271E9
  1. 41
      electrum/lnworker.py
  2. 21
      electrum/tests/test_lnutil.py

41
electrum/lnworker.py

@ -7,7 +7,7 @@ import os
from decimal import Decimal
import random
import time
from typing import Optional, Sequence, Tuple, List, Dict, TYPE_CHECKING, NamedTuple, Union, Mapping
from typing import Optional, Sequence, Tuple, List, Dict, TYPE_CHECKING, NamedTuple, Union, Mapping, Any
import threading
import socket
import aiohttp
@ -968,21 +968,10 @@ class LNWallet(LNWorker):
offset = failure_codes[code]
channel_update_len = int.from_bytes(data[offset:offset+2], byteorder="big")
channel_update_as_received = data[offset+2: offset+2+channel_update_len]
channel_update_typed = (258).to_bytes(length=2, byteorder="big") + channel_update_as_received
# note: some nodes put channel updates in error msgs with the leading msg_type already there.
# we try decoding both ways here.
try:
message_type, payload = decode_msg(channel_update_typed)
if not payload['chain_hash'] != constants.net.rev_genesis_bytes(): raise Exception()
payload['raw'] = channel_update_typed
except: # FIXME: too broad
try:
message_type, payload = decode_msg(channel_update_as_received)
if not payload['chain_hash'] != constants.net.rev_genesis_bytes(): raise Exception()
payload['raw'] = channel_update_as_received
except:
self.logger.info(f'could not decode channel_update for failed htlc: {channel_update_as_received.hex()}')
return True
payload = self._decode_channel_update_msg(channel_update_as_received)
if payload is None:
self.logger.info(f'could not decode channel_update for failed htlc: {channel_update_as_received.hex()}')
return True
r = self.channel_db.add_channel_update(payload)
blacklist = False
short_channel_id = ShortChannelID(payload['short_channel_id'])
@ -1005,6 +994,26 @@ class LNWallet(LNWorker):
blacklist = True
return blacklist
@classmethod
def _decode_channel_update_msg(cls, chan_upd_msg: bytes) -> Optional[Dict[str, Any]]:
channel_update_as_received = chan_upd_msg
channel_update_typed = (258).to_bytes(length=2, byteorder="big") + channel_update_as_received
# note: some nodes put channel updates in error msgs with the leading msg_type already there.
# we try decoding both ways here.
try:
message_type, payload = decode_msg(channel_update_typed)
if payload['chain_hash'] != constants.net.rev_genesis_bytes(): raise Exception()
payload['raw'] = channel_update_typed
return payload
except: # FIXME: too broad
try:
message_type, payload = decode_msg(channel_update_as_received)
if payload['chain_hash'] != constants.net.rev_genesis_bytes(): raise Exception()
payload['raw'] = channel_update_as_received
return payload
except:
return None
@staticmethod
def _check_invoice(invoice: str, *, amount_msat: int = None) -> LnAddr:
addr = lndecode(invoice, expected_hrp=constants.net.SEGWIT_HRP)

21
electrum/tests/test_lnutil.py

@ -11,6 +11,7 @@ from electrum.lnutil import (RevocationStore, get_per_commitment_secret_from_see
ScriptHtlc, extract_nodeid, calc_fees_for_commitment_tx, UpdateAddHtlc, LnFeatures)
from electrum.util import bh2u, bfh, MyEncoder
from electrum.transaction import Transaction, PartialTransaction
from electrum.lnworker import LNWallet
from . import ElectrumTestCase
@ -805,3 +806,23 @@ class TestLNUtil(ElectrumTestCase):
features.for_invoice())
features = LnFeatures.BASIC_MPP_OPT | LnFeatures.PAYMENT_SECRET_REQ | LnFeatures.VAR_ONION_REQ
self.assertEqual(features, features.for_invoice())
def test_lnworker_decode_channel_update_msg(self):
msg_without_prefix = bytes.fromhex("439b71c8ddeff63004e4ff1f9764a57dcf20232b79d9d669aef0e31c42be8e44208f7d868d0133acb334047f30e9399dece226ccd98e5df5330adf7f356290516fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d619000000000008762700054a00005ef2cf9c0101009000000000000003e80000000000000001000000002367b880")
# good messages
self.assertNotEqual(
None,
LNWallet._decode_channel_update_msg(msg_without_prefix))
self.assertNotEqual(
None,
LNWallet._decode_channel_update_msg(bytes.fromhex("0102") + msg_without_prefix))
# bad messages
self.assertEqual(
None,
LNWallet._decode_channel_update_msg(bytes.fromhex("0102030405")))
self.assertEqual(
None,
LNWallet._decode_channel_update_msg(bytes.fromhex("ffff") + msg_without_prefix))
self.assertEqual(
None,
LNWallet._decode_channel_update_msg(bytes.fromhex("0101") + msg_without_prefix))

Loading…
Cancel
Save