1use std::convert::{TryFrom, TryInto};
2
3use cesrox::{
4 group::Group,
5 payload::{parse_payload, Payload},
6 primitives::IndexedSignature as CesrIndexedSignature,
7 ParsedData,
8};
9use said::{version::format::SerializationFormats, SelfAddressingIdentifier};
10use serde::{Deserialize, Serialize};
11
12use crate::event::{
13 event_data::EventData,
14 receipt::Receipt,
15 sections::seal::{EventSeal, SourceSeal},
16 KeyEvent,
17};
18
19#[cfg(feature = "query")]
20use crate::event_message::signed_event_message::Op;
21
22#[cfg(feature = "query")]
23use super::signature::signatures_into_groups;
24#[cfg(feature = "query")]
25use crate::query::{
26 query_event::SignedQueryMessage,
27 query_event::{QueryEvent, SignedKelQuery},
28 reply_event::{ReplyEvent, SignedReply},
29};
30
31#[cfg(feature = "mailbox")]
32use crate::{
33 event_message::signature,
34 mailbox::exchange::{ExchangeMessage, SignedExchange},
35 query::mailbox::{MailboxQuery, SignedMailboxQuery},
36};
37
38use super::{
39 msg::{KeriEvent, TypedEvent},
40 signature::Nontransferable,
41 signed_event_message::{
42 Message, Notice, SignedEventMessage, SignedNontransferableReceipt,
43 SignedTransferableReceipt,
44 },
45 Typeable,
46};
47
48#[derive(Debug, thiserror::Error, Serialize, Deserialize)]
49pub enum ParseError {
50 #[error("Cesr error")]
51 CesrError(String),
52 #[error("Deserialize error: {0}")]
53 DeserializeError(String),
54 #[error("Wrong attachment: {0}")]
55 AttachmentError(String),
56 #[error("Wrong event type: {0}")]
57 WrongEventType(String),
58}
59
60pub fn parse_event_type(input: &[u8]) -> Result<EventType, ParseError> {
61 parse_payload(input)
62 .map_err(|e| ParseError::CesrError(e.to_string()))?
63 .1
64 .try_into()
65}
66
67#[derive(Clone, Debug, PartialEq, Deserialize)]
68#[serde(untagged)]
69pub enum EventType {
70 KeyEvent(KeriEvent<KeyEvent>),
71 Receipt(Receipt),
72 #[cfg(feature = "mailbox")]
73 Exn(ExchangeMessage),
74 #[cfg(feature = "query")]
75 Qry(QueryEvent),
76 #[cfg(feature = "mailbox")]
77 MailboxQry(MailboxQuery),
78 #[cfg(any(feature = "query", feature = "oobi"))]
79 Rpy(ReplyEvent),
80}
81
82impl EventType {
83 pub fn serialize(&self) -> Result<Vec<u8>, crate::error::Error> {
84 match self {
85 EventType::KeyEvent(event) => event.encode(),
86 EventType::Receipt(rcp) => rcp.encode(),
87 #[cfg(feature = "query")]
88 EventType::Qry(qry) => qry.encode(),
89 #[cfg(feature = "query")]
90 EventType::Rpy(rpy) => rpy.encode(),
91 #[cfg(feature = "mailbox")]
92 EventType::Exn(exn) => exn.encode(),
93 #[cfg(feature = "mailbox")]
94 EventType::MailboxQry(qry) => qry.encode(),
95 }
96 }
97}
98
99impl From<&SignedEventMessage> for ParsedData {
100 fn from(ev: &SignedEventMessage) -> Self {
101 let mut attachments = if let Some(SourceSeal { sn, digest }) = ev.delegator_seal.clone() {
102 vec![Group::SourceSealCouples(vec![(sn, digest.said.into())])]
103 } else {
104 vec![]
105 };
106 let sigs = ev
107 .signatures
108 .clone()
109 .into_iter()
110 .map(|sig| sig.into())
111 .collect();
112 let signatures = Group::IndexedControllerSignatures(sigs);
113 attachments.push(signatures);
114
115 if let Some(witness_rcts) = &ev.witness_receipts {
116 witness_rcts.iter().for_each(|rcts| match rcts {
117 Nontransferable::Indexed(indexed) => {
118 let witness_sigs: Vec<CesrIndexedSignature> =
119 indexed.iter().map(|sig| sig.clone().into()).collect();
120 attachments.push(Group::IndexedWitnessSignatures(witness_sigs))
121 }
122 Nontransferable::Couplet(couplets) => {
123 let couples = couplets
124 .iter()
125 .map(|(bp, sp)| (bp.clone().into(), sp.clone().into()))
126 .collect();
127 attachments.push(Group::NontransReceiptCouples(couples))
128 }
129 });
130 };
131
132 ParsedData {
133 payload: ev.event_message.clone().into(),
134 attachments,
135 }
136 }
137}
138
139impl<T: Serialize + Clone, D: Typeable<TypeTag = T> + Serialize + Clone> From<TypedEvent<T, D>>
140 for Payload
141{
142 fn from(pd: TypedEvent<T, D>) -> Self {
143 match pd.serialization_info.kind {
144 SerializationFormats::JSON => Payload::JSON(pd.encode().unwrap()),
145 SerializationFormats::MGPK => Payload::MGPK(pd.encode().unwrap()),
146 SerializationFormats::CBOR => Payload::CBOR(pd.encode().unwrap()),
147 }
148 }
149}
150
151impl From<SignedNontransferableReceipt> for ParsedData {
152 fn from(rcp: SignedNontransferableReceipt) -> ParsedData {
153 let attachments: Vec<Group> = rcp.signatures.into_iter().map(|sig| sig.into()).collect();
154 ParsedData {
155 payload: rcp.body.into(),
156 attachments,
157 }
158 }
159}
160
161impl From<SignedTransferableReceipt> for ParsedData {
162 fn from(rcp: SignedTransferableReceipt) -> ParsedData {
163 let seal = rcp.validator_seal;
164 let event_digest = seal.event_digest();
165 let signatures = rcp.signatures.into_iter().map(|sig| sig.into()).collect();
166 let quadruple = (seal.prefix.into(), seal.sn, event_digest.into(), signatures);
167 let group = Group::TransIndexedSigGroups(vec![quadruple]);
168
169 ParsedData {
170 payload: rcp.body.into(),
171 attachments: vec![group],
172 }
173 }
174}
175
176#[cfg(feature = "query")]
177impl From<SignedReply> for ParsedData {
178 fn from(ev: SignedReply) -> Self {
179 let attachments = vec![ev.signature.into()];
180 ParsedData {
181 payload: ev.reply.into(),
182 attachments,
183 }
184 }
185}
186
187#[cfg(feature = "query")]
188impl From<SignedKelQuery> for ParsedData {
189 fn from(ev: SignedKelQuery) -> Self {
190 let groups = signatures_into_groups(&[ev.signature]);
191
192 ParsedData {
193 payload: ev.query.into(),
194 attachments: groups,
195 }
196 }
197}
198
199#[cfg(feature = "mailbox")]
200impl From<SignedMailboxQuery> for ParsedData {
201 fn from(ev: SignedMailboxQuery) -> Self {
202 let groups = signatures_into_groups(&[ev.signature]);
203
204 ParsedData {
205 payload: ev.query.into(),
206 attachments: groups,
207 }
208 }
209}
210
211#[cfg(feature = "query")]
212impl From<SignedQueryMessage> for ParsedData {
213 fn from(ev: SignedQueryMessage) -> Self {
214 match ev {
215 SignedQueryMessage::KelQuery(kqry) => ParsedData::from(kqry),
216 #[cfg(feature = "mailbox")]
217 SignedQueryMessage::MailboxQuery(mqry) => ParsedData::from(mqry),
218 }
219 }
220}
221
222#[cfg(feature = "mailbox")]
223impl From<SignedExchange> for ParsedData {
224 fn from(ev: SignedExchange) -> Self {
225 let mut attachments = signature::signatures_into_groups(&ev.signature);
226
227 let data_signatures = signature::signatures_into_groups(&ev.data_signature.1);
228
229 let data_attachment = Group::PathedMaterialQuadruplet(ev.data_signature.0, data_signatures);
230 attachments.push(data_attachment);
231 ParsedData {
232 payload: ev.exchange_message.into(),
233 attachments,
234 }
235 }
236}
237
238impl TryFrom<Payload> for EventType {
239 type Error = ParseError;
240
241 fn try_from(value: Payload) -> Result<Self, Self::Error> {
242 let event: Result<EventType, _> = match value {
243 Payload::JSON(event) => serde_json::from_slice(&event),
244 Payload::CBOR(_event) => todo!(),
245 Payload::MGPK(_event) => todo!(),
246 };
247 event.map_err(|e| ParseError::DeserializeError(e.to_string()))
248 }
249}
250
251impl TryFrom<ParsedData> for Message {
252 type Error = ParseError;
253
254 fn try_from(value: ParsedData) -> Result<Self, Self::Error> {
255 let msg = match value.payload.try_into()? {
256 EventType::KeyEvent(ev) => Message::Notice(signed_key_event(ev, value.attachments)?),
257 EventType::Receipt(rct) => Message::Notice(signed_receipt(rct, value.attachments)?),
258 #[cfg(feature = "query")]
259 EventType::Qry(qry) => Message::Op(signed_query(qry, value.attachments)?),
260 #[cfg(feature = "query")]
261 EventType::Rpy(rpy) => Message::Op(signed_reply(rpy, value.attachments)?),
262 #[cfg(feature = "mailbox")]
263 EventType::Exn(exn) => Message::Op(signed_exchange(exn, value.attachments)?),
264 #[cfg(feature = "mailbox")]
265 EventType::MailboxQry(qry) => {
266 Message::Op(signed_management_query(qry, value.attachments)?)
267 }
268 };
269 Ok(msg)
270 }
271}
272
273impl TryFrom<ParsedData> for Notice {
274 type Error = ParseError;
275
276 fn try_from(value: ParsedData) -> Result<Self, Self::Error> {
277 match Message::try_from(value)? {
278 Message::Notice(notice) => Ok(notice),
279 #[cfg(feature = "query")]
280 _ => Err(ParseError::WrongEventType(
281 "Cannot convert SignedEventData to Notice".to_string(),
282 )),
283 }
284 }
285}
286
287#[cfg(any(feature = "query", feature = "oobi"))]
288impl TryFrom<ParsedData> for Op {
289 type Error = ParseError;
290
291 fn try_from(value: ParsedData) -> Result<Self, Self::Error> {
292 let et: EventType = value.payload.try_into()?;
293 match et {
294 #[cfg(feature = "query")]
295 EventType::Qry(qry) => signed_query(qry, value.attachments),
296 #[cfg(feature = "mailbox")]
297 EventType::MailboxQry(qry) => signed_management_query(qry, value.attachments),
298 #[cfg(feature = "oobi")]
299 EventType::Rpy(rpy) => signed_reply(rpy, value.attachments),
300 #[cfg(feature = "mailbox")]
301 EventType::Exn(exn) => signed_exchange(exn, value.attachments),
302 _ => Err(ParseError::WrongEventType(
303 "Cannot convert SignedEventData to Op".to_string(),
304 )),
305 }
306 }
307}
308
309#[cfg(feature = "query")]
310impl TryFrom<ParsedData> for SignedQueryMessage {
311 type Error = ParseError;
312
313 fn try_from(value: ParsedData) -> Result<Self, Self::Error> {
314 match Op::try_from(value)? {
315 Op::Query(qry) => Ok(qry),
316 _ => Err(ParseError::WrongEventType(
318 "Cannot convert SignedEventData to SignedQuery".to_string(),
319 )),
320 }
321 }
322}
323
324#[cfg(feature = "query")]
325impl TryFrom<ParsedData> for SignedReply {
326 type Error = ParseError;
327
328 fn try_from(value: ParsedData) -> Result<Self, Self::Error> {
329 match Op::try_from(value)? {
330 Op::Reply(rpy) => Ok(rpy),
331 _ => Err(ParseError::WrongEventType(
332 "Cannot convert SignedEventData to SignedReply".to_string(),
333 )),
334 }
335 }
336}
337
338#[cfg(feature = "mailbox")]
339impl TryFrom<ParsedData> for SignedExchange {
340 type Error = ParseError;
341
342 fn try_from(value: ParsedData) -> Result<Self, Self::Error> {
343 match Op::try_from(value)? {
344 Op::Exchange(exn) => Ok(exn),
345 _ => Err(ParseError::WrongEventType(
346 "Cannot convert SignedEventData to SignedExchange".to_string(),
347 )),
348 }
349 }
350}
351
352#[cfg(feature = "query")]
353fn signed_reply(rpy: ReplyEvent, mut attachments: Vec<Group>) -> Result<Op, ParseError> {
354 use said::SelfAddressingIdentifier;
355
356 match attachments
357 .pop()
358 .ok_or_else(|| ParseError::AttachmentError("Missing attachment".into()))?
359 {
360 Group::NontransReceiptCouples(couplets) => {
361 let signer = couplets[0].0.clone();
362 let signature = couplets[0].1.clone();
363 Ok(Op::Reply(SignedReply::new_nontrans(
364 rpy,
365 signer.into(),
366 signature.into(),
367 )))
368 }
369 Group::TransIndexedSigGroups(data) => {
370 let (prefix, sn, digest, sigs) = data
371 .last()
373 .ok_or_else(|| ParseError::AttachmentError("More than one seal".into()))?
374 .to_owned();
375 let seal = EventSeal::new(
376 prefix.into(),
377 sn,
378 SelfAddressingIdentifier::from(digest).into(),
379 );
380 let sigs = sigs.into_iter().map(|sig| sig.into()).collect();
381 Ok(Op::Reply(SignedReply::new_trans(rpy, seal, sigs)))
382 }
383 Group::Frame(atts) => signed_reply(rpy, atts),
384 _ => {
385 Err(ParseError::AttachmentError("Improper payload type".into()))
387 }
388 }
389}
390
391#[cfg(feature = "query")]
392fn signed_query(qry: QueryEvent, mut attachments: Vec<Group>) -> Result<Op, ParseError> {
393 use super::signature::get_signatures;
394
395 let att = attachments
396 .pop()
397 .ok_or_else(|| ParseError::AttachmentError("Missing attachment".into()))?;
398 let sigs = get_signatures(att)?;
399 let qry = SignedQueryMessage::KelQuery(SignedKelQuery {
400 query: qry,
401 signature: sigs
403 .get(0)
404 .ok_or(ParseError::AttachmentError("Missing attachment".into()))?
405 .clone(),
406 });
407 Ok(Op::Query(qry))
408}
409
410#[cfg(feature = "mailbox")]
411fn signed_management_query(
412 qry: MailboxQuery,
413 mut attachments: Vec<Group>,
414) -> Result<Op, ParseError> {
415 use super::signature::get_signatures;
416
417 let att = attachments
418 .pop()
419 .ok_or_else(|| ParseError::AttachmentError("Missing attachment".into()))?;
420 let sigs = get_signatures(att)?;
421 let qry = SignedQueryMessage::MailboxQuery(SignedMailboxQuery {
422 query: qry,
423 signature: sigs
425 .get(0)
426 .ok_or(ParseError::AttachmentError("Missing attachment".into()))?
427 .clone(),
428 });
429 Ok(Op::Query(qry))
430}
431
432fn signed_key_event(
433 event_message: KeriEvent<KeyEvent>,
434 mut attachments: Vec<Group>,
435) -> Result<Notice, ParseError> {
436 match event_message.data.get_event_data() {
437 EventData::Dip(_) | EventData::Drt(_) => {
438 let (att1, att2) = (
439 attachments
440 .pop()
441 .ok_or_else(|| ParseError::AttachmentError("Missing attachment".into()))?,
442 attachments.pop(),
443 );
444
445 let (seals, sigs) = match (att1, att2) {
446 (
447 Group::SourceSealCouples(seals),
448 Some(Group::IndexedControllerSignatures(sigs)),
449 ) => Ok((Some(seals), sigs)),
450 (
451 Group::IndexedControllerSignatures(sigs),
452 Some(Group::SourceSealCouples(seals)),
453 ) => Ok((Some(seals), sigs)),
454 (Group::IndexedControllerSignatures(sigs), None) => Ok((None, sigs)),
455 _ => {
456 Err(ParseError::AttachmentError(
458 "Improper attachment type".into(),
459 ))
460 }
461 }?;
462
463 let delegator_seal = if let Some(seal) = seals {
464 match seal.len() {
465 0 => Err(ParseError::AttachmentError("Missing delegator seal".into())),
466 1 => Ok(seal.first().map(|seal| seal.clone().into())),
467 _ => Err(ParseError::AttachmentError("Too many seals".into())),
468 }
469 } else {
470 Ok(None)
471 };
472 let signatures = sigs.into_iter().map(|sig| sig.into()).collect();
473
474 Ok(Notice::Event(SignedEventMessage::new(
475 &event_message,
476 signatures,
477 None,
478 delegator_seal?,
479 )))
480 }
481 _ => {
482 let signatures = if let Group::Frame(atts) = attachments
483 .first()
484 .cloned()
485 .ok_or_else(|| ParseError::AttachmentError("Missing attachment".into()))?
486 {
487 atts
488 } else {
489 attachments
490 };
491 let controller_sigs = signatures
492 .iter()
493 .cloned()
494 .find_map(|att| {
495 if let Group::IndexedControllerSignatures(sigs) = att {
496 Some(sigs.into_iter().map(|sig| sig.into()).collect())
497 } else {
498 None
499 }
500 })
501 .ok_or_else(|| {
502 ParseError::AttachmentError("Missing controller signatures attachment".into())
503 })?;
504 let witness_sigs: Vec<_> = signatures
505 .into_iter()
506 .filter_map(|att| match att {
507 Group::IndexedWitnessSignatures(indexed) => Some(Nontransferable::Indexed(
508 indexed.into_iter().map(|sig| sig.into()).collect(),
509 )),
510 Group::NontransReceiptCouples(couples) => Some(Nontransferable::Couplet(
511 couples
512 .into_iter()
513 .map(|(bp, sp)| (bp.into(), sp.into()))
514 .collect(),
515 )),
516 _ => None,
517 })
518 .collect();
519
520 Ok(Notice::Event(SignedEventMessage::new(
521 &event_message,
522 controller_sigs,
523 if witness_sigs.is_empty() {
524 None
525 } else {
526 Some(witness_sigs)
527 },
528 None,
530 )))
531 }
532 }
533}
534
535fn signed_receipt(
536 event_message: Receipt,
537 mut attachments: Vec<Group>,
538) -> Result<Notice, ParseError> {
539 let nontransferable = attachments
540 .iter()
541 .filter_map(|att| match att {
542 Group::IndexedWitnessSignatures(sigs) => {
543 let converted_signatures = sigs.iter().map(|sig| sig.clone().into()).collect();
544 Some(Nontransferable::Indexed(converted_signatures))
545 }
546 Group::NontransReceiptCouples(couples) => Some(Nontransferable::Couplet(
547 couples
548 .into_iter()
549 .map(|(bp, sp)| (bp.clone().into(), sp.clone().into()))
550 .collect(),
551 )),
552 _ => None,
553 })
554 .collect();
555 let att = attachments
556 .pop()
557 .ok_or_else(|| ParseError::AttachmentError("Missing attachment".into()))?;
558
559 match att {
560 Group::NontransReceiptCouples(_) | Group::IndexedWitnessSignatures(_) => {
562 Ok(Notice::NontransferableRct(SignedNontransferableReceipt {
563 body: event_message,
564 signatures: nontransferable,
565 }))
566 }
567 Group::TransIndexedSigGroups(data) => {
568 let (prefix, sn, event_digest, sigs) = data
570 .last()
572 .ok_or_else(|| ParseError::AttachmentError("Empty seals".into()))?;
573 let seal = EventSeal::new(
574 prefix.clone().into(),
575 *sn,
576 SelfAddressingIdentifier::from(event_digest.clone()).into(),
577 );
578 let converted_signatures = sigs.iter().map(|sig| sig.clone().into()).collect();
579 Ok(Notice::TransferableRct(SignedTransferableReceipt::new(
580 event_message,
581 seal,
582 converted_signatures,
583 )))
584 }
585 Group::Frame(atts) => signed_receipt(event_message, atts),
586 _ => {
587 Err(ParseError::AttachmentError("Improper payload type".into()))
589 }
590 }
591}
592
593#[cfg(feature = "mailbox")]
594pub fn signed_exchange(exn: ExchangeMessage, attachments: Vec<Group>) -> Result<Op, ParseError> {
595 use crate::event_message::signature::get_signatures;
596
597 use super::signature::Signature;
598
599 let mut atts = attachments.into_iter();
600 let att1 = atts
601 .next()
602 .ok_or_else(|| ParseError::AttachmentError("Missing attachment".into()))?;
603 let att2 = atts
604 .next()
605 .ok_or_else(|| ParseError::AttachmentError("Missing attachment".into()))?;
606 let (path, data_sigs, signatures): (_, _, Vec<Signature>) = match (att1, att2) {
607 (Group::PathedMaterialQuadruplet(path, sigs), anything)
608 | (anything, Group::PathedMaterialQuadruplet(path, sigs)) => {
609 (path, sigs, get_signatures(anything)?)
610 }
611 _ => return Err(ParseError::AttachmentError("Wrong attachment".into())),
612 };
613 let data_signatures: Result<Vec<Signature>, ParseError> =
614 data_sigs.into_iter().fold(Ok(vec![]), |acc, group| {
615 let mut signatures: Vec<Signature> = get_signatures(group)?;
616 let mut sigs = acc?;
617 sigs.append(&mut signatures);
618 Ok(sigs)
619 });
620
621 Ok(Op::Exchange(SignedExchange {
622 exchange_message: exn,
623 signature: signatures,
624 data_signature: (path, data_signatures?),
625 }))
626}
627
628#[cfg(test)]
629pub mod test {
630 use cesrox::{parse, parse_many};
631
632 use crate::{
633 event::{receipt::Receipt, KeyEvent},
634 event_message::msg::KeriEvent,
635 };
636
637 #[test]
638 fn test_signed_event() {
639 let stream = br#"{"v":"KERI10JSON0001e7_","t":"icp","d":"EBfxc4RiVY6saIFmUfEtETs1FcqmktZW88UkbnOg0Qen","i":"EBfxc4RiVY6saIFmUfEtETs1FcqmktZW88UkbnOg0Qen","s":"0","kt":"2","k":["DErocgXD2RGSyvn3MObcx59jeOsEQhv2TqHirVkzrp0Q","DFXLiTjiRdSBPLL6hLa0rskIxk3dh4XwJLfctkJFLRSS","DE9YgIQVgpLwocTVrG8tidKScsQSMWwLWywNC48fhq4f"],"nt":"2","n":["EDJk5EEpC4-tQ7YDwBiKbpaZahh1QCyQOnZRF7p2i8k8","EAXfDjKvUFRj-IEB_o4y-Y_qeJAjYfZtOMD9e7vHNFss","EN8l6yJC2PxribTN0xfri6bLz34Qvj-x3cNwcV3DvT2m"],"bt":"0","b":[],"c":[],"a":[]}-AADAAD4SyJSYlsQG22MGXzRGz2PTMqpkgOyUfq7cS99sC2BCWwdVmEMKiTEeWe5kv-l_d9auxdadQuArLtAGEArW8wEABD0z_vQmFImZXfdR-0lclcpZFfkJJJNXDcUNrf7a-mGsxNLprJo-LROwDkH5m7tVrb-a1jcor2dHD9Jez-r4bQIACBFeU05ywfZycLdR0FxCvAR9BfV9im8tWe1DglezqJLf-vHRQSChY1KafbYNc96hYYpbuN90WzuCRMgV8KgRsEC"#;
641 let parsed = parse(stream);
642 assert!(parsed.is_ok());
643 assert_eq!(parsed.unwrap().1.to_cesr().unwrap(), stream);
644 }
645
646 #[test]
647 fn test_key_event_parsing() {
648 let stream = br#"{"v":"KERI10JSON0000fd_","t":"icp","d":"EMW0zK3bagYPO6gx3w7Ua90f-I7x5kGIaI4Xeq9W8_As","i":"BFs8BBx86uytIM0D2BhsE5rrqVIT8ef8mflpNceHo4XH","s":"0","kt":"1","k":["BFs8BBx86uytIM0D2BhsE5rrqVIT8ef8mflpNceHo4XH"],"nt":"0","n":[],"bt":"0","b":[],"c":[],"a":[]}"#;
650 let event: KeriEvent<KeyEvent> = serde_json::from_slice(stream).unwrap();
651 assert_eq!(event.encode().unwrap(), stream);
652
653 let stream = br#"{"v":"KERI10JSON000160_","t":"rot","d":"EFl8nvRCbN2xQJI75nBXp-gaXuHJw8zheVjwMN_rB-pb","i":"DFs8BBx86uytIM0D2BhsE5rrqVIT8ef8mflpNceHo4XH","s":"1","p":"EJQUyxnzIAtmZPoq9f4fExeGN0qfJmaFnUEKTwIiTBPj","kt":"1","k":["DB4GWvru73jWZKpNgMQp8ayDRin0NG0Ymn_RXQP_v-PQ"],"nt":"1","n":["EIsKL3B6Zz5ICGxCQp-SoLXjwOrdlSbLJrEn21c2zVaU"],"bt":"0","br":[],"ba":[],"a":[]}"#;
655 let event: KeriEvent<KeyEvent> = serde_json::from_slice(stream).unwrap();
656 assert_eq!(event.encode().unwrap(), stream);
657
658 let stream = br#"{"v":"KERI10JSON0000cb_","t":"ixn","d":"EKKccCumVQdgxvsrSXvuTtjmS28Xqf3zRJ8T6peKgl9J","i":"DFs8BBx86uytIM0D2BhsE5rrqVIT8ef8mflpNceHo4XH","s":"2","p":"ECauhEzA4DJDXVDnNQiGQ0sKXa6sx_GgS8Ebdzm4E-kQ","a":[]}"#;
660 let event: KeriEvent<KeyEvent> = serde_json::from_slice(stream).unwrap();
661 assert_eq!(event.encode().unwrap(), stream);
662
663 let stream = br#"{"v":"KERI10JSON00013a_","t":"ixn","d":"EJtQndkvwnMpVGE5oVVbLWSCm-jLviGw1AOOkzBvNwsS","i":"EA_SbBUZYwqLVlAAn14d6QUBQCSReJlZ755JqTgmRhXH","s":"1","p":"EA_SbBUZYwqLVlAAn14d6QUBQCSReJlZ755JqTgmRhXH","a":[{"i":"EHng2fV42DdKb5TLMIs6bbjFkPNmIdQ5mSFn6BTnySJj","s":"0","d":"EHng2fV42DdKb5TLMIs6bbjFkPNmIdQ5mSFn6BTnySJj"}]}"#;
665 let event: KeriEvent<KeyEvent> = serde_json::from_slice(stream).unwrap();
666 assert_eq!(event.encode().unwrap(), stream);
667
668 let stream = br#"{"v":"KERI10JSON00015f_","t":"dip","d":"EHng2fV42DdKb5TLMIs6bbjFkPNmIdQ5mSFn6BTnySJj","i":"EHng2fV42DdKb5TLMIs6bbjFkPNmIdQ5mSFn6BTnySJj","s":"0","kt":"1","k":["DLitcfMnabnLt-PNCaXdVwX45wsG93Wd8eW9QiZrlKYQ"],"nt":"1","n":["EDjXvWdaNJx7pAIr72Va6JhHxc7Pf4ScYJG496ky8lK8"],"bt":"0","b":[],"c":[],"a":[],"di":"EA_SbBUZYwqLVlAAn14d6QUBQCSReJlZ755JqTgmRhXH"}"#;
670 let event: KeriEvent<KeyEvent> = serde_json::from_slice(stream).unwrap();
671 assert_eq!(event.encode().unwrap(), stream);
672
673 let stream = br#"{"v":"KERI10JSON000160_","t":"drt","d":"EMBBBkaLV7i6wNgfz3giib2ItrHsr548mtIflW0Hrbuv","i":"EN3PglLbr4mJblS4dyqbqlpUa735hVmLOhYUbUztxaiH","s":"4","p":"EANkcl_QewzrRSKH2p9zUskHI462CuIMS_HQIO132Z30","kt":"1","k":["DPLt4YqQsWZ5DPztI32mSyTJPRESONvE9KbETtCVYIeH"],"nt":"1","n":["EIsKL3B6Zz5ICGxCQp-SoLXjwOrdlSbLJrEn21c2zVaU"],"bt":"0","br":[],"ba":[],"a":[]}"#;
675 let event: KeriEvent<KeyEvent> = serde_json::from_slice(stream).unwrap();
676 assert_eq!(event.encode().unwrap(), stream);
677 }
678
679 #[test]
680 fn test_receipt_parsing() {
681 let stream = br#"{"v":"KERI10JSON000091_","t":"rct","d":"EKKccCumVQdgxvsrSXvuTtjmS28Xqf3zRJ8T6peKgl9J","i":"DFs8BBx86uytIM0D2BhsE5rrqVIT8ef8mflpNceHo4XH","s":"0"}"#;
683 let event = parse(stream).unwrap().1;
684 assert_eq!(event.to_cesr().unwrap(), stream);
685
686 let event: Receipt = serde_json::from_slice(stream).unwrap();
687 assert_eq!(event.encode().unwrap(), stream.to_vec());
688 }
689
690 #[cfg(feature = "query")]
691 #[test]
692 fn test_qry() {
693 use std::convert::TryInto;
694
695 use crate::event_message::cesr_adapter::EventType;
696 let qry_event = br#"{"v":"KERI10JSON000105_","t":"qry","d":"EHtaQHsKzezkQUEYjMjEv6nIf4AhhR9Zy6AvcfyGCXkI","dt":"2021-01-01T00:00:00.000000+00:00","r":"logs","rr":"","q":{"s":0,"i":"EIaGMMWJFPmtXznY1IIiKDIrg-vIyge6mBl2QV8dDjI3","src":"BGKVzj4ve0VSd8z_AmvhLg4lqcC_9WYX90k03q-R_Ydo"}}"#;
698 let rest = "something more".as_bytes();
699 let stream = [qry_event, rest].concat();
700
701 let (_extra, event) = parse(&stream).unwrap();
702 assert!(matches!(
703 event.payload.clone().try_into().unwrap(),
704 EventType::Qry(_)
705 ));
706 assert_eq!(&event.to_cesr().unwrap(), qry_event);
707 }
708
709 #[cfg(feature = "mailbox")]
710 #[test]
711 fn test_exn() {
712 use crate::event_message::cesr_adapter::EventType;
713 use std::convert::TryInto;
714 let exn_event = br#"{"v":"KERI10JSON0002f1_","t":"exn","d":"EBLqTGJXK8ViUGXMOO8_LXbetpjJX8CY_SbA134RIZmf","dt":"2022-10-25T09:53:04.119676+00:00","r":"/fwd","q":{"pre":"EKYLUMmNPZeEs77Zvclf0bSN5IN-mLfLpx2ySb-HDlk4","topic":"multisig"},"a":{"v":"KERI10JSON000215_","t":"icp","d":"EC61gZ9lCKmHAS7U5ehUfEbGId5rcY0D7MirFZHDQcE2","i":"EC61gZ9lCKmHAS7U5ehUfEbGId5rcY0D7MirFZHDQcE2","s":"0","kt":"2","k":["DOZlWGPfDHLMf62zSFzE8thHmnQUOgA3_Y-KpOyF9ScG","DHGb2qY9WwZ1sBnC9Ip0F-M8QjTM27ftI-3jTGF9mc6K"],"nt":"2","n":["EBvD5VIVvf6NpP9GRmTqu_Cd1KN0RKrKNfPJ-uhIxurj","EHlpcaxffvtcpoUUMTc6tpqAVtb2qnOYVk_3HRsZ34PH"],"bt":"3","b":["BBilc4-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha","BLskRTInXnMxWaGqcpSyMgo0nYbalW99cGZESrz3zapM","BIKKuvBwpmDVA4Ds-EpL5bt9OqPzWPja2LigFYZN2YfX"],"c":[],"a":[]}}-HABEJccSRTfXYF6wrUVuenAIHzwcx3hJugeiJsEKmndi5q1-AABAAArUSuSpts5zDQ7CgPcy305IxhAG8lOjf-r_d5yYQXp18OD9No_gd2McOOjGWMfjyLVjDK529pQcbvNv9Uwc6gH-LAZ5AABAA-a-AABAABYHc_lpuYF3SPNWvyPjzek7yquw69Csc6pLv5vrXHkFAFDcwNNTVxq7ZpxpqOO0CAIS-9Qj1zMor-cwvMHAmkE')"#;
715
716 let (_extra, event) = parse(exn_event).unwrap();
717 assert!(matches!(
718 event.payload.try_into().unwrap(),
719 EventType::Exn(_)
720 ));
721 }
722
723 #[cfg(feature = "query")]
724 #[test]
725 fn test_reply() {
726 use crate::event_message::cesr_adapter::EventType;
727 use std::convert::TryInto;
728 let rpy = br#"{"v":"KERI10JSON00029d_","t":"rpy","d":"EYFMuK9IQmHvq9KaJ1r67_MMCq5GnQEgLyN9YPamR3r0","dt":"2021-01-01T00:00:00.000000+00:00","r":"/ksn/E7YbTIkWWyNwOxZQTTnrs6qn8jFbu2A8zftQ33JYQFQ0","a":{"v":"KERI10JSON0001e2_","i":"E7YbTIkWWyNwOxZQTTnrs6qn8jFbu2A8zftQ33JYQFQ0","s":"3","p":"EF7f4gNFCbJz6ZHLacIi_bbIq7kaWAFOzX7ncU_vs5Qg","d":"EOPSPvHHVmU9IIdHa5ksisoVrOnmHRps_tx3OsZSQQ30","f":"3","dt":"2021-01-01T00:00:00.000000+00:00","et":"rot","kt":"1","k":["DrcAz_gmDTuWIHn_mOQDeSK_aJIRiw5IMzPD7igzEDb0"],"nt":"1","n":["EK7ZUmFebD2st48Yvtzc9LajV3Yg2mkeeDzVRL-7uKrU"],"bt":"0","b":[],"c":[],"ee":{"s":"3","d":"EOPSPvHHVmU9IIdHa5ksisoVrOnmHRps_tx3OsZSQQ30","br":[],"ba":[]},"di":""}}-VA0-FABE7YbTIkWWyNwOxZQTTnrs6qn8jFbu2A8zftQ33JYQFQ00AAAAAAAAAAAAAAAAAAAAAAwEOPSPvHHVmU9IIdHa5ksisoVrOnmHRps_tx3OsZSQQ30-AABAAYsqumzPM0bIo04gJ4Ln0zAOsGVnjHZrFjjjS49hGx_nQKbXuD1D4J_jNoEa4TPtPDnQ8d0YcJ4TIRJb-XouJBg"#;
729 let rest = "something more".as_bytes();
730 let stream = [rpy, rest].concat();
731
732 let (_extra, event) = parse(&stream).unwrap();
733 assert!(matches!(
734 event.payload.try_into().unwrap(),
735 EventType::Rpy(_)
736 ));
737 }
738
739 #[cfg(feature = "query")]
740 #[test]
741 fn test_signed_qry() {
742 let stream = br#"{"v":"KERI10JSON0000c9_","t":"qry","d":"E-WvgxrllmjGFhpn0oOiBkAVz3-dEm3bbiV_5qwj81xo","dt":"2021-01-01T00:00:00.000000+00:00","r":"log","rr":"","q":{"i":"DyvCLRr5luWmp7keDvDuLP0kIqcyBYq79b3Dho1QvrjI"}}-VAj-HABEZOIsLsfrVdBvULlg3Hg_Y1r-hadS82ZpglBLojPIQhg-AABAAuISeZIVO_wXjIrGJ-VcVMxr285OkKzAqVEQqVPFx8Ht2A9GQFB-zRA18J1lpqVphOnnXbTc51WR4uAvK90EHBg"#;
744 let se = parse(&stream[..stream.len() - 1]);
745 assert!(se.is_err());
746 let se = parse(stream);
747 assert!(se.is_ok());
748 }
749
750 #[test]
751 fn test_signed_events_stream() {
752 let kerl_str= br#"{"v":"KERI10JSON000120_","t":"icp","d":"EG4EuTsxPiRM7soX10XXzNsS1KqXKUp8xsQ-kW_tWHoI","i":"DSuhyBcPZEZLK-fcw5tzHn2N46wRCG_ZOoeKtWTOunRA","s":"0","kt":"1","k":["DSuhyBcPZEZLK-fcw5tzHn2N46wRCG_ZOoeKtWTOunRA"],"n":"EPYuj8mq_PYYsoBKkzX1kxSPGYBWaIya3slgCOyOtlqU","bt":"0","b":[],"c":[],"a":[]}-AABAA0aSisI4ZZTH_6JCqsvAsEpuf_Jq6bDbvPWj_eCDnAGbSARqYHipNs-9W7MHnwnMfIXwLpcoJkKGrQ-SiaklhAw{"v":"KERI10JSON000155_","t":"rot","d":"Ej30AgJV14mTTs427F3kILLrP_l03a27APg2FBO0-QtA","i":"DSuhyBcPZEZLK-fcw5tzHn2N46wRCG_ZOoeKtWTOunRA","s":"1","p":"EG4EuTsxPiRM7soX10XXzNsS1KqXKUp8xsQ-kW_tWHoI","kt":"1","k":["DVcuJOOJF1IE8svqEtrSuyQjGTd2HhfAkt9y2QkUtFJI"],"n":"E-dapdcC6XR1KWmWDsNl4J_OxcGxNZw1Xd95JH5a34fI","bt":"0","br":[],"ba":[],"a":[]}-AABAAwoiqt07w2UInzzo2DmtwkBfqX1-tTO4cYk_7YdlbJ95qA7PO5sEUkER8fZySQMNCVh64ruAh1yoew3TikwVGAQ{"v":"KERI10JSON000155_","t":"rot","d":"EmtXXRjyz6IdeX4201BgXKRDBm74gGqJF2r2umMMAL6I","i":"DSuhyBcPZEZLK-fcw5tzHn2N46wRCG_ZOoeKtWTOunRA","s":"2","p":"Ej30AgJV14mTTs427F3kILLrP_l03a27APg2FBO0-QtA","kt":"1","k":["DT1iAhBWCkvChxNWsby2J0pJyxBIxbAtbLA0Ljx-Grh8"],"n":"EKrLE2h2nh3ClyJNEjKaikHWT7G-ngimNpK-QgVQv9As","bt":"0","br":[],"ba":[],"a":[]}-AABAAW_RsDfAcHkknyzh9oeliH90KGPJEI8AP3rJPyuTnpVg8yOVtSIp_JFlyRwjV5SEQOqddAcRV6JtaQO8oXtWFCQ{"v":"KERI10JSON0000cb_","t":"ixn","d":"EY7E4RJXPe7FF1zQPbpSMIY-TYz9eAmNIhuprPYqTQ5o","i":"DSuhyBcPZEZLK-fcw5tzHn2N46wRCG_ZOoeKtWTOunRA","s":"3","p":"EmtXXRjyz6IdeX4201BgXKRDBm74gGqJF2r2umMMAL6I","a":[]}-AABAAlB0Ui5NHJpcifXUB6bAutmpZkhSgwxyI5jEZ2JGVBgTI02sC0Ugbq3q0EpOae7ruXW-eabUz2s0FAs26jGwVBg{"v":"KERI10JSON0000cb_","t":"ixn","d":"ENVzbZieVIjYLYkPWQy0gfua11KqdRG-oku5Ut8Dl6hU","i":"DSuhyBcPZEZLK-fcw5tzHn2N46wRCG_ZOoeKtWTOunRA","s":"4","p":"EY7E4RJXPe7FF1zQPbpSMIY-TYz9eAmNIhuprPYqTQ5o","a":[]}-AABAAWITFg460TXvYvxxzN62vpqpLs-vGgeGAbd-onY3DYxd5e3AljHh85pTum4Ha48F5dui9IVYqYvuYJCG8p8KvDw{"v":"KERI10JSON000155_","t":"rot","d":"E6wrLhilpPo4ePq7m7ZccEcKjwPD2q9mqzLUb_aO2Hi0","i":"DSuhyBcPZEZLK-fcw5tzHn2N46wRCG_ZOoeKtWTOunRA","s":"5","p":"ENVzbZieVIjYLYkPWQy0gfua11KqdRG-oku5Ut8Dl6hU","kt":"1","k":["DKPE5eeJRzkRTMOoRGVd2m18o8fLqM2j9kaxLhV3x8AQ"],"n":"EhVTfJFfl6L0Z0432mDUxeaqB_hlWPJ2qUuzG95gEyJU","bt":"0","br":[],"ba":[],"a":[]}-AABAAnqz-vnMx1cqe_SkcIrlx092UhbYzvvkHXjtxfuNDDcqnVtH11_8ZPaWomn3n963_bFTjjRhJaAH1SK8LU7s1DA{"v":"KERI10JSON0000cb_","t":"ixn","d":"Ek9gvRbkCt-wlgQBoV1PGm2iI__gaPURtJ3YrNFsXLzE","i":"DSuhyBcPZEZLK-fcw5tzHn2N46wRCG_ZOoeKtWTOunRA","s":"6","p":"E6wrLhilpPo4ePq7m7ZccEcKjwPD2q9mqzLUb_aO2Hi0","a":[]}-AABAAwGGWMNDpu8t4NuF_3M0jnkn3P063oUHmluwRwsyCg5tIvu-BfwIJRruAsCKry4LaI84dJAfAT5KJnG8xz9lJCw"#;
754 let (rest, messages) = parse_many(kerl_str).unwrap();
755
756 assert!(rest.is_empty());
757 assert_eq!(messages.len(), 7);
758 }
759}