Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(abi)!: add an explicit mapping from ABI params to witness indices #851

Merged
merged 28 commits into from
Feb 17, 2023
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
2f68fe8
feat: track all parameter witnesses in evaluator
TomAFrench Jan 30, 2023
73a083e
chore: use explicit witness map for encoding/decoding witness map
TomAFrench Jan 30, 2023
123f09d
chore: move `param_witnesses` to be stored within ABI
TomAFrench Feb 15, 2023
0f829ed
feat: create separate methods for encoding to a witness vs verifier i…
TomAFrench Feb 3, 2023
f3a78f6
chore: move encode_value and decode_value back inside Abi's impl
TomAFrench Feb 15, 2023
9630143
Merge branch 'master' into abi-to-witness-map
TomAFrench Feb 15, 2023
e301a6d
chore: remove clone from `encode_to_witness`
TomAFrench Feb 15, 2023
03d63c1
chore: use try_btree_map instead of unwrapping
TomAFrench Feb 15, 2023
067a711
feat: check for unexpected inputs when encoding a witness
TomAFrench Feb 15, 2023
876a938
chore: use InputMap and WitnessMap types in ABI
TomAFrench Feb 15, 2023
3262099
chore: update stale comment
TomAFrench Feb 15, 2023
dcb07a4
chore: apply input validation checks on new encoding method
TomAFrench Feb 16, 2023
d004680
chore: clippy
TomAFrench Feb 16, 2023
5b67289
Merge branch 'master' into abi-to-witness-map
TomAFrench Feb 16, 2023
c08d154
chore: remove unnecessary clone
TomAFrench Feb 16, 2023
b71b956
feat: add smoke test for abi encoding and decoding
TomAFrench Feb 16, 2023
0a5598c
chore: remove todo
TomAFrench Feb 16, 2023
f520088
chore: return abi from compile_circuit
TomAFrench Feb 16, 2023
609ffa7
chore: simplify returning `CompiledProgram`
TomAFrench Feb 16, 2023
50af426
chore: clippy
TomAFrench Feb 16, 2023
cc9a7ff
feat: return AbiError if witness value can't be found
TomAFrench Feb 16, 2023
4b94851
chore: add documentation for Abi fields
TomAFrench Feb 16, 2023
8c4125f
fix: re-add `public_inputs` field to `Evaluator`
TomAFrench Feb 16, 2023
da6ee42
chore: remove stale code from BTreeSet experiment
TomAFrench Feb 16, 2023
1f8a9ea
Merge branch 'master' into abi-to-witness-map
TomAFrench Feb 16, 2023
2117c5b
chore: fix merge issues
TomAFrench Feb 16, 2023
4f0574a
fix: re-add deleted `num_witnesses_abi_len` init
TomAFrench Feb 16, 2023
07741a6
Merge branch 'master' into abi-to-witness-map
TomAFrench Feb 16, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

66 changes: 14 additions & 52 deletions crates/nargo/src/cli/execute_cmd.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use clap::ArgMatches;
use std::path::{Path, PathBuf};

use acvm::acir::native_types::Witness;
use acvm::{FieldElement, PartialWitnessGenerator};
use acvm::PartialWitnessGenerator;
use clap::ArgMatches;
use noirc_abi::errors::AbiError;
use noirc_abi::input_parser::{Format, InputValue};
use noirc_abi::{Abi, MAIN_RETURN_NAME};
use noirc_abi::{InputMap, WitnessMap, MAIN_RETURN_NAME};
use noirc_driver::CompiledProgram;

