keri_core/event/event_data/
inception.rs

1use super::{
2    super::sections::{InceptionWitnessConfig, KeyConfig},
3    EventData,
4};
5use crate::{
6    error::Error,
7    event::{sections::seal::Seal, KeyEvent},
8    event_message::{dummy_event::DummyInceptionEvent, msg::KeriEvent, Typeable},
9    prefix::IdentifierPrefix,
10    state::{EventSemantics, IdentifierState, LastEstablishmentData},
11};
12use said::version::format::SerializationFormats;
13use said::{
14    derivation::{HashFunction, HashFunctionCode},
15    sad::SAD,
16};
17use serde::{Deserialize, Serialize};
18
19/// Inception Event
20///
21/// Describes the inception (icp) event data,
22#[derive(
23    Serialize,
24    Deserialize,
25    Debug,
26    Clone,
27    PartialEq,
28    rkyv::Archive,
29    rkyv::Serialize,
30    rkyv::Deserialize,
31)]
32#[rkyv(derive(Debug))]
33pub struct InceptionEvent {
34    #[serde(flatten)]
35    pub key_config: KeyConfig,
36
37    #[serde(flatten)]
38    pub witness_config: InceptionWitnessConfig,
39
40    #[serde(rename = "c")]
41    pub inception_configuration: Vec<String>,
42
43    #[serde(rename = "a")]
44    pub data: Vec<Seal>,
45}
46
47impl InceptionEvent {
48    pub fn new(
49        key_config: KeyConfig,
50        witness_config: Option<InceptionWitnessConfig>,
51        inception_config: Option<Vec<String>>,
52    ) -> Self {
53        Self {
54            key_config,
55            witness_config: witness_config.map_or_else(InceptionWitnessConfig::default, |w| w),
56            inception_configuration: inception_config.map_or_else(Vec::new, |c| c),
57            data: vec![],
58        }
59    }
60
61    /// Incept Self Addressing
62    ///
63    /// Takes the inception data and creates an EventMessage based on it, with
64    /// using the given format and deriving a Self Addressing Identifier with the
65    /// given derivation method
66    pub fn incept_self_addressing(
67        self,
68        derivation: HashFunction,
69        format: SerializationFormats,
70    ) -> Result<KeriEvent<KeyEvent>, Error> {
71        let code: HashFunctionCode = derivation.into();
72        let mut dummy_event =
73            DummyInceptionEvent::dummy_inception_data(self.clone(), &code, format)?;
74        dummy_event.compute_digest(&code, &format);
75        let digest = dummy_event.prefix.unwrap();
76        let event = KeyEvent::new(
77            IdentifierPrefix::self_addressing(digest.clone()),
78            0,
79            EventData::Icp(self),
80        );
81        Ok(KeriEvent {
82            serialization_info: dummy_event.serialization_info,
83            event_type: event.get_type(),
84            digest: Some(digest.into()),
85            data: event,
86        })
87    }
88}
89
90impl EventSemantics for InceptionEvent {
91    fn apply_to(&self, state: IdentifierState) -> Result<IdentifierState, Error> {
92        let last_est = LastEstablishmentData {
93            sn: state.sn,
94            digest: state.last_event_digest.clone(),
95            br: vec![],
96            ba: vec![],
97        };
98
99        Ok(IdentifierState {
100            current: self.key_config.clone(),
101            witness_config: self.witness_config.clone().into(),
102            last_est,
103            ..state
104        })
105    }
106}
107
108#[test]
109fn test_inception_data_derivation() -> Result<(), Error> {
110    use crate::event::sections::{
111        key_config::KeyConfig, key_config::NextKeysData, threshold::SignatureThreshold,
112    };
113    use crate::prefix::BasicPrefix;
114    use cesrox::primitives::CesrPrimitive;
115    use said::{derivation::HashFunctionCode, SelfAddressingIdentifier};
116
117    let keys: Vec<BasicPrefix> = vec![
118        "DErocgXD2RGSyvn3MObcx59jeOsEQhv2TqHirVkzrp0Q"
119            .parse()
120            .unwrap(),
121        "DFXLiTjiRdSBPLL6hLa0rskIxk3dh4XwJLfctkJFLRSS"
122            .parse()
123            .unwrap(),
124        "DE9YgIQVgpLwocTVrG8tidKScsQSMWwLWywNC48fhq4f"
125            .parse()
126            .unwrap(),
127    ];
128    let next_keys_hashes: Vec<SelfAddressingIdentifier> = vec![
129        "EDJk5EEpC4-tQ7YDwBiKbpaZahh1QCyQOnZRF7p2i8k8"
130            .parse()
131            .unwrap(),
132        "EAXfDjKvUFRj-IEB_o4y-Y_qeJAjYfZtOMD9e7vHNFss"
133            .parse()
134            .unwrap(),
135        "EN8l6yJC2PxribTN0xfri6bLz34Qvj-x3cNwcV3DvT2m"
136            .parse()
137            .unwrap(),
138    ];
139
140    let next_keys_data = NextKeysData::new(SignatureThreshold::Simple(2), next_keys_hashes);
141    let key_config = KeyConfig::new(keys, next_keys_data, Some(SignatureThreshold::Simple(2)));
142    let icp_data = InceptionEvent::new(key_config.clone(), None, None).incept_self_addressing(
143        HashFunctionCode::Blake3_256.into(),
144        SerializationFormats::JSON,
145    )?;
146
147    let icp_digest = icp_data.digest()?;
148    assert_eq!(
149        "EBfxc4RiVY6saIFmUfEtETs1FcqmktZW88UkbnOg0Qen",
150        icp_data.data.get_prefix().to_str()
151    );
152    assert_eq!(
153        "EBfxc4RiVY6saIFmUfEtETs1FcqmktZW88UkbnOg0Qen",
154        icp_digest.to_str()
155    );
156
157    assert!(icp_digest.verify_binding(&icp_data.to_derivation_data().unwrap()));
158
159    Ok(())
160}