Skip to main content

clawft_kernel/licence/
mesh_config.rs

1//! The mesh id from node config (ADR-106 section 3): the genesis pin and the
2//! operator's `mesh_nonce`, both 64 hex chars, both in `kernel.mesh`.
3
4use super::MeshId;
5use crate::workload_pkg::codec::hex_decode_exact;
6
7/// Why the configured pin or nonce gives no mesh id.
8#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
9pub enum MeshIdConfigError {
10    /// `genesis_hash` is not 64 hex chars.
11    #[error("kernel.mesh.genesis_hash must be 64 hex characters")]
12    BadGenesis,
13    /// `mesh_nonce` is not 64 hex chars.
14    #[error("kernel.mesh.mesh_nonce must be 64 hex characters (32 random bytes)")]
15    BadNonce,
16}
17
18/// Derive the local mesh id. `Ok(None)` while either value is absent: the
19/// licence path then stays inert (the policy equals `ManifestPolicy`). A
20/// malformed value is an error, never a silent `None`, so the caller can say
21/// why checkout stays off.
22pub fn mesh_id_from_config(
23    genesis_hash: Option<&str>,
24    mesh_nonce: Option<&str>,
25) -> Result<Option<MeshId>, MeshIdConfigError> {
26    let nonce = match mesh_nonce {
27        Some(n) => Some(hex_decode_exact::<32>(n).ok_or(MeshIdConfigError::BadNonce)?),
28        None => None,
29    };
30    let pin = match genesis_hash {
31        Some(g) => Some(hex_decode_exact::<32>(g).ok_or(MeshIdConfigError::BadGenesis)?),
32        None => None,
33    };
34    Ok(match (pin, nonce) {
35        (Some(p), Some(n)) => Some(MeshId::derive(&p, &n)),
36        _ => None,
37    })
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43
44    const PIN: &str = "aa00000000000000000000000000000000000000000000000000000000000001";
45    const NONCE: &str = "bb00000000000000000000000000000000000000000000000000000000000002";
46
47    #[test]
48    fn needs_both_and_matches_derive() {
49        assert_eq!(mesh_id_from_config(Some(PIN), None), Ok(None));
50        assert_eq!(mesh_id_from_config(None, Some(NONCE)), Ok(None));
51        let id = mesh_id_from_config(Some(PIN), Some(NONCE)).unwrap().unwrap();
52        assert_eq!(id, MeshId::derive(&[0xaa, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], &[0xbb, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]));
53        let other = "cc00000000000000000000000000000000000000000000000000000000000002";
54        assert_ne!(Some(id), mesh_id_from_config(Some(PIN), Some(other)).unwrap());
55    }
56
57    #[test]
58    fn malformed_values_are_errors() {
59        assert_eq!(mesh_id_from_config(Some(PIN), Some("zz")), Err(MeshIdConfigError::BadNonce));
60        assert_eq!(mesh_id_from_config(Some("12"), Some(NONCE)), Err(MeshIdConfigError::BadGenesis));
61        assert_eq!(mesh_id_from_config(None, Some("zz")), Err(MeshIdConfigError::BadNonce));
62    }
63}