-
Notifications
You must be signed in to change notification settings - Fork 225
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: move nargo I/O into separate module (#896)
* chore: move IO logic into separate module * chore: remove preprocessing from io module * chore: replace if-lets with match
- Loading branch information
1 parent
811b346
commit 8cafa34
Showing
14 changed files
with
303 additions
and
258 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
use std::path::{Path, PathBuf}; | ||
|
||
use acvm::{acir::circuit::Circuit, hash_constraint_system}; | ||
|
||
use crate::constants::ACIR_EXT; | ||
|
||
use super::{create_named_dir, write_to_file}; | ||
|
||
pub(crate) fn save_acir_to_dir<P: AsRef<Path>>( | ||
circuit: &Circuit, | ||
circuit_name: &str, | ||
circuit_dir: P, | ||
) -> PathBuf { | ||
let mut circuit_path = create_named_dir(circuit_dir.as_ref(), "target"); | ||
circuit_path.push(circuit_name); | ||
|
||
let mut serialized = Vec::new(); | ||
circuit.write(&mut serialized).expect("could not serialize circuit"); | ||
|
||
circuit_path.set_extension(ACIR_EXT); | ||
write_to_file(serialized.as_slice(), &circuit_path); | ||
|
||
// Save a checksum of the circuit to compare against during proving and verification | ||
let acir_hash = hash_constraint_system(circuit); | ||
circuit_path.set_extension(ACIR_EXT.to_owned() + ".sha256"); | ||
write_to_file(hex::encode(acir_hash).as_bytes(), &circuit_path); | ||
|
||
circuit_path | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
use noirc_abi::{ | ||
input_parser::{Format, InputValue}, | ||
Abi, InputMap, MAIN_RETURN_NAME, | ||
}; | ||
use std::{collections::BTreeMap, path::Path}; | ||
|
||
use crate::errors::CliError; | ||
|
||
use super::write_to_file; | ||
|
||
/// Returns the circuit's parameters and its return value, if one exists. | ||
/// # Examples | ||
/// | ||
/// ```ignore | ||
/// let (input_map, return_value): (InputMap, Option<InputValue>) = | ||
/// read_inputs_from_file(path, "Verifier", Format::Toml, &abi)?; | ||
/// ``` | ||
pub fn read_inputs_from_file<P: AsRef<Path>>( | ||
path: P, | ||
file_name: &str, | ||
format: Format, | ||
abi: &Abi, | ||
) -> Result<(InputMap, Option<InputValue>), CliError> { | ||
if abi.is_empty() { | ||
return Ok((BTreeMap::new(), None)); | ||
} | ||
|
||
let file_path = { | ||
let mut dir_path = path.as_ref().to_path_buf(); | ||
dir_path.push(file_name); | ||
dir_path.set_extension(format.ext()); | ||
dir_path | ||
}; | ||
if !file_path.exists() { | ||
return Err(CliError::MissingTomlFile(file_name.to_owned(), file_path)); | ||
} | ||
|
||
let input_string = std::fs::read_to_string(file_path).unwrap(); | ||
let mut input_map = format.parse(&input_string, abi)?; | ||
let return_value = input_map.remove(MAIN_RETURN_NAME); | ||
|
||
Ok((input_map, return_value)) | ||
} | ||
|
||
pub fn write_inputs_to_file<P: AsRef<Path>>( | ||
input_map: &InputMap, | ||
return_value: &Option<InputValue>, | ||
path: P, | ||
file_name: &str, | ||
format: Format, | ||
) -> Result<(), CliError> { | ||
let file_path = { | ||
let mut dir_path = path.as_ref().to_path_buf(); | ||
dir_path.push(file_name); | ||
dir_path.set_extension(format.ext()); | ||
dir_path | ||
}; | ||
|
||
// We must insert the return value into the `InputMap` in order for it to be written to file. | ||
let serialized_output = match return_value { | ||
// Parameters and return values are kept separate except for when they're being written to file. | ||
// As a result, we don't want to modify the original map and must clone it before insertion. | ||
Some(return_value) => { | ||
let mut input_map = input_map.clone(); | ||
input_map.insert(MAIN_RETURN_NAME.to_owned(), return_value.clone()); | ||
format.serialize(&input_map)? | ||
} | ||
// If no return value exists, then we can serialize the original map directly. | ||
None => format.serialize(input_map)?, | ||
}; | ||
|
||
write_to_file(serialized_output.as_bytes(), &file_path); | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
use std::path::{Path, PathBuf}; | ||
|
||
use acvm::{acir::circuit::Circuit, hash_constraint_system}; | ||
|
||
use crate::{ | ||
constants::{ACIR_EXT, PK_EXT, VK_EXT}, | ||
errors::CliError, | ||
}; | ||
|
||
use super::{create_named_dir, load_hex_data, write_to_file}; | ||
|
||
pub(crate) fn save_key_to_dir<P: AsRef<Path>>( | ||
key: Vec<u8>, | ||
key_name: &str, | ||
key_dir: P, | ||
is_proving_key: bool, | ||
) -> Result<PathBuf, CliError> { | ||
let mut key_path = create_named_dir(key_dir.as_ref(), key_name); | ||
key_path.push(key_name); | ||
let extension = if is_proving_key { PK_EXT } else { VK_EXT }; | ||
key_path.set_extension(extension); | ||
|
||
write_to_file(hex::encode(key).as_bytes(), &key_path); | ||
|
||
Ok(key_path) | ||
} | ||
|
||
pub(crate) fn fetch_pk_and_vk<P: AsRef<Path>>( | ||
circuit: &Circuit, | ||
circuit_build_path: P, | ||
prove_circuit: bool, | ||
check_proof: bool, | ||
) -> Result<(Vec<u8>, Vec<u8>), CliError> { | ||
let mut acir_hash_path = PathBuf::new(); | ||
acir_hash_path.push(circuit_build_path.as_ref()); | ||
acir_hash_path.set_extension(ACIR_EXT.to_owned() + ".sha256"); | ||
let expected_acir_hash = load_hex_data(acir_hash_path.clone())?; | ||
|
||
let new_acir_hash = hash_constraint_system(circuit); | ||
|
||
if new_acir_hash[..] != expected_acir_hash { | ||
return Err(CliError::MismatchedAcir(acir_hash_path)); | ||
} | ||
|
||
// This flag exists to avoid an unnecessary read of the proving key during verification | ||
// as this method is used by both `nargo prove` and `nargo verify` | ||
let proving_key = if prove_circuit { | ||
let mut proving_key_path = PathBuf::new(); | ||
proving_key_path.push(circuit_build_path.as_ref()); | ||
proving_key_path.set_extension(PK_EXT); | ||
load_hex_data(proving_key_path)? | ||
} else { | ||
// We can return an empty Vec here as `prove_circuit` should only be false when running `nargo verify` | ||
vec![] | ||
}; | ||
|
||
let verification_key = if check_proof { | ||
let mut verification_key_path = PathBuf::new(); | ||
verification_key_path.push(circuit_build_path); | ||
verification_key_path.set_extension(VK_EXT); | ||
load_hex_data(verification_key_path)? | ||
} else { | ||
// We can return an empty Vec here as the verification key is used only is `check_proof` is true | ||
vec![] | ||
}; | ||
|
||
Ok((proving_key, verification_key)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
use std::{ | ||
fs::File, | ||
io::Write, | ||
path::{Path, PathBuf}, | ||
}; | ||
|
||
use crate::errors::CliError; | ||
|
||
pub mod acir; | ||
pub mod inputs; | ||
pub mod keys; | ||
pub mod proof; | ||
pub mod witness; | ||
|
||
fn create_dir<P: AsRef<Path>>(dir_path: P) -> Result<PathBuf, std::io::Error> { | ||
let mut dir = std::path::PathBuf::new(); | ||
dir.push(dir_path); | ||
std::fs::create_dir_all(&dir)?; | ||
Ok(dir) | ||
} | ||
|
||
pub(crate) fn create_named_dir(named_dir: &Path, name: &str) -> PathBuf { | ||
create_dir(named_dir).unwrap_or_else(|_| panic!("could not create the `{name}` directory")) | ||
} | ||
|
||
pub(crate) fn write_to_file(bytes: &[u8], path: &Path) -> String { | ||
let display = path.display(); | ||
|
||
let mut file = match File::create(path) { | ||
Err(why) => panic!("couldn't create {display}: {why}"), | ||
Ok(file) => file, | ||
}; | ||
|
||
match file.write_all(bytes) { | ||
Err(why) => panic!("couldn't write to {display}: {why}"), | ||
Ok(_) => display.to_string(), | ||
} | ||
} | ||
|
||
pub fn load_hex_data<P: AsRef<Path>>(path: P) -> Result<Vec<u8>, CliError> { | ||
let hex_data: Vec<_> = | ||
std::fs::read(&path).map_err(|_| CliError::PathNotValid(path.as_ref().to_path_buf()))?; | ||
|
||
let raw_bytes = hex::decode(hex_data).map_err(CliError::HexArtifactNotValid)?; | ||
|
||
Ok(raw_bytes) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
use std::path::{Path, PathBuf}; | ||
|
||
use crate::{constants::PROOF_EXT, errors::CliError}; | ||
|
||
use super::{create_named_dir, write_to_file}; | ||
|
||
pub(crate) fn save_proof_to_dir<P: AsRef<Path>>( | ||
proof: &[u8], | ||
proof_name: &str, | ||
proof_dir: P, | ||
) -> Result<PathBuf, CliError> { | ||
let mut proof_path = create_named_dir(proof_dir.as_ref(), "proof"); | ||
proof_path.push(proof_name); | ||
proof_path.set_extension(PROOF_EXT); | ||
|
||
write_to_file(hex::encode(proof).as_bytes(), &proof_path); | ||
|
||
Ok(proof_path) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
use std::path::{Path, PathBuf}; | ||
|
||
use acvm::acir::native_types::Witness; | ||
use noirc_abi::WitnessMap; | ||
|
||
use super::{create_named_dir, write_to_file}; | ||
use crate::{constants::WITNESS_EXT, errors::CliError}; | ||
|
||
pub(crate) fn save_witness_to_dir<P: AsRef<Path>>( | ||
witness: WitnessMap, | ||
witness_name: &str, | ||
witness_dir: P, | ||
) -> Result<PathBuf, CliError> { | ||
let mut witness_path = create_named_dir(witness_dir.as_ref(), "witness"); | ||
witness_path.push(witness_name); | ||
witness_path.set_extension(WITNESS_EXT); | ||
|
||
let buf = Witness::to_bytes(&witness); | ||
|
||
write_to_file(buf.as_slice(), &witness_path); | ||
|
||
Ok(witness_path) | ||
} |
Oops, something went wrong.