Skip to main content

roder_code_index/
proofs.rs

1use roder_api::code_index::{CodeChunk, ContentProof, MerkleHash};
2
3pub fn proof_for_chunk(
4    workspace_root_hash: impl Into<MerkleHash>,
5    generation_id: impl Into<String>,
6    chunk: &CodeChunk,
7) -> ContentProof {
8    ContentProof {
9        path_hash: chunk.path_hash.clone(),
10        content_hash: chunk.content_hash.clone(),
11        workspace_root_hash: workspace_root_hash.into(),
12        generation_id: generation_id.into(),
13    }
14}
15
16pub fn verify_chunk_proof(
17    proof: &ContentProof,
18    expected_workspace_root_hash: &str,
19    chunk: &CodeChunk,
20) -> bool {
21    proof.workspace_root_hash == expected_workspace_root_hash
22        && proof.path_hash == chunk.path_hash
23        && proof.content_hash == chunk.content_hash
24}
25
26#[cfg(test)]
27mod tests {
28    use std::path::PathBuf;
29
30    use roder_api::code_index::{CodeByteRange, CodeLineRange};
31
32    use super::*;
33
34    #[test]
35    fn proofs_verify_chunk_possession() {
36        let chunk = CodeChunk {
37            chunk_hash: "chunk".to_string(),
38            path: PathBuf::from("src/lib.rs"),
39            path_hash: "path".to_string(),
40            byte_range: CodeByteRange { start: 0, end: 10 },
41            line_range: CodeLineRange { start: 1, end: 1 },
42            content_hash: "content".to_string(),
43            language: Some("rust".to_string()),
44            symbol_hint: Some("lib".to_string()),
45        };
46        let proof = proof_for_chunk("root", "gen", &chunk);
47
48        assert!(verify_chunk_proof(&proof, "root", &chunk));
49
50        let mut mismatched = chunk.clone();
51        mismatched.content_hash = "other".to_string();
52        assert!(!verify_chunk_proof(&proof, "root", &mismatched));
53    }
54}