@aztec-foundation/protocol-contracts-artifacts 6.0.0-rc.5 → 6.0.0-rc.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -928,31 +928,31 @@
|
|
|
928
928
|
},
|
|
929
929
|
{
|
|
930
930
|
"name": "Poseidon2::absorb",
|
|
931
|
-
"start":
|
|
931
|
+
"start": 1028
|
|
932
932
|
},
|
|
933
933
|
{
|
|
934
934
|
"name": "Poseidon2::squeeze",
|
|
935
|
-
"start":
|
|
935
|
+
"start": 1558
|
|
936
936
|
},
|
|
937
937
|
{
|
|
938
938
|
"name": "Poseidon2::hash_internal",
|
|
939
|
-
"start":
|
|
939
|
+
"start": 1919
|
|
940
940
|
},
|
|
941
941
|
{
|
|
942
942
|
"name": "<impl Hasher for Poseidon2Hasher>::finish",
|
|
943
|
-
"start":
|
|
943
|
+
"start": 4210
|
|
944
944
|
},
|
|
945
945
|
{
|
|
946
946
|
"name": "<impl Hasher for Poseidon2Hasher>::write",
|
|
947
|
-
"start":
|
|
947
|
+
"start": 4531
|
|
948
948
|
},
|
|
949
949
|
{
|
|
950
950
|
"name": "<impl Default for Poseidon2Hasher>::default",
|
|
951
|
-
"start":
|
|
951
|
+
"start": 4654
|
|
952
952
|
}
|
|
953
953
|
],
|
|
954
|
-
"path": "/home/aztec-dev/nargo/github.com/noir-lang/poseidon/v0.
|
|
955
|
-
"source": "use std::default::Default;\nuse std::hash::Hasher;\n\nglobal RATE: u32 = 3;\n\npub struct Poseidon2 {\n cache: [Field; 3],\n state: [Field; 4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n #[no_predicates]\n pub fn hash<let N: u32>(input: [Field; N], message_size: u32) -> Field {\n Poseidon2::hash_internal(input, message_size)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2 {\n let mut result =\n Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) {\n // add the cache into sponge state\n self.state[0] += self.cache[0];\n self.state[1] += self.cache[1];\n self.state[2] += self.cache[2];\n self.state = crate::poseidon2_permutation(self.state);\n }\n\n fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal<let N: u32>(input: [Field; N], in_len: u32) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv: Field = (in_len as Field) * two_pow_64;\n let mut state = [0; 4];\n state[RATE] = iv;\n\n if std::runtime::is_unconstrained() {\n for i in 0..(in_len / RATE) {\n state[0] += input[i * RATE];\n state[1] += input[i * RATE + 1];\n state[2] += input[i * RATE + 2];\n state = crate::poseidon2_permutation(state);\n }\n\n // handle remaining elements after last full RATE-sized chunk\n let num_extra_fields = in_len % RATE;\n if num_extra_fields != 0 {\n let remainder_start = in_len - num_extra_fields;\n state[0] += input[remainder_start];\n if num_extra_fields > 1 {\n state[1] += input[remainder_start + 1];\n }\n }\n } else {\n let mut states: [[Field; 4]; N / RATE + 1] = [[0; 4]; N / RATE + 1];\n states[0] = state;\n\n // process all full RATE-sized chunks, storing state after each permutation\n for chunk_idx in 0..(N / RATE) {\n for i in 0..RATE {\n state[i] += input[chunk_idx * RATE + i];\n }\n state = crate::poseidon2_permutation(state);\n states[chunk_idx + 1] = state;\n }\n\n // get state at the last full block before in_len\n let first_partially_filled_chunk = in_len / RATE;\n state = states[first_partially_filled_chunk];\n\n // handle remaining elements after last full RATE-sized chunk\n let remainder_start = (in_len / RATE) * RATE;\n for j in 0..RATE {\n let idx = remainder_start + j;\n if idx < in_len {\n state[j] += input[idx];\n }\n }\n }\n\n // always run final permutation unless we just completed a full chunk\n // still need to permute once if in_len is 0\n if (in_len == 0) | (in_len % RATE != 0) {\n state = crate::poseidon2_permutation(state);\n };\n\n state[0]\n }\n}\n\npub struct Poseidon2Hasher {\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv: Field = (self._state.len() as Field) * 18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field) {\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher { _state: @[] }\n }\n}\n"
|
|
954
|
+
"path": "/home/aztec-dev/nargo/github.com/noir-lang/poseidon/v0.4.0/src/poseidon2.nr",
|
|
955
|
+
"source": "use std::default::Default;\nuse std::hash::Hasher;\n\nglobal RATE: u32 = 3;\n\npub struct Poseidon2 {\n cache: [Field; 3],\n state: [Field; 4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n #[no_predicates]\n pub fn hash<let N: u32>(input: [Field; N], message_size: u32) -> Field {\n Poseidon2::hash_internal(input, message_size)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2 {\n let mut result =\n Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) {\n // add the cache into sponge state\n self.state[0] += self.cache[0] * ((0 < self.cache_size) as Field);\n self.state[1] += self.cache[1] * ((1 < self.cache_size) as Field);\n self.state[2] += self.cache[2] * ((2 < self.cache_size) as Field);\n self.state = crate::poseidon2_permutation(self.state);\n }\n\n fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal<let N: u32>(input: [Field; N], in_len: u32) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv: Field = (in_len as Field) * two_pow_64;\n let mut state = [0; 4];\n state[RATE] = iv;\n\n if std::runtime::is_unconstrained() {\n for i in 0..(in_len / RATE) {\n state[0] += input[i * RATE];\n state[1] += input[i * RATE + 1];\n state[2] += input[i * RATE + 2];\n state = crate::poseidon2_permutation(state);\n }\n\n // handle remaining elements after last full RATE-sized chunk\n let num_extra_fields = in_len % RATE;\n if num_extra_fields != 0 {\n let remainder_start = in_len - num_extra_fields;\n state[0] += input[remainder_start];\n if num_extra_fields > 1 {\n state[1] += input[remainder_start + 1];\n }\n }\n } else {\n let mut states: [[Field; 4]; N / RATE + 1] = [[0; 4]; N / RATE + 1];\n states[0] = state;\n\n // process all full RATE-sized chunks, storing state after each permutation\n for chunk_idx in 0..(N / RATE) {\n for i in 0..RATE {\n state[i] += input[chunk_idx * RATE + i];\n }\n state = crate::poseidon2_permutation(state);\n states[chunk_idx + 1] = state;\n }\n\n // get state at the last full block before in_len\n let first_partially_filled_chunk = in_len / RATE;\n state = states[first_partially_filled_chunk];\n\n // handle remaining elements after last full RATE-sized chunk\n let remainder_start = (in_len / RATE) * RATE;\n for j in 0..RATE {\n let idx = remainder_start + j;\n if idx < in_len {\n state[j] += input[idx];\n }\n }\n }\n\n // always run final permutation unless we just completed a full chunk\n // still need to permute once if in_len is 0\n if (in_len == 0) | (in_len % RATE != 0) {\n state = crate::poseidon2_permutation(state);\n };\n\n state[0]\n }\n}\n\npub struct Poseidon2Hasher {\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv: Field = (self._state.len() as Field) * 18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field) {\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher { _state: @[] }\n }\n}\n"
|
|
956
956
|
},
|
|
957
957
|
"234": {
|
|
958
958
|
"function_locations": [
|
|
@@ -1012,23 +1012,23 @@
|
|
|
1012
1012
|
},
|
|
1013
1013
|
{
|
|
1014
1014
|
"name": "derive_deserialize",
|
|
1015
|
-
"start":
|
|
1015
|
+
"start": 7397
|
|
1016
1016
|
},
|
|
1017
1017
|
{
|
|
1018
1018
|
"name": "get_params_len_quote",
|
|
1019
|
-
"start":
|
|
1019
|
+
"start": 11362
|
|
1020
1020
|
},
|
|
1021
1021
|
{
|
|
1022
1022
|
"name": "get_generics_declarations",
|
|
1023
|
-
"start":
|
|
1023
|
+
"start": 11854
|
|
1024
1024
|
},
|
|
1025
1025
|
{
|
|
1026
1026
|
"name": "get_where_trait_clause",
|
|
1027
|
-
"start":
|
|
1027
|
+
"start": 12947
|
|
1028
1028
|
}
|
|
1029
1029
|
],
|
|
1030
1030
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/fnd/noir-protocol-circuits/crates/serde/src/serialization.nr",
|
|
1031
|
-
"source": "use crate::{reader::Reader, writer::Writer};\nuse std::meta::type_def::StructField;\n\n/// Trait for serializing Noir types into arrays of Fields.\n///\n/// An implementation of the Serialize trait has to follow Noir's intrinsic serialization (each member of a struct\n/// converted directly into one or more Fields without any packing or compression). This trait (and Deserialize) are\n/// typically used to communicate between Noir and TypeScript (via oracles and function arguments).\n///\n/// # On Following Noir's Intrinsic Serialization\n/// When calling a Noir function from TypeScript (TS), first the function arguments are serialized into an array\n/// of fields. This array is then included in the initial witness. Noir's intrinsic serialization is then used\n/// to deserialize the arguments from the witness. When the same Noir function is called from Noir this Serialize trait\n/// is used instead of the serialization in TS. For this reason we need to have a match between TS serialization,\n/// Noir's intrinsic serialization and the implementation of this trait. If there is a mismatch, the function calls\n/// fail with an arguments hash mismatch error message.\n///\n/// # Associated Constants\n/// * `N` - The length of the output Field array, known at compile time\n///\n/// # Example\n/// ```\n/// impl<let N: u32> Serialize for str<N> {\n/// let N: u32 = N;\n///\n/// fn serialize(self) -> [Field; Self::N] {\n/// let mut writer: Writer<Self::N> = Writer::new();\n/// self.stream_serialize(&mut writer);\n/// writer.finish()\n/// }\n///\n/// fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n/// let bytes = self.as_bytes();\n/// for i in 0..bytes.len() {\n/// writer.write(bytes[i] as Field);\n/// }\n/// }\n/// }\n/// ```\n#[derive_via(derive_serialize)]\npub trait Serialize {\n let N: u32;\n\n fn serialize(self) -> [Field; Self::N];\n\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>);\n}\n\n/// Generates a `Serialize` trait implementation for a struct type.\n///\n/// # Parameters\n/// - `s`: The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A quoted code block containing the trait implementation\n///\n/// # Example\n/// For a struct defined as:\n/// ```\n/// struct Log<N> {\n/// fields: [Field; N],\n/// length: u32\n/// }\n/// ```\n///\n/// This function generates code equivalent to:\n/// ```\n/// impl<let N: u32> Serialize for Log<N> {\n/// let N: u32 = <[Field; N] as Serialize>::N + <u32 as Serialize>::N;\n///\n/// fn serialize(self) -> [Field; Self::N] {\n/// let mut writer: Writer<Self::N> = Writer::new();\n/// self.stream_serialize(&mut writer);\n/// writer.finish()\n/// }\n///\n/// #[inline_always]\n/// fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n/// Serialize::stream_serialize(self.fields, writer);\n/// Serialize::stream_serialize(self.length, writer);\n/// }\n/// }\n/// ```\npub comptime fn derive_serialize(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n let params = nested_struct.definition().fields(nested_struct.generics());\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Serialize` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_serialize_clause = get_where_trait_clause(s, quote { Serialize });\n\n let params_len_quote = get_params_len_quote(params);\n\n let function_body = params\n .map(|field: StructField| {\n let name = field.name();\n quote {\n $crate::serialization::Serialize::stream_serialize(self.$name, writer);\n }\n })\n .join(quote {});\n\n quote {\n impl$generics_declarations $crate::serialization::Serialize for $typ\n $where_serialize_clause\n {\n let N: u32 = $params_len_quote;\n\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: $crate::writer::Writer<Self::N> = $crate::writer::Writer::new();\n $crate::serialization::Serialize::stream_serialize(self, &mut writer);\n writer.finish()\n }\n\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut $crate::writer::Writer<K>) {\n $function_body\n }\n }\n }\n}\n\n/// Trait for deserializing Noir types from arrays of Fields.\n///\n/// An implementation of the Deserialize trait has to follow Noir's intrinsic serialization (each member of a struct\n/// converted directly into one or more Fields without any packing or compression). This trait is typically used when\n/// deserializing return values from function calls in Noir. Since the same function could be called from TypeScript\n/// (TS), in which case the TS deserialization would get used, we need to have a match between the 2.\n///\n/// # Associated Constants\n/// * `N` - The length of the input Field array, known at compile time\n///\n/// # Example\n/// ```\n/// impl<let M: u32> Deserialize for str<M> {\n/// let N: u32 = M;\n///\n/// fn deserialize(fields: [Field; Self::N]) -> Self {\n/// let mut reader = Reader::new(fields);\n/// let result = Self::stream_deserialize(&mut reader);\n/// reader.finish();\n/// result\n/// }\n///\n/// fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n/// let mut bytes = [0 as u8; M];\n/// for i in 0..M {\n/// bytes[i] = reader.read() as u8;\n/// }\n/// str::<M>::from(bytes)\n/// }\n/// }\n/// ```\n#[derive_via(derive_deserialize)]\npub trait Deserialize {\n let N: u32;\n\n fn deserialize(fields: [Field; Self::N]) -> Self;\n\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self;\n}\n\n/// Generates a `Deserialize` trait implementation for a given struct `s`.\n///\n/// # Arguments\n/// * `s` - The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A `Quoted` block containing the generated trait implementation\n///\n/// # Requirements\n/// Each struct member type must implement the `Deserialize` trait (it gets used in the generated code).\n///\n/// # Example\n/// For a struct like:\n/// ```\n/// struct MyStruct {\n/// x: AztecAddress,\n/// y: Field,\n/// }\n/// ```\n///\n/// This generates:\n/// ```\n/// impl Deserialize for MyStruct {\n/// let N: u32 = <AztecAddress as Deserialize>::N + <Field as Deserialize>::N;\n///\n/// fn deserialize(fields: [Field; Self::N]) -> Self {\n/// let mut reader = Reader::new(fields);\n/// let result = Self::stream_deserialize(&mut reader);\n/// reader.finish();\n/// result\n/// }\n///\n/// #[inline_always]\n/// fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n/// let x = <AztecAddress as Deserialize>::stream_deserialize(reader);\n/// let y = <Field as Deserialize>::stream_deserialize(reader);\n/// Self { x, y }\n/// }\n/// }\n/// ```\npub comptime fn derive_deserialize(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n let params = nested_struct.definition().fields(nested_struct.generics());\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Deserialize` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_deserialize_clause = get_where_trait_clause(s, quote { Deserialize });\n\n // The following will give us:\n // <type_of_struct_member_1 as Deserialize>::N + <type_of_struct_member_2 as Deserialize>::N + ...\n // (or 0 if the struct has no members)\n let right_hand_side_of_definition_of_n = if params.len() > 0 {\n params\n .map(|field: StructField| {\n let param_type = field.typ();\n quote {\n <$param_type as $crate::serialization::Deserialize>::N\n }\n })\n .join(quote {+})\n } else {\n quote { 0 }\n };\n\n // For structs containing a single member, we can enhance performance by directly deserializing the input array,\n // bypassing the need for loop-based array construction. While this optimization yields significant benefits in\n // Brillig where the loops are expected to not be optimized, it is not relevant in ACIR where the loops are\n // expected to be optimized away.\n let function_body = if params.len() > 1 {\n // This generates deserialization code for each struct member and concatenates them together.\n let deserialization_of_struct_members = params\n .map(|field: StructField| {\n let param_name = field.name();\n let param_type = field.typ();\n quote {\n let $param_name = <$param_type as Deserialize>::stream_deserialize(reader);\n }\n })\n .join(quote {});\n\n // We join the struct member names with a comma to be used in the `Self { ... }` syntax\n // This will give us e.g. `a, b, c` for a struct with three fields named `a`, `b`, and `c`.\n let struct_members = params\n .map(|field: StructField| {\n let param_name = field.name();\n quote { $param_name }\n })\n .join(quote {,});\n\n quote {\n $deserialization_of_struct_members\n\n Self { $struct_members }\n }\n } else if params.len() == 1 {\n let param_name = params[0].name();\n quote {\n Self { $param_name: $crate::serialization::Deserialize::stream_deserialize(reader) }\n }\n } else {\n quote {\n Self {}\n }\n };\n\n quote {\n impl$generics_declarations $crate::serialization::Deserialize for $typ\n $where_deserialize_clause\n {\n let N: u32 = $right_hand_side_of_definition_of_n;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = $crate::reader::Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut $crate::reader::Reader<K>) -> Self {\n $function_body\n }\n }\n }\n}\n\n/// Generates a quoted expression that computes the total serialized length of function parameters.\n///\n/// # Parameters\n/// * `params` - The struct fields to serialize. Each field's type needs to implement the Serialize trait.\n///\n/// # Returns\n/// A quoted expression that evaluates to:\n/// * `0` if there are no parameters\n/// * `(<type1 as Serialize>::N + <type2 as Serialize>::N + ...)` for one or more parameters\ncomptime fn get_params_len_quote(params: [StructField]) -> Quoted {\n if params.len() == 0 {\n quote { 0 }\n } else {\n let params_quote_without_parentheses = params\n .map(|field: StructField| {\n let param_type = field.typ();\n quote {\n <$param_type as $crate::serialization::Serialize>::N\n }\n })\n .join(quote {+});\n quote { ($params_quote_without_parentheses) }\n }\n}\n\ncomptime fn get_generics_declarations(s: TypeDefinition) -> Quoted {\n let generics = s.generics();\n\n if generics.len() > 0 {\n let generics_declarations_items = generics\n .map(|generic| {\n let name = generic.typ();\n let maybe_integer_typ = generic.numeric_type();\n // numeric_type is Some only when the generic is numeric.\n if maybe_integer_typ.is_some() {\n // The generic is numeric, so we return a quote defined as e.g. \"let N: u32\"\n let integer_type = maybe_integer_typ.unwrap();\n quote {let $name: $integer_type}\n } else {\n // The generic is not numeric, so we return a quote containing the name of the generic (e.g. \"T\")\n quote { $name }\n }\n })\n .join(quote {,});\n quote {<$generics_declarations_items>}\n } else {\n // The struct doesn't have any generics defined, so we just return an empty quote.\n quote {}\n }\n}\n\ncomptime fn get_where_trait_clause(s: TypeDefinition, trait_name: Quoted) -> Quoted {\n let generics = s.generics();\n\n // numeric_type is Some only when the generic is numeric.\n let non_numeric_generics = generics.filter(|generic| generic.numeric_type().is_none());\n\n if non_numeric_generics.len() > 0 {\n let non_numeric_generics_declarations = non_numeric_generics\n .map(|generic| {\n let name = generic.typ();\n quote {$name: $trait_name}\n })\n .join(quote {,});\n quote {where $non_numeric_generics_declarations}\n } else {\n // There are no non-numeric generics, so we return an empty quote.\n quote {}\n }\n}\n"
|
|
1031
|
+
"source": "use crate::{reader::Reader, writer::Writer};\nuse std::meta::type_def::StructField;\n\n/// Trait for serializing Noir types into arrays of Fields.\n///\n/// An implementation of the Serialize trait has to follow Noir's intrinsic serialization (each member of a struct\n/// converted directly into one or more Fields without any packing or compression). This trait (and Deserialize) are\n/// typically used to communicate between Noir and TypeScript (via oracles and function arguments).\n///\n/// # On Following Noir's Intrinsic Serialization\n/// When calling a Noir function from TypeScript (TS), first the function arguments are serialized into an array\n/// of fields. This array is then included in the initial witness. Noir's intrinsic serialization is then used\n/// to deserialize the arguments from the witness. When the same Noir function is called from Noir this Serialize trait\n/// is used instead of the serialization in TS. For this reason we need to have a match between TS serialization,\n/// Noir's intrinsic serialization and the implementation of this trait. If there is a mismatch, the function calls\n/// fail with an arguments hash mismatch error message.\n///\n/// # Associated Constants\n/// * `N` - The length of the output Field array, known at compile time\n///\n/// # Example\n/// ```\n/// impl<let N: u32> Serialize for str<N> {\n/// let N: u32 = N;\n///\n/// fn serialize(self) -> [Field; Self::N] {\n/// let mut writer: Writer<Self::N> = Writer::new();\n/// self.stream_serialize(&mut writer);\n/// writer.finish()\n/// }\n///\n/// fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n/// let bytes = self.as_bytes();\n/// for i in 0..bytes.len() {\n/// writer.write(bytes[i] as Field);\n/// }\n/// }\n/// }\n/// ```\n#[derive_via(derive_serialize)]\npub trait Serialize {\n let N: u32;\n\n fn serialize(self) -> [Field; Self::N];\n\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>);\n}\n\n/// Generates a `Serialize` trait implementation for a struct type.\n///\n/// # Parameters\n/// - `s`: The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A quoted code block containing the trait implementation\n///\n/// # Example\n/// For a struct defined as:\n/// ```\n/// struct Log<N> {\n/// fields: [Field; N],\n/// length: u32\n/// }\n/// ```\n///\n/// This function generates code equivalent to:\n/// ```\n/// impl<let N: u32> Serialize for Log<N> {\n/// let N: u32 = <[Field; N] as Serialize>::N + <u32 as Serialize>::N;\n///\n/// fn serialize(self) -> [Field; Self::N] {\n/// let mut writer: Writer<Self::N> = Writer::new();\n/// self.stream_serialize(&mut writer);\n/// writer.finish()\n/// }\n///\n/// #[inline_always]\n/// fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n/// Serialize::stream_serialize(self.fields, writer);\n/// Serialize::stream_serialize(self.length, writer);\n/// }\n/// }\n/// ```\npub comptime fn derive_serialize(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n let params = nested_struct.definition().fields(nested_struct.generics());\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Serialize` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_serialize_clause = get_where_trait_clause(s, quote { Serialize });\n\n let params_len_quote = get_params_len_quote(params);\n\n let function_body = if params.len() == 0 {\n // Nothing to serialize, so the parameter is referenced to keep the generated function warning-free.\n quote { let _ = writer; }\n } else {\n params\n .map(|field: StructField| {\n let name = field.name();\n quote {\n $crate::serialization::Serialize::stream_serialize(self.$name, writer);\n }\n })\n .join(quote {})\n };\n\n quote {\n impl$generics_declarations $crate::serialization::Serialize for $typ\n $where_serialize_clause\n {\n let N: u32 = $params_len_quote;\n\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: $crate::writer::Writer<Self::N> = $crate::writer::Writer::new();\n $crate::serialization::Serialize::stream_serialize(self, &mut writer);\n writer.finish()\n }\n\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut $crate::writer::Writer<K>) {\n $function_body\n }\n }\n }\n}\n\n/// Trait for deserializing Noir types from arrays of Fields.\n///\n/// An implementation of the Deserialize trait has to follow Noir's intrinsic serialization (each member of a struct\n/// converted directly into one or more Fields without any packing or compression). This trait is typically used when\n/// deserializing return values from function calls in Noir. Since the same function could be called from TypeScript\n/// (TS), in which case the TS deserialization would get used, we need to have a match between the 2.\n///\n/// # Associated Constants\n/// * `N` - The length of the input Field array, known at compile time\n///\n/// # Example\n/// ```\n/// impl<let M: u32> Deserialize for str<M> {\n/// let N: u32 = M;\n///\n/// fn deserialize(fields: [Field; Self::N]) -> Self {\n/// let mut reader = Reader::new(fields);\n/// let result = Self::stream_deserialize(&mut reader);\n/// reader.finish();\n/// result\n/// }\n///\n/// fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n/// let mut bytes = [0 as u8; M];\n/// for i in 0..M {\n/// bytes[i] = reader.read() as u8;\n/// }\n/// str::<M>::from(bytes)\n/// }\n/// }\n/// ```\n#[derive_via(derive_deserialize)]\npub trait Deserialize {\n let N: u32;\n\n fn deserialize(fields: [Field; Self::N]) -> Self;\n\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self;\n}\n\n/// Generates a `Deserialize` trait implementation for a given struct `s`.\n///\n/// # Arguments\n/// * `s` - The struct type definition to generate the implementation for\n///\n/// # Returns\n/// A `Quoted` block containing the generated trait implementation\n///\n/// # Requirements\n/// Each struct member type must implement the `Deserialize` trait (it gets used in the generated code).\n///\n/// # Example\n/// For a struct like:\n/// ```\n/// struct MyStruct {\n/// x: AztecAddress,\n/// y: Field,\n/// }\n/// ```\n///\n/// This generates:\n/// ```\n/// impl Deserialize for MyStruct {\n/// let N: u32 = <AztecAddress as Deserialize>::N + <Field as Deserialize>::N;\n///\n/// fn deserialize(fields: [Field; Self::N]) -> Self {\n/// let mut reader = Reader::new(fields);\n/// let result = Self::stream_deserialize(&mut reader);\n/// reader.finish();\n/// result\n/// }\n///\n/// #[inline_always]\n/// fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n/// let x = <AztecAddress as Deserialize>::stream_deserialize(reader);\n/// let y = <Field as Deserialize>::stream_deserialize(reader);\n/// Self { x, y }\n/// }\n/// }\n/// ```\npub comptime fn derive_deserialize(s: TypeDefinition) -> Quoted {\n let typ = s.as_type();\n let nested_struct = typ.as_data_type().unwrap();\n let params = nested_struct.definition().fields(nested_struct.generics());\n\n // Generates the generic parameter declarations (to be placed after the `impl` keyword) and the `where` clause\n // for the `Deserialize` trait.\n let generics_declarations = get_generics_declarations(s);\n let where_deserialize_clause = get_where_trait_clause(s, quote { Deserialize });\n\n // The following will give us:\n // <type_of_struct_member_1 as Deserialize>::N + <type_of_struct_member_2 as Deserialize>::N + ...\n // (or 0 if the struct has no members)\n let right_hand_side_of_definition_of_n = if params.len() > 0 {\n params\n .map(|field: StructField| {\n let param_type = field.typ();\n quote {\n <$param_type as $crate::serialization::Deserialize>::N\n }\n })\n .join(quote {+})\n } else {\n quote { 0 }\n };\n\n // For structs containing a single member, we can enhance performance by directly deserializing the input array,\n // bypassing the need for loop-based array construction. While this optimization yields significant benefits in\n // Brillig where the loops are expected to not be optimized, it is not relevant in ACIR where the loops are\n // expected to be optimized away.\n let function_body = if params.len() > 1 {\n // This generates deserialization code for each struct member and concatenates them together.\n let deserialization_of_struct_members = params\n .map(|field: StructField| {\n let param_name = field.name();\n let param_type = field.typ();\n quote {\n let $param_name = <$param_type as Deserialize>::stream_deserialize(reader);\n }\n })\n .join(quote {});\n\n // We join the struct member names with a comma to be used in the `Self { ... }` syntax\n // This will give us e.g. `a, b, c` for a struct with three fields named `a`, `b`, and `c`.\n let struct_members = params\n .map(|field: StructField| {\n let param_name = field.name();\n quote { $param_name }\n })\n .join(quote {,});\n\n quote {\n $deserialization_of_struct_members\n\n Self { $struct_members }\n }\n } else if params.len() == 1 {\n let param_name = params[0].name();\n quote {\n Self { $param_name: $crate::serialization::Deserialize::stream_deserialize(reader) }\n }\n } else {\n // Nothing to deserialize, so the parameter is referenced to keep the generated function warning-free.\n quote {\n let _ = reader;\n Self {}\n }\n };\n\n quote {\n impl$generics_declarations $crate::serialization::Deserialize for $typ\n $where_deserialize_clause\n {\n let N: u32 = $right_hand_side_of_definition_of_n;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = $crate::reader::Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut $crate::reader::Reader<K>) -> Self {\n $function_body\n }\n }\n }\n}\n\n/// Generates a quoted expression that computes the total serialized length of function parameters.\n///\n/// # Parameters\n/// * `params` - The struct fields to serialize. Each field's type needs to implement the Serialize trait.\n///\n/// # Returns\n/// A quoted expression that evaluates to:\n/// * `0` if there are no parameters\n/// * `(<type1 as Serialize>::N + <type2 as Serialize>::N + ...)` for one or more parameters\ncomptime fn get_params_len_quote(params: [StructField]) -> Quoted {\n if params.len() == 0 {\n quote { 0 }\n } else {\n let params_quote_without_parentheses = params\n .map(|field: StructField| {\n let param_type = field.typ();\n quote {\n <$param_type as $crate::serialization::Serialize>::N\n }\n })\n .join(quote {+});\n quote { ($params_quote_without_parentheses) }\n }\n}\n\ncomptime fn get_generics_declarations(s: TypeDefinition) -> Quoted {\n let generics = s.generics();\n\n if generics.len() > 0 {\n let generics_declarations_items = generics\n .map(|generic| {\n let name = generic.typ();\n let maybe_integer_typ = generic.numeric_type();\n // numeric_type is Some only when the generic is numeric.\n if maybe_integer_typ.is_some() {\n // The generic is numeric, so we return a quote defined as e.g. \"let N: u32\"\n let integer_type = maybe_integer_typ.unwrap();\n quote {let $name: $integer_type}\n } else {\n // The generic is not numeric, so we return a quote containing the name of the generic (e.g. \"T\")\n quote { $name }\n }\n })\n .join(quote {,});\n quote {<$generics_declarations_items>}\n } else {\n // The struct doesn't have any generics defined, so we just return an empty quote.\n quote {}\n }\n}\n\ncomptime fn get_where_trait_clause(s: TypeDefinition, trait_name: Quoted) -> Quoted {\n let generics = s.generics();\n\n // numeric_type is Some only when the generic is numeric.\n let non_numeric_generics = generics.filter(|generic| generic.numeric_type().is_none());\n\n if non_numeric_generics.len() > 0 {\n let non_numeric_generics_declarations = non_numeric_generics\n .map(|generic| {\n let name = generic.typ();\n quote {$name: $trait_name}\n })\n .join(quote {,});\n quote {where $non_numeric_generics_declarations}\n } else {\n // There are no non-numeric generics, so we return an empty quote.\n quote {}\n }\n}\n"
|
|
1032
1032
|
},
|
|
1033
1033
|
"237": {
|
|
1034
1034
|
"function_locations": [
|
|
@@ -1234,115 +1234,111 @@
|
|
|
1234
1234
|
},
|
|
1235
1235
|
{
|
|
1236
1236
|
"name": "<impl Deserialize for Option<T>>::deserialize",
|
|
1237
|
-
"start":
|
|
1237
|
+
"start": 11278
|
|
1238
1238
|
},
|
|
1239
1239
|
{
|
|
1240
1240
|
"name": "<impl Deserialize for Option<T>>::stream_deserialize",
|
|
1241
|
-
"start":
|
|
1241
|
+
"start": 11524
|
|
1242
1242
|
},
|
|
1243
1243
|
{
|
|
1244
1244
|
"name": "<impl Serialize for EmbeddedCurveScalar>::serialize",
|
|
1245
|
-
"start":
|
|
1245
|
+
"start": 11902
|
|
1246
1246
|
},
|
|
1247
1247
|
{
|
|
1248
1248
|
"name": "<impl Serialize for EmbeddedCurveScalar>::stream_serialize",
|
|
1249
|
-
"start":
|
|
1249
|
+
"start": 12025
|
|
1250
1250
|
},
|
|
1251
1251
|
{
|
|
1252
1252
|
"name": "<impl Deserialize for EmbeddedCurveScalar>::deserialize",
|
|
1253
|
-
"start":
|
|
1253
|
+
"start": 12225
|
|
1254
1254
|
},
|
|
1255
1255
|
{
|
|
1256
1256
|
"name": "<impl Deserialize for EmbeddedCurveScalar>::stream_deserialize",
|
|
1257
|
-
"start":
|
|
1257
|
+
"start": 12371
|
|
1258
1258
|
},
|
|
1259
1259
|
{
|
|
1260
1260
|
"name": "<impl Serialize for EmbeddedCurvePoint>::serialize",
|
|
1261
|
-
"start":
|
|
1261
|
+
"start": 12578
|
|
1262
1262
|
},
|
|
1263
1263
|
{
|
|
1264
1264
|
"name": "<impl Serialize for EmbeddedCurvePoint>::stream_serialize",
|
|
1265
|
-
"start":
|
|
1265
|
+
"start": 12678
|
|
1266
1266
|
},
|
|
1267
1267
|
{
|
|
1268
1268
|
"name": "<impl Deserialize for EmbeddedCurvePoint>::deserialize",
|
|
1269
|
-
"start":
|
|
1269
|
+
"start": 12874
|
|
1270
1270
|
},
|
|
1271
1271
|
{
|
|
1272
1272
|
"name": "<impl Deserialize for EmbeddedCurvePoint>::stream_deserialize",
|
|
1273
|
-
"start":
|
|
1273
|
+
"start": 13018
|
|
1274
1274
|
},
|
|
1275
1275
|
{
|
|
1276
1276
|
"name": "<impl Deserialize for str<M>>::deserialize",
|
|
1277
|
-
"start":
|
|
1277
|
+
"start": 13197
|
|
1278
1278
|
},
|
|
1279
1279
|
{
|
|
1280
1280
|
"name": "<impl Deserialize for str<M>>::stream_deserialize",
|
|
1281
|
-
"start":
|
|
1281
|
+
"start": 13443
|
|
1282
1282
|
},
|
|
1283
1283
|
{
|
|
1284
1284
|
"name": "<impl Serialize for str<M>>::serialize",
|
|
1285
|
-
"start":
|
|
1285
|
+
"start": 13676
|
|
1286
1286
|
},
|
|
1287
1287
|
{
|
|
1288
1288
|
"name": "<impl Serialize for str<M>>::stream_serialize",
|
|
1289
|
-
"start":
|
|
1289
|
+
"start": 13897
|
|
1290
1290
|
},
|
|
1291
1291
|
{
|
|
1292
1292
|
"name": "<impl Deserialize for BoundedVec<T, M>>::deserialize",
|
|
1293
|
-
"start":
|
|
1293
|
+
"start": 14278
|
|
1294
1294
|
},
|
|
1295
1295
|
{
|
|
1296
1296
|
"name": "<impl Deserialize for BoundedVec<T, M>>::stream_deserialize",
|
|
1297
|
-
"start":
|
|
1297
|
+
"start": 14524
|
|
1298
1298
|
},
|
|
1299
1299
|
{
|
|
1300
1300
|
"name": "<impl Deserialize for ()>::deserialize",
|
|
1301
|
-
"start":
|
|
1301
|
+
"start": 15744
|
|
1302
1302
|
},
|
|
1303
1303
|
{
|
|
1304
1304
|
"name": "<impl Deserialize for ()>::stream_deserialize",
|
|
1305
|
-
"start":
|
|
1305
|
+
"start": 15991
|
|
1306
1306
|
},
|
|
1307
1307
|
{
|
|
1308
1308
|
"name": "<impl Serialize for BoundedVec<T, M>>::serialize",
|
|
1309
|
-
"start":
|
|
1309
|
+
"start": 16356
|
|
1310
1310
|
},
|
|
1311
1311
|
{
|
|
1312
1312
|
"name": "<impl Serialize for BoundedVec<T, M>>::stream_serialize",
|
|
1313
|
-
"start":
|
|
1313
|
+
"start": 16577
|
|
1314
1314
|
},
|
|
1315
1315
|
{
|
|
1316
1316
|
"name": "make_slice",
|
|
1317
|
-
"start":
|
|
1317
|
+
"start": 17137
|
|
1318
1318
|
},
|
|
1319
1319
|
{
|
|
1320
1320
|
"name": "impl_serialize_for_tuple",
|
|
1321
|
-
"start":
|
|
1321
|
+
"start": 17387
|
|
1322
1322
|
},
|
|
1323
1323
|
{
|
|
1324
1324
|
"name": "<impl Serialize for (T1,)>::serialize",
|
|
1325
|
-
"start":
|
|
1325
|
+
"start": 20698
|
|
1326
1326
|
},
|
|
1327
1327
|
{
|
|
1328
1328
|
"name": "<impl Serialize for (T1,)>::stream_serialize",
|
|
1329
|
-
"start":
|
|
1329
|
+
"start": 20949
|
|
1330
1330
|
},
|
|
1331
1331
|
{
|
|
1332
1332
|
"name": "<impl Deserialize for (T1,)>::deserialize",
|
|
1333
|
-
"start":
|
|
1333
|
+
"start": 21156
|
|
1334
1334
|
},
|
|
1335
1335
|
{
|
|
1336
1336
|
"name": "<impl Deserialize for (T1,)>::stream_deserialize",
|
|
1337
|
-
"start":
|
|
1338
|
-
},
|
|
1339
|
-
{
|
|
1340
|
-
"name": "bounded_vec_serialization",
|
|
1341
|
-
"start": 21246
|
|
1337
|
+
"start": 21417
|
|
1342
1338
|
}
|
|
1343
1339
|
],
|
|
1344
1340
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/fnd/noir-protocol-circuits/crates/serde/src/type_impls.nr",
|
|
1345
|
-
"source": "use crate::{reader::Reader, serialization::{Deserialize, Serialize}, writer::Writer};\nuse std::embedded_curve_ops::EmbeddedCurvePoint;\nuse std::embedded_curve_ops::EmbeddedCurveScalar;\n\nglobal BOOL_SERIALIZED_LEN: u32 = 1;\nglobal U8_SERIALIZED_LEN: u32 = 1;\nglobal U16_SERIALIZED_LEN: u32 = 1;\nglobal U32_SERIALIZED_LEN: u32 = 1;\nglobal U64_SERIALIZED_LEN: u32 = 1;\nglobal U128_SERIALIZED_LEN: u32 = 1;\nglobal FIELD_SERIALIZED_LEN: u32 = 1;\nglobal I8_SERIALIZED_LEN: u32 = 1;\nglobal I16_SERIALIZED_LEN: u32 = 1;\nglobal I32_SERIALIZED_LEN: u32 = 1;\nglobal I64_SERIALIZED_LEN: u32 = 1;\n\nimpl Serialize for bool {\n let N: u32 = BOOL_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for bool {\n let N: u32 = BOOL_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> bool {\n reader.read() != 0\n }\n}\n\nimpl Serialize for u8 {\n let N: u32 = U8_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u8 {\n let N: u32 = U8_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u8\n }\n}\n\nimpl Serialize for u16 {\n let N: u32 = U16_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u16 {\n let N: u32 = U16_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u16\n }\n}\n\nimpl Serialize for u32 {\n let N: u32 = U32_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u32 {\n let N: u32 = U32_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u32\n }\n}\n\nimpl Serialize for u64 {\n let N: u32 = U64_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u64 {\n let N: u32 = U64_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u64\n }\n}\n\nimpl Serialize for u128 {\n let N: u32 = U128_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u128 {\n let N: u32 = U128_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u128\n }\n}\n\nimpl Serialize for Field {\n let N: u32 = FIELD_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self);\n }\n}\n\nimpl Deserialize for Field {\n let N: u32 = FIELD_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read()\n }\n}\n\nimpl Serialize for i8 {\n let N: u32 = I8_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u8 as Field);\n }\n}\n\nimpl Deserialize for i8 {\n let N: u32 = I8_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u8 as i8\n }\n}\n\nimpl Serialize for i16 {\n let N: u32 = I16_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u16 as Field);\n }\n}\n\nimpl Deserialize for i16 {\n let N: u32 = I16_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u16 as i16\n }\n}\n\nimpl Serialize for i32 {\n let N: u32 = I32_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u32 as Field);\n }\n}\n\nimpl Deserialize for i32 {\n let N: u32 = I32_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u32 as i32\n }\n}\n\nimpl Serialize for i64 {\n let N: u32 = I64_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u64 as Field);\n }\n}\n\nimpl Deserialize for i64 {\n let N: u32 = I64_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u64 as i64\n }\n}\n\nimpl<T, let M: u32> Serialize for [T; M]\nwhere\n T: Serialize,\n{\n let N: u32 = <T as Serialize>::N * M;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n for i in 0..M {\n self[i].stream_serialize(writer);\n }\n }\n}\n\nimpl<T, let M: u32> Deserialize for [T; M]\nwhere\n T: Deserialize,\n{\n let N: u32 = <T as Deserialize>::N * M;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n let mut result: [T; M] = std::mem::zeroed();\n for i in 0..M {\n result[i] = T::stream_deserialize(reader);\n }\n result\n }\n}\n\nimpl<T> Serialize for Option<T>\nwhere\n T: Serialize,\n{\n let N: u32 = <T as Serialize>::N + 1;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write_bool(self.is_some());\n if self.is_some() {\n self.unwrap_unchecked().stream_serialize(writer);\n } else {\n writer.advance_offset(<T as Serialize>::N);\n }\n }\n}\n\nimpl<T> Deserialize for Option<T>\nwhere\n T: Deserialize,\n{\n let N: u32 = <T as Deserialize>::N + 1;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n if reader.read_bool() {\n Option::some(<T as Deserialize>::stream_deserialize(reader))\n } else {\n reader.advance_offset(<T as Deserialize>::N);\n Option::none()\n }\n }\n}\n\nglobal SCALAR_SIZE: u32 = 2;\n\nimpl Serialize for EmbeddedCurveScalar {\n\n let N: u32 = SCALAR_SIZE;\n\n fn serialize(self) -> [Field; SCALAR_SIZE] {\n [self.lo, self.hi]\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self.lo);\n writer.write(self.hi);\n }\n}\n\nimpl Deserialize for EmbeddedCurveScalar {\n let N: u32 = SCALAR_SIZE;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n Self { lo: fields[0], hi: fields[1] }\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n Self { lo: reader.read(), hi: reader.read() }\n }\n}\n\nglobal POINT_SIZE: u32 = 2;\n\nimpl Serialize for EmbeddedCurvePoint {\n let N: u32 = POINT_SIZE;\n\n fn serialize(self) -> [Field; Self::N] {\n [self.x, self.y]\n }\n\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self.x);\n writer.write(self.y);\n }\n}\n\nimpl Deserialize for EmbeddedCurvePoint {\n let N: u32 = POINT_SIZE;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n Self { x: fields[0], y: fields[1] }\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n Self { x: reader.read(), y: reader.read() }\n }\n}\n\nimpl<let M: u32> Deserialize for str<M> {\n let N: u32 = M;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n let u8_arr = <[u8; Self::N] as Deserialize>::stream_deserialize(reader);\n str::<Self::N>::from(u8_arr)\n }\n}\n\nimpl<let M: u32> Serialize for str<M> {\n let N: u32 = M;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n self.as_bytes().stream_serialize(writer);\n }\n}\n\n// Note: Not deriving this because it's not supported to call derive_serialize on a \"remote\" struct (and it will never\n// be supported).\nimpl<T, let M: u32> Deserialize for BoundedVec<T, M>\nwhere\n T: Deserialize,\n{\n let N: u32 = <T as Deserialize>::N * M + 1;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n let mut new_bounded_vec: BoundedVec<T, M> = BoundedVec::new();\n let payload_len = Self::N - 1;\n\n // Length is stored in the last field as we need to match intrinsic Noir serialization and the `len` struct\n // field is after `storage` struct field (see `bounded_vec.nr` in noir-stdlib)\n let len = reader.peek_offset(payload_len) as u32;\n\n for i in 0..M {\n if i < len {\n new_bounded_vec.push(<T as Deserialize>::stream_deserialize(reader));\n }\n }\n\n // +1 for the length of the BoundedVec\n reader.advance_offset((M - len) * <T as Deserialize>::N + 1);\n\n new_bounded_vec\n }\n}\n\n// This may cause issues if used as program input, because noir disallows empty arrays for program input.\n// I think this is okay because I don't foresee a unit type being used as input. But leaving this comment as a hint\n// if someone does run into this in the future.\nimpl Deserialize for () {\n let N: u32 = 0;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(_reader: &mut Reader<K>) -> Self {\n ()\n }\n}\n\n// Note: Not deriving this because it's not supported to call derive_serialize on a \"remote\" struct (and it will never\n// be supported).\nimpl<T, let M: u32> Serialize for BoundedVec<T, M>\nwhere\n T: Serialize,\n{\n let N: u32 = <T as Serialize>::N * M + 1; // +1 for the length of the BoundedVec\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n self.storage().stream_serialize(writer);\n // Length is stored in the last field as we need to match intrinsic Noir serialization and the `len` struct\n // field is after `storage` struct field (see `bounded_vec.nr` in noir-stdlib)\n writer.write_u32(self.len() as u32);\n }\n}\n\n// Create a slice of the given length with each element made from `f(i)` where `i` is the current index\ncomptime fn make_slice<Env, T>(length: u32, f: fn[Env](u32) -> T) -> [T] {\n let mut slice = @[];\n for i in 0..length {\n slice = slice.push_back(f(i));\n }\n slice\n}\n\n// Implements Serialize and Deserialize for an arbitrary tuple type\ncomptime fn impl_serialize_for_tuple(_m: Module, length: u32) -> Quoted {\n // `T0`, `T1`, `T2`\n let type_names = make_slice(length, |i| f\"T{i}\".quoted_contents());\n\n // `result0`, `result1`, `result2`\n let result_names = make_slice(length, |i| f\"result{i}\".quoted_contents());\n\n // `T0, T1, T2`\n let field_generics = type_names.join(quote [,]);\n\n // `<T0 as Serialize>::N + <T1 as Serialize>::N + <T2 as Serialize>::N`\n let full_size_serialize = type_names\n .map(|type_name| quote {\n <$type_name as Serialize>::N\n })\n .join(quote [+]);\n\n // `<T0 as Deserialize>::N + <T1 as Deserialize>::N + <T2 as Deserialize>::N`\n let full_size_deserialize = type_names\n .map(|type_name| quote {\n <$type_name as Deserialize>::N\n })\n .join(quote [+]);\n\n // `T0: Serialize, T1: Serialize, T2: Serialize,`\n let serialize_constraints = type_names\n .map(|field_name| quote {\n $field_name: Serialize,\n })\n .join(quote []);\n\n // `T0: Deserialize, T1: Deserialize, T2: Deserialize,`\n let deserialize_constraints = type_names\n .map(|field_name| quote {\n $field_name: Deserialize,\n })\n .join(quote []);\n\n // Statements to serialize each field\n let serialized_fields = type_names\n .mapi(|i, _type_name| quote {\n $crate::serialization::Serialize::stream_serialize(self.$i, writer);\n })\n .join(quote []);\n\n // Statements to deserialize each field\n let deserialized_fields = type_names\n .mapi(|i, type_name| {\n let result_name = result_names[i];\n quote {\n let $result_name = <$type_name as $crate::serialization::Deserialize>::stream_deserialize(reader);\n }\n })\n .join(quote []);\n let deserialize_results = result_names.join(quote [,]);\n\n quote {\n impl<$field_generics> Serialize for ($field_generics) where $serialize_constraints {\n let N: u32 = $full_size_serialize;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: $crate::writer::Writer<Self::N> = $crate::writer::Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut $crate::writer::Writer<K>) {\n\n $serialized_fields\n }\n }\n\n impl<$field_generics> Deserialize for ($field_generics) where $deserialize_constraints {\n let N: u32 = $full_size_deserialize;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = $crate::reader::Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n \n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut $crate::reader::Reader<K>) -> Self {\n $deserialized_fields\n ($deserialize_results)\n }\n }\n }\n}\n\n// Keeping these manual impls. They are more efficient since they do not\n// require copying sub-arrays from any serialized arrays.\nimpl<T1> Serialize for (T1,)\nwhere\n T1: Serialize,\n{\n let N: u32 = <T1 as Serialize>::N;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: crate::writer::Writer<Self::N> = crate::writer::Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n self.0.stream_serialize(writer);\n }\n}\n\nimpl<T1> Deserialize for (T1,)\nwhere\n T1: Deserialize,\n{\n let N: u32 = <T1 as Deserialize>::N;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = crate::reader::Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n (<T1 as Deserialize>::stream_deserialize(reader),)\n }\n}\n\n#[impl_serialize_for_tuple(2)]\n#[impl_serialize_for_tuple(3)]\n#[impl_serialize_for_tuple(4)]\n#[impl_serialize_for_tuple(5)]\n#[impl_serialize_for_tuple(6)]\nmod impls {\n use crate::serialization::{Deserialize, Serialize};\n}\n\n#[test]\nunconstrained fn bounded_vec_serialization() {\n // Test empty BoundedVec\n let empty_vec: BoundedVec<Field, 3> = BoundedVec::from_array([]);\n let serialized = empty_vec.serialize();\n let deserialized = BoundedVec::<Field, 3>::deserialize(serialized);\n assert_eq(empty_vec, deserialized);\n assert_eq(deserialized.len(), 0);\n\n // Test partially filled BoundedVec\n let partial_vec: BoundedVec<[u32; 2], 3> = BoundedVec::from_array([[1, 2]]);\n let serialized = partial_vec.serialize();\n let deserialized = BoundedVec::<[u32; 2], 3>::deserialize(serialized);\n assert_eq(partial_vec, deserialized);\n assert_eq(deserialized.len(), 1);\n assert_eq(deserialized.get(0), [1, 2]);\n\n // Test full BoundedVec\n let full_vec: BoundedVec<[u32; 2], 3> = BoundedVec::from_array([[1, 2], [3, 4], [5, 6]]);\n let serialized = full_vec.serialize();\n let deserialized = BoundedVec::<[u32; 2], 3>::deserialize(serialized);\n assert_eq(full_vec, deserialized);\n assert_eq(deserialized.len(), 3);\n assert_eq(deserialized.get(0), [1, 2]);\n assert_eq(deserialized.get(1), [3, 4]);\n assert_eq(deserialized.get(2), [5, 6]);\n}\n"
|
|
1341
|
+
"source": "use crate::{reader::Reader, serialization::{Deserialize, Serialize}, writer::Writer};\nuse std::embedded_curve_ops::EmbeddedCurvePoint;\nuse std::embedded_curve_ops::EmbeddedCurveScalar;\n\nglobal BOOL_SERIALIZED_LEN: u32 = 1;\nglobal U8_SERIALIZED_LEN: u32 = 1;\nglobal U16_SERIALIZED_LEN: u32 = 1;\nglobal U32_SERIALIZED_LEN: u32 = 1;\nglobal U64_SERIALIZED_LEN: u32 = 1;\nglobal U128_SERIALIZED_LEN: u32 = 1;\nglobal FIELD_SERIALIZED_LEN: u32 = 1;\nglobal I8_SERIALIZED_LEN: u32 = 1;\nglobal I16_SERIALIZED_LEN: u32 = 1;\nglobal I32_SERIALIZED_LEN: u32 = 1;\nglobal I64_SERIALIZED_LEN: u32 = 1;\n\nimpl Serialize for bool {\n let N: u32 = BOOL_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for bool {\n let N: u32 = BOOL_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> bool {\n reader.read() != 0\n }\n}\n\nimpl Serialize for u8 {\n let N: u32 = U8_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u8 {\n let N: u32 = U8_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u8\n }\n}\n\nimpl Serialize for u16 {\n let N: u32 = U16_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u16 {\n let N: u32 = U16_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u16\n }\n}\n\nimpl Serialize for u32 {\n let N: u32 = U32_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u32 {\n let N: u32 = U32_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u32\n }\n}\n\nimpl Serialize for u64 {\n let N: u32 = U64_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u64 {\n let N: u32 = U64_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u64\n }\n}\n\nimpl Serialize for u128 {\n let N: u32 = U128_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as Field);\n }\n}\n\nimpl Deserialize for u128 {\n let N: u32 = U128_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u128\n }\n}\n\nimpl Serialize for Field {\n let N: u32 = FIELD_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self);\n }\n}\n\nimpl Deserialize for Field {\n let N: u32 = FIELD_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read()\n }\n}\n\nimpl Serialize for i8 {\n let N: u32 = I8_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u8 as Field);\n }\n}\n\nimpl Deserialize for i8 {\n let N: u32 = I8_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u8 as i8\n }\n}\n\nimpl Serialize for i16 {\n let N: u32 = I16_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u16 as Field);\n }\n}\n\nimpl Deserialize for i16 {\n let N: u32 = I16_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u16 as i16\n }\n}\n\nimpl Serialize for i32 {\n let N: u32 = I32_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u32 as Field);\n }\n}\n\nimpl Deserialize for i32 {\n let N: u32 = I32_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u32 as i32\n }\n}\n\nimpl Serialize for i64 {\n let N: u32 = I64_SERIALIZED_LEN;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self as u64 as Field);\n }\n}\n\nimpl Deserialize for i64 {\n let N: u32 = I64_SERIALIZED_LEN;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n reader.read() as u64 as i64\n }\n}\n\nimpl<T, let M: u32> Serialize for [T; M]\nwhere\n T: Serialize,\n{\n let N: u32 = <T as Serialize>::N * M;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n for i in 0..M {\n self[i].stream_serialize(writer);\n }\n }\n}\n\nimpl<T, let M: u32> Deserialize for [T; M]\nwhere\n T: Deserialize,\n{\n let N: u32 = <T as Deserialize>::N * M;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n let mut result: [T; M] = std::mem::zeroed();\n for i in 0..M {\n result[i] = T::stream_deserialize(reader);\n }\n result\n }\n}\n\nimpl<T> Serialize for Option<T>\nwhere\n T: Serialize,\n{\n let N: u32 = <T as Serialize>::N + 1;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n let is_some = self.is_some();\n writer.write_bool(is_some);\n // A `None` must have an all-zero payload, so every `Option` value has exactly one encoding. Private function\n // arguments are bound to the caller only through a hash of this encoding.\n let payload = self.unwrap_unchecked().serialize();\n if !is_some {\n assert_eq(payload, [0; <T as Serialize>::N], \"Option None payload must be zero\");\n }\n writer.write_array(payload);\n }\n}\n\nimpl<T> Deserialize for Option<T>\nwhere\n T: Deserialize,\n{\n let N: u32 = <T as Deserialize>::N + 1;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n if reader.read_bool() {\n Option::some(<T as Deserialize>::stream_deserialize(reader))\n } else {\n reader.advance_offset(<T as Deserialize>::N);\n Option::none()\n }\n }\n}\n\nglobal SCALAR_SIZE: u32 = 2;\n\nimpl Serialize for EmbeddedCurveScalar {\n\n let N: u32 = SCALAR_SIZE;\n\n fn serialize(self) -> [Field; SCALAR_SIZE] {\n [self.lo, self.hi]\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self.lo);\n writer.write(self.hi);\n }\n}\n\nimpl Deserialize for EmbeddedCurveScalar {\n let N: u32 = SCALAR_SIZE;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n Self { lo: fields[0], hi: fields[1] }\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n Self { lo: reader.read(), hi: reader.read() }\n }\n}\n\nglobal POINT_SIZE: u32 = 2;\n\nimpl Serialize for EmbeddedCurvePoint {\n let N: u32 = POINT_SIZE;\n\n fn serialize(self) -> [Field; Self::N] {\n [self.x, self.y]\n }\n\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n writer.write(self.x);\n writer.write(self.y);\n }\n}\n\nimpl Deserialize for EmbeddedCurvePoint {\n let N: u32 = POINT_SIZE;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n Self { x: fields[0], y: fields[1] }\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n Self { x: reader.read(), y: reader.read() }\n }\n}\n\nimpl<let M: u32> Deserialize for str<M> {\n let N: u32 = M;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n let u8_arr = <[u8; Self::N] as Deserialize>::stream_deserialize(reader);\n str::<Self::N>::from(u8_arr)\n }\n}\n\nimpl<let M: u32> Serialize for str<M> {\n let N: u32 = M;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n self.as_bytes().stream_serialize(writer);\n }\n}\n\n// Note: Not deriving this because it's not supported to call derive_serialize on a \"remote\" struct (and it will never\n// be supported).\nimpl<T, let M: u32> Deserialize for BoundedVec<T, M>\nwhere\n T: Deserialize,\n{\n let N: u32 = <T as Deserialize>::N * M + 1;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n let mut new_bounded_vec: BoundedVec<T, M> = BoundedVec::new();\n let payload_len = Self::N - 1;\n\n // Length is stored in the last field as we need to match intrinsic Noir serialization and the `len` struct\n // field is after `storage` struct field (see `bounded_vec.nr` in noir-stdlib)\n let raw_len = reader.peek_offset(payload_len);\n let len = raw_len as u32;\n assert_eq(raw_len, len as Field, \"BoundedVec length is not u32\");\n assert(len <= M, \"BoundedVec length exceeds max\");\n\n for i in 0..M {\n if i < len {\n new_bounded_vec.push(<T as Deserialize>::stream_deserialize(reader));\n }\n }\n\n // +1 for the length of the BoundedVec\n reader.advance_offset((M - len) * <T as Deserialize>::N + 1);\n\n new_bounded_vec\n }\n}\n\n// This may cause issues if used as program input, because noir disallows empty arrays for program input.\n// I think this is okay because I don't foresee a unit type being used as input. But leaving this comment as a hint\n// if someone does run into this in the future.\nimpl Deserialize for () {\n let N: u32 = 0;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(_reader: &mut Reader<K>) -> Self {\n ()\n }\n}\n\n// Note: Not deriving this because it's not supported to call derive_serialize on a \"remote\" struct (and it will never\n// be supported).\nimpl<T, let M: u32> Serialize for BoundedVec<T, M>\nwhere\n T: Serialize,\n{\n let N: u32 = <T as Serialize>::N * M + 1; // +1 for the length of the BoundedVec\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: Writer<Self::N> = Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n let len = self.len();\n assert(len <= M, \"BoundedVec length exceeds max\");\n self.storage().stream_serialize(writer);\n // Length is stored in the last field as we need to match intrinsic Noir serialization and the `len` struct\n // field is after `storage` struct field (see `bounded_vec.nr` in noir-stdlib)\n writer.write_u32(len);\n }\n}\n\n// Create a slice of the given length with each element made from `f(i)` where `i` is the current index\ncomptime fn make_slice<Env, T>(length: u32, f: fn[Env](u32) -> T) -> [T] {\n let mut slice = @[];\n for i in 0..length {\n slice = slice.push_back(f(i));\n }\n slice\n}\n\n// Implements Serialize and Deserialize for an arbitrary tuple type\ncomptime fn impl_serialize_for_tuple(_m: Module, length: u32) -> Quoted {\n // `T0`, `T1`, `T2`\n let type_names = make_slice(length, |i| f\"T{i}\".quoted_contents());\n\n // `result0`, `result1`, `result2`\n let result_names = make_slice(length, |i| f\"result{i}\".quoted_contents());\n\n // `T0, T1, T2`\n let field_generics = type_names.join(quote [,]);\n\n // `<T0 as Serialize>::N + <T1 as Serialize>::N + <T2 as Serialize>::N`\n let full_size_serialize = type_names\n .map(|type_name| quote {\n <$type_name as Serialize>::N\n })\n .join(quote [+]);\n\n // `<T0 as Deserialize>::N + <T1 as Deserialize>::N + <T2 as Deserialize>::N`\n let full_size_deserialize = type_names\n .map(|type_name| quote {\n <$type_name as Deserialize>::N\n })\n .join(quote [+]);\n\n // `T0: Serialize, T1: Serialize, T2: Serialize,`\n let serialize_constraints = type_names\n .map(|field_name| quote {\n $field_name: Serialize,\n })\n .join(quote []);\n\n // `T0: Deserialize, T1: Deserialize, T2: Deserialize,`\n let deserialize_constraints = type_names\n .map(|field_name| quote {\n $field_name: Deserialize,\n })\n .join(quote []);\n\n // Statements to serialize each field\n let serialized_fields = type_names\n .mapi(|i, _type_name| quote {\n $crate::serialization::Serialize::stream_serialize(self.$i, writer);\n })\n .join(quote []);\n\n // Statements to deserialize each field\n let deserialized_fields = type_names\n .mapi(|i, type_name| {\n let result_name = result_names[i];\n quote {\n let $result_name = <$type_name as $crate::serialization::Deserialize>::stream_deserialize(reader);\n }\n })\n .join(quote []);\n let deserialize_results = result_names.join(quote [,]);\n\n quote {\n impl<$field_generics> Serialize for ($field_generics) where $serialize_constraints {\n let N: u32 = $full_size_serialize;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: $crate::writer::Writer<Self::N> = $crate::writer::Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut $crate::writer::Writer<K>) {\n\n $serialized_fields\n }\n }\n\n impl<$field_generics> Deserialize for ($field_generics) where $deserialize_constraints {\n let N: u32 = $full_size_deserialize;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = $crate::reader::Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n \n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut $crate::reader::Reader<K>) -> Self {\n $deserialized_fields\n ($deserialize_results)\n }\n }\n }\n}\n\n// Keeping these manual impls. They are more efficient since they do not\n// require copying sub-arrays from any serialized arrays.\nimpl<T1> Serialize for (T1,)\nwhere\n T1: Serialize,\n{\n let N: u32 = <T1 as Serialize>::N;\n\n fn serialize(self) -> [Field; Self::N] {\n let mut writer: crate::writer::Writer<Self::N> = crate::writer::Writer::new();\n self.stream_serialize(&mut writer);\n writer.finish()\n }\n\n #[inline_always]\n fn stream_serialize<let K: u32>(self, writer: &mut Writer<K>) {\n self.0.stream_serialize(writer);\n }\n}\n\nimpl<T1> Deserialize for (T1,)\nwhere\n T1: Deserialize,\n{\n let N: u32 = <T1 as Deserialize>::N;\n\n fn deserialize(fields: [Field; Self::N]) -> Self {\n let mut reader = crate::reader::Reader::new(fields);\n let result = Self::stream_deserialize(&mut reader);\n reader.finish();\n result\n }\n\n #[inline_always]\n fn stream_deserialize<let K: u32>(reader: &mut Reader<K>) -> Self {\n (<T1 as Deserialize>::stream_deserialize(reader),)\n }\n}\n\n#[impl_serialize_for_tuple(2)]\n#[impl_serialize_for_tuple(3)]\n#[impl_serialize_for_tuple(4)]\n#[impl_serialize_for_tuple(5)]\n#[impl_serialize_for_tuple(6)]\nmod impls {\n use crate::serialization::{Deserialize, Serialize};\n}\n"
|
|
1346
1342
|
},
|
|
1347
1343
|
"247": {
|
|
1348
1344
|
"function_locations": [
|
|
@@ -2594,15 +2590,15 @@
|
|
|
2594
2590
|
},
|
|
2595
2591
|
{
|
|
2596
2592
|
"name": "PrivateContext::call_public_function_with_calldata_hash",
|
|
2597
|
-
"start":
|
|
2593
|
+
"start": 10500
|
|
2598
2594
|
},
|
|
2599
2595
|
{
|
|
2600
2596
|
"name": "PrivateContext::next_counter",
|
|
2601
|
-
"start":
|
|
2597
|
+
"start": 11069
|
|
2602
2598
|
}
|
|
2603
2599
|
],
|
|
2604
2600
|
"path": "/home/aztec-dev/aztec-packages/noir-projects/fnd/noir-contracts/contracts/protocol/aztec_sublib/src/context/private_context.nr",
|
|
2605
|
-
"source": "use crate::{\n context::{inputs::PrivateContextInputs, NullifierExistenceRequest},\n messaging::process_l1_to_l2_message,\n oracle::{\n logs::notify_created_contract_class_log, nullifiers::notify_created_nullifier,\n public_call::validate_public_calldata, tx_phase::notify_revertible_phase_start,\n },\n};\nuse crate::protocol::{\n abis::{\n block_header::BlockHeader,\n log_hash::LogHash,\n nullifier::Nullifier,\n private_call_request::PrivateCallRequest,\n private_circuit_public_inputs::PrivateCircuitPublicInputs,\n private_log::{PrivateLog, PrivateLogData},\n public_call_request::PublicCallRequest,\n },\n address::{AztecAddress, EthAddress},\n constants::{\n CONTRACT_CLASS_LOG_SIZE_IN_FIELDS, MAX_CONTRACT_CLASS_LOGS_PER_CALL, MAX_ENQUEUED_CALLS_PER_CALL,\n MAX_L2_TO_L1_MSGS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PRIVATE_LOGS_PER_CALL, MAX_TX_LIFETIME,\n NULL_MSG_SENDER_CONTRACT_ADDRESS, PRIVATE_LOG_SIZE_IN_FIELDS,\n },\n hash::poseidon2_hash,\n messaging::l2_to_l1_message::L2ToL1Message,\n side_effect::{Counted, scoped::Scoped},\n traits::Empty,\n utils::arrays::{ClaimedLengthArray, trimmed_array_length_hint},\n};\n\n/// Minimal PrivateContext for protocol contracts going to audit.\n/// Contains only the methods actually used by: fee_juice, auth_registry, contract_class_registry,\n/// contract_instance_registry\npub struct PrivateContext {\n pub inputs: PrivateContextInputs,\n pub side_effect_counter: u32,\n\n pub min_revertible_side_effect_counter: u32,\n pub is_fee_payer: bool,\n\n pub args_hash: Field,\n pub return_hash: Field,\n\n pub expiration_timestamp: u64,\n\n pub nullifier_read_requests: BoundedVec<Scoped<Counted<Field>>, MAX_NULLIFIER_READ_REQUESTS_PER_CALL>,\n\n pub nullifiers: BoundedVec<Counted<Nullifier>, MAX_NULLIFIERS_PER_CALL>,\n\n pub private_call_requests: BoundedVec<PrivateCallRequest, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL>,\n pub public_call_requests: BoundedVec<Counted<PublicCallRequest>, MAX_ENQUEUED_CALLS_PER_CALL>,\n pub public_teardown_call_request: PublicCallRequest,\n pub l2_to_l1_msgs: BoundedVec<Counted<L2ToL1Message>, MAX_L2_TO_L1_MSGS_PER_CALL>,\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n pub anchor_block_header: BlockHeader,\n\n pub private_logs: BoundedVec<Counted<PrivateLogData>, MAX_PRIVATE_LOGS_PER_CALL>,\n pub contract_class_logs_hashes: BoundedVec<Counted<LogHash>, MAX_CONTRACT_CLASS_LOGS_PER_CALL>,\n\n pub expected_non_revertible_side_effect_counter: u32,\n pub expected_revertible_side_effect_counter: u32,\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n PrivateContext {\n inputs,\n side_effect_counter: inputs.start_side_effect_counter + 1,\n min_revertible_side_effect_counter: 0,\n is_fee_payer: false,\n args_hash,\n return_hash: 0,\n expiration_timestamp: inputs.anchor_block_header.global_variables.timestamp + MAX_TX_LIFETIME,\n nullifier_read_requests: BoundedVec::new(),\n nullifiers: BoundedVec::new(),\n anchor_block_header: inputs.anchor_block_header,\n private_call_requests: BoundedVec::new(),\n public_call_requests: BoundedVec::new(),\n public_teardown_call_request: PublicCallRequest::empty(),\n l2_to_l1_msgs: BoundedVec::new(),\n private_logs: BoundedVec::new(),\n contract_class_logs_hashes: BoundedVec::new(),\n expected_non_revertible_side_effect_counter: 0,\n expected_revertible_side_effect_counter: 0,\n }\n }\n\n /// Returns the contract address that initiated this function call (similar to msg.sender in Solidity).\n pub fn maybe_msg_sender(self) -> Option<AztecAddress> {\n let maybe_msg_sender = self.inputs.call_context.msg_sender;\n if maybe_msg_sender == NULL_MSG_SENDER_CONTRACT_ADDRESS {\n Option::none()\n } else {\n Option::some(maybe_msg_sender)\n }\n }\n\n /// Returns the contract address of the current function being executed.\n pub fn this_address(self) -> AztecAddress {\n self.inputs.call_context.contract_address\n }\n\n /// Returns the chain ID of the current network.\n pub fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n /// Returns the protocol version.\n pub fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n /// Builds the PrivateCircuitPublicInputs for this private function.\n pub fn finish(self) -> PrivateCircuitPublicInputs {\n PrivateCircuitPublicInputs {\n call_context: self.inputs.call_context,\n args_hash: self.args_hash,\n returns_hash: self.return_hash,\n min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,\n is_fee_payer: self.is_fee_payer,\n expiration_timestamp: self.expiration_timestamp,\n note_hash_read_requests: ClaimedLengthArray::empty(), // Not used by protocol contracts\n nullifier_read_requests: ClaimedLengthArray::from_bounded_vec(self.nullifier_read_requests),\n key_validation_requests_and_separators: ClaimedLengthArray::empty(), // Not used by protocol contracts\n note_hashes: ClaimedLengthArray::empty(), // Not used by protocol contracts\n nullifiers: ClaimedLengthArray::from_bounded_vec(self.nullifiers),\n private_call_requests: ClaimedLengthArray::from_bounded_vec(self.private_call_requests),\n public_call_requests: ClaimedLengthArray::from_bounded_vec(self.public_call_requests),\n public_teardown_call_request: self.public_teardown_call_request,\n l2_to_l1_msgs: ClaimedLengthArray::from_bounded_vec(self.l2_to_l1_msgs),\n start_side_effect_counter: self.inputs.start_side_effect_counter,\n end_side_effect_counter: self.side_effect_counter,\n private_logs: ClaimedLengthArray::from_bounded_vec(self.private_logs),\n contract_class_logs_hashes: ClaimedLengthArray::from_bounded_vec(self.contract_class_logs_hashes),\n anchor_block_header: self.anchor_block_header,\n tx_context: self.inputs.tx_context,\n expected_non_revertible_side_effect_counter: self.expected_non_revertible_side_effect_counter,\n expected_revertible_side_effect_counter: self.expected_revertible_side_effect_counter,\n protocol_nullifier: self.inputs.protocol_nullifier,\n }\n }\n\n /// Declares the end of the \"setup phase\" of this tx. Used by fee_juice.\n pub fn end_setup(&mut self) {\n self.side_effect_counter += 1;\n self.min_revertible_side_effect_counter = self.next_counter();\n notify_revertible_phase_start(self.min_revertible_side_effect_counter);\n }\n\n /// Pushes a new nullifier. Used by class_registry and instance_registry.\n pub fn push_nullifier(&mut self, nullifier: Field) {\n notify_created_nullifier(nullifier);\n self.nullifiers.push(Nullifier { value: nullifier, note_hash: 0 }.count(self.next_counter()));\n }\n\n /// Asserts that a nullifier has been emitted. Used by instance_registry.\n pub fn assert_nullifier_exists(&mut self, nullifier_existence_request: NullifierExistenceRequest) {\n let nullifier = nullifier_existence_request.nullifier();\n let contract_address = nullifier_existence_request.maybe_contract_address().unwrap_or(AztecAddress::zero());\n\n let request = Scoped::new(\n Counted::new(nullifier, self.next_counter()),\n contract_address,\n );\n\n self.nullifier_read_requests.push(request);\n }\n\n /// Consumes a message sent from Ethereum (L1) to Aztec (L2). Used by fee_juice.\n pub fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress, leaf_index: Field) {\n let nullifier = process_l1_to_l2_message(\n self.anchor_block_header.state.l1_to_l2_message_tree.root,\n self.this_address(),\n sender,\n self.chain_id(),\n self.version(),\n content,\n secret,\n leaf_index,\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_nullifier(nullifier)\n }\n\n /// Emits a private log. Used by instance_registry.\n pub fn emit_private_log(&mut self, log: [Field; PRIVATE_LOG_SIZE_IN_FIELDS], length: u32) {\n let counter = self.next_counter();\n let private_log = PrivateLogData { log: PrivateLog::new(log, length), note_hash_counter: 0 }.count(counter);\n self.private_logs.push(private_log);\n }\n\n /// Emits a contract class log. Used by class_registry.\n pub fn emit_contract_class_log<let N: u32>(&mut self, log: [Field; N]) {\n let contract_address = self.this_address();\n let counter = self.next_counter();\n\n let log_to_emit: [Field; CONTRACT_CLASS_LOG_SIZE_IN_FIELDS] =\n log.concat([0; CONTRACT_CLASS_LOG_SIZE_IN_FIELDS - N]);\n // Safety: The below length is constrained in the base rollup, which will make sure that all the fields beyond\n // length are zero. However, it won't be able to check that we didn't add extra padding (trailing zeroes) or\n // that we cut trailing zeroes from the end.\n let length = unsafe { trimmed_array_length_hint(log_to_emit) };\n // We hash the entire padded log to ensure a user cannot pass a shorter length and so emit incorrect shorter\n // bytecode.\n let log_hash = poseidon2_hash(log_to_emit);\n // Safety: the below only exists to broadcast the raw log, so we can provide it to the base rollup later to be\n // constrained.\n unsafe {\n notify_created_contract_class_log(contract_address, log_to_emit, length, counter);\n }\n\n self.contract_class_logs_hashes.push(LogHash { value: log_hash, length: length }.count(counter));\n }\n\n /// Enqueues a call to a public function with a calldata hash. Used by fee_juice and auth_registry.\n pub fn call_public_function_with_calldata_hash(\n &mut self,\n contract_address: AztecAddress,\n calldata_hash: Field,\n is_static_call: bool,\n hide_msg_sender: bool,\n ) {\n let counter = self.next_counter();\n\n let is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n\n validate_public_calldata(calldata_hash);\n\n let msg_sender = if hide_msg_sender {\n NULL_MSG_SENDER_CONTRACT_ADDRESS\n } else {\n self.this_address()\n };\n\n let call_request = PublicCallRequest { msg_sender, contract_address, is_static_call, calldata_hash };\n\n self.public_call_requests.push(Counted::new(call_request, counter));\n }\n\n fn next_counter(&mut self) -> u32 {\n let counter = self.side_effect_counter;\n self.side_effect_counter += 1;\n counter\n }\n}\n"
|
|
2601
|
+
"source": "use crate::{\n context::{inputs::PrivateContextInputs, NullifierExistenceRequest},\n messaging::process_l1_to_l2_message,\n oracle::{\n logs::notify_created_contract_class_log, nullifiers::notify_created_nullifier,\n public_call::validate_public_calldata, tx_phase::notify_revertible_phase_start,\n },\n};\nuse crate::protocol::{\n abis::{\n block_header::BlockHeader,\n log_hash::LogHash,\n nullifier::Nullifier,\n private_call_request::PrivateCallRequest,\n private_circuit_public_inputs::PrivateCircuitPublicInputs,\n private_log::{PrivateLog, PrivateLogData},\n public_call_request::PublicCallRequest,\n },\n address::{AztecAddress, EthAddress},\n constants::{\n CONTRACT_CLASS_LOG_SIZE_IN_FIELDS, MAX_CONTRACT_CLASS_LOGS_PER_CALL, MAX_ENQUEUED_CALLS_PER_CALL,\n MAX_L2_TO_L1_MSGS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PRIVATE_LOGS_PER_CALL, MAX_TX_LIFETIME,\n NULL_MSG_SENDER_CONTRACT_ADDRESS, PRIVATE_LOG_SIZE_IN_FIELDS,\n },\n hash::poseidon2_hash,\n messaging::l2_to_l1_message::L2ToL1Message,\n side_effect::{Counted, scoped::Scoped},\n traits::Empty,\n utils::arrays::{ClaimedLengthArray, trimmed_array_length_hint},\n};\n\n/// Minimal PrivateContext for protocol contracts going to audit.\n/// Contains only the methods actually used by: fee_juice, auth_registry, contract_class_registry,\n/// contract_instance_registry\npub struct PrivateContext {\n pub inputs: PrivateContextInputs,\n pub side_effect_counter: u32,\n\n pub min_revertible_side_effect_counter: u32,\n pub is_fee_payer: bool,\n\n pub args_hash: Field,\n pub return_hash: Field,\n\n pub expiration_timestamp: u64,\n\n pub nullifier_read_requests: BoundedVec<Scoped<Counted<Field>>, MAX_NULLIFIER_READ_REQUESTS_PER_CALL>,\n\n pub nullifiers: BoundedVec<Counted<Nullifier>, MAX_NULLIFIERS_PER_CALL>,\n\n pub private_call_requests: BoundedVec<PrivateCallRequest, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL>,\n pub public_call_requests: BoundedVec<Counted<PublicCallRequest>, MAX_ENQUEUED_CALLS_PER_CALL>,\n pub public_teardown_call_request: PublicCallRequest,\n pub l2_to_l1_msgs: BoundedVec<Counted<L2ToL1Message>, MAX_L2_TO_L1_MSGS_PER_CALL>,\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n pub anchor_block_header: BlockHeader,\n\n pub private_logs: BoundedVec<Counted<PrivateLogData>, MAX_PRIVATE_LOGS_PER_CALL>,\n pub contract_class_logs_hashes: BoundedVec<Counted<LogHash>, MAX_CONTRACT_CLASS_LOGS_PER_CALL>,\n\n pub expected_non_revertible_side_effect_counter: u32,\n pub expected_revertible_side_effect_counter: u32,\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n PrivateContext {\n inputs,\n side_effect_counter: inputs.start_side_effect_counter + 1,\n min_revertible_side_effect_counter: 0,\n is_fee_payer: false,\n args_hash,\n return_hash: 0,\n expiration_timestamp: inputs.anchor_block_header.global_variables.timestamp + MAX_TX_LIFETIME,\n nullifier_read_requests: BoundedVec::new(),\n nullifiers: BoundedVec::new(),\n anchor_block_header: inputs.anchor_block_header,\n private_call_requests: BoundedVec::new(),\n public_call_requests: BoundedVec::new(),\n public_teardown_call_request: PublicCallRequest::empty(),\n l2_to_l1_msgs: BoundedVec::new(),\n private_logs: BoundedVec::new(),\n contract_class_logs_hashes: BoundedVec::new(),\n expected_non_revertible_side_effect_counter: 0,\n expected_revertible_side_effect_counter: 0,\n }\n }\n\n /// Returns the contract address that initiated this function call (similar to msg.sender in Solidity).\n pub fn maybe_msg_sender(self) -> Option<AztecAddress> {\n let maybe_msg_sender = self.inputs.call_context.msg_sender;\n if maybe_msg_sender == NULL_MSG_SENDER_CONTRACT_ADDRESS {\n Option::none()\n } else {\n Option::some(maybe_msg_sender)\n }\n }\n\n /// Returns the contract address of the current function being executed.\n pub fn this_address(self) -> AztecAddress {\n self.inputs.call_context.contract_address\n }\n\n /// Returns the chain ID of the current network.\n pub fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n /// Returns the protocol version.\n pub fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n /// Builds the PrivateCircuitPublicInputs for this private function.\n pub fn finish(self) -> PrivateCircuitPublicInputs {\n PrivateCircuitPublicInputs {\n call_context: self.inputs.call_context,\n args_hash: self.args_hash,\n returns_hash: self.return_hash,\n min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,\n is_fee_payer: self.is_fee_payer,\n expiration_timestamp: self.expiration_timestamp,\n note_hash_read_requests: ClaimedLengthArray::empty(), // Not used by protocol contracts\n nullifier_read_requests: ClaimedLengthArray::from_bounded_vec(self.nullifier_read_requests),\n key_validation_requests_and_separators: ClaimedLengthArray::empty(), // Not used by protocol contracts\n note_hashes: ClaimedLengthArray::empty(), // Not used by protocol contracts\n nullifiers: ClaimedLengthArray::from_bounded_vec(self.nullifiers),\n private_call_requests: ClaimedLengthArray::from_bounded_vec(self.private_call_requests),\n public_call_requests: ClaimedLengthArray::from_bounded_vec(self.public_call_requests),\n public_teardown_call_request: self.public_teardown_call_request,\n l2_to_l1_msgs: ClaimedLengthArray::from_bounded_vec(self.l2_to_l1_msgs),\n start_side_effect_counter: self.inputs.start_side_effect_counter,\n end_side_effect_counter: self.side_effect_counter,\n private_logs: ClaimedLengthArray::from_bounded_vec(self.private_logs),\n contract_class_logs_hashes: ClaimedLengthArray::from_bounded_vec(self.contract_class_logs_hashes),\n anchor_block_header: self.anchor_block_header,\n tx_context: self.inputs.tx_context,\n expected_non_revertible_side_effect_counter: self.expected_non_revertible_side_effect_counter,\n expected_revertible_side_effect_counter: self.expected_revertible_side_effect_counter,\n protocol_nullifier: self.inputs.protocol_nullifier,\n }\n }\n\n /// Declares the end of the \"setup phase\" of this tx. Used by fee_juice.\n pub fn end_setup(&mut self) {\n self.side_effect_counter += 1;\n self.min_revertible_side_effect_counter = self.next_counter();\n notify_revertible_phase_start(self.min_revertible_side_effect_counter);\n }\n\n /// Pushes a new nullifier. Used by class_registry and instance_registry.\n pub fn push_nullifier(&mut self, nullifier: Field) {\n notify_created_nullifier(nullifier);\n self.nullifiers.push(Nullifier { value: nullifier, note_hash: 0 }.count(self.next_counter()));\n }\n\n /// Asserts that a nullifier has been emitted. Used by instance_registry.\n pub fn assert_nullifier_exists(&mut self, nullifier_existence_request: NullifierExistenceRequest) {\n let nullifier = nullifier_existence_request.nullifier();\n let contract_address = nullifier_existence_request.maybe_contract_address().unwrap_or(AztecAddress::zero());\n\n let request = Scoped::new(\n Counted::new(nullifier, self.next_counter()),\n contract_address,\n );\n\n self.nullifier_read_requests.push(request);\n }\n\n /// Consumes a message sent from Ethereum (L1) to Aztec (L2). Used by fee_juice.\n pub fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress, leaf_index: Field) {\n let nullifier = process_l1_to_l2_message(\n self.anchor_block_header.state.l1_to_l2_message_tree.root,\n self.this_address(),\n sender,\n self.chain_id(),\n self.version(),\n content,\n secret,\n leaf_index,\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_nullifier(nullifier)\n }\n\n /// Emits a private log. Used by instance_registry.\n pub fn emit_private_log(&mut self, log: [Field; PRIVATE_LOG_SIZE_IN_FIELDS], length: u32) {\n let counter = self.next_counter();\n let private_log = PrivateLogData { log: PrivateLog::new(log, length), note_hash_counter: 0 }.count(counter);\n self.private_logs.push(private_log);\n }\n\n /// Emits a contract class log. Used by class_registry.\n pub fn emit_contract_class_log<let N: u32>(&mut self, log: [Field; N]) {\n let contract_address = self.this_address();\n let counter = self.next_counter();\n\n let log_to_emit: [Field; CONTRACT_CLASS_LOG_SIZE_IN_FIELDS] =\n log.concat([0; CONTRACT_CLASS_LOG_SIZE_IN_FIELDS - N]);\n // Safety: The below length is constrained in the base rollup, which checks that all the fields beyond length\n // are zero and that the field at length - 1 is not, i.e. that the length is exactly the trimmed length.\n let length = unsafe { trimmed_array_length_hint(log_to_emit) };\n // We hash the entire padded log to ensure a user cannot pass a shorter length and so emit incorrect shorter\n // bytecode.\n let log_hash = poseidon2_hash(log_to_emit);\n // Safety: the below only exists to broadcast the raw log, so we can provide it to the base rollup later to be\n // constrained.\n unsafe {\n notify_created_contract_class_log(contract_address, log_to_emit, length, counter);\n }\n\n self.contract_class_logs_hashes.push(LogHash { value: log_hash, length: length }.count(counter));\n }\n\n /// Enqueues a call to a public function with a calldata hash. Used by fee_juice and auth_registry.\n pub fn call_public_function_with_calldata_hash(\n &mut self,\n contract_address: AztecAddress,\n calldata_hash: Field,\n is_static_call: bool,\n hide_msg_sender: bool,\n ) {\n let counter = self.next_counter();\n\n let is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n\n validate_public_calldata(calldata_hash);\n\n let msg_sender = if hide_msg_sender {\n NULL_MSG_SENDER_CONTRACT_ADDRESS\n } else {\n self.this_address()\n };\n\n let call_request = PublicCallRequest { msg_sender, contract_address, is_static_call, calldata_hash };\n\n self.public_call_requests.push(Counted::new(call_request, counter));\n }\n\n fn next_counter(&mut self) -> u32 {\n let counter = self.side_effect_counter;\n self.side_effect_counter += 1;\n counter\n }\n}\n"
|
|
2606
2602
|
},
|
|
2607
2603
|
"59": {
|
|
2608
2604
|
"function_locations": [
|
|
@@ -2993,7 +2989,7 @@
|
|
|
2993
2989
|
"abi_public",
|
|
2994
2990
|
"abi_only_self"
|
|
2995
2991
|
],
|
|
2996
|
-
"debug_symbols": "rVjbauMwEP0XP+dBc9Etv7IsJW3dEjBJcJOFpeTfd9RoZLsgYep9iY5H0fHR6Ehj+7N77Z9v70/H09v5o9v/+uyex+MwHN+fhvPL4Xo8nyT62Zn0A4DdnnbS+m5vpUXMrXvECXIr115ahtzma8u5jY/WUbcHk0AQAAI8ZRBAgYyFICDCA6AxGaBG0GZA2kUaYY1wicQMLCkIGThU4DPwegufZWAQQjQJsIKYQdRIzBEyrEAjIDJQ5kVoFJRI+o+kj4gVpAgLYM7AogJRSIkwaSYU4IWQUpe3GQSNhBRxAqJRkCNsSIEkgeWmnBb5AXwGKc9sE7AZpDw/gAjjmIBItXi/7zr1zdN17Ptkm5mRxF6Xw9ifrt3+dBuGXffnMNy+/vRxOZy+2uthlF6ZWX96lVYI345Dn9B9N4029aHeh5hH+wBUCCwvGKDOIL70mQGcnSTYuGDAOgORzQQ0G+/CegVOCcCDryngOgOjppAZZwQ/yiJiLYuuzhBNyAQRYxnPvFpBwFAUcKgpCI0skgPNouyKWhZjnQEdZwLZ97V1bGbRlSzGuZNWZyEYo04IBrnq5oYZAbmYCeOUhrDcUkCNPAR1E8VpJdAs7QQNP4IBj6rCoJkcIWf+
|
|
2992
|
+
"debug_symbols": "rVjbauMwEP0XP+dBc9Etv7IsJW3dEjBJcJOFpeTfd9RoZLsgYep9iY5H0fHR6Ehj+7N77Z9v70/H09v5o9v/+uyex+MwHN+fhvPL4Xo8nyT62Zn0A4DdnnbS+m5vpUXMrXvECXIr115ahtzma8u5jY/WUbcHk0AQAAI8ZRBAgYyFICDCA6AxGaBG0GZA2kUaYY1wicQMLCkIGThU4DPwegufZWAQQjQJsIKYQdRIzBEyrEAjIDJQ5kVoFJRI+o+kj4gVpAgLYM7AogJRSIkwaSYU4IWQUpe3GQSNhBRxAqJRkCNsSIEkgeWmnBb5AXwGKc9sE7AZpDw/gAjjmIBItXi/7zr1zdN17Ptkm5mRxF6Xw9ifrt3+dBuGXffnMNy+/vRxOZy+2uthlF6ZWX96lVYI345Dn9B9N4029aHeh5hH+wBUCCwvGKDOIL70mQGcnSTYuGDAOgORzQQ0G+/CegVOCcCDryngOgOjppAZZwQ/yiJiLYuuzhBNyAQRYxnPvFpBwFAUcKgpCI0skgPNouyKWhZjnQEdZwLZ97V1bGbRlSzGuZNWZyEYo04IBrnq5oYZAbmYCeOUhrDcUkCNPAR1E8VpJdAs7QQNP4IBj6rCoJkcIWf+ksU2PBVBhcRofZ2j4UtKZ9pjLmE2F4Ilg29kA4P6SmD8GQeRuhvJU52j4U6KXjnYgJ1lY7UMNt4VisB1GS1/QYxlmxlX8xc2KGw57myYzpqA6wmsZsKxrxGs3WZULRrY8iZqFqLl6hxaxgRQBgKul52Wq0LUTYZxtse+U2w/NHHrqdmeBvsyDaSaBmpVUDRlGmixqqK5HmZaD1vNBLXOTUt6XqGdGROBfubMWHMmNZyJcZoHTJUY1kuwvkjwrirBb65BFLbWIIr/owax2V6DGLbWIMbtNajJsbIGMW+uQWvdFaruYtda2FAe2GH2yP/t8OWGQclFpZA3qfoTd8ugXCoAykN3dbO3Zbjicjcrhd9kWNPyFpaXDw5QpWgdnkQ41QBaHJ6/5erwchwX3wfuiWs8Hp6HPl++3U4vs97r34v26PeFy3h+6V9vY5+Y5h8Z5DUx2F3wv+/pbv8A",
|
|
2997
2993
|
"is_unconstrained": true,
|
|
2998
2994
|
"name": "_increase_public_balance"
|
|
2999
2995
|
},
|
|
@@ -3042,7 +3038,7 @@
|
|
|
3042
3038
|
"abi_public",
|
|
3043
3039
|
"abi_view"
|
|
3044
3040
|
],
|
|
3045
|
-
"debug_symbols": "
|
|
3041
|
+
"debug_symbols": "nZbdirMwEIbvJcceZCaZ/PRWlqXY1i6C2OLWDz6K976JdaIuJJQ9ad5O9HH+MvoUl+Y0fh3b/nr7FoePpzgNbde1X8fudq4f7a0P1qeQ8cdocVCVMF4cdCWsnheHr8WKA0AlvHmtIGERiCx4S/GWYotmi2YLSRaahV+EUSzcIiw/wi5egItAFQUtwksWiwWlZMEWYAtEN0JUiMCCLSpeY6KgRehosVHQIogt5BYRfcZIjj4jBWEDEONWdPUlZss0VYJTf3wMTRMzv6lFqNC9Hpr+IQ792HWV+Fd343zR973u5/VRD2FXVqLpL2ENwGvbNVFN1Xq3zN/qKfo63+1JUwKQ3hEgT0CKyZoJSGpD8DsC5glE7AJZk+437v0YYnFeMRjpcjGUCEZTIhidI1CeAJgIgH7NgttXwhTy6LiMyq8xhI7dAWzBBRlOB/sgUfoEAat2EFfIhAd2w3uyWYTPI5Tmciq3CUTBvqMK5cBwUril0Pm/MZRyzFDB+Syj0JjKW2ZoCbRJxttuaGlNQjiddaPUWuA9l1VJk2stKCDIcHOSwxWA7wOIE2G0zQHePWCbQ/57zJQ6E/06qLIxlPoSgAkKtMwOqlJTOc8nDP3mgP1GFMZleBNCqqbNj8tCW6JJA9fJ3Lwsh6FtCgNV1gddmncyhYGEOS/K9ZBrPSifidLMJCXTu2fTmAhhWn2Gv/W5HXafN1OEDW196prl73Xsz5vdx/877/Dn0X24nZvLODSRtH4jQXibf4RzYeTnFJ/2Aw==",
|
|
3046
3042
|
"is_unconstrained": true,
|
|
3047
3043
|
"name": "balance_of_public"
|
|
3048
3044
|
},
|
|
@@ -3081,7 +3077,7 @@
|
|
|
3081
3077
|
"abi_public",
|
|
3082
3078
|
"abi_view"
|
|
3083
3079
|
],
|
|
3084
|
-
"debug_symbols": "
|
|
3080
|
+
"debug_symbols": "nZbdbuowDMffpddcxHY+eZWjaepYN1WqCurgSEcT736cEYd2kiO2G/KvS37Yjm3y2b0OL5f353F+O350+z+f3csyTtP4/jwdD/15PM5s/exM/gATuz3tOgDq9jav8baiv60E3T7klZ8TrxbK6m52Z8rKzwAsvBEhlkAiYhERWUQWCUT4m0AIRSCIkFckFhKLFUv25iZSEc6KiEV4EiE/EVAEA9GwiEaEKyKJJRULGSNCLMBuIGThi0CxYP4O55fIiMgWzixZIyIW4dhDysDsMyELz0DKrwKIEEvMFpdFtngWOZk3kbK4XnedHPjzeRmGfN6rCuC6OPXLMJ+7/XyZpl33t58uX1/6OPXz13ruF37LHg3zK68MfBunIavr7r7b6FtjsK7sjsGHCnB2QwCdgA5sIaAjdyekDQF1gnNUAC74ut/Hx2OgKDFE9FoMLUJMksOYwGoEpxPAUygE7iujZcHrBCI5CFrt/5aFpgdeABAgaB5EnWBRkmAtrgC/yiKSWksNRDJykglTBdgfHGSoLrA7qguNagSsHQE8UyoibnsKqNESUZygFCsAzTaTuW1UJwwEFC8MmnskPKy3lEZJpATiSEou6IxWWVppToqrWAi2hNDIBkaQAYGrM/kRg2qLIwXSGakRSQrCsAbcKhsPu2FN8BURre5Gq74gJTlZMl6rL2wNzNrpLuIdgI8DnGTC26ABHmyzxLErbYat2kTJQnJWjaFVmABCILDqxMVWVfGYkqpKqx77jmjMTL52QT3NoP/7NeoSff3/jOrgb4dhQw1jPXe3PhC0hp6pYaBD1YvmeZj7eTg1E9Sam45MvUqsChOBflWZ9nd3AU+V4LeEJ37qD+OyuadfM2sZ+5dpKI9vl/mwenv+d5I3cs8/LcfD8HpZhkxaXfb5gvgn0C64p2v+tf8=",
|
|
3085
3081
|
"is_unconstrained": true,
|
|
3086
3082
|
"name": "check_balance"
|
|
3087
3083
|
},
|
|
@@ -4936,7 +4932,7 @@
|
|
|
4936
4932
|
"custom_attributes": [
|
|
4937
4933
|
"abi_private"
|
|
4938
4934
|
],
|
|
4939
|
-
"debug_symbols": "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",
|
|
4935
|
+
"debug_symbols": "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",
|
|
4940
4936
|
"is_unconstrained": false,
|
|
4941
4937
|
"name": "claim",
|
|
4942
4938
|
"verification_key": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAANGKq8VDTe1r0E8WCP+GsqqYAAAAAAAAAAAAAAAAAAAAAAB/r4SIQtuEoN/PPa+Ft8wAAAAAAAAAAAAAAAAAAADqLsoWEu36/oB2TbMfq1h8iAAAAAAAAAAAAAAAAAAAAAAAci2xkrCw+grHNNlmX+B4AAAAAAAAAAAAAAAAAAACK9+gSEv6bAmg73GjiLnIS3QAAAAAAAAAAAAAAAAAAAAAAJg6WdTopECZ63FFj3nufAAAAAAAAAAAAAAAAAAAAsVXQA3MbwsliWMsheT9ZXxwAAAAAAAAAAAAAAAAAAAAAAAZNlfyK3FlF5iqi6y/17QAAAAAAAAAAAAAAAAAAAL9jQwvLB5GmFsVJFeqsuLnMAAAAAAAAAAAAAAAAAAAAAAAO+n5Dk1DTLqLAWSCA4mYAAAAAAAAAAAAAAAAAAAC4saKgI223JD2VUJI3XxYWmwAAAAAAAAAAAAAAAAAAAAAALAOfIbVA55X9h5F1J6UnAAAAAAAAAAAAAAAAAAAA9u19NInSxJUa98Nh2tVaBU0AAAAAAAAAAAAAAAAAAAAAADA7VEvWsiy9awWgon2TqwAAAAAAAAAAAAAAAAAAAIX+Xyku6x3XynL3rAU0tKkEAAAAAAAAAAAAAAAAAAAAAAAobFEtb8BJJHfBzWb6FdgAAAAAAAAAAAAAAAAAAADh1u8P6QkHUJDcmxEIm8ywbQAAAAAAAAAAAAAAAAAAAAAAAFrp7EEIXyCka0PFPPwgAAAAAAAAAAAAAAAAAAAA58s9zNIzapaFilQdYF0tNH4AAAAAAAAAAAAAAAAAAAAAACyqRNHoDeUuSMvhWGu20AAAAAAAAAAAAAAAAAAAALpNBQaTSzAffbzC9uNjxcYgAAAAAAAAAAAAAAAAAAAAAAASekG+2VRz8/SoI9jSawQAAAAAAAAAAAAAAAAAAACi4yNIue+9plogv/hxL5P6LgAAAAAAAAAAAAAAAAAAAAAABFu4u8jvVnGlwcKfSKYIAAAAAAAAAAAAAAAAAAAAjL25CRE+uE+Yi9izqnN8EkgAAAAAAAAAAAAAAAAAAAAAACiQMaoHvQlSbWagsLj6RwAAAAAAAAAAAAAAAAAAAEaaC8ja0uerPNkesT/FVJiWAAAAAAAAAAAAAAAAAAAAAAADo2UVLJzH8v69cvuPpEkAAAAAAAAAAAAAAAAAAACORWW6bJwZcyqxXQjJOpw/qQAAAAAAAAAAAAAAAAAAAAAAK8YW6FUKAI16QIMcMG08AAAAAAAAAAAAAAAAAAAAphmbVRAk2pyPCg07morUS6AAAAAAAAAAAAAAAAAAAAAAAByof58GDSBhT9A6Kac6FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv5pFyZBLAg40cQaBy/H3yUwAAAAAAAAAAAAAAAAAAAAAAAsPioax8XQoS5IbCx6E9QAAAAAAAAAAAAAAAAAAAGX82/ujn1cTjYoTScIJJ0/VAAAAAAAAAAAAAAAAAAAAAAAp3dwXW3Iy2K1t5Tip62kAAAAAAAAAAAAAAAAAAACiTYcTAkvHLurO0LP+GhaytwAAAAAAAAAAAAAAAAAAAAAAHq7l0rCiCK0+WbyCxw2xAAAAAAAAAAAAAAAAAAAAmLo3oyRw3h/ufw08lliXIKMAAAAAAAAAAAAAAAAAAAAAAC/9/yuxLSlhGgVcG8CuJwAAAAAAAAAAAAAAAAAAACSIylyuxL25c5ipCHOrNaKPAAAAAAAAAAAAAAAAAAAAAAABFo+KYdnFzPxJKx0hon8AAAAAAAAAAAAAAAAAAAAVMF+6z5JPgDvj0QwK87gJMQAAAAAAAAAAAAAAAAAAAAAAI0anxAxRJtM6/3vX5+tKAAAAAAAAAAAAAAAAAAAAtOgs3nqavKj5d+n3gSoUJGEAAAAAAAAAAAAAAAAAAAAAABvOHic8Ct/ISMeiySu5cgAAAAAAAAAAAAAAAAAAADU6z78e5JxL8/hfur4Db/TFAAAAAAAAAAAAAAAAAAAAAAAtezhEYLOhhsgHRKfAU/EAAAAAAAAAAAAAAAAAAABq8eWhOMwaVip/RbrbHitCbgAAAAAAAAAAAAAAAAAAAAAAAO3l9eoPbbaMhmoMzD01AAAAAAAAAAAAAAAAAAAAuOd18iKxJIMrZdpBVB+Tb+kAAAAAAAAAAAAAAAAAAAAAAAYVbF9rxjGYL6+/AZYEGQAAAAAAAAAAAAAAAAAAAJVeyO1NEAlZdqZen6mMpOb0AAAAAAAAAAAAAAAAAAAAAAAEncgQb1VqHKveON+nkkoAAAAAAAAAAAAAAAAAAACmBn8vp5xRyXzXjmfSn/pzIAAAAAAAAAAAAAAAAAAAAAAAF9nmqh2AUwzhmcTH3wnsAAAAAAAAAAAAAAAAAAAAWNjlsozTW43wfdy0kvlXMXgAAAAAAAAAAAAAAAAAAAAAABdHZS5F9VfT8EduABdcVgAAAAAAAAAAAAAAAAAAAGW49UhgE3dDIcN+p439l2WBAAAAAAAAAAAAAAAAAAAAAAASxjVJPny83uK700CmyuoAAAAAAAAAAAAAAAAAAAChlMCeXOFRea9IUPhg892hZQAAAAAAAAAAAAAAAAAAAAAAFtvU96OsI95c70KDm3r4AAAAAAAAAAAAAAAAAAAAG9682xjNaCAfc+K4cyzQpeIAAAAAAAAAAAAAAAAAAAAAAA5PjGNTEZX8D4ZzZWkz8gAAAAAAAAAAAAAAAAAAAHcHf0NwcpZwK9CYS9frzn3AAAAAAAAAAAAAAAAAAAAAAAAwQQUryx00Zvm0l0byDUoAAAAAAAAAAAAAAAAAAAD8sA/drzgMoxO4drqbd6ADjgAAAAAAAAAAAAAAAAAAAAAAKmMkrfsrS/Xb2P1laABOAAAAAAAAAAAAAAAAAAAAlbKr2IsKMo/+GMjn77g0bm0AAAAAAAAAAAAAAAAAAAAAABG7wExmhC6NPZkW52T5WgAAAAAAAAAAAAAAAAAAAJUlM+O+/qphIpOLApgt/LUUAAAAAAAAAAAAAAAAAAAAAAAkaU9hYnba1sr09m0ZPloAAAAAAAAAAAAAAAAAAAAau3sPk0/ld0PNBKeA9yl6NgAAAAAAAAAAAAAAAAAAAAAAGHi51D0hC8Hw1e/AN+KxAAAAAAAAAAAAAAAAAAAAkmvfIcSa3FRWznR3oVFSxboAAAAAAAAAAAAAAAAAAAAAAAyPFtLoT4DOurZpb6Zo0gAAAAAAAAAAAAAAAAAAAKsPi5n5bbcMvjz3F39NEU7sAAAAAAAAAAAAAAAAAAAAAAArUOr+y+WDxQkyfIjvssoAAAAAAAAAAAAAAAAAAACGuqG1iFF9D2BR4WMoITutLQAAAAAAAAAAAAAAAAAAAAAADuNSbgAV0CKkJJ85mdprAAAAAAAAAAAAAAAAAAAAlHZak02Cd7Ex+/MyQLy+x8cAAAAAAAAAAAAAAAAAAAAAABpHp4ZeiPCMZTW6EoKeugAAAAAAAAAAAAAAAAAAAOs3/VWXqSzI7o77wAcITK/NAAAAAAAAAAAAAAAAAAAAAAAeaPsLpFmF2q4tRR0h1T0AAAAAAAAAAAAAAAAAAACnzLrd/R3wVSH4/ql7Cy5WYgAAAAAAAAAAAAAAAAAAAAAAK922L8kgjwUbyYQaVePBAAAAAAAAAAAAAAAAAAAA9eGZ/oZZw8t/zTWl+BhhkOIAAAAAAAAAAAAAAAAAAAAAADArX2Fijz2gcfWzf/2wJAAAAAAAAAAAAAAAAAAAAGT6QpOZBJ2Hgd6OjXY6zinpAAAAAAAAAAAAAAAAAAAAAAAM/BMVBDlnDV8M8H1xq8gAAAAAAAAAAAAAAAAAAAAkMZq0nmBA/wxTqlRJkQJVPgAAAAAAAAAAAAAAAAAAAAAAHctB/qAZeEYBGeOv115WAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADuo/hmjGiiI2fIKb0AzIcYpQAAAAAAAAAAAAAAAAAAAAAAGwL3jnJfKdQSp5Ew1rt5AAAAAAAAAAAAAAAAAAAAS4pNjHfzdGm1DREDNizIh+gAAAAAAAAAAAAAAAAAAAAAABzz7dlI4KlF12vg+ReX4QAAAAAAAAAAAAAAAAAAALdG1/g+4B48aNs3+LFBiW7IAAAAAAAAAAAAAAAAAAAAAAArhbDfNtb+gEdn2prfTzEAAAAAAAAAAAAAAAAAAAAkb6AQcPk8UnkQssz8m2m/DQAAAAAAAAAAAAAAAAAAAAAAKfIN2dkcBrw8VM7V/IebAAAAAAAAAAAAAAAAAAAAhvSEULac3ruVGjWYaAtJ6eAAAAAAAAAAAAAAAAAAAAAAACqijynomdErCkdRNfU8FgAAAAAAAAAAAAAAAAAAALPe49ZKZWhnGAov9A3//uFLAAAAAAAAAAAAAAAAAAAAAAALvroWbfGsJfNmIIs167sAAAAAAAAAAAAAAAAAAACOWO0aucKOCnc4/T2x/ljUkgAAAAAAAAAAAAAAAAAAAAAAGsp9wWrpKR80aezJJeKFAAAAAAAAAAAAAAAAAAAAFeAgFMyFurt/KEPCp36g7I8AAAAAAAAAAAAAAAAAAAAAAAn0XSDoa6bhIMOz3GtD5AAAAAAAAAAAAAAAAAAAAP2TcQxskI1UwDhdN0qlMJ6IAAAAAAAAAAAAAAAAAAAAAAAqOvb5ajbU18kz6wuy0ksAAAAAAAAAAAAAAAAAAAAOL+ZkS/bIr4uZ+ZHbDEZzowAAAAAAAAAAAAAAAAAAAAAAF0KY5VYahMhvpPS0PD03AAAAAAAAAAAAAAAAAAAA3QnrHWcQThm47qItZ4I3XeoAAAAAAAAAAAAAAAAAAAAAABhKTLX35iT2jPzRH3y3HgAAAAAAAAAAAAAAAAAAANd++4FKMPSz+4798s0iuFKmAAAAAAAAAAAAAAAAAAAAAAAvzp9QJrge36Nbfb8lJTsAAAAAAAAAAAAAAAAAAACw4Dlzzcrv+e8SoQEn7VtRrwAAAAAAAAAAAAAAAAAAAAAALzxXwBSOSfW7soeQxvERAAAAAAAAAAAAAAAAAAAA//wpVyMLIN4+iIBGbin0YTIAAAAAAAAAAAAAAAAAAAAAAAbCIwQYJ8kObOnQdwiIvAAAAAAAAAAAAAAAAAAAAH85ect2RaLQe0wuhzoEc/mIAAAAAAAAAAAAAAAAAAAAAAAh7yAjhVxupT7kLSvr4QoAAAAAAAAAAAAAAAAAAAArO7Pn9g5i6p+Jv/xYN1/BZwAAAAAAAAAAAAAAAAAAAAAAJh+1jc9LmVjbtKCv87m0AAAAAAAAAAAAAAAAAAAA84HaruZPpwbnRH34kNUZ/sMAAAAAAAAAAAAAAAAAAAAAACR9MI3AAOaGJCPcF4TNAwAAAAAAAAAAAAAAAAAAACZKM69uwtzD/nZzcldqS70JAAAAAAAAAAAAAAAAAAAAAAAMgeAxdQ74vUEEktOFhRY="
|
|
@@ -6792,7 +6788,7 @@
|
|
|
6792
6788
|
"custom_attributes": [
|
|
6793
6789
|
"abi_private"
|
|
6794
6790
|
],
|
|
6795
|
-
"debug_symbols": "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",
|
|
6791
|
+
"debug_symbols": "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",
|
|
6796
6792
|
"is_unconstrained": false,
|
|
6797
6793
|
"name": "claim_and_end_setup",
|
|
6798
6794
|
"verification_key": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAkTY6i/XMfdtzimGiyUiPOF8AAAAAAAAAAAAAAAAAAAAAAAeKe8laCswPoPAfrvAFpAAAAAAAAAAAAAAAAAAAALAakr5QBK2vBeVorD0HBVCCAAAAAAAAAAAAAAAAAAAAAAAuARrkESKfZq5HFVp+X98AAAAAAAAAAAAAAAAAAAAzbpXtYZzahwj1pXYnPw1xdQAAAAAAAAAAAAAAAAAAAAAAAiSZeapcyWzM8r5MhaZEAAAAAAAAAAAAAAAAAAAAX6geZ+eWpZ+UVB05iagXIz4AAAAAAAAAAAAAAAAAAAAAAAnyxTdr+6Da5P2r6NvwOQAAAAAAAAAAAAAAAAAAAEI6nIIUU/A1R+2ZppkfFJzGAAAAAAAAAAAAAAAAAAAAAAAhstvtwbgpqGBH6DdvsvIAAAAAAAAAAAAAAAAAAABOw0l2rT5edpe4f8gNznt5twAAAAAAAAAAAAAAAAAAAAAAHfsdDNUbKfeUEWFX0BbKAAAAAAAAAAAAAAAAAAAArcuLc+e2Q5xV9DAOVbyNasYAAAAAAAAAAAAAAAAAAAAAACizzjabBavr3uwxJiJwzwAAAAAAAAAAAAAAAAAAAN2pn0/VXcgXo4ryFNoUJEt9AAAAAAAAAAAAAAAAAAAAAAAcM8wlZyM3mi7jQ4cLs2IAAAAAAAAAAAAAAAAAAADgkfHmqFYi9Wva38oMSlPPKgAAAAAAAAAAAAAAAAAAAAAABSyW0Gs6voIq/nHjKaszAAAAAAAAAAAAAAAAAAAAdSbxWjOdJa6w0qoe1CzIfygAAAAAAAAAAAAAAAAAAAAAACRmDSKQfTg28oq6sQLR/QAAAAAAAAAAAAAAAAAAAC+AVCsfPcoS++GElEX9H2LRAAAAAAAAAAAAAAAAAAAAAAAQregLgGO/ji29oJDtAX0AAAAAAAAAAAAAAAAAAAC2zpWT6PHL+LBAoYsqox8xfgAAAAAAAAAAAAAAAAAAAAAAE0MZx84zaBLkD/mep39ZAAAAAAAAAAAAAAAAAAAAw2as9HDRPDvl1hHBeegEWoIAAAAAAAAAAAAAAAAAAAAAACEwOdHpfHxznGk+a2878gAAAAAAAAAAAAAAAAAAAF4+1q+FHp6N1Qeo/P1EIkvHAAAAAAAAAAAAAAAAAAAAAAApiVbndw9rHK3KrFUjpkoAAAAAAAAAAAAAAAAAAACMQJsYKoPeb41UBjvs/aWKDQAAAAAAAAAAAAAAAAAAAAAAF+tPMiaO9DTbEpnLrQRPAAAAAAAAAAAAAAAAAAAAhsR6s2kqmcAdOq7bh8R8x0sAAAAAAAAAAAAAAAAAAAAAACqCUHQFTYB+MDMk/Yi/2gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAepe2V71xANwrvsigXHgXcmsAAAAAAAAAAAAAAAAAAAAAABVMYQhHfbvP6eqH6NqtRgAAAAAAAAAAAAAAAAAAAJaI8g4bX/EPVWsGvRa9Nfi2AAAAAAAAAAAAAAAAAAAAAAAVpWQHOYCI6yxmwM/HKJgAAAAAAAAAAAAAAAAAAACiTYcTAkvHLurO0LP+GhaytwAAAAAAAAAAAAAAAAAAAAAAHq7l0rCiCK0+WbyCxw2xAAAAAAAAAAAAAAAAAAAAmLo3oyRw3h/ufw08lliXIKMAAAAAAAAAAAAAAAAAAAAAAC/9/yuxLSlhGgVcG8CuJwAAAAAAAAAAAAAAAAAAACSIylyuxL25c5ipCHOrNaKPAAAAAAAAAAAAAAAAAAAAAAABFo+KYdnFzPxJKx0hon8AAAAAAAAAAAAAAAAAAAAVMF+6z5JPgDvj0QwK87gJMQAAAAAAAAAAAAAAAAAAAAAAI0anxAxRJtM6/3vX5+tKAAAAAAAAAAAAAAAAAAAAtOgs3nqavKj5d+n3gSoUJGEAAAAAAAAAAAAAAAAAAAAAABvOHic8Ct/ISMeiySu5cgAAAAAAAAAAAAAAAAAAADU6z78e5JxL8/hfur4Db/TFAAAAAAAAAAAAAAAAAAAAAAAtezhEYLOhhsgHRKfAU/EAAAAAAAAAAAAAAAAAAABq8eWhOMwaVip/RbrbHitCbgAAAAAAAAAAAAAAAAAAAAAAAO3l9eoPbbaMhmoMzD01AAAAAAAAAAAAAAAAAAAAuOd18iKxJIMrZdpBVB+Tb+kAAAAAAAAAAAAAAAAAAAAAAAYVbF9rxjGYL6+/AZYEGQAAAAAAAAAAAAAAAAAAAJVeyO1NEAlZdqZen6mMpOb0AAAAAAAAAAAAAAAAAAAAAAAEncgQb1VqHKveON+nkkoAAAAAAAAAAAAAAAAAAACmBn8vp5xRyXzXjmfSn/pzIAAAAAAAAAAAAAAAAAAAAAAAF9nmqh2AUwzhmcTH3wnsAAAAAAAAAAAAAAAAAAAAlI2jkfxdBQEDYVLZK6Mu+E4AAAAAAAAAAAAAAAAAAAAAAB75CU96nn/nGKNP4MiPSAAAAAAAAAAAAAAAAAAAADPr2Nrbi1wdeENur7KZ2jUfAAAAAAAAAAAAAAAAAAAAAAArxt6fm/4WVSkC6C5WFEwAAAAAAAAAAAAAAAAAAABXdbTGt5JuBQKrUDYbezYedQAAAAAAAAAAAAAAAAAAAAAAHtNY5RJgom+x2pa9J5xqAAAAAAAAAAAAAAAAAAAAD8ZOpsKBv63aZ37hPO1Z5xkAAAAAAAAAAAAAAAAAAAAAACo9mdyi4jxSuacsn5YLZAAAAAAAAAAAAAAAAAAAAL6UzBuFx4wFT0IfZBM37Pi0AAAAAAAAAAAAAAAAAAAAAAAKBCqDDngc6SaY18xSCX0AAAAAAAAAAAAAAAAAAACDDuHVB7pUhsX61t23RwG5YwAAAAAAAAAAAAAAAAAAAAAAG4acFNHAImYIv84EaCbgAAAAAAAAAAAAAAAAAAAAyHgy/AWhhRqwiyhREDhNG1UAAAAAAAAAAAAAAAAAAAAAABmBz0b9VhWBcSMWPKIHIAAAAAAAAAAAAAAAAAAAAIa904+aDRPPfvA3KXs6JEpiAAAAAAAAAAAAAAAAAAAAAAAGmqsCjfE+xCxIJC/dvaYAAAAAAAAAAAAAAAAAAAAoT5HAzCef9b4zEj/ZOZOeKQAAAAAAAAAAAAAAAAAAAAAADqMzY6UAEH2gFg17dQNNAAAAAAAAAAAAAAAAAAAA8SFFTAS5fDyLD/fQJWm32skAAAAAAAAAAAAAAAAAAAAAACfxKJHdsQx2Qq3N96jaDgAAAAAAAAAAAAAAAAAAAExQkd8cKda+WzO6NJIlYpzhAAAAAAAAAAAAAAAAAAAAAAAoF6eRZrDKNI4K3D8H8J4AAAAAAAAAAAAAAAAAAAA2L5LAXfmQvkG/RclXmmPV9AAAAAAAAAAAAAAAAAAAAAAAIwGU2ZAxZOQQD9mvWaOyAAAAAAAAAAAAAAAAAAAAlHYpb5pl09ZpVlgFsz0EeUEAAAAAAAAAAAAAAAAAAAAAAAa5LzRyy/S4dwHyvEq7KgAAAAAAAAAAAAAAAAAAAFzTWFGprQ147aqyXy/ksEDHAAAAAAAAAAAAAAAAAAAAAAAiPTf/YpVj8kPR14ayT30AAAAAAAAAAAAAAAAAAACus1hBs1fENFAdTOkTiQNshwAAAAAAAAAAAAAAAAAAAAAALz5SwWtQ4ABw+F4u6dhCAAAAAAAAAAAAAAAAAAAAg3ZyMTrctFYcuL/vRJGJXXkAAAAAAAAAAAAAAAAAAAAAACJs66oPGk0SOBqu56PfyQAAAAAAAAAAAAAAAAAAAORI3sjdYzMntaHxa3EPCDS/AAAAAAAAAAAAAAAAAAAAAAAn9/7/ChAzsP3UmMK0+VYAAAAAAAAAAAAAAAAAAADePWc1brtfYHVBn1khdNZhmwAAAAAAAAAAAAAAAAAAAAAAKd9SOkJQJxyZktzawRq8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACLnUYi3zuqnao50XcOE38F3gAAAAAAAAAAAAAAAAAAAAAAI9DFfjicXLCvg3BZYuZaAAAAAAAAAAAAAAAAAAAAdxqRjg5mSrPiLHvIavnHj6kAAAAAAAAAAAAAAAAAAAAAAAv5gOY9JqX0Y5OftpMPPwAAAAAAAAAAAAAAAAAAALdG1/g+4B48aNs3+LFBiW7IAAAAAAAAAAAAAAAAAAAAAAArhbDfNtb+gEdn2prfTzEAAAAAAAAAAAAAAAAAAAAkb6AQcPk8UnkQssz8m2m/DQAAAAAAAAAAAAAAAAAAAAAAKfIN2dkcBrw8VM7V/IebAAAAAAAAAAAAAAAAAAAAhvSEULac3ruVGjWYaAtJ6eAAAAAAAAAAAAAAAAAAAAAAACqijynomdErCkdRNfU8FgAAAAAAAAAAAAAAAAAAALPe49ZKZWhnGAov9A3//uFLAAAAAAAAAAAAAAAAAAAAAAALvroWbfGsJfNmIIs167sAAAAAAAAAAAAAAAAAAABdIpnboOgk3UyZMd36A7rPRgAAAAAAAAAAAAAAAAAAAAAAFE1+9DILMglKRgCbpXEMAAAAAAAAAAAAAAAAAAAACRnD6/zqqhkpRrBQcssNSXwAAAAAAAAAAAAAAAAAAAAAAByDTjVw4GNoGix9pnLx9AAAAAAAAAAAAAAAAAAAABKZlt9oFxeYMXZbiBSa+Bh8AAAAAAAAAAAAAAAAAAAAAAAXPKAWV84fPLScYBq0oSAAAAAAAAAAAAAAAAAAAAC1T2ZFfqLa/H1aBzhmzFUvGwAAAAAAAAAAAAAAAAAAAAAABoDg8J7IeFK3n0YfiGQDAAAAAAAAAAAAAAAAAAAANhgm/oWJHJec9TSIU5unGJQAAAAAAAAAAAAAAAAAAAAAABlN0RGBgPwANA5YJfTjgwAAAAAAAAAAAAAAAAAAABQbFNBA0hr74Di1thCVou+HAAAAAAAAAAAAAAAAAAAAAAAc9NSeJivgTL0cCVZJmf4AAAAAAAAAAAAAAAAAAABFSbqa73bAHJ7Ic6YfOVDHIwAAAAAAAAAAAAAAAAAAAAAAKBjEdstrGBdFrwJOucjWAAAAAAAAAAAAAAAAAAAAYuXruKi+lYhf30YNHh/5URgAAAAAAAAAAAAAAAAAAAAAABS6DW+eYRi8K9JzArA9qwAAAAAAAAAAAAAAAAAAAAuHZPjUA/0s6bhy15rQ+ctJAAAAAAAAAAAAAAAAAAAAAAAVSpCcS0FpYl140Y5TPwwAAAAAAAAAAAAAAAAAAAAbJb76Z0kvn/eJiVc7U81qRQAAAAAAAAAAAAAAAAAAAAAAJ90XJn+9IB8AjsL9GtwSAAAAAAAAAAAAAAAAAAAAyCC9xZ49NuYzO/Xyirs/2K8AAAAAAAAAAAAAAAAAAAAAABz7jTH1LNe0EZIBfdRdCwAAAAAAAAAAAAAAAAAAACVvpuI2ZAc0tiR1BFZIyaBCAAAAAAAAAAAAAAAAAAAAAAAdjtK/f86AqYaRPmSAhL4="
|
|
@@ -6850,7 +6846,7 @@
|
|
|
6850
6846
|
"custom_attributes": [
|
|
6851
6847
|
"abi_public"
|
|
6852
6848
|
],
|
|
6853
|
-
"debug_symbols": "
|
|
6849
|
+
"debug_symbols": "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",
|
|
6854
6850
|
"is_unconstrained": true,
|
|
6855
6851
|
"name": "public_dispatch"
|
|
6856
6852
|
}
|
|
@@ -7106,5 +7102,5 @@
|
|
|
7106
7102
|
}
|
|
7107
7103
|
},
|
|
7108
7104
|
"transpiled": true,
|
|
7109
|
-
"aztec_version": "6.0.0-rc.
|
|
7105
|
+
"aztec_version": "6.0.0-rc.7"
|
|
7110
7106
|
}
|