Skip to content

Commit 310368d

Browse files
authored
feat: make use of type information when serialising inputs (#1655)
1 parent 1d1e424 commit 310368d

File tree

5 files changed

+104
-42
lines changed

5 files changed

+104
-42
lines changed

crates/nargo_cli/src/cli/fs/inputs.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ pub(crate) fn read_inputs_from_file<P: AsRef<Path>>(
4040
pub(crate) fn write_inputs_to_file<P: AsRef<Path>>(
4141
input_map: &InputMap,
4242
return_value: &Option<InputValue>,
43+
abi: &Abi,
4344
path: P,
4445
file_name: &str,
4546
format: Format,
@@ -53,10 +54,10 @@ pub(crate) fn write_inputs_to_file<P: AsRef<Path>>(
5354
Some(return_value) => {
5455
let mut input_map = input_map.clone();
5556
input_map.insert(MAIN_RETURN_NAME.to_owned(), return_value.clone());
56-
format.serialize(&input_map)?
57+
format.serialize(&input_map, abi)?
5758
}
5859
// If no return value exists, then we can serialize the original map directly.
59-
None => format.serialize(input_map)?,
60+
None => format.serialize(input_map, abi)?,
6061
};
6162

6263
write_to_file(serialized_output.as_bytes(), &file_path);
@@ -113,6 +114,7 @@ mod tests {
113114
write_inputs_to_file(
114115
&input_map,
115116
&return_value,
117+
&abi,
116118
&input_dir,
117119
VERIFIER_INPUT_FILE,
118120
Format::Toml,

crates/nargo_cli/src/cli/prove_cmd.rs

+1
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ pub(crate) fn prove_with_path<B: Backend, P: AsRef<Path>>(
131131
write_inputs_to_file(
132132
&public_inputs,
133133
&return_value,
134+
&public_abi,
134135
&program_dir,
135136
verifier_name.as_str(),
136137
Format::Toml,

crates/noirc_abi/src/input_parser/json.rs

+47-18
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::{parse_str_to_field, InputValue};
22
use crate::{errors::InputParserError, Abi, AbiType, MAIN_RETURN_NAME};
33
use acvm::FieldElement;
4-
use iter_extended::{btree_map, try_btree_map, try_vecmap, vecmap};
4+
use iter_extended::{try_btree_map, try_vecmap, vecmap};
55
use serde::{Deserialize, Serialize};
66
use std::collections::BTreeMap;
77

@@ -37,12 +37,22 @@ pub(crate) fn parse_json(
3737
}
3838

3939
pub(crate) fn serialize_to_json(
40-
w_map: &BTreeMap<String, InputValue>,
40+
input_map: &BTreeMap<String, InputValue>,
41+
abi: &Abi,
4142
) -> Result<String, InputParserError> {
42-
let to_map: BTreeMap<_, _> =
43-
w_map.iter().map(|(key, value)| (key, JsonTypes::from(value.clone()))).collect();
43+
let mut json_map = try_btree_map(abi.to_btree_map(), |(key, param_type)| {
44+
JsonTypes::try_from_input_value(&input_map[&key], &param_type)
45+
.map(|value| (key.to_owned(), value))
46+
})?;
47+
48+
if let (Some(return_type), Some(return_value)) =
49+
(&abi.return_type, input_map.get(MAIN_RETURN_NAME))
50+
{
51+
let return_value = JsonTypes::try_from_input_value(return_value, return_type)?;
52+
json_map.insert(MAIN_RETURN_NAME.to_owned(), return_value);
53+
}
4454

45-
let json_string = serde_json::to_string(&to_map)?;
55+
let json_string = serde_json::to_string(&json_map)?;
4656

4757
Ok(json_string)
4858
}
@@ -71,24 +81,43 @@ enum JsonTypes {
7181
Table(BTreeMap<String, JsonTypes>),
7282
}
7383

74-
impl From<InputValue> for JsonTypes {
75-
fn from(value: InputValue) -> Self {
76-
match value {
77-
InputValue::Field(f) => {
84+
impl JsonTypes {
85+
fn try_from_input_value(
86+
value: &InputValue,
87+
abi_type: &AbiType,
88+
) -> Result<JsonTypes, InputParserError> {
89+
let json_value = match (value, abi_type) {
90+
(InputValue::Field(f), AbiType::Field | AbiType::Integer { .. }) => {
7891
let f_str = format!("0x{}", f.to_hex());
7992
JsonTypes::String(f_str)
8093
}
81-
InputValue::Vec(v) => {
82-
let array = v.iter().map(|i| format!("0x{}", i.to_hex())).collect();
83-
JsonTypes::ArrayString(array)
84-
}
85-
InputValue::String(s) => JsonTypes::String(s),
86-
InputValue::Struct(map) => {
87-
let map_with_json_types =
88-
btree_map(map, |(key, value)| (key, JsonTypes::from(value)));
94+
(InputValue::Field(f), AbiType::Boolean) => JsonTypes::Bool(f.is_one()),
95+
96+
(InputValue::Vec(v), AbiType::Array { typ, .. }) => match typ.as_ref() {
97+
AbiType::Field | AbiType::Integer { .. } => {
98+
let array = v.iter().map(|i| format!("0x{}", i.to_hex())).collect();
99+
JsonTypes::ArrayString(array)
100+
}
101+
AbiType::Boolean => {
102+
let array = v.iter().map(|i| i.is_one()).collect();
103+
JsonTypes::ArrayBool(array)
104+
}
105+
_ => return Err(InputParserError::AbiTypeMismatch(abi_type.clone())),
106+
},
107+
108+
(InputValue::String(s), AbiType::String { .. }) => JsonTypes::String(s.to_string()),
109+
110+
(InputValue::Struct(map), AbiType::Struct { fields }) => {
111+
let map_with_json_types = try_btree_map(fields, |(key, field_type)| {
112+
JsonTypes::try_from_input_value(&map[key], field_type)
113+
.map(|json_value| (key.to_owned(), json_value))
114+
})?;
89115
JsonTypes::Table(map_with_json_types)
90116
}
91-
}
117+
118+
_ => return Err(InputParserError::AbiTypeMismatch(abi_type.clone())),
119+
};
120+
Ok(json_value)
92121
}
93122
}
94123

crates/noirc_abi/src/input_parser/mod.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,12 @@ impl Format {
106106

107107
pub fn serialize(
108108
&self,
109-
w_map: &BTreeMap<String, InputValue>,
109+
input_map: &BTreeMap<String, InputValue>,
110+
abi: &Abi,
110111
) -> Result<String, InputParserError> {
111112
match self {
112-
Format::Json => json::serialize_to_json(w_map),
113-
Format::Toml => toml::serialize_to_toml(w_map),
113+
Format::Json => json::serialize_to_json(input_map, abi),
114+
Format::Toml => toml::serialize_to_toml(input_map, abi),
114115
}
115116
}
116117
}
@@ -170,7 +171,7 @@ mod serialization_tests {
170171
]);
171172

172173
for format in Format::iter() {
173-
let serialized_inputs = format.serialize(&input_map).unwrap();
174+
let serialized_inputs = format.serialize(&input_map, &abi).unwrap();
174175

175176
let reconstructed_input_map = format.parse(&serialized_inputs, &abi).unwrap();
176177

crates/noirc_abi/src/input_parser/toml.rs

+47-18
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::{parse_str_to_field, InputValue};
22
use crate::{errors::InputParserError, Abi, AbiType, MAIN_RETURN_NAME};
33
use acvm::FieldElement;
4-
use iter_extended::{btree_map, try_btree_map, try_vecmap, vecmap};
4+
use iter_extended::{try_btree_map, try_vecmap, vecmap};
55
use serde::{Deserialize, Serialize};
66
use std::collections::BTreeMap;
77

@@ -37,12 +37,22 @@ pub(crate) fn parse_toml(
3737
}
3838

3939
pub(crate) fn serialize_to_toml(
40-
w_map: &BTreeMap<String, InputValue>,
40+
input_map: &BTreeMap<String, InputValue>,
41+
abi: &Abi,
4142
) -> Result<String, InputParserError> {
42-
let to_map: BTreeMap<_, _> =
43-
w_map.iter().map(|(key, value)| (key, TomlTypes::from(value.clone()))).collect();
43+
let mut toml_map = try_btree_map(abi.to_btree_map(), |(key, param_type)| {
44+
TomlTypes::try_from_input_value(&input_map[&key], &param_type)
45+
.map(|toml_value| (key.clone(), toml_value))
46+
})?;
47+
48+
if let (Some(return_type), Some(return_value)) =
49+
(&abi.return_type, input_map.get(MAIN_RETURN_NAME))
50+
{
51+
let return_value = TomlTypes::try_from_input_value(return_value, return_type)?;
52+
toml_map.insert(MAIN_RETURN_NAME.to_owned(), return_value);
53+
}
4454

45-
let toml_string = toml::to_string(&to_map)?;
55+
let toml_string = toml::to_string(&toml_map)?;
4656

4757
Ok(toml_string)
4858
}
@@ -68,24 +78,43 @@ enum TomlTypes {
6878
Table(BTreeMap<String, TomlTypes>),
6979
}
7080

71-
impl From<InputValue> for TomlTypes {
72-
fn from(value: InputValue) -> Self {
73-
match value {
74-
InputValue::Field(f) => {
81+
impl TomlTypes {
82+
fn try_from_input_value(
83+
value: &InputValue,
84+
abi_type: &AbiType,
85+
) -> Result<TomlTypes, InputParserError> {
86+
let toml_value = match (value, abi_type) {
87+
(InputValue::Field(f), AbiType::Field | AbiType::Integer { .. }) => {
7588
let f_str = format!("0x{}", f.to_hex());
7689
TomlTypes::String(f_str)
7790
}
78-
InputValue::Vec(v) => {
79-
let array = v.iter().map(|i| format!("0x{}", i.to_hex())).collect();
80-
TomlTypes::ArrayString(array)
81-
}
82-
InputValue::String(s) => TomlTypes::String(s),
83-
InputValue::Struct(map) => {
84-
let map_with_toml_types =
85-
btree_map(map, |(key, value)| (key, TomlTypes::from(value)));
91+
(InputValue::Field(f), AbiType::Boolean) => TomlTypes::Bool(f.is_one()),
92+
93+
(InputValue::Vec(v), AbiType::Array { typ, .. }) => match typ.as_ref() {
94+
AbiType::Field | AbiType::Integer { .. } => {
95+
let array = v.iter().map(|i| format!("0x{}", i.to_hex())).collect();
96+
TomlTypes::ArrayString(array)
97+
}
98+
AbiType::Boolean => {
99+
let array = v.iter().map(|i| i.is_one()).collect();
100+
TomlTypes::ArrayBool(array)
101+
}
102+
_ => return Err(InputParserError::AbiTypeMismatch(abi_type.clone())),
103+
},
104+
105+
(InputValue::String(s), AbiType::String { .. }) => TomlTypes::String(s.to_string()),
106+
107+
(InputValue::Struct(map), AbiType::Struct { fields }) => {
108+
let map_with_toml_types = try_btree_map(fields, |(key, field_type)| {
109+
TomlTypes::try_from_input_value(&map[key], field_type)
110+
.map(|toml_value| (key.to_owned(), toml_value))
111+
})?;
86112
TomlTypes::Table(map_with_toml_types)
87113
}
88-
}
114+
115+
_ => return Err(InputParserError::AbiTypeMismatch(abi_type.clone())),
116+
};
117+
Ok(toml_value)
89118
}
90119
}
91120

0 commit comments

Comments
 (0)