use super::*;
impl<N: Network> Package<N> {
pub fn build<A: crate::circuit::Aleo<Network = N, BaseField = N::Field>>(&self) -> Result<()> {
if !self.is_build_required::<A>() {
return Ok(());
}
let program = self.program();
let program_id = program.id();
dev_println!("⏳ Compiling '{}'...\n", program_id.to_string());
let build_directory = self.build_directory();
if !build_directory.exists() {
std::fs::create_dir_all(&build_directory)?;
}
let process = self.get_process()?;
for function_name in program.functions().keys() {
process.synthesize_key::<A, _>(program_id, function_name, &mut rand::thread_rng())?;
}
for function_name in program.functions().keys() {
let stack = process.get_stack(program_id)?;
let program = stack.program();
let function = program.get_function(function_name)?;
for instruction in function.instructions() {
if let Instruction::Call(call) = instruction {
let (external_stack, resource) = match call.operator() {
CallOperator::Locator(locator) => {
(Some(process.get_stack(locator.program_id())?), locator.resource())
}
CallOperator::Resource(resource) => (None, resource),
};
let program = match &external_stack {
Some(external_stack) => external_stack.program(),
None => program,
};
if program.contains_function(resource) {
let function_name = resource;
let proving_key = process.get_proving_key(program.id(), resource)?;
let verifying_key = process.get_verifying_key(program.id(), resource)?;
let import_build_directory =
self.build_directory().join(format!("{}-{}", program.id().name(), program.id().network()));
if !import_build_directory.exists() {
std::fs::create_dir_all(&import_build_directory)?;
}
let _prover = ProverFile::create(&import_build_directory, function_name, proving_key)?;
let _verifier = VerifierFile::create(&import_build_directory, function_name, verifying_key)?;
}
}
}
let proving_key = process.get_proving_key(program_id, function_name)?;
let verifying_key = process.get_verifying_key(program_id, function_name)?;
let _prover = ProverFile::create(&build_directory, function_name, proving_key)?;
let _verifier = VerifierFile::create(&build_directory, function_name, verifying_key)?;
}
let _avm_file = AVMFile::create(&build_directory, program.clone(), true)?;
if !self.build_directory().exists() {
bail!("Build directory does not exist: {}", self.build_directory().display());
}
Ok(())
}
}
#[cfg(test)]
mod tests {
type CurrentAleo = snarkvm_circuit::network::AleoV0;
#[test]
fn test_build() {
let (directory, package) = crate::package::test_helpers::sample_token_package();
assert!(!package.build_directory().exists());
package.build::<CurrentAleo>().unwrap();
assert!(package.build_directory().exists());
std::fs::remove_dir_all(directory).unwrap();
}
#[test]
fn test_build_with_import() {
let (directory, package) = crate::package::test_helpers::sample_wallet_package();
assert!(!package.build_directory().exists());
package.build::<CurrentAleo>().unwrap();
assert!(package.build_directory().exists());
std::fs::remove_dir_all(directory).unwrap();
}
#[test]
#[ignore]
fn test_build_with_import_credits() {
let (directory, package) = crate::package::test_helpers::sample_transfer_package();
assert!(!package.build_directory().exists());
package.build::<CurrentAleo>().unwrap();
assert!(package.build_directory().exists());
std::fs::remove_dir_all(directory).unwrap();
}
}