Skip to main content

keri_controller/identifier/mechanics/
query_mailbox.rs

1use keri_core::actor::possible_response::PossibleResponse;
2use keri_core::actor::prelude::HashFunctionCode;
3use keri_core::{
4    actor::prelude::SerializationFormats,
5    oobi::Scheme,
6    prefix::{BasicPrefix, IdentifierPrefix, IndexedSignature, SelfSigningPrefix},
7    query::{
8        mailbox::{MailboxQuery, MailboxRoute, QueryArgsMbx},
9        query_event::SignedQuery,
10    },
11};
12
13#[cfg(not(feature = "query_cache"))]
14use crate::mailbox_updating::MailboxReminder;
15
16use crate::{
17    communication::SendingError, error::ControllerError, identifier::Identifier,
18    mailbox_updating::ActionRequired,
19};
20
21use super::MechanicsError;
22
23#[derive(Debug, thiserror::Error)]
24pub enum ResponseProcessingError {
25    #[error("Unexpected response")]
26    UnexpectedResponse,
27    #[error("Error while processing receipts from response: {0}")]
28    Receipts(keri_core::error::Error),
29    #[error("Error while processing multisig from response: {0}")]
30    Multisig(keri_core::error::Error),
31    #[error("Error while processing delegate from response: {0}")]
32    Delegate(keri_core::error::Error),
33}
34
35impl Identifier {
36    /// Generates query message of route `mbx` to query own identifier mailbox.
37    pub fn query_mailbox(
38        &self,
39        identifier: &IdentifierPrefix,
40        witnesses: &[BasicPrefix],
41    ) -> Result<Vec<MailboxQuery>, ControllerError> {
42        witnesses
43            .iter()
44            .map(|wit| -> Result<_, ControllerError> {
45                let recipient = IdentifierPrefix::Basic(wit.clone());
46
47                #[cfg(feature = "query_cache")]
48                let reminder = if identifier == &self.id {
49                    // request own mailbox
50                    self.query_cache.last_asked_index(&recipient)
51                } else {
52                    // request group mailbox
53                    self.query_cache.last_asked_group_index(&recipient)
54                }?;
55                #[cfg(not(feature = "query_cache"))]
56                let reminder = MailboxReminder::default();
57
58                Ok(MailboxQuery::new_query(
59                    MailboxRoute::Mbx {
60                        args: QueryArgsMbx {
61                            // about who
62                            i: identifier.clone(),
63                            // who is asking
64                            pre: self.id.clone(),
65                            // who will get the query
66                            src: recipient,
67                            topics: reminder.to_query_topics(),
68                        },
69                        reply_route: "".to_string(),
70                    },
71                    SerializationFormats::JSON,
72                    HashFunctionCode::Blake3_256,
73                ))
74            })
75            .collect()
76    }
77
78    /// Joins query events with their signatures, sends it to witness and
79    /// process its response. If user action is needed to finalize process,
80    /// returns proper notification.
81    pub async fn finalize_query_mailbox(
82        &mut self,
83        queries: Vec<(MailboxQuery, SelfSigningPrefix)>,
84    ) -> Result<Vec<ActionRequired>, ControllerError> {
85        let mut actions = Vec::new();
86        for (qry, sig) in queries {
87            let args = qry.get_args();
88            let (recipient, about_who, from_who) =
89                (args.src.clone(), Some(&args.i), Some(&args.pre));
90            match self.handle_management_query(&qry, sig).await? {
91                PossibleResponse::Mbx(mbx) => {
92                    // only process if we actually asked about mailbox
93                    if let (Some(from_who), Some(about_who)) =
94                        (from_who.as_ref(), about_who.as_ref())
95                    {
96                        actions.append(
97                            &mut self
98                                .mailbox_response(&recipient, from_who, about_who, &mbx)
99                                .await?,
100                        );
101                        let witnesses = self
102                            .witnesses()
103                            .map(IdentifierPrefix::Basic)
104                            .collect::<Vec<_>>();
105                        self.broadcast_receipts(&witnesses)
106                            .await
107                            .map_err(MechanicsError::BroadcastingError)?;
108                    }
109                }
110                _ => panic!("Unexpected response"),
111            };
112        }
113
114        Ok(actions)
115    }
116
117    /// Joins query events with their signatures, sends it to witness.
118    async fn handle_management_query(
119        &self,
120        qry: &MailboxQuery,
121        sig: SelfSigningPrefix,
122    ) -> Result<PossibleResponse, SendingError> {
123        let recipient = match &qry.data.data {
124            MailboxRoute::Mbx {
125                reply_route: _,
126                args,
127            } => Some(args.src.clone()),
128        };
129
130        let query = match &self.id {
131            IdentifierPrefix::Basic(bp) => SignedQuery::new_nontrans(qry.clone(), bp.clone(), sig),
132            _ => {
133                let signatures = vec![IndexedSignature::new_both_same(sig, 0)];
134                SignedQuery::new_trans(qry.clone(), self.id().clone(), signatures)
135            }
136        };
137        self.communication
138            .send_management_query_to(recipient.as_ref().unwrap(), Scheme::Http, query)
139            .await
140    }
141}