use super::*;
impl<N: Network> Stack<N> {
#[inline]
pub fn evaluate_closure<A: circuit::Aleo<Network = N>>(
&self,
closure: &Closure<N>,
inputs: &[Value<N>],
call_stack: CallStack<N>,
caller: Address<N>,
tvk: Field<N>,
) -> Result<Vec<Value<N>>> {
if closure.inputs().len() != inputs.len() {
bail!("Expected {} inputs, found {}", closure.inputs().len(), inputs.len())
}
let mut registers = Registers::<N, A>::new(call_stack, self.get_register_types(closure.name())?.clone());
registers.set_caller(caller);
registers.set_tvk(tvk);
closure.inputs().iter().map(|i| i.register()).zip_eq(inputs).try_for_each(|(register, input)| {
registers.store(self, register, input.clone())
})?;
for instruction in closure.instructions() {
if let Err(error) = instruction.evaluate(self, &mut registers) {
bail!("Failed to evaluate instruction ({instruction}): {error}");
}
}
let outputs = closure.outputs().iter().map(|output| {
registers.load(self, &Operand::Register(output.register().clone()))
});
outputs.collect()
}
#[inline]
pub fn evaluate_function<A: circuit::Aleo<Network = N>>(&self, call_stack: CallStack<N>) -> Result<Response<N>> {
let (request, call_stack) = match &call_stack {
CallStack::Evaluate(authorization) => (authorization.next()?, call_stack),
CallStack::Execute(authorization, ..) => (authorization.peek_next()?, call_stack.replicate()),
_ => bail!("Illegal operation: call stack must be `Evaluate` or `Execute` in `evaluate_function`."),
};
ensure!(
**request.network_id() == N::ID,
"Network ID mismatch. Expected {}, but found {}",
N::ID,
request.network_id()
);
let function = self.get_function(request.function_name())?;
let inputs = request.inputs();
let caller = *request.caller();
let tvk = *request.tvk();
if function.inputs().len() != inputs.len() {
bail!(
"Function '{}' in the program '{}' expects {} inputs, but {} were provided.",
function.name(),
self.program.id(),
function.inputs().len(),
inputs.len()
)
}
let mut registers = Registers::<N, A>::new(call_stack, self.get_register_types(function.name())?.clone());
registers.set_caller(caller);
registers.set_tvk(tvk);
ensure!(request.verify(&function.input_types()), "Request is invalid");
function.inputs().iter().map(|i| i.register()).zip_eq(inputs).try_for_each(|(register, input)| {
registers.store(self, register, input.clone())
})?;
for instruction in function.instructions() {
if let Err(error) = instruction.evaluate(self, &mut registers) {
bail!("Failed to evaluate instruction ({instruction}): {error}");
}
}
let output_registers = &function.outputs().iter().map(|output| output.register().clone()).collect::<Vec<_>>();
let outputs = output_registers
.iter()
.map(|register| {
registers.load(self, &Operand::Register(register.clone()))
})
.collect::<Result<Vec<_>>>()?;
Response::new(
self.program.id(),
request.inputs().len(),
request.tvk(),
request.tcm(),
outputs,
&function.output_types(),
output_registers,
)
}
}