use crate::{Frame, Sqs, QfeError, PatternType, Sha512Hash};
use crate::{PHI, RESONANCE_FREQ};
use std::hash::{Hash, Hasher};
use std::collections::hash_map::DefaultHasher;
use sha2::{Sha512, Digest};
use rand::RngCore;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ZkpChallenge {
pub value: Vec<u8>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ZkpValidityResponse {
pub validity_proof_hash: Sha512Hash, }
pub fn establish_zkp_sqs(
prover_id: &str,
verifier_id: &str,
public_statement: &[u8],
context_string: &str,
) -> Result<Sqs, QfeError> {
let mut components_hasher = Sha512::new();
components_hasher.update(b"QFE_ZKP_SQS_COMPONENTS_V1");
components_hasher.update(prover_id.as_bytes());
components_hasher.update(verifier_id.as_bytes());
components_hasher.update(public_statement);
components_hasher.update(context_string.as_bytes());
components_hasher.update(PHI.to_le_bytes());
components_hasher.update(RESONANCE_FREQ.to_le_bytes());
let sqs_components: Vec<u8> = components_hasher.finalize().to_vec();
let mut phase_hasher = DefaultHasher::new();
b"QFE_ZKP_SQS_PHASE_V1".hash(&mut phase_hasher);
prover_id.as_bytes().hash(&mut phase_hasher);
verifier_id.as_bytes().hash(&mut phase_hasher);
public_statement.hash(&mut phase_hasher);
context_string.as_bytes().hash(&mut phase_hasher);
PHI.to_bits().hash(&mut phase_hasher);
RESONANCE_FREQ.to_bits().hash(&mut phase_hasher);
let phase_hash_output = phase_hasher.finish();
let shared_phase_lock = (phase_hash_output as f64 / u64::MAX as f64) * 2.0 * std::f64::consts::PI;
let sqs = Sqs {
pattern_type: PatternType::Sqs,
components: sqs_components,
shared_phase_lock,
resonance_freq: RESONANCE_FREQ,
validation: true, };
if sqs.components.len() != 64 {
return Err(QfeError::InternalError(format!(
"Derived ZKP SQS components have unexpected length: {}", sqs.components.len()
)));
}
Ok(sqs)
}
pub fn generate_zkp_challenge(challenge_len: usize) -> ZkpChallenge {
let mut challenge_value = vec![0u8; challenge_len];
rand::rng().fill_bytes(&mut challenge_value);
ZkpChallenge { value: challenge_value }
}
impl Frame {
pub fn store_zkp_witness(&mut self, witness: &[u8]) -> Result<(), QfeError> {
if !self.is_valid() { return Err(QfeError::FrameInvalid); }
self.zkp_witness = Some(witness.to_vec());
Ok(())
}
pub fn generate_validity_proof(
&self,
challenge: &ZkpChallenge,
zkp_sqs: &Sqs,
public_statement_h_public: &[u8],
) -> Result<ZkpValidityResponse, QfeError> {
if !self.is_valid() { return Err(QfeError::FrameInvalid); }
if !zkp_sqs.validation { return Err(QfeError::InternalError("Invalid ZKP SQS provided for proof".to_string())); }
let witness_w = self.zkp_witness.as_ref().ok_or_else(|| QfeError::InternalError("ZKP witness not set for proof generation".to_string()))?;
let calculated_hash_of_w: Sha512Hash = Sha512::digest(witness_w).into();
let is_valid_witness: bool = calculated_hash_of_w.as_slice() == public_statement_h_public;
let mut response_hasher = Sha512::new();
response_hasher.update(b"QFE_ZKP_VALIDITY_PROOF_V1"); response_hasher.update(&challenge.value);
response_hasher.update([is_valid_witness as u8]); response_hasher.update(&zkp_sqs.components);
response_hasher.update(zkp_sqs.shared_phase_lock.to_le_bytes());
response_hasher.update(PHI.to_le_bytes());
response_hasher.update(RESONANCE_FREQ.to_le_bytes());
let proof_hash: Sha512Hash = response_hasher.finalize().into();
Ok(ZkpValidityResponse { validity_proof_hash: proof_hash })
}
pub fn verify_validity_proof(
&mut self, challenge: &ZkpChallenge,
response: &ZkpValidityResponse,
zkp_sqs: &Sqs,
_public_statement_h_public: &[u8],
) -> Result<(), QfeError> {
if !self.is_valid() { return Err(QfeError::FrameInvalid); }
if !zkp_sqs.validation { return Err(QfeError::InternalError("Invalid ZKP SQS provided for verification".to_string())); }
let expected_hash = {
let mut response_hasher = Sha512::new();
response_hasher.update(b"QFE_ZKP_VALIDITY_PROOF_V1"); response_hasher.update(&challenge.value);
response_hasher.update([true as u8]); response_hasher.update(&zkp_sqs.components);
response_hasher.update(zkp_sqs.shared_phase_lock.to_le_bytes());
response_hasher.update(PHI.to_le_bytes());
response_hasher.update(RESONANCE_FREQ.to_le_bytes());
let hash: Sha512Hash = response_hasher.finalize().into();
hash
};
if response.validity_proof_hash != expected_hash {
self.validation_status = false; return Err(QfeError::DecodingFailed(
"ZKP Validity Proof Check Failed".to_string()
));
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*; use crate::{Frame}; use sha2::{Sha512, Digest};
#[allow(dead_code)]
struct SimpleZkpTestData {
prover: Frame,
verifier: Frame,
zkp_sqs: Sqs,
witness: Vec<u8>,
h_public: Sha512Hash, context: String,
}
fn setup_simple_zkp_test() -> SimpleZkpTestData {
let mut prover = Frame::initialize("ValidityProver".to_string(), 20250404);
let verifier = Frame::initialize("ValidityVerifier".to_string(), 20250404);
let witness = b"a_valid_witness_for_simple_zkp".to_vec();
let h_public: Sha512Hash = Sha512::digest(&witness).into(); prover.store_zkp_witness(&witness).expect("Failed to store witness");
let context = "simple_validity_test_v1".to_string();
let zkp_sqs = establish_zkp_sqs(
prover.id(),
verifier.id(),
&h_public, &context,
).expect("Failed to establish ZKP SQS");
let zkp_sqs_clone = zkp_sqs.clone();
SimpleZkpTestData {
prover,
verifier,
zkp_sqs: zkp_sqs_clone,
witness,
h_public,
context,
}
}
#[test]
fn test_simple_zkp_successful_proof() {
let test_data = setup_simple_zkp_test();
let prover = test_data.prover;
let mut verifier = test_data.verifier; let zkp_sqs = test_data.zkp_sqs;
let h_public = test_data.h_public;
let challenge = generate_zkp_challenge(32);
let response = prover.generate_validity_proof(
&challenge,
&zkp_sqs,
&h_public,
).expect("Prover failed to generate validity proof");
let verification_result = verifier.verify_validity_proof(
&challenge,
&response,
&zkp_sqs,
&h_public, );
assert!(verification_result.is_ok(), "Verification failed unexpectedly: {:?}", verification_result.err());
assert!(verifier.is_valid(), "Verifier should remain valid after successful verification");
}
#[test]
fn test_simple_zkp_invalid_witness() {
let test_data = setup_simple_zkp_test();
let mut prover = test_data.prover; let mut verifier = test_data.verifier;
let zkp_sqs = test_data.zkp_sqs;
let h_public = test_data.h_public;
let wrong_witness = b"this_is_the_wrong_witness".to_vec();
prover.store_zkp_witness(&wrong_witness).expect("Storing wrong witness failed");
let challenge = generate_zkp_challenge(32);
let response = prover.generate_validity_proof(
&challenge,
&zkp_sqs,
&h_public, ).expect("Prover failed proof generation (using wrong witness)");
let verification_result = verifier.verify_validity_proof(
&challenge,
&response,
&zkp_sqs,
&h_public,
);
assert!(verification_result.is_err(), "Verification should fail for invalid witness");
let err = verification_result.unwrap_err();
assert!(matches!(err, QfeError::DecodingFailed(_)), "Expected DecodingFailed, got {:?}", err);
if let QfeError::DecodingFailed(msg) = err {
assert!(msg.contains("Validity Proof Check Failed"), "Expected Validity Proof failure message, got: {}", msg);
}
assert!(!verifier.is_valid(), "Verifier should become invalid after failed verification");
}
#[test]
fn test_simple_zkp_tampered_response_hash() {
let test_data = setup_simple_zkp_test();
let prover = test_data.prover;
let mut verifier = test_data.verifier;
let zkp_sqs = test_data.zkp_sqs;
let h_public = test_data.h_public;
let challenge = generate_zkp_challenge(32);
let mut response = prover.generate_validity_proof(&challenge, &zkp_sqs, &h_public)
.expect("Prover failed proof generation");
response.validity_proof_hash[0] ^= 0xAA;
let verification_result = verifier.verify_validity_proof(
&challenge,
&response, &zkp_sqs,
&h_public,
);
assert!(verification_result.is_err(), "Verification should fail for tampered validity proof hash");
let err = verification_result.unwrap_err();
assert!(matches!(err, QfeError::DecodingFailed(_)), "Expected DecodingFailed, got {:?}", err);
if let QfeError::DecodingFailed(msg) = err {
assert!(msg.contains("Validity Proof Check Failed"), "Expected Validity Proof failure message, got: {}", msg);
}
assert!(!verifier.is_valid());
}
#[test]
fn test_simple_zkp_wrong_challenge() {
let test_data = setup_simple_zkp_test();
let prover = test_data.prover;
let mut verifier = test_data.verifier;
let zkp_sqs = test_data.zkp_sqs;
let h_public = test_data.h_public;
let challenge_c1 = generate_zkp_challenge(32);
let response = prover.generate_validity_proof(&challenge_c1, &zkp_sqs, &h_public)
.expect("Prover failed proof generation");
let challenge_c2 = generate_zkp_challenge(32);
if challenge_c1 == challenge_c2 {
println!("Warning: Collision in random challenge generation, test may be less effective.");
}
assert_ne!(challenge_c1, challenge_c2);
let verification_result = verifier.verify_validity_proof(
&challenge_c2, &response,
&zkp_sqs,
&h_public,
);
assert!(verification_result.is_err(), "Verification should fail when Verifier uses wrong challenge");
let err = verification_result.unwrap_err();
assert!(matches!(err, QfeError::DecodingFailed(_)), "Expected DecodingFailed, got {:?}", err);
if let QfeError::DecodingFailed(msg) = err {
assert!(msg.contains("Validity Proof Check Failed"), "Expected Validity Proof failure message, got: {}", msg);
}
assert!(!verifier.is_valid());
}
#[test]
fn test_simple_zkp_wrong_sqs() {
let test_data1 = setup_simple_zkp_test(); let prover = test_data1.prover;
let zkp_sqs1 = test_data1.zkp_sqs;
let h_public = test_data1.h_public;
let mut verifier2 = Frame::initialize("Verifier2_WrongSQS".to_string(), 909090);
let zkp_sqs2 = establish_zkp_sqs(
prover.id(),
verifier2.id(), &h_public,
"a_completely_different_context", ).expect("Failed to establish ZKP SQS2");
assert_ne!(zkp_sqs1.components, zkp_sqs2.components);
let challenge = generate_zkp_challenge(32);
let response = prover.generate_validity_proof(&challenge, &zkp_sqs1, &h_public)
.expect("Prover failed proof generation");
let verification_result = verifier2.verify_validity_proof(
&challenge,
&response,
&zkp_sqs2, &h_public,
);
assert!(verification_result.is_err(), "Verification should fail when using wrong SQS");
let err = verification_result.unwrap_err();
assert!(matches!(err, QfeError::DecodingFailed(_)), "Expected DecodingFailed, got {:?}", err);
if let QfeError::DecodingFailed(msg) = err {
assert!(msg.contains("Validity Proof Check Failed"), "Expected Validity Proof failure message, got: {}", msg);
}
assert!(!verifier2.is_valid());
}
}