dwn_core/message/
cid.rs

1use std::collections::TryReserveError;
2
3use ipld_core::cid::{Cid, multihash::Multihash};
4use serde::Serialize;
5use serde_ipld_dagcbor::EncodeError;
6use sha3::{Digest, Sha3_256};
7use thiserror::Error;
8
9#[derive(Error, Debug)]
10pub enum CidGenerationError {
11    #[error("failed to DAG-CBOR encoding: {0}")]
12    Encode(#[from] EncodeError<TryReserveError>),
13    #[error("failed to parse multihash: {0}")]
14    Multihash(#[from] ipld_core::cid::multihash::Error),
15}
16
17/// Returns a stringified CIDv1 of the provided data after DAG-CBOR serialization.
18pub fn compute_cid_cbor<T: Serialize>(value: &T) -> Result<String, CidGenerationError> {
19    let encoded = serde_ipld_dagcbor::to_vec(value)?;
20
21    let mut hasher = Sha3_256::new();
22    hasher.update(&encoded);
23    let hash = hasher.finalize();
24
25    let multihash = Multihash::wrap(CODE_SHA3_256, &hash)?;
26    let cid = Cid::new_v1(CODEC_DAG_CBOR, multihash);
27    Ok(cid.to_string())
28}
29
30const CODEC_DAG_CBOR: u64 = 0x71;
31const CODE_SHA3_256: u64 = 0x16;
32
33#[cfg(test)]
34mod tests {
35    use std::str::FromStr;
36
37    use super::*;
38
39    #[derive(Serialize)]
40    struct TestData {
41        hello: String,
42    }
43
44    #[test]
45    fn test_cid_cbor() {
46        let data = TestData {
47            hello: "world".to_string(),
48        };
49
50        let cid_str = compute_cid_cbor(&data).unwrap();
51
52        let cid = Cid::from_str(&cid_str).unwrap();
53        assert_eq!(cid.codec(), CODEC_DAG_CBOR);
54
55        let hash = cid.hash();
56        assert_eq!(hash.code(), CODE_SHA3_256);
57    }
58}