pub mod cesr_adapter;
pub mod dummy_event;
pub mod event_msg_builder;
pub mod key_event_message;
pub mod msg;
pub mod serializer;
pub mod signature;
pub mod signed_event_message;
pub mod timestamped;
use std::cmp::Ordering;
use crate::event::KeyEvent;
use chrono::{DateTime, Local};
use serde::{Deserialize, Serialize};
use self::msg::KeriEvent;
pub trait Typeable {
type TypeTag;
fn get_type(&self) -> Self::TypeTag;
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum EventTypeTag {
Icp,
Rot,
Ixn,
Dip,
Drt,
Rct,
Exn,
#[cfg(feature = "query")]
Rpy,
Qry,
}
#[derive(Serialize, Deserialize, PartialEq)]
pub struct TimestampedEventMessage {
pub timestamp: DateTime<Local>,
pub event_message: KeriEvent<KeyEvent>,
}
impl TimestampedEventMessage {
pub fn new(event: KeriEvent<KeyEvent>) -> Self {
Self {
timestamp: Local::now(),
event_message: event,
}
}
}
impl PartialOrd for TimestampedEventMessage {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(
match self.event_message.data.get_sn() == other.event_message.data.get_sn() {
true => Ordering::Equal,
false => {
match self.event_message.data.get_sn() > other.event_message.data.get_sn() {
true => Ordering::Greater,
false => Ordering::Less,
}
}
},
)
}
}
impl Ord for TimestampedEventMessage {
fn cmp(&self, other: &Self) -> Ordering {
match self.event_message.data.get_sn() == other.event_message.data.get_sn() {
true => Ordering::Equal,
false => match self.event_message.data.get_sn() > other.event_message.data.get_sn() {
true => Ordering::Greater,
false => Ordering::Less,
},
}
}
}
impl Eq for TimestampedEventMessage {}
impl From<TimestampedEventMessage> for KeriEvent<KeyEvent> {
fn from(event: TimestampedEventMessage) -> KeriEvent<KeyEvent> {
event.event_message
}
}
impl From<KeriEvent<KeyEvent>> for TimestampedEventMessage {
fn from(event: KeriEvent<KeyEvent>) -> TimestampedEventMessage {
TimestampedEventMessage::new(event)
}
}
#[cfg(test)]
mod tests {
mod test_utils;
use self::test_utils::test_mock_event_sequence;
use super::{event_msg_builder::EventMsgBuilder, *};
use crate::{
error::Error,
event::{
event_data::{inception::InceptionEvent, EventData},
sections::{
key_config::nxt_commitment, threshold::SignatureThreshold, InceptionWitnessConfig,
KeyConfig,
},
KeyEvent,
},
keys::{PrivateKey, PublicKey},
prefix::{BasicPrefix, IdentifierPrefix, IndexedSignature, SelfSigningPrefix},
signer::setup_signers,
state::{EventSemantics, IdentifierState},
};
use cesrox::primitives::CesrPrimitive;
use ed25519_dalek::Keypair;
use rand::rngs::OsRng;
use said::derivation::HashFunctionCode;
use said::version::format::SerializationFormats;
#[test]
fn basic_create() -> Result<(), Error> {
let kp0 = Keypair::generate(&mut OsRng);
let kp1 = Keypair::generate(&mut OsRng);
let pub_key0 = PublicKey::new(kp0.public.to_bytes().to_vec());
let priv_key0 = PrivateKey::new(kp0.secret.to_bytes().to_vec());
let (pub_key1, _priv_key1) = (
PublicKey::new(kp1.public.to_bytes().to_vec()),
PrivateKey::new(kp1.secret.to_bytes().to_vec()),
);
let pref0 = BasicPrefix::Ed25519(pub_key0);
let pref1 = BasicPrefix::Ed25519(pub_key1);
let nxt = nxt_commitment(
SignatureThreshold::Simple(1),
&vec![pref1],
&HashFunctionCode::Blake3_256.into(),
);
let icp = KeyEvent::new(
IdentifierPrefix::Basic(pref0.clone()),
0,
EventData::Icp(InceptionEvent {
key_config: KeyConfig::new(
vec![pref0.clone()],
nxt.clone(),
Some(SignatureThreshold::Simple(1)),
),
witness_config: InceptionWitnessConfig::default(),
inception_configuration: vec![],
data: vec![],
}),
);
let icp_m = icp.to_message(
SerializationFormats::JSON,
HashFunctionCode::Blake3_256.into(),
)?;
let ser: Vec<_> = icp_m.encode()?;
let sig = priv_key0.sign_ed(&ser)?;
let attached_sig =
IndexedSignature::new_both_same(SelfSigningPrefix::Ed25519Sha512(sig), 0);
assert!(pref0.verify(&ser, &attached_sig.signature)?);
let signed_event = icp_m.sign(vec![attached_sig], None, None);
let s_ = IdentifierState::default();
let s0 = s_.apply(&signed_event)?;
assert!(s0.current.verify(&ser, &signed_event.signatures)?);
assert_eq!(s0.prefix, IdentifierPrefix::Basic(pref0.clone()));
assert_eq!(s0.sn, 0);
assert!(icp_m.compare_digest(&s0.last_event_digest)?);
assert_eq!(s0.current.public_keys.len(), 1);
assert_eq!(s0.current.public_keys[0], pref0);
assert_eq!(s0.current.threshold, SignatureThreshold::Simple(1));
assert_eq!(s0.current.next_keys_data, nxt);
assert_eq!(s0.witness_config.witnesses, vec![]);
assert_eq!(s0.witness_config.tally, SignatureThreshold::Simple(0));
Ok(())
}
#[test]
fn self_addressing_create() -> Result<(), Error> {
let kp0 = Keypair::generate(&mut OsRng);
let kp1 = Keypair::generate(&mut OsRng);
let kp2 = Keypair::generate(&mut OsRng);
let pub_key0 = PublicKey::new(kp0.public.to_bytes().to_vec());
let priv_key0 = PrivateKey::new(kp0.secret.to_bytes().to_vec());
let (pub_key1, sig_key_1) = (
PublicKey::new(kp1.public.to_bytes().to_vec()),
PrivateKey::new(kp1.secret.to_bytes().to_vec()),
);
let (enc_key_0, _enc_priv_0) = (PublicKey::new(kp2.public.to_bytes().to_vec()), sig_key_1);
let (enc_key_1, _enc_priv_1) = (
PublicKey::new(kp2.public.to_bytes().to_vec()),
PrivateKey::new(kp2.secret.to_bytes().to_vec()),
);
let sig_pref_0 = BasicPrefix::Ed25519(pub_key0);
let enc_pref_0 = BasicPrefix::X25519(enc_key_0);
let sig_pref_1 = BasicPrefix::Ed25519(pub_key1);
let enc_pref_1 = BasicPrefix::X25519(enc_key_1);
let nexter_pref = nxt_commitment(
SignatureThreshold::default(),
&[sig_pref_1, enc_pref_1],
&HashFunctionCode::Blake3_256.into(),
);
let icp = InceptionEvent::new(
KeyConfig::new(
vec![sig_pref_0.clone(), enc_pref_0.clone()],
nexter_pref.clone(),
Some(SignatureThreshold::default()),
),
None,
None,
)
.incept_self_addressing(
HashFunctionCode::Blake3_256.into(),
SerializationFormats::JSON,
)?;
let serialized: Vec<_> = icp.encode()?;
let sk = priv_key0;
let sig = sk.sign_ed(&serialized)?;
let attached_sig =
IndexedSignature::new_both_same(SelfSigningPrefix::Ed25519Sha512(sig), 0);
assert!(sig_pref_0.verify(&serialized, &attached_sig.signature)?);
let signed_event = icp.sign(vec![attached_sig], None, None);
let s_ = IdentifierState::default();
let s0 = s_.apply(&signed_event)?;
assert!(s0.current.verify(&serialized, &signed_event.signatures)?);
assert_eq!(s0.prefix, icp.data.get_prefix());
assert_eq!(s0.sn, 0);
assert!(icp.compare_digest(&s0.last_event_digest)?);
assert_eq!(s0.current.public_keys.len(), 2);
assert_eq!(s0.current.public_keys[0], sig_pref_0);
assert_eq!(s0.current.public_keys[1], enc_pref_0);
assert_eq!(s0.current.threshold, SignatureThreshold::default());
assert_eq!(s0.current.next_keys_data, nexter_pref);
assert_eq!(s0.witness_config.witnesses, vec![]);
assert_eq!(s0.witness_config.tally, SignatureThreshold::Simple(0));
Ok(())
}
#[test]
fn test_basic_establishment_sequence() -> Result<(), Error> {
let no_inception_seq = vec![EventTypeTag::Rot, EventTypeTag::Rot];
assert!(test_mock_event_sequence(no_inception_seq).is_err());
let rotation_first_seq = vec![EventTypeTag::Rot, EventTypeTag::Icp];
assert!(test_mock_event_sequence(rotation_first_seq).is_err());
let wrong_seq = vec![
EventTypeTag::Icp,
EventTypeTag::Rot,
EventTypeTag::Rot,
EventTypeTag::Icp,
];
assert!(test_mock_event_sequence(wrong_seq).is_err());
let ok_seq = vec![EventTypeTag::Icp, EventTypeTag::Rot, EventTypeTag::Rot];
assert!(test_mock_event_sequence(ok_seq).is_ok());
let wrong_delegated_sequence =
vec![EventTypeTag::Dip, EventTypeTag::Drt, EventTypeTag::Rot];
assert!(test_mock_event_sequence(wrong_delegated_sequence).is_err());
let delegated_sequence = vec![EventTypeTag::Dip, EventTypeTag::Drt, EventTypeTag::Ixn];
assert!(test_mock_event_sequence(delegated_sequence).is_ok());
Ok(())
}
#[test]
fn test_basic_sequence() -> Result<(), Error> {
let ok_seq = vec![
EventTypeTag::Icp,
EventTypeTag::Ixn,
EventTypeTag::Ixn,
EventTypeTag::Ixn,
EventTypeTag::Rot,
EventTypeTag::Ixn,
];
assert!(test_mock_event_sequence(ok_seq).is_ok());
let delegated_sequence = vec![
EventTypeTag::Dip,
EventTypeTag::Drt,
EventTypeTag::Ixn,
EventTypeTag::Drt,
];
assert!(test_mock_event_sequence(delegated_sequence).is_ok());
Ok(())
}
#[test]
pub fn test_partial_rotation() -> Result<(), Error> {
let signers = setup_signers();
let keys = vec![BasicPrefix::Ed25519(signers[0].public_key())];
let next_pks = signers[1..6]
.iter()
.map(|signer| BasicPrefix::Ed25519(signer.public_key()))
.collect::<Vec<_>>();
let icp = EventMsgBuilder::new(EventTypeTag::Icp)
.with_keys(keys)
.with_threshold(&SignatureThreshold::Simple(1))
.with_next_keys(next_pks)
.with_next_threshold(&SignatureThreshold::single_weighted(vec![
(1, 2),
(1, 2),
(1, 3),
(1, 3),
(1, 3),
]))
.build()
.unwrap();
let id_prefix = icp.data.get_prefix();
let icp_digest = icp.digest()?;
assert_eq!(
id_prefix,
IdentifierPrefix::SelfAddressing(icp_digest.clone())
);
assert_eq!(
id_prefix.to_str(),
"EM2y0cPBcua33FMaji79hQ2NVq7mzIIEX8Zlw0Ch5OQQ"
);
let state = IdentifierState::default();
let state = icp.apply_to(state)?;
let current_signers = [&signers[3], &signers[4], &signers[5]];
let current_public_keys = current_signers
.iter()
.map(|sig| BasicPrefix::Ed25519(sig.public_key()))
.collect::<Vec<_>>();
let next_public_keys = signers[11..16]
.iter()
.map(|sig| BasicPrefix::Ed25519(sig.public_key()))
.collect::<Vec<_>>();
let rotation = EventMsgBuilder::new(EventTypeTag::Rot)
.with_prefix(&id_prefix)
.with_previous_event(&icp_digest)
.with_keys(current_public_keys.clone())
.with_threshold(&SignatureThreshold::single_weighted(vec![
(1, 2),
(1, 2),
(1, 3),
]))
.with_next_keys(next_public_keys)
.with_next_threshold(&SignatureThreshold::single_weighted(vec![
(1, 2),
(1, 2),
(1, 3),
(1, 3),
(1, 3),
]))
.build()?;
let rot_digest = rotation.digest()?;
let state = rotation.apply_to(state)?;
assert_eq!(state.sn, 1);
assert_eq!(&state.current.public_keys, ¤t_public_keys);
assert_eq!(
serde_json::to_string(&state.current.threshold).unwrap(),
"[\"1/2\",\"1/2\",\"1/3\"]"
);
let current_signers = [&signers[13], &signers[14]];
let next_public_keys = vec![];
let current_public_keys = current_signers
.iter()
.map(|sig| BasicPrefix::Ed25519(sig.public_key()))
.collect::<Vec<_>>();
let rotation = EventMsgBuilder::new(EventTypeTag::Rot)
.with_prefix(&id_prefix)
.with_keys(current_public_keys)
.with_threshold(&SignatureThreshold::Simple(2))
.with_next_keys(next_public_keys)
.with_next_threshold(&SignatureThreshold::Simple(0))
.with_sn(2)
.with_previous_event(&rot_digest)
.build()?;
let res = rotation.apply_to(state);
assert!(matches!(res.unwrap_err(), Error::NotEnoughSigsError));
Ok(())
}
}