Skip to main content

keri_controller/identifier/mechanics/
kel_managing.rs

1use keri_core::{
2    actor::{event_generator, prelude::SelfAddressingIdentifier},
3    event::{
4        event_data::EventData,
5        sections::{seal::Seal, KeyConfig},
6        KeyEvent,
7    },
8    event_message::{
9        cesr_adapter::{parse_event_type, EventType},
10        msg::KeriEvent,
11        signed_event_message::{Message, Notice},
12    },
13    oobi::{LocationScheme, Scheme},
14    prefix::{BasicPrefix, IdentifierPrefix, IndexedSignature, SelfSigningPrefix},
15};
16
17use keri_core::prefix::CesrPrimitive;
18
19use crate::identifier::Identifier;
20
21use super::MechanicsError;
22
23impl Identifier {
24    /// Generate and return rotation event for Identifier
25    pub async fn rotate(
26        &self,
27        current_keys: Vec<BasicPrefix>,
28        new_next_keys: Vec<BasicPrefix>,
29        new_next_threshold: u64,
30        witness_to_add: Vec<LocationScheme>,
31        witness_to_remove: Vec<BasicPrefix>,
32        witness_threshold: u64,
33    ) -> Result<String, MechanicsError> {
34        for wit_oobi in &witness_to_add {
35            self.communication.resolve_loc_schema(wit_oobi).await?;
36        }
37
38        let witnesses_to_add = witness_to_add
39            .iter()
40            .map(|wit| {
41                if let IdentifierPrefix::Basic(bp) = &wit.eid {
42                    Ok(bp.clone())
43                } else {
44                    Err(MechanicsError::WrongWitnessPrefixError)
45                }
46            })
47            .collect::<Result<Vec<_>, _>>()?;
48
49        let state = self.known_events.get_state(&self.id)?;
50
51        event_generator::rotate(
52            state,
53            current_keys,
54            new_next_keys,
55            new_next_threshold,
56            witnesses_to_add,
57            witness_to_remove,
58            witness_threshold,
59        )
60        .map_err(|e| MechanicsError::EventGenerationError(e.to_string()))
61    }
62
63    /// Generate and return interaction event for Identifier
64    pub fn anchor(&self, payload: &[SelfAddressingIdentifier]) -> Result<String, MechanicsError> {
65        let state = self.known_events.get_state(&self.id)?;
66        event_generator::anchor(state, payload)
67            .map_err(|e| MechanicsError::EventGenerationError(e.to_string()))
68    }
69
70    pub fn anchor_with_seal(
71        &self,
72        seal_list: &[Seal],
73    ) -> Result<KeriEvent<KeyEvent>, MechanicsError> {
74        let state = self.known_events.get_state(&self.id)?;
75        event_generator::anchor_with_seal(state, seal_list)
76            .map_err(|e| MechanicsError::EventGenerationError(e.to_string()))
77    }
78
79    pub async fn finalize_rotate(
80        &mut self,
81        event: &[u8],
82        sig: SelfSigningPrefix,
83    ) -> Result<(), MechanicsError> {
84        let parsed_event =
85            parse_event_type(event).map_err(|_e| MechanicsError::EventFormatError)?;
86        if let EventType::KeyEvent(ke) = parsed_event {
87            // Provide kel for new witnesses
88            // TODO  should add to notify_witness instead of sending directly?
89            match &ke.data.event_data {
90                EventData::Rot(rot) | EventData::Drt(rot) => {
91                    let own_kel = self.known_events.find_kel_with_receipts(&self.id).unwrap();
92                    for witness in &rot.witness_config.graft {
93                        let witness_id = IdentifierPrefix::Basic(witness.clone());
94                        for msg in &own_kel {
95                            self.communication
96                                .send_message_to(
97                                    witness_id.clone(),
98                                    Scheme::Http,
99                                    Message::Notice(msg.clone()),
100                                )
101                                .await?;
102                        }
103                    }
104                }
105                _ => (),
106            };
107            self.finalize_key_event(&ke, &sig)?;
108            Ok(())
109        } else {
110            Err(MechanicsError::WrongEventTypeError)
111        }
112    }
113
114    pub async fn finalize_anchor(
115        &mut self,
116        event: &[u8],
117        sig: SelfSigningPrefix,
118    ) -> Result<(), MechanicsError> {
119        let parsed_event =
120            parse_event_type(event).map_err(|_e| MechanicsError::EventFormatError)?;
121        if let EventType::KeyEvent(ke) = parsed_event {
122            match &ke.data.event_data {
123                EventData::Ixn(_) => self.finalize_key_event(&ke, &sig),
124                _ => Err(MechanicsError::WrongEventTypeError),
125            }
126        } else {
127            Err(MechanicsError::WrongEventTypeError)
128        }
129    }
130
131    /// Checks signatures and updates database.
132    /// Must call [`IdentifierController::notify_witnesses`] after calling this function if event is a key event.
133    pub(crate) fn finalize_key_event(
134        &mut self,
135        event: &KeriEvent<KeyEvent>,
136        sig: &SelfSigningPrefix,
137    ) -> Result<(), MechanicsError> {
138        let own_index = self.get_index(&event.data).unwrap();
139        let signature = IndexedSignature::new_both_same(sig.clone(), own_index as u16);
140
141        let signed_message = event.sign(vec![signature], None, None);
142        self.known_events
143            .save(&Message::Notice(Notice::Event(signed_message.clone())))?;
144
145        let st = self.cached_state.clone().apply(event)?;
146        self.cached_state = st;
147
148        self.to_notify.push(signed_message);
149
150        Ok(())
151    }
152
153    pub fn index_in_current_keys(&self, key_config: &KeyConfig) -> Result<usize, MechanicsError> {
154        // TODO what if group participant is a group and has more than one
155        // public key?
156        let own_pk = self.known_events.current_public_keys(&self.id)?[0].clone();
157        key_config
158            .public_keys
159            .iter()
160            .position(|pk| pk.eq(&own_pk))
161            .ok_or(MechanicsError::NotGroupParticipantError)
162    }
163
164    /// Helper function for getting the position of identifier's public key in
165    /// group's current keys list.
166    pub(crate) fn get_index(&self, key_event: &KeyEvent) -> Result<usize, MechanicsError> {
167        match &key_event.event_data {
168            EventData::Icp(icp) => self.index_in_current_keys(&icp.key_config),
169            EventData::Rot(rot) => {
170                let own_npk = &self.known_events.next_keys_hashes(&self.id)?[0];
171                rot.key_config
172                    .public_keys
173                    .iter()
174                    .position(|pk| own_npk.verify_binding(pk.to_str().as_bytes()))
175                    .ok_or(MechanicsError::NotGroupParticipantError)
176            }
177            EventData::Dip(dip) => self.index_in_current_keys(&dip.inception_data.key_config),
178            EventData::Drt(drt) => {
179                let own_npk = &self.known_events.next_keys_hashes(&self.id)?[0];
180                drt.key_config
181                    .public_keys
182                    .iter()
183                    .position(|pk| own_npk.verify_binding(pk.to_str().as_bytes()))
184                    .ok_or(MechanicsError::NotGroupParticipantError)
185            }
186            EventData::Ixn(_ixn) => {
187                let own_pk = self.known_events.current_public_keys(&self.id)?[0].clone();
188                self.known_events
189                    .current_public_keys(&key_event.get_prefix())?
190                    .iter()
191                    .position(|pk| pk.eq(&own_pk))
192                    .ok_or(MechanicsError::NotGroupParticipantError)
193            }
194        }
195    }
196}