Skip to content

Improve Error Message Readability in Lightning Protocol Tests #140

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

arnav-makkar
Copy link

@arnav-makkar arnav-makkar commented Apr 14, 2025

Improve Error Message Readability in Lightning Protocol Tests

Fixes #43

This PR enhances the error message handling in the Lightning Network protocol testing framework by automatically decoding hex-encoded error messages into human-readable text.

Problem

When testing Lightning Network protocol implementations, error messages often contain hex-encoded data that is difficult to read and interpret. For example, an error message about an unknown channel would appear as:

Expected msgtype-shutdown, got msgtype-error: message was error channel_id=a37362839b13f61cfe82d35bd397b1264c389b245847cfb6111b38892546dc77 data=556e6b6e6f776e206368616e6e656c20666f7220574952455f53485554444f574e

The hex data 556e6b6e6f776e206368616e6e656c20666f7220574952455f53485554444f574e is actually the ASCII/UTF-8 encoded string "Unknown channel for WIRE_SHUTDOWN", but this is not immediately obvious to developers.

Solution

Automatic hex data decoding has been added to the error handling system:

  1. Added a new decode_hex_data method in errors.py that:

    • Attempts to decode hex data into ASCII/UTF-8 text
    • Validates that the decoded text is readable (contains only ASCII characters)
    • Handles cases where decoding fails
  2. Enhanced the EventError.__str__ method to:

    • Automatically detect hex data in error messages
    • Decode and append the human-readable text
    • Preserve the original hex data for debugging

Expected Error Message Format

After these changes, the same error message will now appear as:

Expected msgtype-shutdown, got msgtype-error: message was error channel_id=a37362839b13f61cfe82d35bd397b1264c389b245847cfb6111b38892546dc77 data=556e6b6e6f776e206368616e6e656c20666f7220574952455f53485554444f574e (decoded: Unknown channel for WIRE_SHUTDOWN)

Implementation Details

The solution:

  • Uses Python's built-in bytes.fromhex() and decode() methods
  • Validates decoded text to ensure it's readable
  • Preserves the original error message structure
  • Adds decoded text as additional context
  • Handles edge cases and invalid hex data robustly

Testing

The changes have been tested with:

  • Valid hex-encoded error messages
  • Invalid hex data
  • Non-ASCII hex data
  • Various error message formats

The existing test suite continues to pass, and the error messages are now more informative.

@vincenzopalazzo vincenzopalazzo self-assigned this Apr 15, 2025
@arnav-makkar
Copy link
Author

I wasn’t aware of the Black style formatting requirement earlier — I’ve updated the code accordingly now, so the tests should pass. Thanks!

@arnav-makkar
Copy link
Author

@vincenzopalazzo I noticed that the test test_bolt1-01-init.py::test_init_is_first_msg is now failing with a FileNotFoundError, even though it passed earlier when the formatting wasn't yet corrected.

Since the changes in this PR are limited to formatting and improving error message readability, the error could possibly be related to temporary file handling or timing.

All other tests are passing consistently. Please let me know if you'd like me to look into this further or if there's anything else you'd like me to adjust.

@vincenzopalazzo
Copy link
Collaborator

Probably @Psycho-Pirate know more about it

DEBUG    lnprototest.runner:ldk_runner.py:138 RUN Bitcoind
DEBUG    lnprototest.runner:ldk_runner.py:169 ldk dir /tmp/lnpt-cl-hhvyyf5b/ldk
DEBUG    lnprototest.runner:ldk_runner.py:174 Node id : 027f921585f2ac0c7c70e36110adecfd8fd14b8a99bfb3d000a283fcac358fce88
DEBUG    lnprototest.runner:ldk_runner.py:175 RUN LDK
INFO     root:event.py:59 # running {'event': 'Sequence', 'file': 'runner.py', 'pos': '97'}:
DEBUG    root:structure.py:49 receiving event {"event": "Connect", "file": "test_bolt1-01-init.py", "pos": "182"}
INFO     root:event.py:59 # running {'event': 'Connect', 'file': 'test_bolt1-01-init.py', 'pos': '182'}:
DEBUG    lnprototest.runner:ldk_runner.py:186 [STOP]
DEBUG    root:bitcoind.py:39 Calling stop with arguments ()
DEBUG    root:bitcoind.py:43 Result for stop call: Bitcoin Core stopping
=========================== short test summary info ============================
FAILED tests/test_bolt1-01-init.py::test_init_is_first_msg - FileNotFoundErro...
================== 1 failed, 29 passed, 17 skipped in 45.45s ===================
make: *** [Makefile:14: check] Error 1
iteration range1 failed

Copy link
Collaborator

@vincenzopalazzo vincenzopalazzo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this!

Commit 751b5f8 need to be squash inside the previous because unrelated to the git history, see https://stackoverflow.com/a/5201642/10854225 on how to squash.

if all(ord(c) < 128 for c in decoded):
return f" (decoded: {decoded})"
except (ValueError, UnicodeDecodeError):
pass
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really dangerous, please do not try to shoot yourself in the foot when you do not need it, we are already using Python.

return f" (decoded: {decoded})"
except (ValueError, UnicodeDecodeError):
pass
return ""
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not understanding whe need to return an empty string here, can you explainit to me?

Comment on lines +379 to +380
if hasattr(msg, "fields"):
error_msg += f": {msg.to_str()}"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not understand why we are checking the fields here, can you expand more on this part too?

@Psycho-Pirate
Copy link
Contributor

It looks like the CI is failing because poetry tries to uninstall a pre-installed version of blinker (1.4), which was installed using distutils. We can probably create a good first issue for this. @vincenzopalazzo

@vincenzopalazzo
Copy link
Collaborator

I think the cln error is unrelated to this message #140 (comment)

The error is inside the comment itself and was happening in the ldk runner

@Psycho-Pirate
Copy link
Contributor

I think the cln error is unrelated to this message #140 (comment)

The error is inside the comment itself and was happening in the ldk runner

Where is it happening? in the old commits as well the LDK CI ran successfully.

@vincenzopalazzo
Copy link
Collaborator

Where is it happening? in the old commits as well the LDK CI ran successfully.

it was happening inside the CI, then I restarted and not it is green, but it is something that we need to to make sure that we are not ignoring a bug

@arnav-makkar
Copy link
Author

It looks like the CI is failing because poetry tries to uninstall a pre-installed version of blinker (1.4), which was installed using distutils. We can probably create a good first issue for this. @/vincenzopalazzo

@Psycho-Pirate I’ve opened PR #141 to address this issue by removing the system-installed blinker before running poetry install.
Please take a look when you get a chance. Thanks!

@vincenzopalazzo
Copy link
Collaborator

@arnav-makkar left some questions in the review, please focus on the code and not the CI, the CI is broken anyway with core lightning if you see #135

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

improve error printing
3 participants