miden_protocol/protocol_config/
kernel_config.rs1use alloc::string::ToString;
2use alloc::vec::Vec;
3
4use miden_verifier::KernelDescriptor;
5
6use super::ProtocolConfigError;
7use crate::utils::serde::{
8 ByteReader,
9 ByteWriter,
10 Deserializable,
11 DeserializationError,
12 Serializable,
13};
14use crate::{Felt, Hasher, Word};
15
16#[derive(Debug, Clone, PartialEq, Eq)]
30pub struct KernelConfig {
31 main_proc: Word,
33
34 kernel_procs: Vec<Word>,
36}
37
38impl KernelConfig {
39 pub const MAX_NUM_KERNEL_PROCEDURES: usize = KernelDescriptor::MAX_NUM_PROCEDURES;
44
45 pub fn new(main_proc: Word, kernel_procs: Vec<Word>) -> Result<Self, ProtocolConfigError> {
55 if kernel_procs.len() > Self::MAX_NUM_KERNEL_PROCEDURES {
56 return Err(ProtocolConfigError::TooManyKernelProcedures { count: kernel_procs.len() });
57 }
58
59 Ok(Self { main_proc, kernel_procs })
60 }
61
62 pub fn main_proc(&self) -> Word {
67 self.main_proc
68 }
69
70 pub fn kernel_procs(&self) -> &[Word] {
72 &self.kernel_procs
73 }
74
75 pub fn num_kernel_procs(&self) -> u8 {
77 u8::try_from(self.kernel_procs.len())
78 .expect("constructor should validate num procs fits in u8")
79 }
80
81 pub fn kernel_procs_elements(&self) -> &[Felt] {
83 Word::words_as_elements(&self.kernel_procs)
84 }
85
86 pub fn kernel_procs_commitment(&self) -> Word {
88 Hasher::hash_elements(self.kernel_procs_elements())
89 }
90
91 pub fn to_commitment(&self) -> Word {
93 Hasher::merge(&[self.main_proc, self.kernel_procs_commitment()])
94 }
95
96 pub fn to_elements(&self) -> Vec<Felt> {
98 let kernel_procs_commitment = self.kernel_procs_commitment();
99 [self.main_proc.as_elements(), kernel_procs_commitment.as_elements()].concat()
100 }
101}
102
103impl Serializable for KernelConfig {
107 fn write_into<W: ByteWriter>(&self, target: &mut W) {
108 let num_kernel_procs = self.num_kernel_procs();
109 let Self { main_proc, kernel_procs } = self;
110
111 main_proc.write_into(target);
112 num_kernel_procs.write_into(target);
113 target.write_many(kernel_procs);
114 }
115}
116
117impl Deserializable for KernelConfig {
118 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
119 let main_proc = source.read()?;
120 let num_kernel_procs: u8 = source.read()?;
121 let kernel_procs = source
122 .read_many_iter(num_kernel_procs as usize)?
123 .collect::<Result<Vec<Word>, _>>()?;
124
125 Self::new(main_proc, kernel_procs)
126 .map_err(|err| DeserializationError::InvalidValue(err.to_string()))
127 }
128}
129
130#[cfg(test)]
134mod tests {
135 use alloc::vec;
136
137 use assert_matches::assert_matches;
138 use miden_crypto::rand::test_utils::rand_value;
139
140 use super::*;
141
142 #[test]
143 fn new_rejects_too_many_procedures() {
144 let procs = vec![Word::empty(); KernelConfig::MAX_NUM_KERNEL_PROCEDURES + 1];
145
146 let error = KernelConfig::new(Word::empty(), procs).unwrap_err();
147 assert_matches!(error, ProtocolConfigError::TooManyKernelProcedures { count } => {
148 assert_eq!(count, KernelConfig::MAX_NUM_KERNEL_PROCEDURES + 1);
149 });
150 }
151
152 #[test]
153 fn serde_round_trip() -> anyhow::Result<()> {
154 let config = KernelConfig::new(rand_value::<Word>(), vec![rand_value::<Word>(); 3])?;
155
156 let deserialized = KernelConfig::read_from_bytes(&config.to_bytes())?;
157 assert_eq!(config, deserialized);
158
159 Ok(())
160 }
161}