macroonz_compiler/identity/transcript.rs
1//! The transcript byte string, written from the specification stated on [`Transcript`].
2//!
3//! It reads the transcript through the transcript's own accessors and touches no private field.
4//! The role's declared name and slot are not restated here either, and neither is the grammar's: the roster answers them at their declarations, and this file reads those answers back.
5//!
6//! The generator is not written.
7//! It is carried on the transcript for the derivation record and named by no grammar, so a producer's rendered shape moving renames nothing here.
8
9use super::encode::encode_bytes;
10use super::{Subject, Transcript};
11
12impl Transcript<'_> {
13 /// The transcript's bytes for one identity subject, exactly as the specification on [`Transcript`] states them.
14 ///
15 /// # Authority
16 ///
17 /// **The subject is the TYPE's and never an argument.** Member four of the preimage is the subject's declared name, and it is part of what separates one subject's identities from another's — so an encoder that took the name as text would let a caller write member four to any key space it could spell, and the typed identity above it would be a promise this road never had to keep.
18 #[must_use]
19 pub fn encoded<S: Subject>(&self) -> Vec<u8> {
20 let profile = self.profile();
21 let role = self.role();
22 let mut bytes = Vec::new();
23 encode_bytes(profile.stem().as_bytes(), &mut bytes);
24 encode_bytes(profile.name().as_bytes(), &mut bytes);
25 bytes.extend_from_slice(&profile.version().position().to_be_bytes());
26 encode_bytes(S::NAME.as_bytes(), &mut bytes);
27 encode_bytes(role.name().as_bytes(), &mut bytes);
28 bytes.push(role.slot());
29 bytes.push(self.anchoring().slot());
30 match self.anchoring().commitment() {
31 Some(anchor) => encode_bytes(anchor, &mut bytes),
32 None => encode_bytes(&[], &mut bytes),
33 }
34 encode_bytes(self.material(), &mut bytes);
35 bytes.extend_from_slice(&self.position().to_be_bytes());
36 bytes
37 }
38}