hbkr-rs 0.3.2

Hashblock Key Rotation
Documentation
//! hbkr Event module

use crate::{
    basicpre::BasicPrefix,
    dummy_event::DummyInceptionEvent,
    errors::KrError,
    event_data::EventData,
    event_message::EventMessage,
    identifier_prefix::IdentifierPrefix,
    identifier_state::{IdentifierState, LastEstablishmentData},
    key_config::KeyConfig,
    key_event_message::KeyEvent,
    said::{SelfAddressing, SelfAddressingPrefix},
    seal::Seal,
    serialization_info::SerializationFormats,
    witness_config::{InceptionWitnessConfig, WitnessConfig},
    EventSemantics, EventTypeTag, SaidEvent, Typeable,
};
use serde::{Deserialize, Serialize};
use serde_hex::{Compact, SerHex};
#[derive(Clone, Debug)]
pub enum EventType {
    Inception,
    Rotation,
    Delegation,
    Termination,
}

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub struct Event {
    #[serde(rename = "i")]
    pub prefix: IdentifierPrefix,

    #[serde(rename = "s", with = "SerHex::<Compact>")]
    pub sn: u64,

    #[serde(flatten)]
    pub event_data: EventData,
}

impl Event {
    pub fn new(prefix: IdentifierPrefix, sn: u64, event_data: EventData) -> Self {
        Event {
            prefix,
            sn,
            event_data,
        }
    }

    pub fn to_message(
        self,
        format: SerializationFormats,
        derivation: &SelfAddressing,
    ) -> Result<EventMessage<KeyEvent>, KrError> {
        match (&self.prefix, self.event_data.clone()) {
            (IdentifierPrefix::SelfAddressing(_), EventData::Icp(icp)) => {
                icp.incept_self_addressing(derivation.clone(), format)
            }
            (IdentifierPrefix::SelfAddressing(_), EventData::Dip(dip)) => {
                dip.incept_self_addressing(derivation.clone(), format)
            }
            _ => SaidEvent::<Event>::to_message(self, format, derivation),
        }
    }
}

impl Typeable for Event {
    fn get_type(&self) -> EventTypeTag {
        self.event_data.get_type()
    }
}

impl EventSemantics for Event {
    fn apply_to(&self, state: IdentifierState) -> Result<IdentifierState, KrError> {
        match self.event_data {
            EventData::Icp(_) | EventData::Dip(_) => {
                // ICP events require the state to be uninitialized
                if state.prefix != IdentifierPrefix::default() {
                    return Err(KrError::EventDuplicateError);
                }
                if self.sn != 0 {
                    return Err(KrError::SemanticError("SN is not correct".to_string()));
                }
            }
            _ => {
                // prefix must equal.
                if self.prefix != state.prefix {
                    return Err(KrError::SemanticError("Prefix does not match".to_string()));
                // sn must be incremented
                // TODO recovery will break this rule when we implement it
                } else if self.sn < state.sn + 1 {
                    return Err(KrError::EventDuplicateError);
                } else if self.sn > state.sn + 1 {
                    return Err(KrError::EventOutOfOrderError);
                }
            }
        };
        self.event_data.apply_to(IdentifierState {
            sn: self.sn,
            prefix: self.prefix.clone(),
            ..state
        })
    }
}

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
// #[derive(Clone, Debug, PartialEq)]
pub struct KrInceptionEvent {
    #[serde(flatten)]
    pub key_config: KeyConfig,
    #[serde(flatten)]
    pub witness_config: InceptionWitnessConfig,
    #[serde(rename = "c")]
    pub inception_configuration: Vec<String>,
    #[serde(rename = "a")]
    pub data: Vec<Seal>,
}

impl KrInceptionEvent {
    pub fn new(
        key_config: KeyConfig,
        witness_config: Option<InceptionWitnessConfig>,
        inception_config: Option<Vec<String>>,
    ) -> Self {
        Self {
            key_config,
            witness_config: witness_config.map_or_else(InceptionWitnessConfig::default, |w| w),
            inception_configuration: inception_config.map_or_else(Vec::new, |c| c),
            data: vec![],
        }
    }

    /// Incept Self Addressing
    ///
    /// Takes the inception data and creates an EventMessage based on it, with
    /// using the given format and deriving a Self Addressing Identifier with the
    /// given derivation method
    pub fn incept_self_addressing(
        self,
        derivation: SelfAddressing,
        format: SerializationFormats,
    ) -> Result<EventMessage<KeyEvent>, KrError> {
        let dummy_event =
            DummyInceptionEvent::dummy_inception_data(self.clone(), &derivation, format)?;
        let digest = derivation.derive(&dummy_event.serialize()?);
        let event = Event::new(
            IdentifierPrefix::SelfAddressing(digest.clone()),
            0,
            EventData::Icp(self),
        );
        Ok(EventMessage {
            serialization_info: dummy_event.serialization_info,
            event: SaidEvent::new(digest, event),
        })
    }
}

impl EventSemantics for KrInceptionEvent {
    fn apply_to(&self, state: IdentifierState) -> Result<IdentifierState, KrError> {
        let last_est = LastEstablishmentData {
            sn: state.sn,
            digest: state.last_event_digest.clone(),
            br: vec![],
            ba: vec![],
        };
        Ok(IdentifierState {
            current: self.key_config.clone(),

            // tally: self.witness_config.tally,
            last_est,
            ..state
        })
    }
}

/// Rotation Event
///
/// Describes the rotation (rot) event data
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub struct KrRotationEvent {
    #[serde(rename = "p")]
    pub previous_event_hash: SelfAddressingPrefix,
    #[serde(flatten)]
    pub key_config: KeyConfig,
    #[serde(flatten)]
    pub witness_config: WitnessConfig,
    #[serde(rename = "a")]
    pub data: Vec<Seal>,
}

impl EventSemantics for KrRotationEvent {
    fn apply_to(&self, state: IdentifierState) -> Result<IdentifierState, KrError> {
        if state.current.verify_next(&self.key_config) {
            // witness rotation processing
            let witnesses =
                if !self.witness_config.prune.is_empty() || !self.witness_config.graft.is_empty() {
                    let mut prunned = state
                        .witnesses
                        .into_iter()
                        .filter(|e| !self.witness_config.prune.contains(e))
                        .collect::<Vec<BasicPrefix>>();
                    prunned.append(&mut self.witness_config.graft.clone());
                    prunned
                } else {
                    state.witnesses.clone()
                };
            let last_est = LastEstablishmentData {
                sn: state.sn,
                digest: state.last_event_digest.clone(),
                br: self.witness_config.graft.clone(),
                ba: self.witness_config.prune.clone(),
            };

            Ok(IdentifierState {
                current: self.key_config.clone(),
                tally: self.witness_config.tally,
                witnesses,
                last_est,
                ..state
            })
        } else {
            Err(KrError::SemanticError(
                "Incorrect Key Config binding".into(),
            ))
        }
    }
}