build(agent): jabba#56a767 iteration
This commit is contained in:
parent
77f5b06711
commit
45bc190445
|
|
@ -98,17 +98,34 @@ def verify_inclusion(chain_head_hash: str, proof_hashes: List[str], chain_map: O
|
||||||
if chain_map is None:
|
if chain_map is None:
|
||||||
# best-effort: we have only hashes; accept if tip matches
|
# best-effort: we have only hashes; accept if tip matches
|
||||||
return True
|
return True
|
||||||
# verify backward links using chain_map
|
# verify forward links using chain_map
|
||||||
# proof_hashes = [h_target, h_next, ..., h_head]
|
# proof_hashes = [h_target, h_next, ..., h_head]
|
||||||
|
# For each adjacent pair, the later entry's prev_hash must equal the
|
||||||
|
# earlier entry's hash. We consult chain_map which maps hash->entry.
|
||||||
for i in range(len(proof_hashes) - 1):
|
for i in range(len(proof_hashes) - 1):
|
||||||
h = proof_hashes[i]
|
h_curr = proof_hashes[i]
|
||||||
next_h = proof_hashes[i + 1]
|
h_next = proof_hashes[i + 1]
|
||||||
entry = chain_map.get(h)
|
# ensure the provided map contains the entry and that the entry's
|
||||||
if entry is None:
|
# recorded hash matches the canonical hash of its payload. This
|
||||||
|
# prevents silent tampering where prev_hash is changed but hash left
|
||||||
|
# un-updated.
|
||||||
|
next_entry = chain_map.get(h_next)
|
||||||
|
if next_entry is None:
|
||||||
|
return False
|
||||||
|
# recompute the entry hash and ensure it matches the expected key
|
||||||
|
try:
|
||||||
|
# debug: show object id
|
||||||
|
# print(f"verify_inclusion: next_entry id={id(next_entry)}")
|
||||||
|
recomputed = _entry_hash(next_entry)
|
||||||
|
except Exception:
|
||||||
|
print(f"verify_inclusion: failed to recompute hash for {h_next}")
|
||||||
|
return False
|
||||||
|
if recomputed != h_next:
|
||||||
|
return False
|
||||||
|
# next_entry.prev_hash should point to current hash
|
||||||
|
prev = next_entry.get("prev_hash", "")
|
||||||
|
# debug print
|
||||||
|
# print(f"verify link: next={h_next} prev={prev} expected={h_curr}")
|
||||||
|
if prev != h_curr:
|
||||||
return False
|
return False
|
||||||
if entry.get("prev_hash", "") != (chain_map.get(next_h, {}).get("prev_hash", entry.get("prev_hash", "")) and None):
|
|
||||||
# We cannot reliably reconstruct prev pointers from hashes alone
|
|
||||||
# so this strict check is left as a placeholder. For now we require
|
|
||||||
# that next hash exists in the map (sanity) and tip matches.
|
|
||||||
pass
|
|
||||||
return True
|
return True
|
||||||
|
|
|
||||||
|
|
@ -23,3 +23,18 @@ def test_inclusion_proof_and_head():
|
||||||
assert proof[-1] == head
|
assert proof[-1] == head
|
||||||
# verify inclusion using head-only verification (best-effort)
|
# verify inclusion using head-only verification (best-effort)
|
||||||
assert verify_inclusion(head, proof)
|
assert verify_inclusion(head, proof)
|
||||||
|
|
||||||
|
|
||||||
|
def test_verify_inclusion_with_chain_map():
|
||||||
|
ops = [("opA", "X"), ("opB", "Y"), ("opC", "Z")]
|
||||||
|
chain = build_chain(ops)
|
||||||
|
head = head_hash(chain)
|
||||||
|
target = chain[0]
|
||||||
|
proof = inclusion_proof(chain, target_entry_id=target["entry_id"])
|
||||||
|
# build chain_map: hash -> entry
|
||||||
|
chain_map = {e["hash"]: e for e in chain}
|
||||||
|
# verification should succeed when supplying chain_map
|
||||||
|
assert verify_inclusion(head, proof, chain_map=chain_map)
|
||||||
|
# build a clean chain_map and verify inclusion with the map provided
|
||||||
|
chain_map = {e["hash"]: e for e in chain}
|
||||||
|
assert verify_inclusion(head, proof, chain_map=chain_map)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue