Skip to content

Commit

Permalink
feat: make use of type information when serialising inputs (#1655)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomAFrench authored Jul 4, 2023
1 parent 1d1e424 commit 310368d
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 42 deletions.
6 changes: 4 additions & 2 deletions crates/nargo_cli/src/cli/fs/inputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub(crate) fn read_inputs_from_file<P: AsRef<Path>>(
pub(crate) fn write_inputs_to_file<P: AsRef<Path>>(
input_map: &InputMap,
return_value: &Option<InputValue>,
abi: &Abi,
path: P,
file_name: &str,
format: Format,
Expand All @@ -53,10 +54,10 @@ pub(crate) fn write_inputs_to_file<P: AsRef<Path>>(
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);
Expand Down Expand Up @@ -113,6 +114,7 @@ mod tests {
write_inputs_to_file(
&input_map,
&return_value,
&abi,
&input_dir,
VERIFIER_INPUT_FILE,
Format::Toml,
Expand Down
1 change: 1 addition & 0 deletions crates/nargo_cli/src/cli/prove_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ pub(crate) fn prove_with_path<B: Backend, P: AsRef<Path>>(
write_inputs_to_file(
&public_inputs,
&return_value,
&public_abi,
&program_dir,
verifier_name.as_str(),
Format::Toml,
Expand Down
65 changes: 47 additions & 18 deletions crates/noirc_abi/src/input_parser/json.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -37,12 +37,22 @@ pub(crate) fn parse_json(
}

pub(crate) fn serialize_to_json(
w_map: &BTreeMap<String, InputValue>,
input_map: &BTreeMap<String, InputValue>,
abi: &Abi,
) -> Result<String, InputParserError> {
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], &param_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)
}
Expand Down Expand Up @@ -71,24 +81,43 @@ enum JsonTypes {
Table(BTreeMap<String, JsonTypes>),
}

impl From<InputValue> 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<JsonTypes, InputParserError> {
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)
}
}

Expand Down
9 changes: 5 additions & 4 deletions crates/noirc_abi/src/input_parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,12 @@ impl Format {

pub fn serialize(
&self,
w_map: &BTreeMap<String, InputValue>,
input_map: &BTreeMap<String, InputValue>,
abi: &Abi,
) -> Result<String, InputParserError> {
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),
}
}
}
Expand Down Expand Up @@ -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();

Expand Down
65 changes: 47 additions & 18 deletions crates/noirc_abi/src/input_parser/toml.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -37,12 +37,22 @@ pub(crate) fn parse_toml(
}

pub(crate) fn serialize_to_toml(
w_map: &BTreeMap<String, InputValue>,
input_map: &BTreeMap<String, InputValue>,
abi: &Abi,
) -> Result<String, InputParserError> {
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], &param_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)
}
Expand All @@ -68,24 +78,43 @@ enum TomlTypes {
Table(BTreeMap<String, TomlTypes>),
}

impl From<InputValue> 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<TomlTypes, InputParserError> {
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)
}
}

Expand Down

0 comments on commit 310368d

Please sign in to comment.