-
-
Notifications
You must be signed in to change notification settings - Fork 28
Description
Bug Description
Description
There is a structural inconsistency in how odd-length tree levels are handled between compute_merkle_root() and generate_merkle_proof(). While both functions produce correct results today, they use different strategies for padding odd nodes — meaning any future modification to one function without the other will cause proofs to silently fail against the root.
Additionally, the sibling index calculation uses a raw XOR (index ^ 1), which is only safe because of the pre-padding step above it. This is fragile and non-obvious.
Root Cause
| Function | Odd-node strategy |
|---|---|
compute_merkle_root() |
Inline: right = left if i+1 >= len(leaves) |
generate_merkle_proof() |
Pre-pads: leaves.append(leaves[-1]) |
The sibling calculation in generate_merkle_proof():
# Fragile — only safe due to pre-padding above
sibling_index = index ^ 1Expected Behaviour
Both functions should use the same, explicit odd-node strategy, and sibling index calculation should be self-evidently safe without relying on a prior mutation of the array.
Suggested Fix
Replace the XOR with an explicit parity check:
# In generate_merkle_proof()
sibling_index = index - 1 if index % 2 == 1 else index + 1
# Guard: ensure sibling doesn't exceed bounds (handles odd levels)
if sibling_index >= len(leaves):
sibling_index = index # duplicate selfAnd unify the padding strategy across both functions for long-term maintainability.
Impact
- Merkle proofs may silently fail if either function is modified independently
Medium - Feature works but has issues
Code of Conduct
- I have joined the Discord server and will post updates there
- I have searched existing issues to avoid duplicates