1use crate::certificate::CertificateError::CertificateLengthError;
18use crate::certificate::{Certificate, CertificateError};
19use crate::chain::Chain;
20use crate::public_key_hashable::PublicKeyHashable as PK;
21use crate::revoke::Revocation;
22use crate::revoke::RevokeError;
23use crate::trust::Trust;
24use crate::trust_graph::TrustGraphError::{
25 CertificateCheckError, EmptyChain, InternalStorageError, NoRoot,
26};
27use crate::trust_graph_storage::Storage;
28use crate::trust_relation::Auth;
29use crate::{StorageError, TrustError};
30use fluence_keypair::public_key::PublicKey;
31use nonempty::NonEmpty;
32use std::borrow::Borrow;
33use std::collections::{HashSet, VecDeque};
34use std::convert::{From, Into};
35use std::result::Result;
36use std::time::Duration;
37use thiserror::Error as ThisError;
38
39pub type WeightFactor = u32;
41
42pub static MAX_WEIGHT_FACTOR: u32 = 16;
43
44#[allow(dead_code)]
48pub struct TrustGraph<S>
49where
50 S: Storage,
51{
52 storage: S,
53}
54
55#[derive(ThisError, Debug)]
56pub enum TrustGraphError {
57 #[error("Internal storage error: {0}")]
58 InternalStorageError(Box<dyn StorageError>),
59 #[error("There is no root for this certificate.")]
60 NoRoot,
61 #[error("Chain is empty")]
62 EmptyChain,
63 #[error("Certificate check error: {0}")]
64 CertificateCheckError(
65 #[from]
66 #[source]
67 CertificateError,
68 ),
69 #[error("Error on revoking a trust: {0}")]
70 RevokeCheckError(
71 #[from]
72 #[source]
73 RevokeError,
74 ),
75 #[error("Path to {0} not found")]
76 AddTrustError(String),
77 #[error("Trust verification error: {0}")]
78 TrustVerificationError(
79 #[from]
80 #[source]
81 TrustError,
82 ),
83}
84
85impl<T: StorageError + 'static> From<T> for TrustGraphError {
86 fn from(err: T) -> Self {
87 InternalStorageError(Box::new(err))
88 }
89}
90
91impl From<TrustGraphError> for String {
92 fn from(err: TrustGraphError) -> Self {
93 format!("{err}")
94 }
95}
96
97fn get_weight_factor(max_chain_len: u32) -> u32 {
98 MAX_WEIGHT_FACTOR.saturating_sub(max_chain_len)
99}
100
101pub fn get_weight_from_factor(wf: WeightFactor) -> u32 {
102 2u32.pow(MAX_WEIGHT_FACTOR.saturating_sub(wf))
103}
104
105impl<S> TrustGraph<S>
106where
107 S: Storage,
108{
109 pub fn new(storage: S) -> Self {
110 Self { storage }
111 }
112
113 pub fn set_root(&mut self, pk: PublicKey, max_chain_len: u32) -> Result<(), TrustGraphError> {
115 Ok(self
116 .storage
117 .set_root_weight_factor(pk.into(), get_weight_factor(max_chain_len))?)
118 }
119
120 pub fn add_trust<T, P>(
121 &mut self,
122 trust: T,
123 issued_by: P,
124 cur_time: Duration,
125 ) -> Result<u32, TrustGraphError>
126 where
127 T: Borrow<Trust>,
128 P: Borrow<PublicKey>,
129 {
130 Trust::verify(trust.borrow(), issued_by.borrow(), cur_time)?;
131 let next_weight = self.get_next_weight(
132 issued_by.borrow().as_ref(),
133 trust.borrow().issued_for.as_ref(),
134 cur_time,
135 )?;
136
137 if next_weight == 0u32 {
138 return Ok(0u32);
139 }
140
141 let auth = Auth {
142 trust: trust.borrow().clone(),
143 issued_by: issued_by.borrow().clone(),
144 };
145
146 self.storage.update_auth(auth, cur_time)?;
147
148 Ok(next_weight)
149 }
150
151 pub fn add<C>(&mut self, cert: C, cur_time: Duration) -> Result<(), TrustGraphError>
153 where
154 C: Borrow<Certificate>,
155 {
156 let chain = &cert.borrow().chain;
157 let mut issued_by = chain.first().ok_or(EmptyChain)?.issued_for.clone();
158
159 for trust in chain {
161 self.add_trust(trust, issued_by, cur_time)?;
162 issued_by = trust.issued_for.clone();
163 }
164
165 Ok(())
166 }
167
168 fn get_next_weight(
169 &mut self,
170 issued_by: &PK,
171 issued_for: &PK,
172 cur_time: Duration,
173 ) -> Result<u32, TrustGraphError> {
174 let issued_by_weight = self.weight(issued_by.as_ref(), cur_time)?;
175
176 if issued_by.eq(issued_for) {
178 Ok(issued_by_weight)
179 } else {
180 Ok(issued_by_weight / 2)
181 }
182 }
183
184 pub fn weight<P>(&mut self, pk: P, cur_time: Duration) -> Result<u32, TrustGraphError>
186 where
187 P: Borrow<PublicKey>,
188 {
189 let mut max_weight = 0;
190 if let Some(weight_factor) = self.storage.get_root_weight_factor(pk.borrow().as_ref())? {
191 max_weight = get_weight_from_factor(weight_factor);
192 }
193
194 let certs = self.get_all_certs(pk, cur_time)?;
196 if let Some(weight_factor) = self.certificates_weight_factor(certs)? {
197 max_weight = std::cmp::max(max_weight, get_weight_from_factor(weight_factor))
198 }
199
200 Ok(max_weight)
201 }
202
203 pub fn weight_from<P>(
206 &mut self,
207 issued_for: P,
208 issuer: P,
209 cur_time: Duration,
210 ) -> Result<u32, TrustGraphError>
211 where
212 P: Borrow<PublicKey>,
213 {
214 let mut max_weight = 0;
215
216 let certs = self.get_all_certs_from(issued_for, issuer, cur_time)?;
219 if let Some(weight_factor) = self.certificates_weight_factor(certs)? {
220 max_weight = std::cmp::max(max_weight, get_weight_from_factor(weight_factor))
221 }
222
223 Ok(max_weight)
224 }
225
226 pub fn certificates_weight_factor<C, I>(
230 &self,
231 certs: I,
232 ) -> Result<Option<WeightFactor>, TrustGraphError>
233 where
234 C: Borrow<Certificate>,
235 I: IntoIterator<Item = C>,
236 {
237 let mut certs = certs.into_iter().peekable();
238 if certs.peek().is_none() {
241 return Ok(None);
242 }
243
244 let mut weight_factor = u32::MAX;
245
246 for cert in certs {
247 let c = cert.borrow();
248
249 let first = c
250 .chain
251 .first()
252 .ok_or(CertificateCheckError(CertificateLengthError))?;
253
254 let root_weight_factor = self
255 .storage
256 .get_root_weight_factor(first.issued_for.as_ref())?
257 .ok_or(NoRoot)?;
258
259 weight_factor =
262 std::cmp::min(weight_factor, root_weight_factor + c.chain.len() as u32 - 1)
263 }
264
265 Ok(Some(weight_factor))
266 }
267
268 fn bf_search_paths(
270 &self,
271 pk: &PK,
272 roots: HashSet<&PK>,
273 ) -> Result<Vec<Vec<Auth>>, TrustGraphError> {
274 let mut chains_queue: VecDeque<Chain> = VecDeque::new();
276
277 let node_auths: Vec<Auth> = self.storage.get_authorizations(pk)?;
278 let node_revocations = self.storage.get_revocations(pk)?;
279
280 for auth in node_auths {
282 chains_queue.push_back(Chain::new(NonEmpty::new(auth), node_revocations.clone()));
283 }
284
285 let mut terminated_chains: Vec<Vec<Auth>> = Vec::new();
287
288 while !chains_queue.is_empty() {
289 let cur_chain = chains_queue
290 .pop_front()
291 .expect("`chains_queue` always has at least one element");
292
293 let last = cur_chain.auths.last();
294
295 let auths = self
296 .storage
297 .get_authorizations(&last.issued_by.clone().into())?;
298
299 for auth in auths {
300 if cur_chain.can_be_extended_by(&auth.issued_by) {
302 let mut new_chain = cur_chain.clone();
303 new_chain.add_revocations(
304 self.storage
305 .get_revocations(&auth.issued_by.clone().into())?,
306 );
307 new_chain.auths.push(auth);
308 chains_queue.push_back(new_chain);
309 }
310 }
311
312 let self_signed = last.issued_by == last.trust.issued_for;
317 let issued_by: &PK = last.issued_by.as_ref();
318 let converges_to_root = roots.contains(issued_by);
319
320 if self_signed && converges_to_root && cur_chain.auths.len() > 1 {
321 terminated_chains.push(cur_chain.auths.into());
322 }
323 }
324
325 Ok(terminated_chains)
326 }
327
328 pub fn get_all_certs_from<P>(
332 &mut self,
333 issued_for: P,
334 issuer: P,
335 cur_time: Duration,
336 ) -> Result<Vec<Certificate>, TrustGraphError>
337 where
338 P: Borrow<PublicKey>,
339 {
340 self.get_all_certs(issued_for, cur_time).map(|c| {
341 c.into_iter()
342 .filter(|cert: &Certificate| {
343 cert.chain.iter().any(|t| t.issued_for.eq(issuer.borrow()))
344 })
345 .collect()
346 })
347 }
348
349 pub fn get_all_certs<P>(
352 &mut self,
353 issued_for: P,
354 cur_time: Duration,
355 ) -> Result<Vec<Certificate>, TrustGraphError>
356 where
357 P: Borrow<PublicKey>,
358 {
359 self.storage.remove_expired(cur_time)?;
361
362 let keys = self.storage.root_keys()?;
364 let roots = keys.iter().collect();
365
366 Ok(self
367 .bf_search_paths(issued_for.borrow().as_ref(), roots)?
368 .into_iter()
369 .map(|auths| {
370 let trusts: Vec<Trust> = auths.into_iter().map(|auth| auth.trust).rev().collect();
371 Certificate::new_unverified(trusts)
372 })
373 .filter(|c| {
374 debug_assert!(
376 c.chain.len() > 1,
377 "certificate with chain of len 1 arose: {c:#?}",
378 );
379 c.chain.len() > 1
380 })
381 .collect())
382 }
383
384 pub fn revoke(&mut self, revocation: Revocation) -> Result<(), TrustGraphError> {
388 Revocation::verify(&revocation)?;
389
390 Ok(self.storage.revoke(revocation)?)
391 }
392
393 pub fn get_revocations<P>(&self, issued_for: P) -> Result<Vec<Revocation>, TrustGraphError>
394 where
395 P: Borrow<PublicKey>,
396 {
397 Ok(self.storage.get_revocations(issued_for.borrow().as_ref())?)
398 }
399}