-
Notifications
You must be signed in to change notification settings - Fork 1
Fix decoding of principal #5
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
base: master
Are you sure you want to change the base?
Fix decoding of principal #5
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| res = safeReadByte(b) | ||
| if leb128.u.decode(res) != 1: | ||
| raise ValueError("Cannot decode principal") | ||
| length = leb128uDecode(b) | ||
| raw = safeRead(b, length) | ||
| if raw == b"\x00": | ||
| return P.from_str("aaaaa-aa") | ||
| return P.from_hex(raw.hex()) | ||
| return P.from_hex(safeRead(b, length).hex()) |
Copilot
AI
Nov 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The updated decodeValue method expects a flag byte (value 1) before the length, but the corresponding encodeValue method (lines 844-855) does not write this flag byte. This creates an encode/decode incompatibility.
The current encoder produces:
- For 'aaaaa-aa': "0100" (length=1, data=0x00)
- For a 29-byte principal: "1d" + 29 bytes (length=29, data=29 bytes)
The new decoder interprets:
- For 'aaaaa-aa': "0100" as flag=1 ✓, length=0, data= → this works by coincidence
- For a 29-byte principal: "1d..." as flag=29 ✗ → this fails the check on line 863
The encoder should be updated to write a flag byte:
def encodeValue(self, val) -> bytes:
if isinstance(val, str):
buf = P.from_str(val).bytes
elif isinstance(val, bytes):
buf = val
else:
raise ValueError("Principal should be string or bytes.")
flag = b"\x01"
length = leb128.u.encode(len(buf))
return flag + length + bufNote: This would change the encoded format and break compatibility with data encoded by the old encoder. The test_principal_encode test would also need updating.
| if leb128.u.decode(res) != 1: | ||
| raise ValueError("Cannot decode principal") |
Copilot
AI
Nov 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message "Cannot decode principal" doesn't indicate what went wrong. Consider making it more descriptive to help with debugging:
raise ValueError(f"Invalid principal flag byte: expected 1, got {leb128.u.decode(res)}")This would make it clearer when the decoder encounters incorrectly formatted principal data.
| if leb128.u.decode(res) != 1: | |
| raise ValueError("Cannot decode principal") | |
| val = leb128.u.decode(res) | |
| if val != 1: | |
| raise ValueError(f"Invalid principal flag byte: expected 1, got {val}") |
Fix for #4
I included an additional test in tests/test_candid.py,
test_principal_decode_2that demonstrates the bug & the fix.