tests/test_proof.py
1.9 KB · 63 lines · python Raw
1 """Tests for ReasoningProver inclusion proofs."""
2
3 from __future__ import annotations
4
5 import pytest
6
7 from pqc_reasoning_ledger import (
8 ReasoningProver,
9 ReasoningRecorder,
10 StepNotFoundError,
11 )
12
13
14 def _build_sealed(recorder: ReasoningRecorder):
15 recorder.record_observation("step 1")
16 recorder.record_hypothesis("step 2")
17 recorder.record_deduction("step 3")
18 recorder.record_self_critique("step 4")
19 recorder.record_decision("step 5")
20 return recorder.seal()
21
22
23 def test_prove_step_existing_returns_proof(
24 sample_trace_started: ReasoningRecorder,
25 ) -> None:
26 sealed = _build_sealed(sample_trace_started)
27 target = sealed.steps[2]
28 proof = ReasoningProver.prove_step(sealed, target.step_id)
29 assert proof.step.step_id == target.step_id
30 assert proof.trace_id == sealed.metadata.trace_id
31 assert proof.merkle_root == sealed.merkle_root
32 assert proof.proof.index == 2
33 assert proof.proof.leaf_hash == target.step_hash
34
35
36 def test_verify_proof_passes(
37 sample_trace_started: ReasoningRecorder,
38 ) -> None:
39 sealed = _build_sealed(sample_trace_started)
40 for idx in range(len(sealed.steps)):
41 target = sealed.steps[idx]
42 proof = ReasoningProver.prove_step(sealed, target.step_id)
43 assert ReasoningProver.verify_proof(proof) is True
44
45
46 def test_prove_step_missing_raises(
47 sample_trace_started: ReasoningRecorder,
48 ) -> None:
49 sealed = _build_sealed(sample_trace_started)
50 with pytest.raises(StepNotFoundError):
51 ReasoningProver.prove_step(sealed, "urn:pqc-step:does-not-exist")
52
53
54 def test_verify_proof_fails_on_tampered_step(
55 sample_trace_started: ReasoningRecorder,
56 ) -> None:
57 sealed = _build_sealed(sample_trace_started)
58 target = sealed.steps[1]
59 proof = ReasoningProver.prove_step(sealed, target.step_id)
60 # Tamper the step's step_hash on the proof so it disagrees with proof.leaf_hash
61 proof.step.step_hash = "0" * 64
62 assert ReasoningProver.verify_proof(proof) is False
63