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(),
stacks: Arc::downgrade(&process.stacks),
register_types: Default::default(),
finalize_types: Default::default(),
universal_srs: process.universal_srs().clone(),
proving_keys: Default::default(),
verifying_keys: Default::default(),
program_address: program.id().to_address()?,
};
for import in program.imports().keys() {
ensure!(import != program.id(), "Program cannot import itself");
if !process.contains_program(import) {
bail!("Cannot add program '{}' because its import '{import}' must be added first", program.id())
}
}
for closure in program.closures().values() {
stack.insert_closure(closure)?;
}
for function in program.functions().values() {
stack.insert_function(function)?;
stack.get_number_of_calls(function.name())?;
let finalize_cost = cost_in_microcredits_v2(&stack, function.name())?;
ensure!(
finalize_cost <= N::TRANSACTION_SPEND_LIMIT,
"Finalize block '{}' has a cost '{finalize_cost}' which exceeds the transaction spend limit '{}'",
function.name(),
N::TRANSACTION_SPEND_LIMIT
);
}
Ok(stack)
}
}
impl<N: Network> Stack<N> {
#[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_logic() {
let finalize_types = FinalizeTypes::from_finalize(self, finalize)?;
self.finalize_types.insert(*name, finalize_types);
}
Ok(())
}
}