keri_core/actor/
mod.rs

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