snarkvm_ledger_puzzle_epoch/synthesis/program/
to_r1cs.rsuse super::*;
impl<N: Network> EpochProgram<N> {
pub fn to_r1cs<A: circuit::Aleo<Network = N>>(&self, console_inputs: Vec<Value<N>>) -> Result<R1CS<A::BaseField>> {
let timer = timer!("synthesize_r1cs");
let function_name = Identifier::from_str("synthesize")?;
let function = self.stack.get_function(&function_name)?;
let num_inputs = function.inputs().len();
let register_types = self.stack.get_register_types(&function_name)?.clone();
ensure!(num_inputs == console_inputs.len(), "Expected {num_inputs} inputs, found {}", console_inputs.len());
let call_stack = CallStack::PackageRun(vec![], PrivateKey::new(&mut rand::thread_rng())?, Default::default());
let mut registers = Registers::<N, A>::new(call_stack, register_types);
lap!(timer, "Initialize the registers");
A::reset();
let mut circuit_inputs = Vec::with_capacity(console_inputs.len());
for input in console_inputs {
let input = <circuit::Value<A> as circuit::Inject>::new(Mode::Public, input);
circuit_inputs.push(input);
}
lap!(timer, "Inject the inputs");
function.inputs().iter().map(|i| i.register()).zip_eq(&circuit_inputs).try_for_each(|(register, input)| {
registers.store_circuit(&self.stack, register, input.clone())
})?;
lap!(timer, "Store the inputs");
for instruction in function.instructions() {
if let Err(error) = instruction.execute(&self.stack, &mut registers) {
bail!("Failed to execute instruction ({instruction}): {error}");
}
#[cfg(debug_assertions)]
{
use circuit::Eject;
use snarkvm_synthesizer_program::RegistersLoadCircuit;
use colored::Colorize;
let is_satisfied = A::is_satisfied();
println!(
"Executing instruction ({instruction}) ({})",
if is_satisfied { "✅".green() } else { "❌".red() }
);
if !is_satisfied {
for operand in instruction.operands() {
let value = registers.load_circuit(&self.stack, operand)?;
println!(" {operand} = {}", value.eject_value());
}
}
}
}
lap!(timer, "Execute the instructions");
#[cfg(debug_assertions)]
log_circuit::<N, A, _>(function_name.to_string());
ensure!(
A::num_constraints() > 0 && A::is_satisfied(),
"'{}/{function_name}' is not satisfied on the given inputs.",
self.stack.program_id(),
);
lap!(timer, "Ensure the circuit is satisfied");
let r1cs = A::eject_r1cs_and_reset();
finish!(timer, "Eject the circuit assignment and reset the circuit");
Ok(r1cs)
}
}
#[cfg(debug_assertions)]
pub(crate) fn log_circuit<N: Network, A: circuit::Aleo<Network = N>, S: Into<String>>(scope: S) {
use colored::Colorize;
let is_satisfied = if A::is_satisfied() { "✅".green() } else { "❌".red() };
let (num_constant, num_public, num_private, num_constraints, num_nonzeros) = A::count();
println!(
"{is_satisfied} {:width$} (Constant: {num_constant}, Public: {num_public}, Private: {num_private}, Constraints: {num_constraints}, NonZeros: {num_nonzeros:?})",
scope.into().bold(),
width = 20
);
}