1use std::convert::TryFrom;
2
3use serde::{Deserialize, Serialize};
4
5#[cfg(feature = "oobi-manager")]
6use crate::oobi_manager::OobiManager;
7#[cfg(feature = "query")]
8use crate::{
9 database::EventDatabase,
10 event_message::{signature::Signature, signed_event_message::Op},
11 processor::event_storage::EventStorage,
12 query::{
13 key_state_notice::KeyStateNotice,
14 query_event::QueryRoute,
15 query_event::SignedQueryMessage,
16 reply_event::{ReplyRoute, SignedReply},
17 ReplyType,
18 },
19};
20use crate::{
21 error::Error,
22 event_message::{
23 cesr_adapter::ParseError,
24 signed_event_message::{Message, Notice},
25 },
26 prefix::IdentifierPrefix,
27 processor::Processor,
28};
29#[cfg(feature = "mailbox")]
30use crate::{
31 event_message::signed_event_message::SignedEventMessage,
32 mailbox::exchange::{Exchange, ExchangeMessage, ForwardTopic, SignedExchange},
33 query::mailbox::MailboxRoute,
34};
35pub use cesrox::cesr_proof::MaterialPath;
36use cesrox::parse_many;
37#[cfg(feature = "query")]
38use said::version::format::SerializationFormats;
39
40pub mod error;
41pub mod event_generator;
42
43#[cfg(feature = "query")]
44pub mod possible_response;
45#[cfg(all(feature = "mailbox", feature = "oobi-manager"))]
46pub mod simple_controller;
47
48pub fn parse_event_stream(stream: &[u8]) -> Result<Vec<Message>, ParseError> {
49 let (_rest, events) = parse_many(stream).map_err(|e| ParseError::CesrError(e.to_string()))?;
50 events.into_iter().map(Message::try_from).collect()
51}
52
53pub fn parse_notice_stream(stream: &[u8]) -> Result<Vec<Notice>, ParseError> {
54 let (_rest, notices) = parse_many(stream).map_err(|e| ParseError::CesrError(e.to_string()))?;
55 notices.into_iter().map(Notice::try_from).collect()
56}
57
58#[cfg(any(feature = "query", feature = "oobi-manager"))]
59pub fn parse_op_stream(stream: &[u8]) -> Result<Vec<Op>, ParseError> {
60 let (_rest, ops) = parse_many(stream).map_err(|e| ParseError::CesrError(e.to_string()))?;
61 ops.into_iter().map(Op::try_from).collect()
62}
63
64#[cfg(any(feature = "query", feature = "oobi-manager"))]
65pub fn parse_query_stream(stream: &[u8]) -> Result<Vec<SignedQueryMessage>, ParseError> {
66 let (_rest, queries) = parse_many(stream).map_err(|e| ParseError::CesrError(e.to_string()))?;
67 queries
68 .into_iter()
69 .map(SignedQueryMessage::try_from)
70 .collect()
71}
72
73#[cfg(feature = "query")]
74pub fn parse_reply_stream(stream: &[u8]) -> Result<Vec<SignedReply>, ParseError> {
75 let (_rest, replies) = parse_many(stream).map_err(|e| ParseError::CesrError(e.to_string()))?;
76 replies.into_iter().map(SignedReply::try_from).collect()
77}
78
79#[cfg(feature = "mailbox")]
80pub fn parse_exchange_stream(stream: &[u8]) -> Result<Vec<SignedExchange>, ParseError> {
81 let (_rest, exchanges) =
82 parse_many(stream).map_err(|e| ParseError::CesrError(e.to_string()))?;
83 exchanges
84 .into_iter()
85 .map(SignedExchange::try_from)
86 .collect()
87}
88
89pub fn process_notice<P: Processor>(msg: Notice, processor: &P) -> Result<(), Error> {
90 processor.process_notice(&msg)
91}
92
93#[cfg(feature = "query")]
94pub fn process_reply<P: Processor>(
95 sr: SignedReply,
96 #[cfg(feature = "oobi-manager")] oobi_manager: &OobiManager,
97 processor: &P,
98 event_storage: &EventStorage<P::Database>,
99) -> Result<(), Error> {
100 match sr.reply.get_route() {
101 #[cfg(feature = "oobi-manager")]
102 ReplyRoute::LocScheme(_) | ReplyRoute::EndRoleAdd(_) | ReplyRoute::EndRoleCut(_) => {
103 process_signed_oobi(&sr, oobi_manager, event_storage)
104 }
105 ReplyRoute::Ksn(_, _) => processor.process_op_reply(&sr),
106 _ => { Ok(()) }
107 }
108}
109
110#[cfg(feature = "oobi-manager")]
111pub fn process_signed_oobi<D: EventDatabase + 'static>(
112 signed_oobi: &SignedReply,
113 oobi_manager: &OobiManager,
114 event_storage: &EventStorage<D>,
115) -> Result<(), Error> {
116 use crate::processor::validator::EventValidator;
117
118 let validator = EventValidator::new(event_storage.events_db.clone());
119 validator.verify(&signed_oobi.reply.encode()?, &signed_oobi.signature)?;
121 signed_oobi.reply.check_digest()?;
123 let r = oobi_manager
125 .process_oobi(signed_oobi)
126 .map_err(|e| Error::SemanticError(e.to_string()))?;
127
128 Ok(())
129}
130
131#[cfg(feature = "mailbox")]
132pub fn process_signed_exn<D: EventDatabase>(
133 exn: SignedExchange,
134 storage: &EventStorage<D>,
135) -> Result<(), Error> {
136 let exn_message = &exn.exchange_message;
137 let verification_result =
138 exn.signature
139 .iter()
140 .try_fold(true, |acc, signature| -> Result<bool, Error> {
141 Ok(acc && signature.verify(&exn_message.encode()?, storage)?)
142 });
143 if verification_result? {
144 process_exn(exn_message, exn.data_signature, storage)
145 } else {
146 Err(Error::SignatureVerificationError)
147 }
148}
149
150#[cfg(feature = "mailbox")]
151fn process_exn<D: EventDatabase>(
152 exn: &ExchangeMessage,
153 attachment: (MaterialPath, Vec<Signature>),
154 storage: &EventStorage<D>,
155) -> Result<(), Error> {
156 let (recipient, to_forward, topic) = match &exn.data.data {
157 Exchange::Fwd { args, to_forward } => (&args.recipient_id, to_forward, &args.topic),
158 };
159 let (sigs, witness_receipts) = attachment.1.into_iter().fold(
160 (vec![], vec![]),
161 |(mut signatures, mut witness_receipts), s| {
162 match s {
163 Signature::Transferable(_sd, mut sigs) => signatures.append(&mut sigs),
164 Signature::NonTransferable(receipts) => witness_receipts.push(receipts),
165 }
166 (signatures, witness_receipts)
167 },
168 );
169
170 let signed_to_forward = SignedEventMessage {
171 event_message: to_forward.clone(),
172 signatures: sigs,
173 witness_receipts: if witness_receipts.is_empty() {
174 None
175 } else {
176 Some(witness_receipts)
177 },
178 delegator_seal: None,
179 };
180
181 match topic {
182 ForwardTopic::Multisig => {
183 storage.add_mailbox_multisig(recipient, signed_to_forward)?;
184 }
185 ForwardTopic::Delegate => {
186 storage.add_mailbox_delegate(recipient, signed_to_forward)?;
187 }
188 };
189 Ok(())
190}
191
192#[cfg(feature = "query")]
193pub fn process_signed_query<D: EventDatabase>(
194 qr: SignedQueryMessage,
195 storage: &EventStorage<D>,
196) -> Result<ReplyType, SignedQueryError> {
197 let verify = |data: &[u8], signature: Signature| -> Result<_, SignedQueryError> {
198 let ver_result = signature.verify(&data, storage)?;
199 if !ver_result {
200 Err(SignedQueryError::InvalidSignature)
201 } else {
202 Ok(())
203 }
204 };
205 match qr {
206 SignedQueryMessage::KelQuery(kqry) => {
207 let signature = kqry.signature;
208 let data = &kqry.query.encode().map_err(|_e| Error::VersionError)?;
209 verify(&data, signature)?;
211
212 Ok(process_query(kqry.query.get_route(), storage)?)
215 }
216 #[cfg(feature = "mailbox")]
217 SignedQueryMessage::MailboxQuery(mqry) => {
218 let signature = mqry.signature;
219 let data = &mqry.query.encode().map_err(|_e| Error::VersionError)?;
220 verify(&data, signature)?;
222 Ok(process_mailbox_query(&mqry.query.data.data, storage)?)
223 }
224 }
225}
226
227#[derive(Debug, thiserror::Error, Serialize, Deserialize)]
228pub enum SignedQueryError {
229 #[error(transparent)]
230 KeriError(#[from] crate::error::Error),
231
232 #[error(transparent)]
233 QueryError(#[from] QueryError),
234
235 #[error("unknown signer with id {id:?}")]
236 UnknownSigner { id: IdentifierPrefix },
237
238 #[error("signature verification failed")]
239 InvalidSignature,
240}
241
242#[cfg(feature = "query")]
243pub fn process_query<D: EventDatabase>(
244 qr: &QueryRoute,
245 storage: &EventStorage<D>,
246) -> Result<ReplyType, QueryError> {
247 match qr {
248 QueryRoute::Ksn { args, .. } => {
249 let state = storage
251 .get_state(&args.i)
252 .ok_or_else(|| QueryError::UnknownId { id: args.i.clone() })?;
253 let ksn = KeyStateNotice::new_ksn(state, SerializationFormats::JSON);
254 Ok(ReplyType::Ksn(ksn))
255 }
256 QueryRoute::Logs {
257 reply_route: _,
258 args,
259 } => {
260 let response = match (args.s, args.limit) {
261 (None, _) => storage.get_kel_messages_with_receipts_all(&args.i)?,
262 (Some(sn), None) => storage
263 .get_event_at_sn(&args.i, sn)
264 .map(|event| vec![Notice::Event(event.signed_event_message)]),
265 (Some(sn), Some(limit)) => {
266 storage.get_kel_messages_with_receipts_range(&args.i, sn, limit)?
267 }
268 }
269 .ok_or_else(|| QueryError::UnknownId { id: args.i.clone() })?
270 .into_iter()
271 .map(Message::Notice)
272 .collect::<Vec<_>>();
273
274 Ok(ReplyType::Kel(response))
275 }
276 }
277}
278
279#[cfg(feature = "mailbox")]
280pub fn process_mailbox_query<D: EventDatabase>(
281 qr: &MailboxRoute,
282 storage: &EventStorage<D>,
283) -> Result<ReplyType, QueryError> {
284 match qr {
285 MailboxRoute::Mbx { args, .. } => {
286 let mail = storage.get_mailbox_messages(args)?;
287 Ok(ReplyType::Mbx(mail))
288 }
289 }
290}
291
292#[derive(Debug, thiserror::Error, Serialize, Deserialize)]
293pub enum QueryError {
294 #[error(transparent)]
295 KeriError(#[from] crate::error::Error),
296
297 #[error("unknown identifier {id:?}")]
298 UnknownId { id: IdentifierPrefix },
299}
300
301pub mod prelude {
302 #[cfg(feature = "oobi-manager")]
303 pub use crate::actor::process_signed_oobi;
304 #[cfg(feature = "query")]
305 pub use crate::actor::{process_reply, process_signed_query};
306 #[cfg(feature = "query")]
307 pub use crate::query::ReplyType;
308 pub use crate::{
309 actor::process_notice,
310 event_message::signed_event_message::Message,
311 processor::{basic_processor::BasicProcessor, event_storage::EventStorage, Processor},
312 };
313 pub use said::version::{error::Error as VersionError, format::SerializationFormats};
314 pub use said::{
315 derivation::HashFunction, derivation::HashFunctionCode, SelfAddressingIdentifier,
316 };
317}