Skip to main content

noirc_abi/
lib.rs

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// This is the ABI used to bridge the different TOML formats for the initial
22// witness, the partial witness generator and the interpreter.
23//
24// This ABI has nothing to do with ACVM or ACIR. Although they implicitly have a relationship
25
26#[cfg(test)]
27mod arbitrary;
28
29pub mod errors;
30pub mod input_parser;
31mod serialization;
32
33/// A map from the fields in an TOML/JSON file which correspond to some ABI to their values
34pub 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/// Types that are allowed in the (main function in binary)
41///
42/// we use this separation so that we can have types like Strings
43/// without needing to introduce this in the Noir types
44///
45/// NOTE: If Strings are introduced as a native type, the translation will
46/// be straightforward. Whether exotic types like String will be natively supported
47/// depends on the types of programs that users want to do. I don't envision string manipulation
48/// in programs, however it is possible to support, with many complications like encoding character set
49/// support.
50#[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")]
82/// Represents whether the parameter is public or known only to the prover.
83pub enum AbiVisibility {
84    Public,
85    // Constants are not allowed in the ABI for main at the moment.
86    // Constant,
87    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    /// Returns the number of field elements required to represent the type once encoded.
101    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))]
150/// An argument or return value of the circuit's `main` function.
151pub 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    /// An ordered list of the arguments to the program's `main` function, specifying their types and visibility.
177    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    /// Returns the number of field elements required to represent the ABI's input once encoded.
193    pub fn field_count(&self) -> u32 {
194        self.parameters.iter().map(|param| param.typ.field_count()).sum()
195    }
196
197    /// Returns whether any values are needed to be made public for verification.
198    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    /// Returns `true` if the ABI contains no parameters or return value.
208    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    /// Encode a set of inputs as described in the ABI into a `WitnessMap`.
221    pub fn encode(
222        &self,
223        input_map: &InputMap,
224        return_value: Option<InputValue>,
225    ) -> Result<WitnessMap<FieldElement>, AbiError> {
226        // Check that no extra witness values have been provided.
227        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        // First encode each input separately, performing any input validation.
235        let mut encoded_inputs: Vec<Vec<FieldElement>> = self
236            .parameters
237            .iter()
238            .map(|param| {
239                let value = input_map
240                    .get(&param.name)
241                    .ok_or_else(|| AbiError::MissingParam(param.name.clone()))?
242                    .clone();
243
244                value.find_type_mismatch(&param.typ, param.name.clone())?;
245
246                Self::encode_value(value, &param.typ)
247            })
248            .collect::<Result<_, _>>()?;
249
250        // When encoding public inputs to be passed to the verifier, the user can must provide a return value
251        // to be inserted into the witness map. This is not needed when generating a witness when proving the circuit.
252        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            // We allow not passing a return value despite the circuit defining one
267            // in order to generate the initial partial witness.
268            (_, None) => {}
269        }
270
271        // Write input field elements into witness map.
272        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    /// Decode a `WitnessMap` into the types specified in the ABI.
315    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        // We also attempt to decode the circuit's return value from `witness_map`.
340        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                // Unlike for the circuit inputs, we tolerate not being able to find the witness values for the return value.
356                // This is because the user may be decoding a partial witness map for which is hasn't been calculated yet.
357                // If a return value is expected, this should be checked for by the user.
358                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    // This function assumes that `field_iterator` contains enough `FieldElement`s in order to decode a `value_type`
373    // `Abi.decode` enforces that the encoded inputs matches the expected length defined by the ABI so this is safe.
374    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
457/// Decode the raw revert data according to some error type descriptor.
458///
459/// By contrast to how arguments are passed to foreign calls, the revert data is already flattened,
460/// so we don't have control over how we flatten the data before decoding, however note that slices
461/// are not allowed in revert data, so this shouldn't be a problem.
462pub 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}