pic_continuity/artifacts/
pca.rs1use super::check_profile;
20use crate::authority::indexed::IndexedAuthorityMap;
21use crate::cose::CoseSigned;
22use crate::error::RejectReason;
23use serde::{Deserialize, Serialize};
24
25#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
28pub struct PcaChallenge {
29 #[serde(with = "serde_bytes")]
32 pub next_challenge: Vec<u8>,
33}
34
35#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
37pub struct PicPcaPayload {
38 pub profile: String,
40 pub position: u64,
42 pub context_of_authority: IndexedAuthorityMap,
44 pub challenge: PcaChallenge,
46}
47
48impl PicPcaPayload {
49 pub fn new(position: u64, context: IndexedAuthorityMap, next_challenge: Vec<u8>) -> Self {
52 Self {
53 profile: crate::PROFILE_0_2.to_string(),
54 position,
55 context_of_authority: context,
56 challenge: PcaChallenge { next_challenge },
57 }
58 }
59
60 pub fn check_profile(&self) -> Result<(), RejectReason> {
62 check_profile("pic-pca+cose", &self.profile)
63 }
64
65 pub fn validate(&self) -> Result<(), RejectReason> {
67 self.check_profile()?;
68 if self.challenge.next_challenge.is_empty() {
69 return Err(RejectReason::NextChallengeInvalid);
70 }
71 self.context_of_authority.validate()
72 }
73}
74
75pub type PicPcaCose = CoseSigned<PicPcaPayload>;
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81 use crate::authority::{AuthorityValue, Invariant, LogicalAuthority};
82 use std::collections::BTreeMap;
83
84 fn sample_map() -> IndexedAuthorityMap {
85 let mut contract = BTreeMap::new();
86 contract.insert("corporation".into(), AuthorityValue::One("ACME".into()));
87 let logical = LogicalAuthority::new(
88 None,
89 vec![Invariant::new("storage:save", "save", "storage", "*")],
90 contract,
91 );
92 IndexedAuthorityMap::from_logical(&logical).unwrap()
93 }
94
95 #[test]
96 fn pca_cbor_roundtrip() {
97 let pca = PicPcaPayload::new(0, sample_map(), b"challenge-0".to_vec());
98 let mut buf = Vec::new();
99 ciborium::into_writer(&pca, &mut buf).unwrap();
100 let decoded: PicPcaPayload = ciborium::from_reader(buf.as_slice()).unwrap();
101 assert_eq!(pca, decoded);
102 assert!(decoded.check_profile().is_ok());
103 }
104}