use super::{create_named_dir, read_inputs_from_file, write_to_file, InputMap, WitnessMap};
use super::{create_named_dir, read_inputs_from_file, write_to_file};
use crate::{
cli::compile_cmd::compile_circuit,
constants::{PROVER_INPUT_FILE, TARGET_DIR, WITNESS_EXT},
Expand Down Expand Up @@ -40,10 +40,6 @@ pub(crate) fn run(args: ArgMatches) -> Result<(), CliError> {
Ok(())
}

/// In Barretenberg, the proof system adds a zero witness in the first index,
/// So when we add witness values, their index start from 1.
const WITNESS_OFFSET: u32 = 1;
kevaundray marked this conversation as resolved.
Show resolved Hide resolved

fn execute_with_path<P: AsRef<Path>>(
program_dir: P,
show_ssa: bool,
Expand All @@ -69,66 +65,32 @@ pub(crate) fn execute_program(
// Solve the remaining witnesses
let solved_witness = solve_witness(compiled_program, inputs_map)?;

let public_inputs = extract_public_inputs(compiled_program, &solved_witness)?;
let public_abi = compiled_program.abi.as_ref().unwrap().clone().public_abi();
let public_inputs = public_abi.decode_from_witness(&solved_witness)?;
let return_value = public_inputs.get(MAIN_RETURN_NAME).cloned();

Ok((return_value, solved_witness))
}

pub(crate) fn extract_public_inputs(
compiled_program: &CompiledProgram,
solved_witness: &WitnessMap,
) -> Result<InputMap, AbiError> {
let encoded_public_inputs: Vec<FieldElement> = compiled_program
.circuit
.public_inputs
.0
.iter()
.map(|index| solved_witness[index])
.collect();

let public_abi = compiled_program.abi.as_ref().unwrap().clone().public_abi();

public_abi.decode(&encoded_public_inputs)
}

pub(crate) fn solve_witness(
compiled_program: &CompiledProgram,
input_map: &InputMap,
) -> Result<WitnessMap, CliError> {
let abi = compiled_program.abi.as_ref().unwrap().clone();
let mut solved_witness =
input_map_to_witness_map(abi, input_map).map_err(|error| match error {
AbiError::UndefinedInput(_) => {
CliError::Generic(format!("{error} in the {PROVER_INPUT_FILE}.toml file."))
}
_ => CliError::from(error),
})?;
let abi = compiled_program.abi.as_ref().unwrap();

let mut solved_witness = abi.encode_to_witness(input_map).map_err(|error| match error {
AbiError::UndefinedInput(_) => {
CliError::Generic(format!("{error} in the {PROVER_INPUT_FILE}.toml file."))
}
_ => CliError::from(error),
})?;

let backend = crate::backends::ConcreteBackend;
backend.solve(&mut solved_witness, compiled_program.circuit.opcodes.clone())?;

Ok(solved_witness)
}

/// Given an InputMap and an Abi, produce a WitnessMap
///
/// In particular, this method shows one how to associate values in a Toml/JSON
/// file with witness indices
fn input_map_to_witness_map(abi: Abi, input_map: &InputMap) -> Result<WitnessMap, AbiError> {
// The ABI map is first encoded as a vector of field elements
let encoded_inputs = abi.encode(input_map, true)?;

Ok(encoded_inputs
.into_iter()
.enumerate()
.map(|(index, witness_value)| {
let witness = Witness::new(WITNESS_OFFSET + (index as u32));
(witness, witness_value)
})
.collect())
}

pub(crate) fn save_witness_to_dir<P: AsRef<Path>>(
witness: WitnessMap,
witness_name: &str,
Expand Down
18 changes: 3 additions & 15 deletions crates/nargo/src/cli/mod.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
use acvm::{
acir::{circuit::PublicInputs, native_types::Witness},
FieldElement,
};
use acvm::{acir::circuit::PublicInputs, FieldElement};
pub use check_cmd::check_from_path;
use clap::{App, AppSettings, Arg};
use const_format::formatcp;
use noirc_abi::{
input_parser::{Format, InputValue},
Abi,
};
use noirc_abi::{input_parser::Format, Abi, InputMap};
use noirc_driver::Driver;
use noirc_frontend::graph::{CrateName, CrateType};
use std::{
collections::{BTreeMap, HashMap, HashSet},
collections::{HashMap, HashSet},
fs::File,
io::Write,
path::{Path, PathBuf},
Expand All @@ -39,12 +33,6 @@ const CARGO_PKG_VERSION: &str = env!("CARGO_PKG_VERSION");
static VERSION_STRING: &str =
formatcp!("{} (git version hash: {}, is dirty: {})", CARGO_PKG_VERSION, GIT_HASH, IS_DIRTY);

/// A map from the fields in an TOML/JSON file which correspond to some ABI to their values
pub type InputMap = BTreeMap<String, InputValue>;

/// A map from the witnesses in a constraint system to the field element values
pub type WitnessMap = BTreeMap<Witness, FieldElement>;

pub fn start_cli() {
let allow_warnings = Arg::with_name("allow-warnings")
.long("allow-warnings")
Expand Down
8 changes: 3 additions & 5 deletions crates/nargo/src/cli/prove_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ use super::{
write_to_file,
};
use crate::{
cli::{
execute_cmd::{execute_program, extract_public_inputs},
verify_cmd::verify_proof,
},
cli::{execute_cmd::execute_program, verify_cmd::verify_proof},
constants::{PROOFS_DIR, PROOF_EXT, PROVER_INPUT_FILE, VERIFIER_INPUT_FILE},
errors::CliError,
};
Expand Down Expand Up @@ -57,7 +54,8 @@ pub fn prove_with_path<P: AsRef<Path>>(
let (_, solved_witness) = execute_program(&compiled_program, &inputs_map)?;

// Write public inputs into Verifier.toml
let public_inputs = extract_public_inputs(&compiled_program, &solved_witness)?;
let public_abi = compiled_program.abi.as_ref().unwrap().clone().public_abi();
let public_inputs = public_abi.decode_from_witness(&solved_witness)?;
write_inputs_to_file(&public_inputs, &program_dir, VERIFIER_INPUT_FILE, Format::Toml)?;

// Since the public outputs are added onto the public inputs list, there can be duplicates.
Expand Down
2 changes: 1 addition & 1 deletion crates/nargo/src/cli/verify_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ pub(crate) fn verify_proof(
) -> Result<bool, CliError> {
let public_abi = compiled_program.abi.unwrap().public_abi();
let public_inputs =
public_abi.encode(&public_inputs_map, false).map_err(|error| match error {
public_abi.encode_to_array(&public_inputs_map).map_err(|error| match error {
AbiError::UndefinedInput(_) => {
CliError::Generic(format!("{error} in the {VERIFIER_INPUT_FILE}.toml file."))
}
Expand Down
1 change: 1 addition & 0 deletions crates/noirc_abi/src/input_parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::{Abi, AbiType};
/// This is what all formats eventually transform into
/// For example, a toml file will parse into TomlTypes
/// and those TomlTypes will be mapped to Value
#[cfg_attr(test, derive(PartialEq))]
kevaundray marked this conversation as resolved.
Show resolved Hide resolved
#[derive(Debug, Clone, Serialize)]
pub enum InputValue {
Field(FieldElement),
Expand Down
Loading