crates/guest-host/src/census.rs
//! **A module is named by its digest.**
//!
//! A file name is a label an operator chose; a digest is what was loaded. The
//! census a host reports (holger: `AdminService.ServerProfile`; monetize: the
//! console's product row) names each module by the blake3-256 of its bytes —
//! the same bytes [`crate::verify::ModuleTrust::verify`] checks the signature
//! over — so "which guest build is running" has one answer on every box.
/// Lowercase hex blake3-256 of `bytes`.
pub fn digest_hex(bytes: &[u8]) -> String {
blake3::hash(bytes).to_hex().to_string()
}
/// One census row: where a module came from, what it hashes to, who signed it.
///
/// A host extends this with its own facts (holger: kind, receipt, grants) — the
/// three here are the ones every host has.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CensusRow {
/// The module file name, or `linked` for a compiled-in guest.
pub origin: String,
/// Hex blake3-256 of the module bytes; empty for a linked guest, which has
/// no bytes to digest.
pub digest: String,
/// The verified signer's common name, when the module was loaded under a
/// trust policy. `None` means no provenance was REQUIRED — never "it failed
/// and we carried on", which is a load error and the module is not here.
pub signer: Option<String>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_digest_is_blake3_256_in_lowercase_hex() {
let d = digest_hex(b"\0asm\x01\0\0\0");
assert_eq!(d.len(), 64);
assert!(d.bytes().all(|b| matches!(b, b'0'..=b'9' | b'a'..=b'f')));
assert_ne!(d, digest_hex(b"\0asm\x01\0\0\0x"), "one byte changes the name");
}
}