1#![forbid(unsafe_code)]
2#![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))]
3
4use acvm::{
5 AcirField, FieldElement,
6 acir::{
7 circuit::ErrorSelector,
8 native_types::{Witness, WitnessMap},
9 },
10};
11use errors::AbiError;
12use input_parser::InputValue;
13use iter_extended::{try_btree_map, try_vecmap};
14use noirc_printable_type::{
15 PrintableType, PrintableValue, PrintableValueDisplay, decode_printable_value,
16 decode_string_value,
17};
18use serde::{Deserialize, Serialize};
19use std::borrow::Borrow;
20use std::{collections::BTreeMap, str};
21#[cfg(test)]
27mod arbitrary;
28
29pub mod errors;
30pub mod input_parser;
31mod serialization;
32
33pub type InputMap = BTreeMap<String, InputValue>;
35
36pub const MAIN_RETURN_NAME: &str = "return";
37
38#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
39#[serde(tag = "kind", rename_all = "lowercase")]
40#[derive(Hash)]
51pub enum AbiType {
52 Field,
53 Array {
54 length: u32,
55 #[serde(rename = "type")]
56 typ: Box<AbiType>,
57 },
58 Integer {
59 sign: Sign,
60 width: u32,
61 },
62 Boolean,
63 Struct {
64 path: String,
65 #[serde(
66 serialize_with = "serialization::serialize_struct_fields",
67 deserialize_with = "serialization::deserialize_struct_fields"
68 )]
69 fields: Vec<(String, AbiType)>,
70 },
71 Tuple {
72 fields: Vec<AbiType>,
73 },
74 String {
75 length: u32,
76 },
77}
78
79#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Hash)]
80#[cfg_attr(test, derive(arbitrary::Arbitrary))]
81#[serde(rename_all = "lowercase")]
82pub enum AbiVisibility {
84 Public,
85 Private,
88 DataBus,
89}
90
91#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Hash)]
92#[cfg_attr(test, derive(arbitrary::Arbitrary))]
93#[serde(rename_all = "lowercase")]
94pub enum Sign {
95 Unsigned,
96 Signed,
97}
98
99impl AbiType {
100 pub fn field_count(&self) -> u32 {
102 match self {
103 AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean => 1,
104 AbiType::Array { length, typ } => typ.field_count() * *length,
105 AbiType::Struct { fields, .. } => {
106 fields.iter().fold(0, |acc, (_, field_type)| acc + field_type.field_count())
107 }
108 AbiType::Tuple { fields } => {
109 fields.iter().fold(0, |acc, field_typ| acc + field_typ.field_count())
110 }
111 AbiType::String { length } => *length,
112 }
113 }
114}
115
116impl From<&AbiType> for PrintableType {
117 fn from(value: &AbiType) -> Self {
118 match value {
119 AbiType::Field => PrintableType::Field,
120 AbiType::String { length } => PrintableType::String { length: *length },
121 AbiType::Tuple { fields } => {
122 let fields = fields.iter().map(|field| field.into()).collect();
123 PrintableType::Tuple { types: fields }
124 }
125 AbiType::Array { length, typ } => {
126 let borrowed: &AbiType = typ.borrow();
127 PrintableType::Array { length: *length, typ: Box::new(borrowed.into()) }
128 }
129 AbiType::Boolean => PrintableType::Boolean,
130 AbiType::Struct { path, fields } => {
131 let fields =
132 fields.iter().map(|(name, field)| (name.clone(), field.into())).collect();
133 PrintableType::Struct {
134 name: path.split("::").last().unwrap_or_default().to_string(),
135 fields,
136 }
137 }
138 AbiType::Integer { sign: Sign::Unsigned, width } => {
139 PrintableType::UnsignedInteger { width: *width }
140 }
141 AbiType::Integer { sign: Sign::Signed, width } => {
142 PrintableType::SignedInteger { width: *width }
143 }
144 }
145 }
146}
147
148#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Hash)]
149#[cfg_attr(test, derive(arbitrary::Arbitrary))]
150pub struct AbiParameter {
152 pub name: String,
153 #[serde(rename = "type")]
154 #[cfg_attr(test, proptest(strategy = "arbitrary::arb_abi_type()"))]
155 pub typ: AbiType,
156 pub visibility: AbiVisibility,
157}
158
159impl AbiParameter {
160 pub fn is_public(&self) -> bool {
161 self.visibility == AbiVisibility::Public
162 }
163}
164
165#[derive(Clone, Debug, Serialize, Deserialize, Hash)]
166#[cfg_attr(test, derive(arbitrary::Arbitrary))]
167pub struct AbiReturnType {
168 #[cfg_attr(test, proptest(strategy = "arbitrary::arb_abi_type()"))]
169 pub abi_type: AbiType,
170 pub visibility: AbiVisibility,
171}
172
173#[derive(Clone, Debug, Default, Serialize, Deserialize, Hash)]
174#[cfg_attr(test, derive(arbitrary::Arbitrary))]
175pub struct Abi {
176 pub parameters: Vec<AbiParameter>,
178 pub return_type: Option<AbiReturnType>,
179 #[cfg_attr(test, proptest(strategy = "proptest::prelude::Just(BTreeMap::from([]))"))]
180 pub error_types: BTreeMap<ErrorSelector, AbiErrorType>,
181}
182
183impl Abi {
184 pub fn parameter_names(&self) -> Vec<&String> {
185 self.parameters.iter().map(|x| &x.name).collect()
186 }
187
188 pub fn num_parameters(&self) -> usize {
189 self.parameters.len()
190 }
191
192 pub fn field_count(&self) -> u32 {
194 self.parameters.iter().map(|param| param.typ.field_count()).sum()
195 }
196
197 pub fn has_public_inputs(&self) -> bool {
199 let has_public_args = self.parameters.iter().any(|param| param.is_public());
200 let has_public_return = self
201 .return_type
202 .as_ref()
203 .is_some_and(|typ| matches!(typ.visibility, AbiVisibility::Public));
204 has_public_args || has_public_return
205 }
206
207 pub fn is_empty(&self) -> bool {
209 self.return_type.is_none() && self.parameters.is_empty()
210 }
211
212 pub fn to_btree_map(&self) -> BTreeMap<String, AbiType> {
213 let mut map = BTreeMap::new();
214 for param in self.parameters.iter() {
215 map.insert(param.name.clone(), param.typ.clone());
216 }
217 map
218 }
219
220 pub fn encode(
222 &self,
223 input_map: &InputMap,
224 return_value: Option<InputValue>,
225 ) -> Result<WitnessMap<FieldElement>, AbiError> {
226 let param_names = self.parameter_names();
228 if param_names.len() < input_map.len() {
229 let unexpected_params: Vec<String> =
230 input_map.keys().filter(|param| !param_names.contains(param)).cloned().collect();
231 return Err(AbiError::UnexpectedParams(unexpected_params));
232 }
233
234 let mut encoded_inputs: Vec<Vec<FieldElement>> = self
236 .parameters
237 .iter()
238 .map(|param| {
239 let value = input_map
240 .get(¶m.name)
241 .ok_or_else(|| AbiError::MissingParam(param.name.clone()))?
242 .clone();
243
244 value.find_type_mismatch(¶m.typ, param.name.clone())?;
245
246 Self::encode_value(value, ¶m.typ)
247 })
248 .collect::<Result<_, _>>()?;
249
250 match (&self.return_type, return_value) {
253 (Some(AbiReturnType { abi_type: return_type, .. }), Some(return_value)) => {
254 if !return_value.matches_abi(return_type) {
255 return Err(AbiError::ReturnTypeMismatch {
256 return_type: return_type.clone(),
257 value: return_value,
258 });
259 }
260 let encoded_return_fields = Self::encode_value(return_value, return_type)?;
261 encoded_inputs.push(encoded_return_fields);
262 }
263 (None, Some(return_value)) => {
264 return Err(AbiError::UnexpectedReturnValue(return_value));
265 }
266 (_, None) => {}
269 }
270
271 let witness_map: BTreeMap<Witness, FieldElement> = encoded_inputs
273 .into_iter()
274 .flatten()
275 .enumerate()
276 .map(|(index, field_element)| (Witness(index as u32), field_element))
277 .collect::<BTreeMap<Witness, FieldElement>>();
278
279 Ok(witness_map.into())
280 }
281
282 fn encode_value(value: InputValue, abi_type: &AbiType) -> Result<Vec<FieldElement>, AbiError> {
283 let mut encoded_value = Vec::new();
284 match (value, abi_type) {
285 (InputValue::Field(elem), _) => encoded_value.push(elem),
286
287 (InputValue::Vec(vec_elements), AbiType::Array { typ, .. }) => {
288 for elem in vec_elements {
289 encoded_value.extend(Self::encode_value(elem, typ)?);
290 }
291 }
292
293 (InputValue::String(string), _) => {
294 let str_as_fields =
295 string.bytes().map(|byte| FieldElement::from_be_bytes_reduce(&[byte]));
296 encoded_value.extend(str_as_fields);
297 }
298
299 (InputValue::Struct(object), AbiType::Struct { fields, .. }) => {
300 for (field, typ) in fields {
301 encoded_value.extend(Self::encode_value(object[field].clone(), typ)?);
302 }
303 }
304 (InputValue::Vec(vec_elements), AbiType::Tuple { fields }) => {
305 for (value, typ) in vec_elements.into_iter().zip(fields) {
306 encoded_value.extend(Self::encode_value(value, typ)?);
307 }
308 }
309 _ => unreachable!("value should have already been checked to match abi type"),
310 }
311 Ok(encoded_value)
312 }
313
314 pub fn decode(
316 &self,
317 witness_map: &WitnessMap<FieldElement>,
318 ) -> Result<(InputMap, Option<InputValue>), AbiError> {
319 let mut pointer: u32 = 0;
320 let public_inputs_map =
321 try_btree_map(self.parameters.clone(), |AbiParameter { name, typ, .. }| {
322 let num_fields = typ.field_count();
323 let param_witness_values = try_vecmap(0..num_fields, |index| {
324 let witness_index = Witness(pointer + index);
325 witness_map
326 .get(&witness_index)
327 .ok_or_else(|| AbiError::MissingParamWitnessValue {
328 name: name.clone(),
329 witness_index,
330 })
331 .copied()
332 })?;
333 pointer += num_fields;
334
335 decode_value(&mut param_witness_values.into_iter(), &typ)
336 .map(|input_value| (name.clone(), input_value))
337 })?;
338
339 let return_value = if let Some(return_type) = &self.return_type {
341 if let Ok(return_witness_values) =
342 try_vecmap(0..return_type.abi_type.field_count(), |index| {
343 let witness_index = Witness(pointer + index);
344 witness_map
345 .get(&witness_index)
346 .ok_or_else(|| AbiError::MissingParamWitnessValue {
347 name: MAIN_RETURN_NAME.to_string(),
348 witness_index,
349 })
350 .copied()
351 })
352 {
353 Some(decode_value(&mut return_witness_values.into_iter(), &return_type.abi_type)?)
354 } else {
355 None
359 }
360 } else {
361 None
362 };
363
364 Ok((public_inputs_map, return_value))
365 }
366}
367
368pub fn decode_value(
369 field_iterator: &mut impl Iterator<Item = FieldElement>,
370 value_type: &AbiType,
371) -> Result<InputValue, AbiError> {
372 let value = match value_type {
375 AbiType::Field | AbiType::Integer { .. } | AbiType::Boolean => {
376 let field_element = field_iterator.next().unwrap();
377
378 InputValue::Field(field_element)
379 }
380 AbiType::Array { length, typ } => {
381 let length = *length as usize;
382 let mut array_elements = Vec::with_capacity(length);
383 for _ in 0..length {
384 array_elements.push(decode_value(field_iterator, typ)?);
385 }
386
387 InputValue::Vec(array_elements)
388 }
389 AbiType::String { length } => {
390 let field_elements: Vec<FieldElement> = field_iterator.take(*length as usize).collect();
391
392 InputValue::String(decode_string_value(&field_elements))
393 }
394 AbiType::Struct { fields, .. } => {
395 let mut struct_map = BTreeMap::new();
396
397 for (field_key, param_type) in fields {
398 let field_value = decode_value(field_iterator, param_type)?;
399
400 struct_map.insert(field_key.to_owned(), field_value);
401 }
402
403 InputValue::Struct(struct_map)
404 }
405 AbiType::Tuple { fields } => {
406 let mut tuple_elements = Vec::with_capacity(fields.len());
407 for field_typ in fields {
408 tuple_elements.push(decode_value(field_iterator, field_typ)?);
409 }
410
411 InputValue::Vec(tuple_elements)
412 }
413 };
414
415 Ok(value)
416}
417
418#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
419#[serde(tag = "kind", rename_all = "lowercase")]
420pub enum AbiValue {
421 Field {
422 value: FieldElement,
423 },
424 Integer {
425 sign: bool,
426 value: String,
427 },
428 Boolean {
429 value: bool,
430 },
431 String {
432 value: String,
433 },
434 Array {
435 value: Vec<AbiValue>,
436 },
437 Struct {
438 #[serde(
439 serialize_with = "serialization::serialize_struct_field_values",
440 deserialize_with = "serialization::deserialize_struct_field_values"
441 )]
442 fields: Vec<(String, AbiValue)>,
443 },
444 Tuple {
445 fields: Vec<AbiValue>,
446 },
447}
448
449#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Hash)]
450#[serde(tag = "error_kind", rename_all = "lowercase")]
451pub enum AbiErrorType {
452 FmtString { length: u32, item_types: Vec<AbiType> },
453 Custom(AbiType),
454 String { string: String },
455}
456
457pub fn display_abi_error<F: AcirField>(
463 fields: &[F],
464 error_type: AbiErrorType,
465) -> PrintableValueDisplay<F> {
466 match error_type {
467 AbiErrorType::FmtString { length, item_types } => {
468 let mut fields_iter = fields.iter().copied();
469 let PrintableValue::String(string) =
470 decode_printable_value(&mut fields_iter, &PrintableType::String { length })
471 else {
472 unreachable!("Got non-string from string decoding");
473 };
474 let _length_of_items = fields_iter.next();
475 let items = item_types.into_iter().map(|abi_type| {
476 let printable_type = (&abi_type).into();
477 let decoded = decode_printable_value(&mut fields_iter, &printable_type);
478 (decoded, printable_type)
479 });
480 PrintableValueDisplay::FmtString(string, items.collect())
481 }
482 AbiErrorType::Custom(abi_typ) => {
483 let printable_type = (&abi_typ).into();
484 let decoded = decode_printable_value(&mut fields.iter().copied(), &printable_type);
485 PrintableValueDisplay::Plain(decoded, printable_type)
486 }
487 AbiErrorType::String { string } => {
488 let length = string.len() as u32;
489 PrintableValueDisplay::Plain(
490 PrintableValue::String(string),
491 PrintableType::String { length },
492 )
493 }
494 }
495}
496
497#[cfg(test)]
498mod test {
499 use proptest::prelude::*;
500
501 use crate::arbitrary::arb_abi_and_input_map;
502
503 proptest! {
504 #[test]
505 fn encoding_and_decoding_returns_original_witness_map((abi, input_map) in arb_abi_and_input_map()) {
506 let witness_map = abi.encode(&input_map, None).unwrap();
507 let (decoded_inputs, return_value) = abi.decode(&witness_map).unwrap();
508
509 prop_assert_eq!(decoded_inputs, input_map);
510 prop_assert_eq!(return_value, None);
511 }
512 }
513}