use super::types::{Challenge, FileMetadata, PreparedFile, Proof};
use crate::{ledger::FileLedger, NovaPoRError, Result};
use std::collections::BTreeMap;
use tracing::debug;
pub struct PorSystem<'a> {
ledger: &'a FileLedger,
}
impl<'a> PorSystem<'a> {
pub fn new(ledger: &'a FileLedger) -> Self {
Self { ledger }
}
pub fn prepare_file(
&self,
data: &[u8],
filename: &str,
) -> Result<(PreparedFile, FileMetadata)> {
super::prepare_file(data, filename)
}
pub fn prove(&self, files: Vec<&PreparedFile>, challenges: &[Challenge]) -> Result<Proof> {
let mut files_map = BTreeMap::new();
for file in files {
if files_map.insert(file.file_id.clone(), file).is_some() {
return Err(NovaPoRError::InvalidInput(format!(
"Duplicate file_id provided: {}",
file.file_id
)));
}
}
for challenge in challenges {
if !files_map.contains_key(&challenge.file_metadata.file_id) {
return Err(NovaPoRError::FileNotFound {
file_id: challenge.file_metadata.file_id.clone(),
});
}
}
debug!(
"PorSystem::prove - {} files, {} challenges",
files_map.len(),
challenges.len()
);
super::prove::prove(challenges, &files_map, self.ledger, None)
}
pub fn verify(&self, proof: &Proof, challenges: &[Challenge]) -> Result<bool> {
let expected_ids: Vec<_> = challenges.iter().map(|c| c.id()).collect();
if proof.challenge_ids.len() != expected_ids.len() {
return Err(NovaPoRError::InvalidInput(format!(
"Challenge count mismatch: proof covers {} challenges, provided {}",
proof.challenge_ids.len(),
expected_ids.len()
)));
}
for (i, (proof_id, expected_id)) in proof
.challenge_ids
.iter()
.zip(expected_ids.iter())
.enumerate()
{
if proof_id != expected_id {
return Err(NovaPoRError::InvalidInput(format!(
"Challenge ID mismatch at position {}: proof has {:?}, expected {:?}",
i, proof_id.0, expected_id.0
)));
}
}
debug!(
"PorSystem::verify - validated {} challenge IDs",
challenges.len()
);
super::verify::verify(challenges, proof, self.ledger)
}
}