diff --git a/crates/nargo_cli/src/cli/fs/inputs.rs b/crates/nargo_cli/src/cli/fs/inputs.rs index eaf94cc22fd..bd55e4b0abd 100644 --- a/crates/nargo_cli/src/cli/fs/inputs.rs +++ b/crates/nargo_cli/src/cli/fs/inputs.rs @@ -40,6 +40,7 @@ pub(crate) fn read_inputs_from_file>( pub(crate) fn write_inputs_to_file>( input_map: &InputMap, return_value: &Option, + abi: &Abi, path: P, file_name: &str, format: Format, @@ -53,10 +54,10 @@ pub(crate) fn write_inputs_to_file>( 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)? + format.serialize(&input_map, abi)? } // If no return value exists, then we can serialize the original map directly. - None => format.serialize(input_map)?, + None => format.serialize(input_map, abi)?, }; write_to_file(serialized_output.as_bytes(), &file_path); @@ -113,6 +114,7 @@ mod tests { write_inputs_to_file( &input_map, &return_value, + &abi, &input_dir, VERIFIER_INPUT_FILE, Format::Toml, diff --git a/crates/nargo_cli/src/cli/prove_cmd.rs b/crates/nargo_cli/src/cli/prove_cmd.rs index 25948ba1784..44f3bf62484 100644 --- a/crates/nargo_cli/src/cli/prove_cmd.rs +++ b/crates/nargo_cli/src/cli/prove_cmd.rs @@ -131,6 +131,7 @@ pub(crate) fn prove_with_path>( write_inputs_to_file( &public_inputs, &return_value, + &public_abi, &program_dir, verifier_name.as_str(), Format::Toml, diff --git a/crates/noirc_abi/src/input_parser/json.rs b/crates/noirc_abi/src/input_parser/json.rs index 18d14a69126..22b0b49852b 100644 --- a/crates/noirc_abi/src/input_parser/json.rs +++ b/crates/noirc_abi/src/input_parser/json.rs @@ -1,7 +1,7 @@ use super::{parse_str_to_field, InputValue}; use crate::{errors::InputParserError, Abi, AbiType, MAIN_RETURN_NAME}; use acvm::FieldElement; -use iter_extended::{btree_map, try_btree_map, try_vecmap, vecmap}; +use iter_extended::{try_btree_map, try_vecmap, vecmap}; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; @@ -37,12 +37,22 @@ pub(crate) fn parse_json( } pub(crate) fn serialize_to_json( - w_map: &BTreeMap, + input_map: &BTreeMap, + abi: &Abi, ) -> Result { - let to_map: BTreeMap<_, _> = - w_map.iter().map(|(key, value)| (key, JsonTypes::from(value.clone()))).collect(); + let mut json_map = try_btree_map(abi.to_btree_map(), |(key, param_type)| { + JsonTypes::try_from_input_value(&input_map[&key], ¶m_type) + .map(|value| (key.to_owned(), value)) + })?; + + if let (Some(return_type), Some(return_value)) = + (&abi.return_type, input_map.get(MAIN_RETURN_NAME)) + { + let return_value = JsonTypes::try_from_input_value(return_value, return_type)?; + json_map.insert(MAIN_RETURN_NAME.to_owned(), return_value); + } - let json_string = serde_json::to_string(&to_map)?; + let json_string = serde_json::to_string(&json_map)?; Ok(json_string) } @@ -71,24 +81,43 @@ enum JsonTypes { Table(BTreeMap), } -impl From for JsonTypes { - fn from(value: InputValue) -> Self { - match value { - InputValue::Field(f) => { +impl JsonTypes { + fn try_from_input_value( + value: &InputValue, + abi_type: &AbiType, + ) -> Result { + let json_value = match (value, abi_type) { + (InputValue::Field(f), AbiType::Field | AbiType::Integer { .. }) => { let f_str = format!("0x{}", f.to_hex()); JsonTypes::String(f_str) } - InputValue::Vec(v) => { - let array = v.iter().map(|i| format!("0x{}", i.to_hex())).collect(); - JsonTypes::ArrayString(array) - } - InputValue::String(s) => JsonTypes::String(s), - InputValue::Struct(map) => { - let map_with_json_types = - btree_map(map, |(key, value)| (key, JsonTypes::from(value))); + (InputValue::Field(f), AbiType::Boolean) => JsonTypes::Bool(f.is_one()), + + (InputValue::Vec(v), AbiType::Array { typ, .. }) => match typ.as_ref() { + AbiType::Field | AbiType::Integer { .. } => { + let array = v.iter().map(|i| format!("0x{}", i.to_hex())).collect(); + JsonTypes::ArrayString(array) + } + AbiType::Boolean => { + let array = v.iter().map(|i| i.is_one()).collect(); + JsonTypes::ArrayBool(array) + } + _ => return Err(InputParserError::AbiTypeMismatch(abi_type.clone())), + }, + + (InputValue::String(s), AbiType::String { .. }) => JsonTypes::String(s.to_string()), + + (InputValue::Struct(map), AbiType::Struct { fields }) => { + let map_with_json_types = try_btree_map(fields, |(key, field_type)| { + JsonTypes::try_from_input_value(&map[key], field_type) + .map(|json_value| (key.to_owned(), json_value)) + })?; JsonTypes::Table(map_with_json_types) } - } + + _ => return Err(InputParserError::AbiTypeMismatch(abi_type.clone())), + }; + Ok(json_value) } } diff --git a/crates/noirc_abi/src/input_parser/mod.rs b/crates/noirc_abi/src/input_parser/mod.rs index 7eaa5c6322c..2c90aac862c 100644 --- a/crates/noirc_abi/src/input_parser/mod.rs +++ b/crates/noirc_abi/src/input_parser/mod.rs @@ -106,11 +106,12 @@ impl Format { pub fn serialize( &self, - w_map: &BTreeMap, + input_map: &BTreeMap, + abi: &Abi, ) -> Result { match self { - Format::Json => json::serialize_to_json(w_map), - Format::Toml => toml::serialize_to_toml(w_map), + Format::Json => json::serialize_to_json(input_map, abi), + Format::Toml => toml::serialize_to_toml(input_map, abi), } } } @@ -170,7 +171,7 @@ mod serialization_tests { ]); for format in Format::iter() { - let serialized_inputs = format.serialize(&input_map).unwrap(); + let serialized_inputs = format.serialize(&input_map, &abi).unwrap(); let reconstructed_input_map = format.parse(&serialized_inputs, &abi).unwrap(); diff --git a/crates/noirc_abi/src/input_parser/toml.rs b/crates/noirc_abi/src/input_parser/toml.rs index 0e10aa7f49b..316f52a4048 100644 --- a/crates/noirc_abi/src/input_parser/toml.rs +++ b/crates/noirc_abi/src/input_parser/toml.rs @@ -1,7 +1,7 @@ use super::{parse_str_to_field, InputValue}; use crate::{errors::InputParserError, Abi, AbiType, MAIN_RETURN_NAME}; use acvm::FieldElement; -use iter_extended::{btree_map, try_btree_map, try_vecmap, vecmap}; +use iter_extended::{try_btree_map, try_vecmap, vecmap}; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; @@ -37,12 +37,22 @@ pub(crate) fn parse_toml( } pub(crate) fn serialize_to_toml( - w_map: &BTreeMap, + input_map: &BTreeMap, + abi: &Abi, ) -> Result { - let to_map: BTreeMap<_, _> = - w_map.iter().map(|(key, value)| (key, TomlTypes::from(value.clone()))).collect(); + let mut toml_map = try_btree_map(abi.to_btree_map(), |(key, param_type)| { + TomlTypes::try_from_input_value(&input_map[&key], ¶m_type) + .map(|toml_value| (key.clone(), toml_value)) + })?; + + if let (Some(return_type), Some(return_value)) = + (&abi.return_type, input_map.get(MAIN_RETURN_NAME)) + { + let return_value = TomlTypes::try_from_input_value(return_value, return_type)?; + toml_map.insert(MAIN_RETURN_NAME.to_owned(), return_value); + } - let toml_string = toml::to_string(&to_map)?; + let toml_string = toml::to_string(&toml_map)?; Ok(toml_string) } @@ -68,24 +78,43 @@ enum TomlTypes { Table(BTreeMap), } -impl From for TomlTypes { - fn from(value: InputValue) -> Self { - match value { - InputValue::Field(f) => { +impl TomlTypes { + fn try_from_input_value( + value: &InputValue, + abi_type: &AbiType, + ) -> Result { + let toml_value = match (value, abi_type) { + (InputValue::Field(f), AbiType::Field | AbiType::Integer { .. }) => { let f_str = format!("0x{}", f.to_hex()); TomlTypes::String(f_str) } - InputValue::Vec(v) => { - let array = v.iter().map(|i| format!("0x{}", i.to_hex())).collect(); - TomlTypes::ArrayString(array) - } - InputValue::String(s) => TomlTypes::String(s), - InputValue::Struct(map) => { - let map_with_toml_types = - btree_map(map, |(key, value)| (key, TomlTypes::from(value))); + (InputValue::Field(f), AbiType::Boolean) => TomlTypes::Bool(f.is_one()), + + (InputValue::Vec(v), AbiType::Array { typ, .. }) => match typ.as_ref() { + AbiType::Field | AbiType::Integer { .. } => { + let array = v.iter().map(|i| format!("0x{}", i.to_hex())).collect(); + TomlTypes::ArrayString(array) + } + AbiType::Boolean => { + let array = v.iter().map(|i| i.is_one()).collect(); + TomlTypes::ArrayBool(array) + } + _ => return Err(InputParserError::AbiTypeMismatch(abi_type.clone())), + }, + + (InputValue::String(s), AbiType::String { .. }) => TomlTypes::String(s.to_string()), + + (InputValue::Struct(map), AbiType::Struct { fields }) => { + let map_with_toml_types = try_btree_map(fields, |(key, field_type)| { + TomlTypes::try_from_input_value(&map[key], field_type) + .map(|toml_value| (key.to_owned(), toml_value)) + })?; TomlTypes::Table(map_with_toml_types) } - } + + _ => return Err(InputParserError::AbiTypeMismatch(abi_type.clone())), + }; + Ok(toml_value) } }