use super::*;
impl<N: Network> Process<N> {
#[inline]
pub fn execute_additional_fee<A: circuit::Aleo<Network = N>, R: Rng + CryptoRng>(
&self,
private_key: &PrivateKey<N>,
credits: Record<N, Plaintext<N>>,
additional_fee_in_gates: u64,
rng: &mut R,
) -> Result<(Response<N>, AdditionalFee<N>)> {
let program_id = ProgramID::from_str("credits.aleo")?;
let function_name = Identifier::from_str("fee")?;
let input_types = self.get_program(&program_id)?.get_function(&function_name)?.input_types();
let inputs =
vec![Value::Record(credits), Value::from_str(&format!("{}", U64::<N>::new(additional_fee_in_gates)))?];
let request = Request::sign(private_key, program_id, function_name, &inputs, &input_types, rng)?;
let authorization = Authorization::new(&[request.clone()]);
let call_stack = CallStack::Authorize(vec![request], *private_key, authorization.clone());
let _response = self.get_stack(&program_id)?.execute_function::<A, R>(call_stack, rng)?;
let request = authorization.peek_next()?;
let stack = self.get_stack(request.program_id())?;
#[cfg(feature = "aleo-cli")]
println!("{}", format!(" • Calling '{}/{}'...", request.program_id(), request.function_name()).dimmed());
let execution = Arc::new(RwLock::new(Execution::new()));
let response = stack.execute_function::<A, R>(CallStack::execute(authorization, execution.clone())?, rng)?;
let execution = execution.read().clone();
ensure!(execution.len() == 1, "Execution of '{}/{}' does not contain 1 transition", program_id, function_name);
Ok((response, execution.peek()?))
}
#[inline]
pub fn verify_additional_fee(&self, additional_fee: &AdditionalFee<N>) -> Result<()> {
#[cfg(debug_assertions)]
println!("Verifying additional fee for {}/{}...", additional_fee.program_id(), additional_fee.function_name());
let fee_program_id = ProgramID::from_str("credits.aleo")?;
ensure!(*additional_fee.program_id() == fee_program_id, "Incorrect program ID for additional fee");
let fee_function = Identifier::from_str("fee")?;
ensure!(*additional_fee.function_name() == fee_function, "Incorrect function name for additional fee");
ensure!(**additional_fee.id() == additional_fee.to_root()?, "Transition ID of the additional fee is incorrect");
ensure!(additional_fee.inputs().len() <= N::MAX_INPUTS, "Additional fee exceeded maximum number of inputs");
ensure!(additional_fee.outputs().len() <= N::MAX_INPUTS, "Additional fee exceeded maximum number of outputs");
if additional_fee.inputs().iter().enumerate().any(|(index, input)| !input.verify(additional_fee.tcm(), index)) {
bail!("Failed to verify an additional fee input")
}
let num_inputs = additional_fee.inputs().len();
if additional_fee
.outputs()
.iter()
.enumerate()
.any(|(index, output)| !output.verify(additional_fee.tcm(), num_inputs + index))
{
bail!("Failed to verify an additional fee output")
}
ensure!(additional_fee.fee() >= &0, "The fee must be zero or positive");
let (tpk_x, tpk_y) = additional_fee.tpk().to_xy_coordinate();
let mut inputs = vec![N::Field::one(), *tpk_x, *tpk_y, **additional_fee.tcm()];
inputs.extend(additional_fee.inputs().iter().flat_map(|input| input.verifier_inputs()));
inputs.extend(additional_fee.outputs().iter().flat_map(|output| output.verifier_inputs()));
inputs.push(*I64::<N>::new(*additional_fee.fee()).to_field()?);
let stack = self.get_stack(additional_fee.program_id())?;
let function = stack.get_function(additional_fee.function_name())?;
if stack.get_number_of_calls(function.name())? != 1 {
bail!("The number of function calls in '{}/{}' should be 1", stack.program_id(), function.name())
}
#[cfg(debug_assertions)]
println!("Additional fee public inputs ({} elements): {:#?}", inputs.len(), inputs);
let verifying_key = self.get_verifying_key(stack.program_id(), function.name())?;
ensure!(
verifying_key.verify(function.name(), &inputs, additional_fee.proof()),
"The proof for the additional fee is invalid"
);
Ok(())
}
}