use std::sync::Arc;
use keri_core::{
database::EventDatabase,
event::{event_data::EventData, sections::seal::Seal},
prefix::IdentifierPrefix,
processor::event_storage::EventStorage,
};
use said::SelfAddressingIdentifier;
use crate::{
database::TelEventDatabase,
error::Error,
event::{
manager_event::{ManagerEventType, ManagerTelEventMessage},
vc_event::VCEventMessage,
verifiable_event::VerifiableEvent,
Event,
},
seal::AttachedSourceSeal,
};
use super::TelEventStorage;
pub struct TelEventValidator<D: TelEventDatabase, K: EventDatabase> {
kel_reference: Arc<EventStorage<K>>,
db: Arc<TelEventStorage<D>>,
}
impl<D: TelEventDatabase, K: EventDatabase> TelEventValidator<D, K> {
pub fn new(db: Arc<TelEventStorage<D>>, kel_reference: Arc<EventStorage<K>>) -> Self {
Self {
db: db.clone(),
kel_reference,
}
}
pub fn check_kel_event(
kel_reference: Arc<EventStorage<K>>,
seal: &AttachedSourceSeal,
issuer_id: &IdentifierPrefix,
expected_digest: SelfAddressingIdentifier,
) -> Result<(), Error> {
let reference_kel_event = kel_reference
.get_event_at_sn(issuer_id, seal.seal.sn)
.ok_or(Error::MissingIssuerEventError)?;
match &reference_kel_event
.signed_event_message
.event_message
.digest()
{
Ok(dig) if dig == &seal.seal.digest => Ok(()),
_ => Err(Error::DigestsNotMatchError),
}?;
let event_type = reference_kel_event
.signed_event_message
.event_message
.data
.event_data;
if let EventData::Ixn(ixn) = event_type {
if ixn.data.into_iter().any(|seal| match seal {
Seal::Event(es) => es.event_digest().eq(&expected_digest),
_ => false,
}) {
Ok(())
} else {
Err(Error::MissingSealError)
}
} else {
Err(Error::Generic("Wrong event type".to_string()))
}
}
pub fn validate_management(
&self,
event: &ManagerTelEventMessage,
seal: &AttachedSourceSeal,
) -> Result<(), Error> {
let id = match &event.data.event_type {
ManagerEventType::Vcp(vcp) => vcp.issuer_id.clone(),
ManagerEventType::Vrt(_vrt) => {
self.db
.compute_management_tel_state(&event.data.prefix)?
.ok_or(Error::MissingRegistryError)?
.issuer
}
};
Self::check_kel_event(
self.kel_reference.clone(),
seal,
&id,
event.digest().unwrap(),
)?;
let state = self
.db
.compute_management_tel_state(&event.data.prefix)?
.unwrap_or_default();
state.apply(event)?;
Ok(())
}
pub fn validate_vc(
&self,
vc_event: &VCEventMessage,
seal: &AttachedSourceSeal,
) -> Result<(), Error> {
let registry_id = vc_event.data.data.registry_id()?;
let issuer_id = self
.db
.compute_management_tel_state(®istry_id)?
.ok_or(Error::MissingRegistryError)?
.issuer;
Self::check_kel_event(
self.kel_reference.clone(),
seal,
&issuer_id,
vc_event.digest().unwrap(),
)?;
self.db
.compute_vc_state(&vc_event.data.data.prefix)?
.unwrap_or_default()
.apply(vc_event)?;
Ok(())
}
pub fn validate(&self, verifiable_event: &VerifiableEvent) -> Result<(), Error> {
match verifiable_event.event {
Event::Management(ref man) => self.validate_management(man, &verifiable_event.seal),
Event::Vc(ref vc) => self.validate_vc(vc, &verifiable_event.seal),
}
}
}