use super::{Account, InvalidationTrigger, PlanError, PlanIssue};
use crate::identity::{self, Anchoring, Identity, Transcript};
use crate::kind::Kind;
use crate::origin::{OriginEdge, OriginRelation};
const CAPTURED_CONTENT_NODE: &[u8] = b"content";
fn captured_content_node(
commitment: Identity<identity::CapturedDeclaration>,
) -> Identity<identity::OriginNode> {
Identity::derived(Transcript::under_projection(
identity::Role::OriginNode,
&commitment,
CAPTURED_CONTENT_NODE,
0,
))
}
const BOUND_CONTENT_NODE: &[u8] = b"content";
fn content_node(content: Identity<identity::ProjectionContent>) -> Identity<identity::OriginNode> {
Identity::derived(Transcript::under_projection(
identity::Role::OriginNode,
&content,
BOUND_CONTENT_NODE,
0,
))
}
impl<K: Kind> Account<K> {
#[must_use]
pub fn anchoring(&self) -> Anchoring {
Anchoring::UnderProjection(*self.commitment().as_bytes())
}
#[must_use]
pub fn origin_node(&self) -> Identity<identity::OriginNode> {
content_node(self.content_commitment())
}
#[must_use]
pub fn dependency_edges(&self) -> Vec<OriginEdge> {
let to = self.origin_node();
self.dependencies()
.iter()
.map(|dependency| OriginEdge {
from: captured_content_node(*dependency),
relation: OriginRelation::ExplicitLink,
to,
})
.collect()
}
#[must_use]
pub fn cause_triggers(&self) -> Vec<InvalidationTrigger> {
let (first, rest) = self.caused_by();
core::iter::once(first).chain(rest).collect()
}
pub fn cause_trigger(&self) -> Result<InvalidationTrigger, PlanError> {
let (first, rest) = self.caused_by();
if rest.is_empty() {
return Ok(first);
}
Err(PlanError::of(PlanIssue::CauseSetUnwatchable {
named: u32::try_from(rest.len().saturating_add(1)).unwrap_or(u32::MAX),
watchable: 1,
}))
}
pub(super) fn caused_by(&self) -> (InvalidationTrigger, Vec<InvalidationTrigger>) {
(
InvalidationTrigger::ProjectionContent {
watched: self.content_commitment(),
},
self.dependencies()
.iter()
.map(|watched| InvalidationTrigger::CapturedDeclaration { watched: *watched })
.collect(),
)
}
}