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:
|
||||
# best-effort: we have only hashes; accept if tip matches
|
||||
return True
|
||||
# verify backward links using chain_map
|
||||
# verify forward links using chain_map
|
||||
# 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):
|
||||
h = proof_hashes[i]
|
||||
next_h = proof_hashes[i + 1]
|
||||
entry = chain_map.get(h)
|
||||
if entry is None:
|
||||
h_curr = proof_hashes[i]
|
||||
h_next = proof_hashes[i + 1]
|
||||
# ensure the provided map contains the entry and that the entry's
|
||||
# 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
|
||||
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
|
||||
|
|
|
|||
|
|
@ -23,3 +23,18 @@ def test_inclusion_proof_and_head():
|
|||
assert proof[-1] == head
|
||||
# verify inclusion using head-only verification (best-effort)
|
||||
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