structured_xades/hashes/
participants.rs1use super::{HashBinding, HashError, HashProblem, HashXml, Hashes, check, check_selected};
4use crate::pki::CounterPaths;
5use crate::prepare::Prepared;
6use crate::xml::{Access, Snapshot, Xml};
7use structured_asn1::memory::{OwnedVec, Work};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub struct ParticipantProblem<N> {
12 pub signature: N,
14 pub cause: HashProblem<N>,
16}
17
18pub struct ParticipantHashes<N, D, G> {
21 root: Hashes<N, D, G>,
22 counters: OwnedVec<Hashes<N, D, G>>,
23}
24
25impl<N: Copy, D: Copy, G: Copy> ParticipantHashes<N, D, G> {
26 #[must_use]
28 pub fn snapshot(&self) -> Snapshot<D, G> {
29 self.root.snapshot()
30 }
31 #[must_use]
33 pub fn signature(&self) -> N {
34 self.root.signature()
35 }
36 #[must_use]
38 pub fn root(&self) -> &Hashes<N, D, G> {
39 &self.root
40 }
41 #[must_use]
43 pub fn counters(&self) -> &[Hashes<N, D, G>] {
44 &self.counters
45 }
46}
47
48pub enum ParticipantBinding<N, D, G> {
51 Bound(ParticipantHashes<N, D, G>),
53 Unproven(ParticipantProblem<N>),
55}
56
57pub type Result<X> = core::result::Result<
59 ParticipantBinding<<X as Xml>::Id, <X as Xml>::Document, <X as Xml>::Generation>,
60 HashError<<X as Xml>::Error, <X as Xml>::Id>,
61>;
62
63pub fn check_participants<X: HashXml, W: Work>(
73 prepared: &Prepared<X>,
74 counters: &CounterPaths<'_, '_, X::Id, X::Document, X::Generation>,
75 access: &Access<'_, X, W>,
76) -> Result<X> {
77 let layout = prepared.bound().containers();
78 let signature = layout.signature();
79 if layout.snapshot() != access.snapshot() || counters.snapshot() != access.snapshot() {
80 return Err(HashError::Foreign { node: signature });
81 }
82 if !access
83 .equal_id(signature, counters.signature())
84 .map_err(|cause| HashError::Resource {
85 node: signature,
86 cause,
87 })?
88 {
89 return Err(HashError::Foreign { node: signature });
90 }
91 let mut children = access.execution().vector();
92 children
93 .try_reserve_exact(counters.actors().len())
94 .map_err(|cause| HashError::Resource {
95 node: signature,
96 cause,
97 })?;
98 let root = match check(prepared.bound(), access)? {
99 HashBinding::Bound(root) => root,
100 HashBinding::Unproven(cause) => {
101 return Ok(ParticipantBinding::Unproven(ParticipantProblem {
102 signature,
103 cause,
104 }));
105 }
106 };
107 for actor in counters.actors() {
108 let signature = actor.signer().counter().original().child();
109 access
110 .execution()
111 .charge_work(1)
112 .map_err(|cause| HashError::Resource {
113 node: signature,
114 cause,
115 })?;
116 match check_selected(signature, access)? {
117 HashBinding::Bound(receipt) => {
118 children
119 .try_push(receipt)
120 .map_err(|cause| HashError::Resource {
121 node: signature,
122 cause,
123 })?;
124 }
125 HashBinding::Unproven(cause) => {
126 return Ok(ParticipantBinding::Unproven(ParticipantProblem {
127 signature,
128 cause,
129 }));
130 }
131 }
132 }
133 access
134 .query(signature, |_, _, _| Ok(()))
135 .map_err(HashError::Access)?;
136 Ok(ParticipantBinding::Bound(ParticipantHashes {
137 root,
138 counters: children.into_owned(),
139 }))
140}