use super::proof_certificate::{ProofCertificate, Verified};
use blake3::Hasher;
pub const BLAKE3_DETERMINISTIC_CERT: ProofCertificate = ProofCertificate::new(
200, 1, 2026_0205, 0, );
pub const BLAKE3_NON_DEGENERATE_CERT: ProofCertificate = ProofCertificate::new(
201, 1, 2026_0205, 1, );
pub const BLAKE3_TREE_SOUNDNESS_CERT: ProofCertificate = ProofCertificate::new(
202, 1, 2026_0205, 1, );
pub const BLAKE3_PARALLEL_SOUNDNESS_CERT: ProofCertificate = ProofCertificate::new(
203, 1, 2026_0205, 1, );
pub const BLAKE3_INCREMENTAL_CERT: ProofCertificate = ProofCertificate::new(
204, 1, 2026_0205, 0, );
pub const BLAKE3_TREE_DETERMINISTIC_CERT: ProofCertificate = ProofCertificate::new(
205, 1, 2026_0205, 0, );
pub struct VerifiedBlake3;
impl VerifiedBlake3 {
pub fn hash(data: &[u8]) -> [u8; 32] {
let result: [u8; 32] = blake3::hash(data).into();
assert_ne!(
result, [0u8; 32],
"BLAKE3 produced all zeros (violation of non_degenerate theorem)"
);
result
}
pub fn new_hasher() -> VerifiedBlake3Hasher {
VerifiedBlake3Hasher {
inner: Hasher::new(),
}
}
}
pub struct VerifiedBlake3Hasher {
inner: Hasher,
}
impl VerifiedBlake3Hasher {
pub fn update(&mut self, data: &[u8]) {
self.inner.update(data);
}
pub fn finalize(&self) -> [u8; 32] {
let result: [u8; 32] = self.inner.finalize().into();
assert_ne!(result, [0u8; 32]);
result
}
}
impl Verified for VerifiedBlake3 {
fn proof_certificate() -> ProofCertificate {
BLAKE3_DETERMINISTIC_CERT
}
fn theorem_name() -> &'static str {
"blake3_deterministic"
}
fn theorem_description() -> &'static str {
"BLAKE3 is deterministic: hashing the same input always produces the same output"
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_blake3_deterministic() {
let data = b"test data";
let hash1 = VerifiedBlake3::hash(data);
let hash2 = VerifiedBlake3::hash(data);
assert_eq!(hash1, hash2);
}
#[test]
fn test_blake3_non_degenerate() {
let data = b"any data";
let hash = VerifiedBlake3::hash(data);
assert_ne!(hash, [0u8; 32]);
}
#[test]
fn test_blake3_different_inputs_different_outputs() {
let hash1 = VerifiedBlake3::hash(b"data1");
let hash2 = VerifiedBlake3::hash(b"data2");
assert_ne!(hash1, hash2);
}
#[test]
fn test_incremental_matches_oneshot() {
let data = b"hello world from blake3";
let oneshot = VerifiedBlake3::hash(data);
let mut hasher = VerifiedBlake3::new_hasher();
hasher.update(data);
let incremental = hasher.finalize();
assert_eq!(oneshot, incremental);
}
#[test]
fn test_incremental_chunked() {
let data = b"hello world from blake3";
let oneshot = VerifiedBlake3::hash(data);
let mut hasher = VerifiedBlake3::new_hasher();
hasher.update(b"hello ");
hasher.update(b"world ");
hasher.update(b"from ");
hasher.update(b"blake3");
let incremental = hasher.finalize();
assert_eq!(oneshot, incremental);
}
#[test]
fn test_empty_input() {
let hash = VerifiedBlake3::hash(b"");
assert_ne!(hash, [0u8; 32]);
let hash2 = VerifiedBlake3::hash(b"");
assert_eq!(hash, hash2);
}
#[test]
fn test_proof_certificate() {
let cert = VerifiedBlake3::proof_certificate();
assert_eq!(cert.theorem_id, 200);
assert_eq!(cert.proof_system_id, 1);
assert_eq!(cert.verified_at, 20_260_205);
assert_eq!(cert.assumption_count, 0);
assert!(cert.is_complete());
}
#[test]
fn test_verified_trait() {
assert_eq!(VerifiedBlake3::theorem_name(), "blake3_deterministic");
assert!(VerifiedBlake3::theorem_description().contains("deterministic"));
}
#[test]
fn test_matches_existing_implementation() {
let data = b"test compatibility";
let verified_hash = VerifiedBlake3::hash(data);
let direct_hash: [u8; 32] = blake3::hash(data).into();
assert_eq!(verified_hash, direct_hash);
}
#[test]
fn test_large_input() {
let data = vec![0xAB; 1024 * 1024]; let hash = VerifiedBlake3::hash(&data);
assert_ne!(hash, [0u8; 32]);
let hash2 = VerifiedBlake3::hash(&data);
assert_eq!(hash, hash2);
}
#[test]
fn test_parallelization_soundness() {
let large_data = vec![0x42; 100_000];
let hash1 = VerifiedBlake3::hash(&large_data);
let hash2 = VerifiedBlake3::hash(&large_data);
assert_eq!(hash1, hash2);
}
}
#[cfg(test)]
mod proptests {
use super::*;
use proptest::prelude::*;
proptest! {
#[test]
fn prop_blake3_deterministic(data in prop::collection::vec(any::<u8>(), 0..10000)) {
let hash1 = VerifiedBlake3::hash(&data);
let hash2 = VerifiedBlake3::hash(&data);
prop_assert_eq!(hash1, hash2);
}
#[test]
fn prop_different_inputs_different_hashes(
data1 in prop::collection::vec(any::<u8>(), 1..1000),
data2 in prop::collection::vec(any::<u8>(), 1..1000)
) {
prop_assume!(data1 != data2);
let hash1 = VerifiedBlake3::hash(&data1);
let hash2 = VerifiedBlake3::hash(&data2);
prop_assert_ne!(hash1, hash2);
}
#[test]
fn prop_blake3_non_degenerate(data in prop::collection::vec(any::<u8>(), 0..10000)) {
let hash = VerifiedBlake3::hash(&data);
prop_assert_ne!(hash, [0u8; 32]);
}
#[test]
fn prop_incremental_matches_oneshot(data in prop::collection::vec(any::<u8>(), 0..10000)) {
let oneshot = VerifiedBlake3::hash(&data);
let mut hasher = VerifiedBlake3::new_hasher();
hasher.update(&data);
let incremental = hasher.finalize();
prop_assert_eq!(oneshot, incremental);
}
#[test]
fn prop_incremental_chunked_matches_oneshot(
chunks in prop::collection::vec(
prop::collection::vec(any::<u8>(), 0..100),
1..10
)
) {
let data: Vec<u8> = chunks.iter().flatten().copied().collect();
let oneshot = VerifiedBlake3::hash(&data);
let mut hasher = VerifiedBlake3::new_hasher();
for chunk in &chunks {
hasher.update(chunk);
}
let incremental = hasher.finalize();
prop_assert_eq!(oneshot, incremental);
}
#[test]
fn prop_tree_construction_deterministic(data in prop::collection::vec(any::<u8>(), 0..100_000)) {
let hash1 = VerifiedBlake3::hash(&data);
let hash2 = VerifiedBlake3::hash(&data);
prop_assert_eq!(hash1, hash2);
}
}
}
#[cfg(kani)]
mod kani_harness {
use super::VerifiedBlake3;
#[kani::proof]
#[kani::unwind(4)]
fn verify_blake3_hash_determinism() {
let b0: u8 = kani::any();
let b1: u8 = kani::any();
let data = [b0, b1];
let h1 = VerifiedBlake3::hash(&data);
let h2 = VerifiedBlake3::hash(&data);
assert_eq!(h1, h2, "VerifiedBlake3::hash must be deterministic");
}
}