use super::*;
impl<N: Network> Stack<N> {
#[inline]
pub(crate) fn initialize(process: &Process<N>, program: &Program<N>) -> Result<Self> {
let mut stack = Self {
program: program.clone(),
external_stacks: Default::default(),
register_types: Default::default(),
finalize_types: Default::default(),
universal_srs: process.universal_srs().clone(),
proving_keys: Default::default(),
verifying_keys: Default::default(),
};
for import in program.imports().keys() {
if !process.contains_program(import) {
bail!("Cannot add program '{}' because its import '{import}' must be added first", program.id())
}
let external_stack = process.get_stack(import)?;
stack.insert_external_stack(external_stack.clone())?;
}
for closure in program.closures().values() {
stack.insert_closure(closure)?;
}
for function in program.functions().values() {
stack.insert_function(function)?;
}
Ok(stack)
}
}
impl<N: Network> Stack<N> {
#[inline]
fn insert_external_stack(&mut self, external_stack: Stack<N>) -> Result<()> {
let program_id = *external_stack.program_id();
ensure!(!self.external_stacks.contains_key(&program_id), "Program '{program_id}' already exists");
ensure!(self.program.contains_import(&program_id), "'{program_id}' does not exist in the main program imports");
ensure!(self.program.id() != external_stack.program_id(), "External stack program cannot be the main program");
self.external_stacks.insert(program_id, external_stack);
Ok(())
}
#[inline]
fn insert_closure(&mut self, closure: &Closure<N>) -> Result<()> {
let name = closure.name();
ensure!(!self.register_types.contains_key(name), "Closure '{name}' already exists");
let register_types = RegisterTypes::from_closure(self, closure)?;
self.register_types.insert(*name, register_types);
Ok(())
}
#[inline]
fn insert_function(&mut self, function: &Function<N>) -> Result<()> {
let name = function.name();
ensure!(!self.register_types.contains_key(name), "Function '{name}' already exists");
let register_types = RegisterTypes::from_function(self, function)?;
self.register_types.insert(*name, register_types);
if let Some((_, finalize)) = function.finalize() {
let finalize_types = FinalizeTypes::from_finalize(self, finalize)?;
self.finalize_types.insert(*name, finalize_types);
}
Ok(())
}
}