1use crate::{
4 Cades, ISSUER,
5 basic::SignerBinding,
6 counters::Paths,
7 credential::Complete,
8 source::{DocumentId, Node},
9};
10use structured_ltv::{
11 pki::{self, ParticipantError, ParticipantRequirements},
12 source::{Query, Source},
13 timestamp::TimestampPaths,
14};
15
16#[derive(Debug)]
18pub enum Error {
19 Participants(ParticipantError<Node>),
21 Preservation {
23 property: Node,
25 kind: crate::preservation::Kind,
27 },
28 PreservationSource {
31 source: Node,
33 },
34}
35
36pub fn participants<'view, 'path, 'm, 'd, E, Q>(
42 signer: &'view SignerBinding<'_, 'm, 'd, 'path>,
43 counters: &'view Paths<'_, 'm, 'd, 'path>,
44 credentials: &'view Complete<'_, 'm, 'd, 'path, E>,
45 timestamps: &'view TimestampPaths<'view, '_, 'd, Node, DocumentId<'m, 'd>, (), Cades>,
46 query: &Q,
47) -> Result<ParticipantRequirements<'view, 'd, Node, DocumentId<'m, 'd>, (), Cades>, Error>
48where
49 Q: Query<Id = Node, Document = DocumentId<'m, 'd>, Generation = ()>,
50 'path: 'view,
51 'd: 'path,
52{
53 participants_in(signer, counters, credentials, timestamps, None, query)
54}
55
56pub fn participants_preserved<'view, 'path, 'm, 'd, E, Q>(
60 signer: &'view SignerBinding<'_, 'm, 'd, 'path>,
61 counters: &'view Paths<'_, 'm, 'd, 'path>,
62 credentials: &'view Complete<'_, 'm, 'd, 'path, E>,
63 timestamps: &'view TimestampPaths<'view, '_, 'd, Node, DocumentId<'m, 'd>, (), Cades>,
64 preservation: &crate::evidence::Closure<'_, '_, 'm, 'd, '_>,
65 query: &Q,
66) -> Result<ParticipantRequirements<'view, 'd, Node, DocumentId<'m, 'd>, (), Cades>, Error>
67where
68 Q: Query<Id = Node, Document = DocumentId<'m, 'd>, Generation = ()>,
69 'path: 'view,
70 'd: 'path,
71{
72 participants_in(
73 signer,
74 counters,
75 credentials,
76 timestamps,
77 Some(preservation),
78 query,
79 )
80}
81fn participants_in<'view, 'path, 'm, 'd, E, Q>(
82 signer: &'view SignerBinding<'_, 'm, 'd, 'path>,
83 counters: &'view Paths<'_, 'm, 'd, 'path>,
84 credentials: &'view Complete<'_, 'm, 'd, 'path, E>,
85 timestamps: &'view TimestampPaths<'view, '_, 'd, Node, DocumentId<'m, 'd>, (), Cades>,
86 preservation: Option<&crate::evidence::Closure<'_, '_, 'm, 'd, '_>>,
87 query: &Q,
88) -> Result<ParticipantRequirements<'view, 'd, Node, DocumentId<'m, 'd>, (), Cades>, Error>
89where
90 Q: Query<Id = Node, Document = DocumentId<'m, 'd>, Generation = ()>,
91 'path: 'view,
92 'd: 'path,
93{
94 let prepared = signer.prepared();
95 if let Some(proofs) = preservation
96 && !core::ptr::eq(proofs.prepared(), prepared)
97 {
98 return Err(Error::Participants(ParticipantError::Foreign {
99 signature: Node::of(prepared.signer().span()),
100 }));
101 }
102 let selected = prepared.document().signer(prepared.signer()).map_err(|_| {
103 Error::Participants(ParticipantError::Foreign {
104 signature: Node::of(prepared.signer().span()),
105 })
106 })?;
107 if prepared.document().snapshot() != query.snapshot() {
108 return Err(Error::Participants(ParticipantError::Foreign {
109 signature: selected.node,
110 }));
111 }
112 query
113 .admit(selected.node, 1)
114 .map_err(|cause| Error::Participants(ParticipantError::Scope(cause)))?;
115 for required in prepared.preservation() {
116 query
117 .admit(required.property, 1)
118 .map_err(|cause| Error::Participants(ParticipantError::Scope(cause)))?;
119 if !required.kind.is_archive() && !required.kind.is_reference_timestamp() {
123 if let Some(proofs) = preservation
124 && required.kind.is_evidence()
125 && proofs
126 .contains(required, query.execution())
127 .map_err(|cause| {
128 Error::Participants(ParticipantError::Resource {
129 node: required.property,
130 cause,
131 })
132 })?
133 {
134 continue;
135 }
136
137 return Err(Error::Preservation {
138 property: required.property,
139 kind: required.kind,
140 });
141 }
142 }
143 if !prepared.preservation().is_empty() {
144 for finding in prepared.preservation_findings() {
145 query
146 .admit(finding.location.node, 1)
147 .map_err(|cause| Error::Participants(ParticipantError::Scope(cause)))?;
148 if finding.severity == crate::prepare::Severity::Required {
149 return Err(Error::PreservationSource {
150 source: finding.location.node,
151 });
152 }
153 }
154 }
155 pki::participants(ISSUER, signer, counters, credentials, timestamps, query)
156 .map_err(Error::Participants)
157}