Skip to main content

teliox/state/
vc_state.rs

1use crate::{
2    error::Error,
3    event::vc_event::{VCEventMessage, VCEventType},
4};
5use said::SelfAddressingIdentifier;
6use serde::{Deserialize, Serialize};
7
8#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
9pub enum TelState {
10    #[default]
11    NotIssued,
12    Issued(SelfAddressingIdentifier),
13    Revoked,
14}
15
16impl TelState {
17    pub fn apply(&self, event: &VCEventMessage) -> Result<Self, Error> {
18        let event_content = event.data.data.clone();
19        match event_content.event_type {
20            VCEventType::Bis(_iss) => match self {
21                TelState::NotIssued => {
22                    if event_content.sn == 0 {
23                        Ok(TelState::Issued(event.digest()?))
24                    } else {
25                        Err(Error::Generic("Wrong sn".into()))
26                    }
27                }
28                _ => Err(Error::EventAlreadySavedError),
29            },
30            VCEventType::Brv(rev) => match self {
31                TelState::Issued(last) => {
32                    if rev.prev_event_hash.eq(last) && event_content.sn == 1 {
33                        Ok(TelState::Revoked)
34                    } else {
35                        Err(Error::Generic("Previous event doesn't match".to_string()))
36                    }
37                }
38                TelState::NotIssued => Err(Error::OutOfOrderError),
39                TelState::Revoked => Err(Error::Generic("Already revoked".into())),
40            },
41            VCEventType::Iss(_iss) => match self {
42                TelState::NotIssued => Ok(TelState::Issued(event.digest()?)),
43                _ => Err(Error::EventAlreadySavedError),
44            },
45            VCEventType::Rev(rev) => match self {
46                TelState::Issued(last) => {
47                    if &rev.prev_event_hash == last {
48                        Ok(TelState::Revoked)
49                    } else {
50                        Err(Error::Generic("Previous event doesn't match".to_string()))
51                    }
52                }
53                TelState::NotIssued => Err(Error::OutOfOrderError),
54                TelState::Revoked => Err(Error::Generic("Already revoked".into())),
55            },
56        }
57    }
58}
59
60#[test]
61fn test_apply() -> Result<(), Error> {
62    let bis_raw = r#"{"v":"KERI10JSON000162_","t":"bis","d":"EFXbFFjdUNRgg_blTx76RAdcIoRoLtPl5tA3yAw5vS9W","i":"EC8Oej-3HAUpBY_kxzBK3B-0RV9j4dXw1H0NRKxJg7g-","s":"0","ii":"EKKJ0FoLxO1TYmyuprguKO7kJ7Hbn0m0Wuk5aMtSrMtY","ra":{"i":"EIZlA3TANi3p8vEu4VQMjPnY0sPFAag1ekIwyyR6lAsq","s":"0","d":"EFSL6HebpbWsxKxfdS4t6NbKTdO4hAUIAxvhmWVf3Z8o"},"dt":"2023-01-10T10:36:50.842679+00:00"}"#;
63    let bis_ev: VCEventMessage = serde_json::from_str(&bis_raw).unwrap();
64    assert_eq!(serde_json::to_string(&bis_ev).unwrap(), bis_raw);
65
66    let brv_raw = r#"{"v":"KERI10JSON000161_","t":"brv","d":"ENJrZygsUPsqzxjrmgXIjweuQX5I2lXbgcGFn7iEyDyG","i":"EC8Oej-3HAUpBY_kxzBK3B-0RV9j4dXw1H0NRKxJg7g-","s":"1","p":"EFXbFFjdUNRgg_blTx76RAdcIoRoLtPl5tA3yAw5vS9W","ra":{"i":"EIZlA3TANi3p8vEu4VQMjPnY0sPFAag1ekIwyyR6lAsq","s":"0","d":"EFSL6HebpbWsxKxfdS4t6NbKTdO4hAUIAxvhmWVf3Z8o"},"dt":"2023-01-10T10:36:50.843652+00:00"}"#;
67    let brv_ev: VCEventMessage = serde_json::from_str(&brv_raw).unwrap();
68    assert_eq!(serde_json::to_string(&brv_ev).unwrap(), brv_raw);
69
70    let state = TelState::default();
71    let state = state.apply(&bis_ev)?;
72    assert!(matches!(state, TelState::Issued(_)));
73
74    if let TelState::Issued(last) = state.clone() {
75        match brv_ev.data.data.event_type {
76            VCEventType::Brv(ref brv) => assert!(brv.prev_event_hash == last),
77            _ => (),
78        };
79    }
80    let state = state.apply(&brv_ev)?;
81    assert_eq!(state, TelState::Revoked);
82
83    let state = state.apply(&brv_ev);
84    assert!(state.is_err());
85
86    Ok(())
87}