lnmsg: add details to FailedToParseMsg, log message type
note: Would it be ok to log potentially secret (semi-sensitive) data? We take care not to log onchain private keys as they are extremely sensitive, but what about logging a LN transport message that might contain channel secrets? Decided not to, for now.
This commit is contained in:
@@ -7,7 +7,9 @@ from collections import OrderedDict
|
|||||||
from .lnutil import OnionFailureCodeMetaFlag
|
from .lnutil import OnionFailureCodeMetaFlag
|
||||||
|
|
||||||
|
|
||||||
class FailedToParseMsg(Exception): pass
|
class FailedToParseMsg(Exception):
|
||||||
|
msg_type_int: Optional[int] = None
|
||||||
|
msg_type_name: Optional[str] = None
|
||||||
|
|
||||||
class UnknownMsgType(FailedToParseMsg): pass
|
class UnknownMsgType(FailedToParseMsg): pass
|
||||||
class UnknownOptionalMsgType(UnknownMsgType): pass
|
class UnknownOptionalMsgType(UnknownMsgType): pass
|
||||||
@@ -488,33 +490,38 @@ class LNSerializer:
|
|||||||
assert scheme[0][2] == msg_type_int
|
assert scheme[0][2] == msg_type_int
|
||||||
msg_type_name = scheme[0][1]
|
msg_type_name = scheme[0][1]
|
||||||
parsed = {}
|
parsed = {}
|
||||||
with io.BytesIO(data[2:]) as fd:
|
try:
|
||||||
for row in scheme:
|
with io.BytesIO(data[2:]) as fd:
|
||||||
#print(f"row: {row!r}")
|
for row in scheme:
|
||||||
if row[0] == "msgtype":
|
#print(f"row: {row!r}")
|
||||||
pass
|
if row[0] == "msgtype":
|
||||||
elif row[0] == "msgdata":
|
pass
|
||||||
field_name = row[2]
|
elif row[0] == "msgdata":
|
||||||
field_type = row[3]
|
field_name = row[2]
|
||||||
field_count_str = row[4]
|
field_type = row[3]
|
||||||
field_count = _resolve_field_count(field_count_str, vars_dict=parsed)
|
field_count_str = row[4]
|
||||||
if field_name == "tlvs":
|
field_count = _resolve_field_count(field_count_str, vars_dict=parsed)
|
||||||
tlv_stream_name = field_type
|
if field_name == "tlvs":
|
||||||
d = self.read_tlv_stream(fd=fd, tlv_stream_name=tlv_stream_name)
|
tlv_stream_name = field_type
|
||||||
parsed[tlv_stream_name] = d
|
d = self.read_tlv_stream(fd=fd, tlv_stream_name=tlv_stream_name)
|
||||||
continue
|
parsed[tlv_stream_name] = d
|
||||||
#print(f">> count={field_count}. parsed={parsed}")
|
continue
|
||||||
try:
|
#print(f">> count={field_count}. parsed={parsed}")
|
||||||
parsed[field_name] = _read_field(fd=fd,
|
try:
|
||||||
field_type=field_type,
|
parsed[field_name] = _read_field(fd=fd,
|
||||||
count=field_count)
|
field_type=field_type,
|
||||||
except UnexpectedEndOfStream as e:
|
count=field_count)
|
||||||
if len(row) > 5:
|
except UnexpectedEndOfStream as e:
|
||||||
break # optional feature field not present
|
if len(row) > 5:
|
||||||
else:
|
break # optional feature field not present
|
||||||
raise
|
else:
|
||||||
else:
|
raise
|
||||||
raise Exception(f"unexpected row in scheme: {row!r}")
|
else:
|
||||||
|
raise Exception(f"unexpected row in scheme: {row!r}")
|
||||||
|
except FailedToParseMsg as e:
|
||||||
|
e.msg_type_int = msg_type_int
|
||||||
|
e.msg_type_name = msg_type_name
|
||||||
|
raise
|
||||||
return msg_type_name, parsed
|
return msg_type_name, parsed
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ from .lnutil import (Outpoint, LocalConfig, RECEIVED, UpdateAddHtlc, ChannelConf
|
|||||||
ChannelType, LNProtocolWarning)
|
ChannelType, LNProtocolWarning)
|
||||||
from .lnutil import FeeUpdate, channel_id_from_funding_tx
|
from .lnutil import FeeUpdate, channel_id_from_funding_tx
|
||||||
from .lntransport import LNTransport, LNTransportBase
|
from .lntransport import LNTransport, LNTransportBase
|
||||||
from .lnmsg import encode_msg, decode_msg, UnknownOptionalMsgType
|
from .lnmsg import encode_msg, decode_msg, UnknownOptionalMsgType, FailedToParseMsg
|
||||||
from .interface import GracefulDisconnect
|
from .interface import GracefulDisconnect
|
||||||
from .lnrouter import fee_for_edge_msat
|
from .lnrouter import fee_for_edge_msat
|
||||||
from .lnutil import ln_dummy_address
|
from .lnutil import ln_dummy_address
|
||||||
@@ -194,12 +194,18 @@ class Peer(Logger):
|
|||||||
self.pong_event.clear()
|
self.pong_event.clear()
|
||||||
await self.pong_event.wait()
|
await self.pong_event.wait()
|
||||||
|
|
||||||
def process_message(self, message):
|
def process_message(self, message: bytes):
|
||||||
try:
|
try:
|
||||||
message_type, payload = decode_msg(message)
|
message_type, payload = decode_msg(message)
|
||||||
except UnknownOptionalMsgType as e:
|
except UnknownOptionalMsgType as e:
|
||||||
self.logger.info(f"received unknown message from peer. ignoring: {e!r}")
|
self.logger.info(f"received unknown message from peer. ignoring: {e!r}")
|
||||||
return
|
return
|
||||||
|
except FailedToParseMsg as e:
|
||||||
|
self.logger.info(
|
||||||
|
f"failed to parse message from peer. disconnecting. "
|
||||||
|
f"msg_type={e.msg_type_name}({e.msg_type_int}). exc={e!r}")
|
||||||
|
#self.logger.info(f"failed to parse message: message(SECRET?)={message.hex()}")
|
||||||
|
raise GracefulDisconnect() from e
|
||||||
self.last_message_time = time.time()
|
self.last_message_time = time.time()
|
||||||
if message_type not in self.SPAMMY_MESSAGES:
|
if message_type not in self.SPAMMY_MESSAGES:
|
||||||
self.logger.debug(f"Received {message_type.upper()}")
|
self.logger.debug(f"Received {message_type.upper()}")
|
||||||
|
|||||||
Reference in New Issue
Block a user