ic_certification/
certificate.rs

1use crate::hash_tree::HashTree;
2
3/// A `Certificate` as defined in <https://internetcomputer.org/docs/current/references/ic-interface-spec/#certificate>
4#[derive(Debug, Clone, PartialEq, Eq)]
5#[cfg_attr(feature = "serde", derive(serde::Serialize))]
6#[cfg_attr(
7    feature = "serde",
8    serde(bound(serialize = "Storage: serde_bytes::Serialize"))
9)]
10pub struct Certificate<Storage: AsRef<[u8]>> {
11    /// The hash tree.
12    pub tree: HashTree<Storage>,
13
14    /// The signature of the root hash in `tree`.
15    #[cfg_attr(feature = "serde", serde(with = "serde_bytes"))]
16    pub signature: Storage,
17
18    /// A delegation from the root key to the key used to sign `signature`, if one exists.
19    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
20    pub delegation: Option<Delegation<Storage>>,
21}
22
23/// A `Delegation` as defined in <https://internetcomputer.org/docs/current/references/ic-interface-spec/#certification-delegation>
24#[derive(Debug, Clone, PartialEq, Eq)]
25#[cfg_attr(feature = "serde", derive(serde::Serialize))]
26#[cfg_attr(
27    feature = "serde",
28    serde(bound(serialize = "Storage: serde_bytes::Serialize"))
29)]
30pub struct Delegation<Storage: AsRef<[u8]>> {
31    #[cfg_attr(feature = "serde", serde(with = "serde_bytes"))]
32    pub subnet_id: Storage,
33
34    #[cfg_attr(feature = "serde", serde(with = "serde_bytes"))]
35    pub certificate: Storage,
36}
37
38#[cfg(feature = "serde")]
39mod serde_impl {
40    use super::{Certificate, Delegation};
41    use crate::{hash_tree::HashTreeNode, serde_impl::*};
42
43    use std::{borrow::Cow, fmt, marker::PhantomData};
44
45    use serde::{
46        de::{self, MapAccess, SeqAccess, Visitor},
47        Deserialize, Deserializer,
48    };
49
50    #[derive(Deserialize)]
51    #[serde(field_identifier, rename_all = "snake_case")]
52    enum CertificateField {
53        Tree,
54        Signature,
55        Delegation,
56    }
57    struct CertificateVisitor<S>(PhantomData<S>);
58
59    impl<'de, S: Storage> Visitor<'de> for CertificateVisitor<S>
60    where
61        Delegation<S::Value<'de>>: Deserialize<'de>,
62        HashTreeNode<S::Value<'de>>: Deserialize<'de>,
63    {
64        type Value = Certificate<S::Value<'de>>;
65
66        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
67            formatter.write_str("struct Delegation")
68        }
69
70        fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
71        where
72            V: SeqAccess<'de>,
73        {
74            let tree = seq
75                .next_element()?
76                .ok_or_else(|| de::Error::invalid_length(0, &self))?;
77            let signature = S::convert(
78                seq.next_element()?
79                    .ok_or_else(|| de::Error::invalid_length(1, &self))?,
80            );
81            let delegation = seq.next_element()?;
82
83            Ok(Certificate {
84                tree,
85                signature,
86                delegation,
87            })
88        }
89
90        fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
91        where
92            V: MapAccess<'de>,
93        {
94            let mut tree = None;
95            let mut signature = None;
96            let mut delegation = None;
97            while let Some(key) = map.next_key()? {
98                match key {
99                    CertificateField::Tree => {
100                        if tree.is_some() {
101                            return Err(de::Error::duplicate_field("tree"));
102                        }
103                        tree = Some(map.next_value()?);
104                    }
105                    CertificateField::Signature => {
106                        if signature.is_some() {
107                            return Err(de::Error::duplicate_field("signature"));
108                        }
109                        signature = Some(map.next_value()?);
110                    }
111                    CertificateField::Delegation => {
112                        if delegation.is_some() {
113                            return Err(de::Error::duplicate_field("signature"));
114                        }
115                        delegation = Some(map.next_value()?);
116                    }
117                }
118            }
119            let tree = tree.ok_or_else(|| de::Error::missing_field("tree"))?;
120            let signature =
121                S::convert(signature.ok_or_else(|| de::Error::missing_field("signature"))?);
122            Ok(Certificate {
123                tree,
124                signature,
125                delegation,
126            })
127        }
128    }
129
130    fn deserialize_certificate<'de, S: Storage, D>(
131        deserializer: D,
132    ) -> Result<Certificate<S::Value<'de>>, D::Error>
133    where
134        Delegation<S::Value<'de>>: Deserialize<'de>,
135        HashTreeNode<S::Value<'de>>: Deserialize<'de>,
136        D: Deserializer<'de>,
137    {
138        const FIELDS: &[&str] = &["tree", "signature", "delegation"];
139        deserializer.deserialize_struct("Certificate", FIELDS, CertificateVisitor::<S>(PhantomData))
140    }
141
142    impl<'de> Deserialize<'de> for Certificate<Vec<u8>> {
143        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
144        where
145            D: Deserializer<'de>,
146        {
147            deserialize_certificate::<VecStorage, _>(deserializer)
148        }
149    }
150
151    impl<'de> Deserialize<'de> for Certificate<&'de [u8]> {
152        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
153        where
154            D: Deserializer<'de>,
155        {
156            deserialize_certificate::<SliceStorage, _>(deserializer)
157        }
158    }
159
160    impl<'de> Deserialize<'de> for Certificate<Cow<'de, [u8]>> {
161        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
162        where
163            D: Deserializer<'de>,
164        {
165            deserialize_certificate::<CowStorage, _>(deserializer)
166        }
167    }
168
169    #[derive(Deserialize)]
170    #[serde(field_identifier, rename_all = "snake_case")]
171    enum DelegationField {
172        SubnetId,
173        Certificate,
174    }
175    struct DelegationVisitor<S>(PhantomData<S>);
176
177    impl<'de, S: Storage> Visitor<'de> for DelegationVisitor<S> {
178        type Value = Delegation<S::Value<'de>>;
179
180        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
181            formatter.write_str("struct Delegation")
182        }
183
184        fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
185        where
186            V: SeqAccess<'de>,
187        {
188            let subnet_id = S::convert(
189                seq.next_element()?
190                    .ok_or_else(|| de::Error::invalid_length(0, &self))?,
191            );
192            let certificate = S::convert(
193                seq.next_element()?
194                    .ok_or_else(|| de::Error::invalid_length(1, &self))?,
195            );
196            Ok(Delegation {
197                subnet_id,
198                certificate,
199            })
200        }
201
202        fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
203        where
204            V: MapAccess<'de>,
205        {
206            let mut subnet_id = None;
207            let mut certificate = None;
208            while let Some(key) = map.next_key()? {
209                match key {
210                    DelegationField::SubnetId => {
211                        if subnet_id.is_some() {
212                            return Err(de::Error::duplicate_field("subnet_id"));
213                        }
214                        subnet_id = Some(map.next_value()?);
215                    }
216                    DelegationField::Certificate => {
217                        if certificate.is_some() {
218                            return Err(de::Error::duplicate_field("certificate"));
219                        }
220                        certificate = Some(map.next_value()?);
221                    }
222                }
223            }
224            let subnet_id =
225                S::convert(subnet_id.ok_or_else(|| de::Error::missing_field("subnet_id"))?);
226            let certificate =
227                S::convert(certificate.ok_or_else(|| de::Error::missing_field("certificate"))?);
228            Ok(Delegation {
229                subnet_id,
230                certificate,
231            })
232        }
233    }
234
235    fn deserialize_delegation<'de, S: Storage, D>(
236        deserializer: D,
237    ) -> Result<Delegation<S::Value<'de>>, D::Error>
238    where
239        D: Deserializer<'de>,
240    {
241        const FIELDS: &[&str] = &["subnet_id", "certificate"];
242        deserializer.deserialize_struct("Delegation", FIELDS, DelegationVisitor::<S>(PhantomData))
243    }
244
245    impl<'de> Deserialize<'de> for Delegation<Vec<u8>> {
246        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
247        where
248            D: Deserializer<'de>,
249        {
250            deserialize_delegation::<VecStorage, _>(deserializer)
251        }
252    }
253
254    impl<'de> Deserialize<'de> for Delegation<&'de [u8]> {
255        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
256        where
257            D: Deserializer<'de>,
258        {
259            deserialize_delegation::<SliceStorage, _>(deserializer)
260        }
261    }
262
263    impl<'de> Deserialize<'de> for Delegation<Cow<'de, [u8]>> {
264        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
265        where
266            D: Deserializer<'de>,
267        {
268            deserialize_delegation::<CowStorage, _>(deserializer)
269        }
270    }
271}
272
273#[cfg(test)]
274#[cfg(feature = "serde")]
275mod tests {
276    use super::*;
277    use crate::hash_tree::{empty, fork, label, leaf};
278
279    fn create_tree() -> HashTree<Vec<u8>> {
280        fork(
281            fork(
282                label(
283                    "a",
284                    fork(
285                        fork(label("x", leaf(*b"hello")), empty()),
286                        label("y", leaf(*b"world")),
287                    ),
288                ),
289                label("b", leaf(*b"good")),
290            ),
291            fork(label("c", empty()), label("d", leaf(*b"morning"))),
292        )
293    }
294
295    #[test]
296    fn serialize_to_cbor() {
297        let tree = create_tree();
298        let signature = vec![1, 2, 3, 4, 5, 6];
299
300        let certificate = Certificate {
301            tree,
302            signature,
303            delegation: None,
304        };
305
306        let cbor_bytes =
307            serde_cbor::to_vec(&certificate).expect("Failed to encode certificate to cbor");
308        let cbor_hex = hex::encode(cbor_bytes);
309
310        assert_eq!(cbor_hex, "a264747265658301830183024161830183018302417882034568656c6c6f810083024179820345776f726c6483024162820344676f6f648301830241638100830241648203476d6f726e696e67697369676e617475726546010203040506");
311    }
312
313    #[test]
314    fn serialize_to_cbor_with_delegation() {
315        let tree = create_tree();
316        let signature = vec![1, 2, 3, 4, 5, 6];
317        let delegation = Delegation {
318            subnet_id: vec![7, 8, 9, 10, 11, 12],
319            certificate: vec![13, 14, 15, 16, 17, 18],
320        };
321
322        let certificate = Certificate {
323            tree,
324            signature,
325            delegation: Some(delegation),
326        };
327
328        let cbor_bytes =
329            serde_cbor::to_vec(&certificate).expect("Failed to encode certificate to cbor");
330        let cbor_hex = hex::encode(cbor_bytes);
331
332        assert_eq!(cbor_hex, "a364747265658301830183024161830183018302417882034568656c6c6f810083024179820345776f726c6483024162820344676f6f648301830241638100830241648203476d6f726e696e67697369676e6174757265460102030405066a64656c65676174696f6ea2697375626e65745f6964460708090a0b0c6b6365727469666963617465460d0e0f101112");
333    }
334}