Update app.py
Browse files
app.py
CHANGED
|
@@ -313,17 +313,15 @@ def merkle_root_and_proofs(leaves: List[bytes]) -> Tuple[bytes, List[List[Dict[s
|
|
| 313 |
- "L" means sibling was on the left (sib || cur)
|
| 314 |
- "R" means sibling was on the right (cur || sib)
|
| 315 |
|
| 316 |
-
|
|
|
|
| 317 |
"""
|
| 318 |
n = len(leaves)
|
| 319 |
if n == 0:
|
| 320 |
return _h(b"\x00"), []
|
| 321 |
|
| 322 |
-
# initial leaf hashes
|
| 323 |
level_hashes = [merkle_leaf(x) for x in leaves]
|
| 324 |
proofs: List[List[Dict[str, str]]] = [[] for _ in range(n)]
|
| 325 |
-
|
| 326 |
-
# track which original leaf indices are covered by each node
|
| 327 |
level_sets: List[List[int]] = [[i] for i in range(n)]
|
| 328 |
|
| 329 |
while len(level_hashes) > 1:
|
|
@@ -338,23 +336,30 @@ def merkle_root_and_proofs(leaves: List[bytes]) -> Tuple[bytes, List[List[Dict[s
|
|
| 338 |
if j + 1 < len(level_hashes):
|
| 339 |
right = level_hashes[j + 1]
|
| 340 |
right_set = level_sets[j + 1]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 341 |
else:
|
| 342 |
-
# duplicate last node
|
| 343 |
-
|
| 344 |
-
|
| 345 |
-
|
| 346 |
-
|
| 347 |
-
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
|
| 351 |
-
proofs[idx].append({"dir": "R", "hash_hex": right_hex})
|
| 352 |
-
for idx in right_set:
|
| 353 |
-
proofs[idx].append({"dir": "L", "hash_hex": left_hex})
|
| 354 |
-
|
| 355 |
-
parent = merkle_node(left, right)
|
| 356 |
-
next_hashes.append(parent)
|
| 357 |
-
next_sets.append(left_set + right_set)
|
| 358 |
|
| 359 |
j += 2
|
| 360 |
|
|
|
|
| 313 |
- "L" means sibling was on the left (sib || cur)
|
| 314 |
- "R" means sibling was on the right (cur || sib)
|
| 315 |
|
| 316 |
+
Odd leaf counts are handled by duplicating the last node.
|
| 317 |
+
IMPORTANT: duplicated nodes add exactly ONE proof step (not two).
|
| 318 |
"""
|
| 319 |
n = len(leaves)
|
| 320 |
if n == 0:
|
| 321 |
return _h(b"\x00"), []
|
| 322 |
|
|
|
|
| 323 |
level_hashes = [merkle_leaf(x) for x in leaves]
|
| 324 |
proofs: List[List[Dict[str, str]]] = [[] for _ in range(n)]
|
|
|
|
|
|
|
| 325 |
level_sets: List[List[int]] = [[i] for i in range(n)]
|
| 326 |
|
| 327 |
while len(level_hashes) > 1:
|
|
|
|
| 336 |
if j + 1 < len(level_hashes):
|
| 337 |
right = level_hashes[j + 1]
|
| 338 |
right_set = level_sets[j + 1]
|
| 339 |
+
|
| 340 |
+
# normal pair: add sibling to each side
|
| 341 |
+
right_hex = right.hex()
|
| 342 |
+
left_hex = left.hex()
|
| 343 |
+
|
| 344 |
+
for idx in left_set:
|
| 345 |
+
proofs[idx].append({"dir": "R", "hash_hex": right_hex})
|
| 346 |
+
for idx in right_set:
|
| 347 |
+
proofs[idx].append({"dir": "L", "hash_hex": left_hex})
|
| 348 |
+
|
| 349 |
+
parent = merkle_node(left, right)
|
| 350 |
+
next_hashes.append(parent)
|
| 351 |
+
next_sets.append(left_set + right_set)
|
| 352 |
+
|
| 353 |
else:
|
| 354 |
+
# odd leaf: duplicate last node
|
| 355 |
+
# add exactly ONE step: sibling is itself
|
| 356 |
+
left_hex = left.hex()
|
| 357 |
+
for idx in left_set:
|
| 358 |
+
proofs[idx].append({"dir": "R", "hash_hex": left_hex})
|
| 359 |
+
|
| 360 |
+
parent = merkle_node(left, left)
|
| 361 |
+
next_hashes.append(parent)
|
| 362 |
+
next_sets.append(left_set)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 363 |
|
| 364 |
j += 2
|
| 365 |
|