From f0e025c778527281c2829064cf54bd95dd71c9ce Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Thu, 16 May 2024 16:11:23 -0400 Subject: [PATCH 01/12] chore: move acir docs to code declaration and cleanup (some opcodes from the readme are already removed and some are missing) --- acvm-repo/acir/README.md | 335 +++++++++++------- .../acir/src/circuit/black_box_functions.rs | 203 ++++++++++- acvm-repo/acir/src/circuit/opcodes.rs | 75 +++- .../src/circuit/opcodes/memory_operation.rs | 5 +- 4 files changed, 464 insertions(+), 154 deletions(-) diff --git a/acvm-repo/acir/README.md b/acvm-repo/acir/README.md index f7fccad0799..902769e3ad7 100644 --- a/acvm-repo/acir/README.md +++ b/acvm-repo/acir/README.md @@ -1,214 +1,291 @@ # ACIR documentation (draft) ## Abstract -This document describes the purpose of ACIR, what it is and how ACIR programs can be used by compilers and proving systems. It is intended to be a reference documentation for ACIR. + +This document describes the purpose of ACIR, what it is and how ACIR programs +can be used by compilers and proving systems. It is intended to be a reference +documentation for ACIR. ## Introduction -The purpose of ACIR is to make the link between a generic proving system, such as Aztec's Barretenberg, and a frontend, such as Noir, which describes user-specific computations. -More precisely, Noir is a programming language for zero-knowledge proofs (ZKP) which allows users to write programs in an intuitive way using a high-level language close to Rust syntax. Noir is able to generate a proof of execution of a Noir program, using an external proving system. However, proving systems use specific low-level constrain-based languages. Similarly, frontends have their own internal representation in order to represent user programs. +The purpose of ACIR is to make the link between a generic proving system, such +as Aztec's Barretenberg, and a frontend, such as Noir, which describes user +specific computations. + +More precisely, Noir is a programming language for zero-knowledge proofs (ZKP) +which allows users to write programs in an intuitive way using a high-level +language close to Rust syntax. Noir is able to generate a proof of execution of +a Noir program, using an external proving system. However, proving systems use +specific low-level constrain-based languages. Similarly, frontends have their +own internal representation in order to represent user programs. -The goal of ACIR is to provide a generic open-source intermediate representation close to proving system 'languages', but agnostic to a specific proving system, that can be used both by proving system as well as a target for frontends. So, at the end of the day, an ACIR program is just another representation of a program, dedicated to proving systems. +The goal of ACIR is to provide a generic open-source intermediate +representation close to proving system 'languages', but agnostic to a specific +proving system, that can be used both by proving system as well as a target for +frontends. So, at the end of the day, an ACIR program is just another +representation of a program, dedicated to proving systems. ## Abstract Circuit Intermediate Representation ACIR stands for abstract circuit intermediate representation: -- **abstract circuit**: circuits are a simple computation model where basic computation units, named gates, are connected with wires. Data flows through the wires while gates compute output wires based on their input. More formally, they are directed acyclic graphs (DAG) where the vertices are the gates and the edges are the wires. Due to the immutability nature of the wires (their value does not change during an execution), they are well suited for describing computations for ZKPs. Furthermore, we do not lose any expressiveness when using a circuit as it is well known that any bounded computation can be translated into an arithmetic circuit (i.e a circuit with only addition and multiplication gates). -The term abstract here simply means that we do not refer to an actual physical circuit (such as an electronic circuit). Furthermore, we will not exactly use the circuit model, but another model even better suited to ZKPs, the constraint model (see below). -- **intermediate representation**: The ACIR representation is intermediate because it lies between a frontend and its proving system. ACIR bytecode makes the link between noir compiler output and the proving system backend input. +- **abstract circuit**: circuits are a simple computation model where basic + computation units, named gates, are connected with wires. Data flows + through the wires while gates compute output wires based on their input. + More formally, they are directed acyclic graphs (DAG) where the vertices + are the gates and the edges are the wires. Due to the immutability nature + of the wires (their value does not change during an execution), they are + well suited for describing computations for ZKPs. Furthermore, we do not + lose any expressiveness when using a circuit as it is well known that any + bounded computation can be translated into an arithmetic circuit (i.e a + circuit with only addition and multiplication gates). +The term abstract here simply means that we do not refer to an actual physical +circuit (such as an electronic circuit). Furthermore, we will not exactly use +the circuit model, but another model even better suited to ZKPs, the constraint +model (see below). +- **intermediate representation**: The ACIR representation is intermediate +because it lies between a frontend and its proving system. ACIR bytecode makes +the link between noir compiler output and the proving system backend input. ## The constraint model -The first step for generating a proof that a specific program was executed, is to execute this program. Since the proving system is going to handle ACIR programs, we need in fact to execute an ACIR program, using the user-supplied inputs. -In ACIR terminology, the gates are called opcodes and the wires are called partial witnesses. However, instead of connecting the opcodes together through wires, we create constraints: an opcode constraints together a set of wires. -This constraint model trivially supersedes the circuit model. For instance, an addition gate output_wire = input_wire_1 + input_wire_2 can be expressed with the following arithmetic constraint: output_wire - (input_wire_1 + input_wire_2) = 0 +The first step for generating a proof that a specific program was executed, is +to execute this program. Since the proving system is going to handle ACIR +programs, we need in fact to execute an ACIR program, using the user-supplied +inputs. +In ACIR terminology, the gates are called opcodes and the wires are called +partial witnesses. However, instead of connecting the opcodes together through +wires, we create constraints: an opcode constraints together a set of wires. +This constraint model trivially supersedes the circuit model. For instance, an +addition gate `output_wire = input_wire_1 + input_wire_2` can be expressed with +the following arithmetic constraint: +`output_wire - (input_wire_1 + input_wire_2) = 0` ## Solving -Because of these constraints, executing an ACIR program is called solving the witnesses. From the witnesses representing the inputs of the program, whose values are supplied by the user, we find out what the other witnesses should be by executing/solving the constraints one-by-one in the order they were defined. -For instance, if input_wire_1 and input_wire_2 values are supplied as 3 and 8, then we can solve the opcode output_wire - (input_wire_1 + input_wire_2) = 0 by saying that output_wire is 11. +Because of these constraints, executing an ACIR program is called solving the +witnesses. From the witnesses representing the inputs of the program, whose +values are supplied by the user, we find out what the other witnesses should be +by executing/solving the constraints one-by-one in the order they were defined. + +For instance, if `input_wire_1` and `input_wire_2` values are supplied as `3` and +`8`, then we can solve the opcode +`output_wire - (input_wire_1 + input_wire_2) = 0` by saying that `output_wire` is +`11`. In summary, the workflow is the following: -1. user program -> (compilation) ACIR, a list of opcodes which constrain (partial) witnesses -2. user inputs + ACIR -> (execution/solving) assign values to all the (partial) witnesses +1. user program -> (compilation) ACIR, a list of opcodes which constrain + (partial) witnesses +2. user inputs + ACIR -> (execution/solving) assign values to all the + (partial) witnesses 3. witness assignment + ACIR -> (proving system) proof +Although the ordering of opcode does not matter in theory, since a system of +equations is not dependent on its ordering, in practice it matters a lot for the +solving (i.e the performance of the execution). ACIR opcodes **must be ordered** +so that each opcode can be resolved one after the other. -Although the ordering of opcode does not matter in theory, since a system of equations is not dependent on its ordering, in practice it matters a lot for the solving (i.e the performance of the execution). ACIR opcodes **must be ordered** so that each opcode can be resolved one after the other. +The values of the witnesses lie in the scalar field of the proving system. We +will refer to it as `FieldElement` or ACIR field. The proving system needs the +values of all the partial witnesses and all the constraints in order to generate +a proof. +*Remark*: The value of a partial witness is unique and fixed throughout a program + execution, although in some rare cases, multiple values are possible for a + same execution and witness (when there are several valid solutions to the + constraints). Having multiple possible values for a witness may indicate that + the circuit is not safe. -The values of the witnesses lie in the scalar field of the proving system. We will refer to it as FieldElement or ACIR field. The proving system needs the values of all the partial witnesses and all the constraints in order to generate a proof. +*Remark*: Why do we use the term partial witnesses? It is because the proving + system may create other constraints and witnesses (especially with + `BlackBoxFuncCall`, see below). A proof refers to a full witness assignments + and their constraints. ACIR opcodes and their partial witnesses are still an + intermediate representation before getting the full list of constraints and + witnesses. For the sake of simplicity, we will refer to witness instead of + partial witness from now on. -*Remark*: The value of a partial witness is unique and fixed throughout a program execution, although in some rare cases, multiple values are possible for a same execution and witness (when there are several valid solutions to the constraints). Having multiple possible values for a witness may indicate that the circuit is not safe. +## ACIR Reference -*Remark*: Why do we use the term partial witnesses? It is because the proving system may create other constraints and witnesses (especially with BlackBoxFuncCall, see below). A proof refers to a full witness assignments and their constraints. ACIR opcodes and their partial witnesses are still an intermediate representation before getting the full list of constraints and witnesses. For the sake of simplicity, we will refer to witness instead of partial witness from now on. +We assume here that the proving system is Barretenberg. Some parameters may +slightly change with another proving system, in particular the bit size of +`FieldElement`, which is 254 for Barretenberg. +Some opcodes have inputs and outputs, which means that the output is constrained +to be the result of the opcode computation from the inputs. The solver expects +that all inputs are known when solving such opcodes. -## ACIR Reference -We assume here that the proving system is Barretenberg. Some parameters may slightly change with another proving system, in particular the bit size of FieldElement, which is 254 for Barretenberg. +Some opcodes are not constrained, which means they will not be used by the +proving system and are only used by the solver. -Some opcodes have inputs and outputs, which means that the output is constrained to be the result of the opcode computation from the inputs. The solver expects that all inputs are known when solving such opcodes. +Finally, some opcodes will have a predicate, whose value is `0` or `1`. Its +purpose is to nullify the opcode when the value is `0`, so that it has no +effect. Note that removing the opcode is not a solution because this modifies +the circuit (the circuit being mainly the list of the opcodes). -Some opcodes are not constrained, which means they will not be used by the proving system and are only used by the solver. +*Remark*: Opcodes operate on witnesses, but we will see that some opcode work on + expressions of witnesses. We call an expression a linear combination of + witnesses and/or products of two witnesses (and also a constant term). A + single witness is a (simple) expression, and conversely, an expression can + be turned into a single witness using an assert-zero opcode (see below). So + basically, using witnesses or expressions is equivalent, but the latter can + avoid the creation of witness in some cases. -Finally, some opcodes will have a predicate, whose value is 0 or 1. Its purpose is to nullify the opcode when the value is 0, so that it has no effect. Note that removing the opcode is not a solution because this modifies the circuit (the circuit being mainly the list of the opcodes). +### AssertZero opcode -*Remark*: Opcodes operate on witnesses, but we will see that some opcode work on expressions of witnesses. We call an expression a linear combination of witnesses and/or products of two witnesses (and also a constant term). A single witness is a (simple) expression, and conversely, an expression can be turned into a single witness using an assert-zero opcode (see below). So basically, using witnesses or expressions is equivalent, but the latter can avoid the creation of witness in some cases. +An `AssertZero` opcode adds the constraint that `P(w) = 0`, where +`w=(w_1,..w_n)` is a tuple of `n` witnesses, and `P` is a multi-variate +polynomial of total degree at most `2`. -### AssertZero opcode -An AssertZero opcode adds the constraint that P(w) = 0, where w=(w_1,..w_n) is a tuple of n witnesses, and P is a multi-variate polynomial of total degree at most 2. -The coefficients ${q_M}_{i,j}, q_i,q_c$ of the polynomial are known values which define the opcode. -A general expression of assert-zero opcode is the following: $\sum_{i,j} {q_M}_{i,j}w_iw_j + \sum_i q_iw_i +q_c = 0$ +### BlackBoxFuncCall opcode -An assert-zero opcode can be used to: -- **express a constraint** on witnesses; for instance to express that a witness $w$ is a boolean, you can add the opcode: $w*w-w=0$ -- or, to **compute the value** of an arithmetic operation of some inputs. For instance, to multiply two witnesses $x$ and $y$, you would use the opcode $z-x*y=0$, which would constraint $z$ to be $x*y$. +These opcodes represent a specific computation. Even if any computation can be +done using only assert-zero opcodes, it is not always efficient. Some proving +systems, and in particular the proving system from Aztec, can implement several +computations more efficiently using for instance look-up tables. The +`BlackBoxFuncCall` opcode is used to ask the proving system to handle the +computation by itself. +All black box functions take as input a tuple `(witness, num_bits)`, where +`num_bits` is a constant representing the bit size of the input witness, and they +have one or several witnesses as output. -The solver expects that at most one witness is not known when executing the opcode. +Some more advanced computations assume that the proving system has an +"embedded curve". It is a curve that cycles with the main curve of the proving +system, i.e the scalar field of the embedded curve is the base field of the main +one, and vice-versa. The curves used by the proving system are dependent on the +proving system (and/or its configuration). Aztec's Barretenberg uses BN254 as the +main curve and Grumpkin as the embedded curve. -### BlackBoxFuncCall opcode -These opcodes represent a specific computation. Even if any computation can be done using only assert-zero opcodes, it is not always efficient. Some proving systems, and in particular the proving system from Aztec, can implement several computations more efficiently using for instance look-up tables. The BlackBoxFuncCall opcode is used to ask the proving system to handle the computation by itself. -All black box functions take as input a tuple (witness, num_bits), where num_bits is a constant representing the bit size of the input witness, and they have one or several witnesses as output. -Some more advanced computations assume that the proving system has an 'embedded curve'. It is a curve that cycle with the main curve of the proving system, i.e the scalar field of the embedded curve is the base field of the main one, and vice-versa. The curves used by the proving system are dependent on the proving system (and/or its configuration). Aztec's Barretenberg uses BN254 as the main curve and Grumpkin as the embedded curve. +NOTE: see the [black_box_functions](src/circuit/black_box_functions.rs) file for +the most up-to-date documentation on these opcodes. The black box functions supported by ACIR are: **AES128Encrypt**: ciphers the provided plaintext using AES128 in CBC mode, padding the input using PKCS#7. -- inputs: byte array [u8; N] -- iv: initialization vector [u8; 16] -- key: user key [u8; 16] -- outputs: byte vector [u8] of length `input.len() + (16 - input.len() % 16)`` -**AND**: performs the bitwise AND of lhs and rhs. bit_size must be the same for both inputs. -- lhs: (witness, bit_size) -- rhs: (witness, bit_size) -- output: a witness whose value is constrained to be lhs AND rhs, as bit_size bit integers +**AND**: performs the bitwise AND of `lhs` and `rhs`. `bit_size` must be the same for both inputs. -**XOR**: performs the bitwise XOR of lhs and rhs. bit_size must be the same for both inputs. -- lhs: (witness, bit_size) -- rhs: (witness, bit_size) -- output: a witness whose value is constrained to be lhs XOR rhs, as bit_size bit integers +**XOR**: performs the bitwise XOR of `lhs` and `rhs`. `bit_size` must be the same for both inputs. **RANGE**: constraint the input to be of the provided bit size -input: (witness, bit_size) **SHA256**: computes sha256 of the inputs -- inputs are a byte array, i.e a vector of (FieldElement, 8) -- output is a byte array of len 32, i.e a vector of 32 (FieldElement, 8), constrained to be the sha256 of the inputs. **Blake2s**: computes the Blake2s hash of the inputs, as specified in https://tools.ietf.org/html/rfc7693 -- inputs are a byte array, i.e a vector of (FieldElement, 8) -- output is a byte array of length 32, i.e a vector of 32 (FieldElement, 8), constrained to be the blake2s of the inputs. +**Blake3**: computes the Blake3 hash of the inputs **SchnorrVerify**: Verify a Schnorr signature over the embedded curve -- inputs are: - - Public key as 2 (FieldElement, 254) - - signature as a vector of 64 bytes (FieldElement, 8) - - message as a vector of (FieldElement, 8) -- output: A witness representing the result of the signature verification; 0 for failure and 1 for success. - -Since the scalar field of the embedded curve is NOT the ACIR field, the (r,s) signature is represented as a 64 bytes array for the two field elements. On the other hand, the public key coordinates are ACIR fields. -The proving system decides how the message is to be hashed. Barretenberg uses Blake2s. - **PedersenCommitment**: Computes a Pedersen commitments of the inputs using generators of the embedded curve -- input: vector of (FieldElement, 254) -- output: 2 witnesses representing the x,y coordinates of the resulting Grumpkin point -- domain separator: a constant public value (a field element) that you can use so that the commitment also depends on the domain separator. Noir uses 0 as domain separator. - -The backend should handle proper conversion between the inputs being ACIR field elements and the scalar field of the embedded curve. In the case of Aztec's Barretenberg, the latter is bigger than the ACIR field so it is straightforward. The Pedersen generators are managed by the proving system. - **PedersenHash**: Computes a Pedersen commitments of the inputs and their number, using generators of the embedded curve -- input: vector of (FieldElement, 254) -- output: the x-coordinate of the pedersen commitment of the 'prepended input' (see below) -- domain separator: a constant public value (a field element) that you can use so that the hash also depends on the domain separator. Noir uses 0 as domain separator. -In Barretenberg, PedersenHash is doing the same as PedersenCommitment, except that it prepends the inputs with their length. +**EcdsaSecp256k1**: Verify an ECDSA signature over Secp256k1 +**EcdsaSecp256r1**: Same as EcdsaSecp256k1, but done over another curve. -**HashToField128Security**: This opcode is deprecated and will be removed. +**MultiScalarMul**: scalar multiplication with a variable base/input point (`P`) of the embedded curve -**EcdsaSecp256k1**: Verify an ECDSA signature over Secp256k1 -- inputs: - - x coordinate of public key as 32 bytes - - y coordinate of public key as 32 bytes - - the signature, as a 64 bytes array - - the hash of the message, as a vector of bytes -- output: 0 for failure and 1 for success +**Keccak256**: Computes the Keccak-256 (Ethereum version) of the inputs. -Inputs and outputs are similar to SchnorrVerify, except that because we use a different curve (secp256k1), the field elements involved in the signature and the public key are defined as an array of 32 bytes. Another difference is that we assume the message is already hashed. +**Keccakf1600**: Keccak Permutation function of width 1600 -**EcdsaSecp256r1**: Same as EcdsaSecp256k1, but done over another curve. +**EmbeddedCurveAdd**: Embedded curve addition -**MultiScalarMul**: scalar multiplication with a variable base/input point (P) of the embedded curve -- input: - points (FieldElement, N) a vector of x and y coordinates of input points [x1, y1, x2, y2,...]. - scalars (FieldElement, N) a vector of low and high limbs of input scalars [s1_low, s1_high, s2_low, s2_high, ...]. (FieldElement, N) For Barretenberg, they must both be less than 128 bits. -- output: (FieldElement, N) a vector of x and y coordinates of output points [op1_x, op1_y, op2_x, op2_y, ...]. Points computed as $s_low*P+s_high*2^{128}*P$ +**BigIntAdd**: BigInt addition -Because the Grumpkin scalar field is bigger than the ACIR field, we provide 2 ACIR fields representing the low and high parts of the Grumpkin scalar $a$: -$a=low+high*2^{128},$ with $low, high < 2^{128}$ +**BigIntSub**: BigInt subtraction -**Keccak256**: Computes the Keccak-256 (Ethereum version) of the inputs. -- inputs: Vector of bytes (FieldElement, 8) -- outputs: Vector of 32 bytes (FieldElement, 8) +**BigIntMul**: BigInt multiplication + +**BigIntDiv**: BigInt division +**BigIntFromLeBytes**: BigInt from le bytes -**Keccak256VariableLength**: Computes the Keccak-256 (Ethereum version) of the inputs, restricted to the given length. -- inputs: Vector of bytes (FieldElement, 8) -- var_message_size: number of inputs to hash; it must be less (or equal) than the inputs length -- outputs: a vector of 32 bytes (FieldElement, 8) +**BigIntToLeBytes**: BigInt to le bytes +**Poseidon2Permutation**: Permutation function of Poseidon2 +**Sha256Compression**: SHA256 compression function **RecursiveAggregation**: verify a proof inside the circuit. **Warning: this opcode is subject to change.** -- verification_key: Vector of (FieldElement, 254) representing the verification key of the circuit being verified -- public_inputs: Vector of (FieldElement, 254) representing the public inputs corresponding to the proof being verified -- key_hash: one (FieldElement, 254). It should be the hash of the verification key. Barretenberg expects the Pedersen hash of the verification key -- input_aggregation_object: an optional vector of (FieldElement, 254). It is a blob of data specific to the proving system. -- output_aggregation_object: Some witnesses returned by the function, representing some data internal to the proving system. -This black box function does not fully verify a proof, what it does is verifying that the key_hash is indeed a hash of verification_key, allowing the user to use the verification key as private inputs and only have the key_hash as public input, which is more performant. -Another thing that it does is preparing the verification of the proof. In order to fully verify a proof, some operations may still be required to be done by the final verifier. This is why this black box function does not say if verification is passing or not. -If you have several proofs to verify in one ACIR program, you would call RecursiveAggregation() multiple times and passing the output_aggregation_object as input_aggregation_object to the next RecursiveAggregation() call, except for the first call where you do not have any input_aggregation_object. -If one of the proof you verify with the black box function does not verify, then the verification of the proof of the main ACIR program will ultimately fail. +This black box function does not fully verify a proof, what it does is verify +that the provided `key_hash` is indeed a hash of `verification_key`, allowing +the user to use the verification key as private inputs and only have the +`key_hash` as public input, which is more performant. +Another thing that it does is preparing the verification of the proof. In order +to fully verify a proof, some operations may still be required to be done by the +final verifier. This is why this black box function does not say if verification +is passing or not. -### Brillig -This opcode is used as a hint for the solver when executing (solving) the circuit. The opcode does not generate any constraint and is usually the result of the compilation of an unconstrained noir function. -- inputs: inputs to the opcode, as 'arithmetic expressions'. -- outputs: opcode outputs, as witnesses -- bytecode: assembly code representing the computation to perform within this opcode. The noir assembly specification is not part of this document. -- predicate: an arithmetic expression that disable the opcode when it is null. +If you have several proofs to verify in one ACIR program, you would call +`RecursiveAggregation()` multiple times while passing the +`output_aggregation_object` as `input_aggregation_object` to the next +`RecursiveAggregation()` call, except for the first call where you do not have +any `input_aggregation_object`. -Let's see an example with euclidean division. -The normal way to compute a/b, where a and b are 8-bits integers, is to implement Euclid algorithm which computes in a loop (or recursively) modulus of the kind 'a mod b'. Doing this computation requires a lot of steps to be properly implemented in ACIR, especially the loop with a condition. However, euclidean division can be easily constrained with one assert-zero opcode: a = bq+r, assuming q is 8 bits and r, }, - MemoryInit { - block_id: BlockId, - init: Vec, - }, + + /// Initialize an ACIR array from a vector of witnesses. + /// - block_id: identifier of the array + /// - init: Vector of witnesses specifying the initial value of the arrays + /// + /// There must be only one MemoryInit per block_id, and MemoryOp opcodes must + /// come after the MemoryInit. + MemoryInit { block_id: BlockId, init: Vec }, + /// Calls to unconstrained functions BrilligCall { /// Id for the function being called. It is the responsibility of the executor @@ -43,6 +105,7 @@ pub enum Opcode { /// Predicate of the Brillig execution - indicates if it should be skipped predicate: Option, }, + /// Calls to functions represented as a separate circuit. A call opcode allows us /// to build a call stack when executing the outer-most circuit. Call { diff --git a/acvm-repo/acir/src/circuit/opcodes/memory_operation.rs b/acvm-repo/acir/src/circuit/opcodes/memory_operation.rs index 0e94c0f051e..6f31fb1383c 100644 --- a/acvm-repo/acir/src/circuit/opcodes/memory_operation.rs +++ b/acvm-repo/acir/src/circuit/opcodes/memory_operation.rs @@ -8,9 +8,12 @@ pub struct BlockId(pub u32); /// We can either write or read at an index in memory #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub struct MemOp { - /// Can be 0 (read) or 1 (write) + /// A constant expression that can be 0 (read) or 1 (write) pub operation: Expression, + /// array index, it must be less than the array length pub index: Expression, + /// the value we are reading, when operation is 0, or the value we write at + /// the specified index, when operation is 1 pub value: Expression, } From 5c918a9d991af09b0d6813fc12ba14cf3f1ef02d Mon Sep 17 00:00:00 2001 From: Michael J Klein Date: Thu, 16 May 2024 20:54:16 -0400 Subject: [PATCH 02/12] Update acvm-repo/acir/src/circuit/opcodes.rs Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- acvm-repo/acir/src/circuit/opcodes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index b161db07a34..eb163b71013 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -87,7 +87,7 @@ pub enum Opcode { /// Initialize an ACIR array from a vector of witnesses. /// - block_id: identifier of the array - /// - init: Vector of witnesses specifying the initial value of the arrays + /// - init: Vector of witnesses specifying the initial value of the array /// /// There must be only one MemoryInit per block_id, and MemoryOp opcodes must /// come after the MemoryInit. From 0a8bf9b8be85baa2671e841731d50a128e106657 Mon Sep 17 00:00:00 2001 From: Tom French Date: Mon, 20 May 2024 17:05:47 +0100 Subject: [PATCH 03/12] chore: misc stuff --- .../acir/src/circuit/black_box_functions.rs | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/acvm-repo/acir/src/circuit/black_box_functions.rs b/acvm-repo/acir/src/circuit/black_box_functions.rs index dd67777be42..78053d78aea 100644 --- a/acvm-repo/acir/src/circuit/black_box_functions.rs +++ b/acvm-repo/acir/src/circuit/black_box_functions.rs @@ -13,13 +13,13 @@ use strum_macros::EnumIter; pub enum BlackBoxFunc { /// Ciphers (encrypts) the provided plaintext using AES128 in CBC mode, /// padding the input using PKCS#7. - /// - inputs: byte array [u8; N] - /// - iv: initialization vector [u8; 16] - /// - key: user key [u8; 16] - /// - outputs: byte vector [u8] of length `input.len() + (16 - input.len() % 16)`` + /// - inputs: byte array `[u8; N]` + /// - iv: initialization vector `[u8; 16]` + /// - key: user key `[u8; 16]` + /// - outputs: byte vector `[u8]` of length `input.len() + (16 - input.len() % 16)` AES128Encrypt, - /// Performs the bitwise AND of lhs and rhs. bit_size must be the same for + /// Performs the bitwise AND of `lhs` and `rhs`. `bit_size` must be the same for /// both inputs. /// - lhs: (witness, bit_size) /// - rhs: (witness, bit_size) @@ -27,7 +27,7 @@ pub enum BlackBoxFunc { /// bit_size bit integers AND, - /// Performs the bitwise XOR of lhs and rhs. bit_size must be the same for + /// Performs the bitwise XOR of `lhs` and `rhs`. `bit_size` must be the same for /// both inputs. /// - lhs: (witness, bit_size) /// - rhs: (witness, bit_size) @@ -35,28 +35,27 @@ pub enum BlackBoxFunc { /// bit_size bit integers XOR, - /// Range constraint to ensure that a - /// [`FieldElement`][acir_field::FieldElement] can be represented in the - /// specified number of bits. - /// input: (witness, bit_size) + /// Range constraint to ensure that a [`FieldElement`][acir_field::FieldElement] + /// can be represented in the specified number of bits. + /// - input: (witness, bit_size) RANGE, /// Computes SHA256 of the inputs /// - inputs are a byte array, i.e a vector of (FieldElement, 8) - /// - output is a byte array of len 32, i.e a vector of 32 (FieldElement, 8), + /// - output is a byte array of len 32, i.e an array of 32 (FieldElement, 8), /// constrained to be the sha256 of the inputs. SHA256, /// Computes the Blake2s hash of the inputs, as specified in /// https://tools.ietf.org/html/rfc7693 /// - inputs are a byte array, i.e a vector of (FieldElement, 8) - /// - output is a byte array of length 32, i.e a vector of 32 + /// - output is a byte array of length 32, i.e. an array of 32 /// (FieldElement, 8), constrained to be the blake2s of the inputs. Blake2s, /// Computes the Blake3 hash of the inputs /// - inputs are a byte array, i.e a vector of (FieldElement, 8) - /// - output is a byte array of length 32, i.e a vector of 32 + /// - output is a byte array of length 32, i.e an array of 32 /// (FieldElement, 8), constrained to be the blake3 of the inputs. Blake3, @@ -139,12 +138,12 @@ pub enum BlackBoxFunc { /// Multiple scalar multiplication with a variable base/input point (P) of the embedded curve /// - input: /// points (FieldElement, N) a vector of x and y coordinates of input - /// points [x1, y1, x2, y2,...]. + /// points `[x1, y1, x2, y2,...]`. /// scalars (FieldElement, N) a vector of low and high limbs of input - /// scalars [s1_low, s1_high, s2_low, s2_high, ...]. (FieldElement, N) + /// scalars `[s1_low, s1_high, s2_low, s2_high, ...]`. (FieldElement, N) /// For Barretenberg, they must both be less than 128 bits. /// - output: (FieldElement, N) a vector of x and y coordinates of output - /// points [op1_x, op1_y, op2_x, op2_y, ...]. Points computed as + /// points `[op1_x, op1_y, op2_x, op2_y, ...]``. Points computed as /// `s_low*P+s_high*2^{128}*P` /// /// Because the Grumpkin scalar field is bigger than the ACIR field, we @@ -154,7 +153,7 @@ pub enum BlackBoxFunc { /// Computes the Keccak-256 (Ethereum version) of the inputs. /// - inputs: Vector of bytes (FieldElement, 8) - /// - outputs: Vector of 32 bytes (FieldElement, 8) + /// - outputs: Array of 32 bytes (FieldElement, 8) Keccak256, /// Keccak Permutation function of width 1600 From 2e0a11f6380063cb28cf6f3eb8f477e4aa9d630d Mon Sep 17 00:00:00 2001 From: Michael J Klein Date: Tue, 21 May 2024 14:57:54 -0400 Subject: [PATCH 04/12] Update acvm-repo/acir/src/circuit/black_box_functions.rs Co-authored-by: Maxim Vezenov --- acvm-repo/acir/src/circuit/black_box_functions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acvm-repo/acir/src/circuit/black_box_functions.rs b/acvm-repo/acir/src/circuit/black_box_functions.rs index 78053d78aea..69dc7a979e4 100644 --- a/acvm-repo/acir/src/circuit/black_box_functions.rs +++ b/acvm-repo/acir/src/circuit/black_box_functions.rs @@ -85,7 +85,7 @@ pub enum BlackBoxFunc { /// Calculates a Pedersen commitment to the inputs. /// - /// Computes a Pedersen commitments of the inputs using generators of the + /// Computes a Pedersen commitment of the inputs using generators of the /// embedded curve /// - input: vector of (FieldElement, 254) /// - output: 2 witnesses representing the x,y coordinates of the resulting From 242875151563ec9c4cd36f157359cf8538c4e9a0 Mon Sep 17 00:00:00 2001 From: Michael J Klein Date: Tue, 21 May 2024 14:58:03 -0400 Subject: [PATCH 05/12] Update acvm-repo/acir/src/circuit/black_box_functions.rs Co-authored-by: Maxim Vezenov --- acvm-repo/acir/src/circuit/black_box_functions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acvm-repo/acir/src/circuit/black_box_functions.rs b/acvm-repo/acir/src/circuit/black_box_functions.rs index 69dc7a979e4..eb81cfcf5a0 100644 --- a/acvm-repo/acir/src/circuit/black_box_functions.rs +++ b/acvm-repo/acir/src/circuit/black_box_functions.rs @@ -103,7 +103,7 @@ pub enum BlackBoxFunc { /// Calculates a Pedersen hash to the inputs. /// - /// Computes a Pedersen commitments of the inputs and their number, using + /// Computes a Pedersen hash of the inputs and their number, using /// generators of the embedded curve /// - input: vector of (FieldElement, 254) /// - output: the x-coordinate of the pedersen commitment of the From a44b0d351ce04f265facfaedaa4c92e4443a14f6 Mon Sep 17 00:00:00 2001 From: Michael J Klein Date: Tue, 21 May 2024 14:58:23 -0400 Subject: [PATCH 06/12] Update acvm-repo/acir/src/circuit/black_box_functions.rs Co-authored-by: Maxim Vezenov --- acvm-repo/acir/src/circuit/black_box_functions.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/acvm-repo/acir/src/circuit/black_box_functions.rs b/acvm-repo/acir/src/circuit/black_box_functions.rs index eb81cfcf5a0..60b4c5b484c 100644 --- a/acvm-repo/acir/src/circuit/black_box_functions.rs +++ b/acvm-repo/acir/src/circuit/black_box_functions.rs @@ -157,7 +157,8 @@ pub enum BlackBoxFunc { Keccak256, /// Keccak Permutation function of width 1600 - /// - TODO: inputs/outputs?? + /// - inputs: An array of 25 64-bit Keccak lanes that represent a keccak sponge of 1600 bits + /// - outputs: The result of a keccak f1600 permutation on the input state. Also an array of 25 Keccak lanes. Keccakf1600, /// Compute a recursive aggregation object when verifying a proof inside From 209844f48f2fd7be74e7024fe5fe0ae69ff7a30f Mon Sep 17 00:00:00 2001 From: Michael J Klein Date: Tue, 21 May 2024 14:58:41 -0400 Subject: [PATCH 07/12] Update acvm-repo/acir/src/circuit/black_box_functions.rs Co-authored-by: Maxim Vezenov --- acvm-repo/acir/src/circuit/black_box_functions.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/acvm-repo/acir/src/circuit/black_box_functions.rs b/acvm-repo/acir/src/circuit/black_box_functions.rs index 60b4c5b484c..e678e762ccc 100644 --- a/acvm-repo/acir/src/circuit/black_box_functions.rs +++ b/acvm-repo/acir/src/circuit/black_box_functions.rs @@ -191,11 +191,6 @@ pub enum BlackBoxFunc { /// to be done by the final verifier. This is why this black box function /// does not say if verification is passing or not. /// - /// If you have several proofs to verify in one ACIR program, you would call - /// RecursiveAggregation() multiple times and passing the - /// output_aggregation_object as input_aggregation_object to the next - /// RecursiveAggregation() call, except for the first call where you do not - /// have any input_aggregation_object. /// /// If one of the proof you verify with the black box function does not /// verify, then the verification of the proof of the main ACIR program will From 537cc5b5154c7f1cd03a5ed25d5b6548b870d791 Mon Sep 17 00:00:00 2001 From: Michael J Klein Date: Tue, 21 May 2024 14:58:57 -0400 Subject: [PATCH 08/12] Update acvm-repo/acir/src/circuit/black_box_functions.rs Co-authored-by: Maxim Vezenov --- acvm-repo/acir/src/circuit/black_box_functions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acvm-repo/acir/src/circuit/black_box_functions.rs b/acvm-repo/acir/src/circuit/black_box_functions.rs index e678e762ccc..f3d57daaf36 100644 --- a/acvm-repo/acir/src/circuit/black_box_functions.rs +++ b/acvm-repo/acir/src/circuit/black_box_functions.rs @@ -192,7 +192,7 @@ pub enum BlackBoxFunc { /// does not say if verification is passing or not. /// /// - /// If one of the proof you verify with the black box function does not + /// If one of the recursive proofs you verify with the black box function does not /// verify, then the verification of the proof of the main ACIR program will /// ultimately fail. RecursiveAggregation, From 671ce805b816d65cc98cf2967cfc45fc0fef04f8 Mon Sep 17 00:00:00 2001 From: Michael J Klein Date: Wed, 29 May 2024 16:26:57 -0400 Subject: [PATCH 09/12] Update acvm-repo/acir/src/circuit/black_box_functions.rs Co-authored-by: Maxim Vezenov --- acvm-repo/acir/src/circuit/black_box_functions.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/acvm-repo/acir/src/circuit/black_box_functions.rs b/acvm-repo/acir/src/circuit/black_box_functions.rs index f3d57daaf36..147dfd6aa40 100644 --- a/acvm-repo/acir/src/circuit/black_box_functions.rs +++ b/acvm-repo/acir/src/circuit/black_box_functions.rs @@ -176,10 +176,6 @@ pub enum BlackBoxFunc { /// - key_hash: one (FieldElement, 254). It should be the hash of the /// verification key. Barretenberg expects the Pedersen hash of the /// verification key - /// - input_aggregation_object: an optional vector of (FieldElement, 254). - /// It is a blob of data specific to the proving system. - /// - output_aggregation_object: Some witnesses returned by the function, - /// representing some data internal to the proving system. /// /// This black box function does not fully verify a proof, what it does is /// verifying that the key_hash is indeed a hash of verification_key, From 478f3787bb018686f118edb987489bc8ee5f62bb Mon Sep 17 00:00:00 2001 From: Michael J Klein Date: Fri, 31 May 2024 13:31:05 -0400 Subject: [PATCH 10/12] Update acvm-repo/acir/src/circuit/opcodes.rs Co-authored-by: Maxim Vezenov --- acvm-repo/acir/src/circuit/opcodes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index eb163b71013..1272acaa691 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -71,7 +71,7 @@ pub enum Opcode { /// ACIR is able to address any array of witnesses. Each array is assigned /// an id (BlockId) and needs to be initialized with the MemoryInit opcode. /// Then it is possible to read and write from/to an array by providing the - /// index and the value we read/write, as arithmetic expression. Note that + /// index and the value we read/write as arithmetic expressions. Note that /// ACIR arrays all have a known fixed length (given in the MemoryInit /// opcode below) /// From 2da11bf0e1b11cadee36ccd5f65a278a5fd7b5f2 Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Mon, 3 Jun 2024 12:05:42 +0100 Subject: [PATCH 11/12] renamed FieldElement to witness when it could be more generic than a FieldElement, other responses to review comments / cleanup, cargo fmt --- .../acir/src/circuit/black_box_functions.rs | 77 ++++++++++--------- acvm-repo/acir/src/circuit/opcodes.rs | 18 ++--- .../src/circuit/opcodes/memory_operation.rs | 2 +- 3 files changed, 48 insertions(+), 49 deletions(-) diff --git a/acvm-repo/acir/src/circuit/black_box_functions.rs b/acvm-repo/acir/src/circuit/black_box_functions.rs index 147dfd6aa40..419c0266b69 100644 --- a/acvm-repo/acir/src/circuit/black_box_functions.rs +++ b/acvm-repo/acir/src/circuit/black_box_functions.rs @@ -35,35 +35,35 @@ pub enum BlackBoxFunc { /// bit_size bit integers XOR, - /// Range constraint to ensure that a [`FieldElement`][acir_field::FieldElement] + /// Range constraint to ensure that a witness /// can be represented in the specified number of bits. /// - input: (witness, bit_size) RANGE, /// Computes SHA256 of the inputs - /// - inputs are a byte array, i.e a vector of (FieldElement, 8) - /// - output is a byte array of len 32, i.e an array of 32 (FieldElement, 8), + /// - inputs are a byte array, i.e a vector of (witness, 8) + /// - output is a byte array of len 32, i.e an array of 32 (witness, 8), /// constrained to be the sha256 of the inputs. SHA256, /// Computes the Blake2s hash of the inputs, as specified in /// https://tools.ietf.org/html/rfc7693 - /// - inputs are a byte array, i.e a vector of (FieldElement, 8) + /// - inputs are a byte array, i.e a vector of (witness, 8) /// - output is a byte array of length 32, i.e. an array of 32 - /// (FieldElement, 8), constrained to be the blake2s of the inputs. + /// (witness, 8), constrained to be the blake2s of the inputs. Blake2s, /// Computes the Blake3 hash of the inputs - /// - inputs are a byte array, i.e a vector of (FieldElement, 8) + /// - inputs are a byte array, i.e a vector of (witness, 8) /// - output is a byte array of length 32, i.e an array of 32 - /// (FieldElement, 8), constrained to be the blake3 of the inputs. + /// (witness, 8), constrained to be the blake3 of the inputs. Blake3, /// Verify a Schnorr signature over the embedded curve /// - inputs are: - /// - Public key as 2 (FieldElement, 254) - /// - signature as a vector of 64 bytes (FieldElement, 8) - /// - message as a vector of (FieldElement, 8) + /// - Public key as 2 (witness, 254) + /// - signature as a vector of 64 bytes (witness, 8) + /// - message as a vector of (witness, 8) /// - output: A witness representing the result of the signature /// verification; 0 for failure and 1 for success. /// @@ -87,7 +87,7 @@ pub enum BlackBoxFunc { /// /// Computes a Pedersen commitment of the inputs using generators of the /// embedded curve - /// - input: vector of (FieldElement, 254) + /// - input: vector of (witness, 254) /// - output: 2 witnesses representing the x,y coordinates of the resulting /// Grumpkin point /// - domain separator: a constant public value (a field element) that you @@ -99,13 +99,15 @@ pub enum BlackBoxFunc { /// Aztec's Barretenberg, the latter is bigger than the ACIR field so it is /// straightforward. The Pedersen generators are managed by the proving /// system. + /// + /// The commitment is expected to be additively homomorphic PedersenCommitment, /// Calculates a Pedersen hash to the inputs. /// /// Computes a Pedersen hash of the inputs and their number, using /// generators of the embedded curve - /// - input: vector of (FieldElement, 254) + /// - input: vector of (witness, 254) /// - output: the x-coordinate of the pedersen commitment of the /// 'prepended input' (see below) /// - domain separator: a constant public value (a field element) that you @@ -113,7 +115,8 @@ pub enum BlackBoxFunc { /// uses 0 as domain separator. /// /// In Barretenberg, PedersenHash is doing the same as PedersenCommitment, - /// except that it prepends the inputs with their length. + /// except that it prepends the inputs with their length. This is expected + /// to not be additively homomorphic. PedersenHash, /// Verifies a ECDSA signature over the secp256k1 curve. @@ -135,16 +138,18 @@ pub enum BlackBoxFunc { /// Same as EcdsaSecp256k1, but done over another curve. EcdsaSecp256r1, - /// Multiple scalar multiplication with a variable base/input point (P) of the embedded curve + /// Multiple scalar multiplication (MSM) with a variable base/input point + /// (P) of the embedded curve. An MSM multiplies the points and scalars and + /// sums the results. /// - input: - /// points (FieldElement, N) a vector of x and y coordinates of input + /// points (witness, N) a vector of x and y coordinates of input /// points `[x1, y1, x2, y2,...]`. - /// scalars (FieldElement, N) a vector of low and high limbs of input - /// scalars `[s1_low, s1_high, s2_low, s2_high, ...]`. (FieldElement, N) + /// scalars (witness, N) a vector of low and high limbs of input + /// scalars `[s1_low, s1_high, s2_low, s2_high, ...]`. (witness, N) /// For Barretenberg, they must both be less than 128 bits. - /// - output: (FieldElement, N) a vector of x and y coordinates of output - /// points `[op1_x, op1_y, op2_x, op2_y, ...]``. Points computed as - /// `s_low*P+s_high*2^{128}*P` + /// - output: + /// a tuple of `x` and `y` coordinates of output. + /// Points computed as `s_low*P+s_high*2^{128}*P` /// /// Because the Grumpkin scalar field is bigger than the ACIR field, we /// provide 2 ACIR fields representing the low and high parts of the Grumpkin @@ -152,8 +157,8 @@ pub enum BlackBoxFunc { MultiScalarMul, /// Computes the Keccak-256 (Ethereum version) of the inputs. - /// - inputs: Vector of bytes (FieldElement, 8) - /// - outputs: Array of 32 bytes (FieldElement, 8) + /// - inputs: Vector of bytes (witness, 8) + /// - outputs: Array of 32 bytes (witness, 8) Keccak256, /// Keccak Permutation function of width 1600 @@ -167,34 +172,32 @@ pub enum BlackBoxFunc { /// top-level verifier or aggregated upon again. /// /// **Warning: this opcode is subject to change.** - /// Note that the `254` in `(FieldElement, 254)` refers to the upper bound of - /// the `FieldElement`. - /// - verification_key: Vector of (FieldElement, 254) representing the + /// Note that the `254` in `(witness, 254)` refers to the upper bound of + /// the `witness`. + /// - verification_key: Vector of (witness, 254) representing the /// verification key of the circuit being verified - /// - public_inputs: Vector of (FieldElement, 254) representing the public + /// - public_inputs: Vector of (witness, 254) representing the public /// inputs corresponding to the proof being verified - /// - key_hash: one (FieldElement, 254). It should be the hash of the + /// - key_hash: one (witness, 254). It should be the hash of the /// verification key. Barretenberg expects the Pedersen hash of the /// verification key /// - /// This black box function does not fully verify a proof, what it does is - /// verifying that the key_hash is indeed a hash of verification_key, - /// allowing the user to use the verification key as private inputs and only - /// have the key_hash as public input, which is more performant. - /// /// Another thing that it does is preparing the verification of the proof. /// In order to fully verify a proof, some operations may still be required /// to be done by the final verifier. This is why this black box function /// does not say if verification is passing or not. /// + /// This black box function does not fully verify a proof, what it does is + /// verifying that the key_hash is indeed a hash of verification_key, + /// allowing the user to use the verification key as private inputs and only + /// have the key_hash as public input, which is more performant. /// /// If one of the recursive proofs you verify with the black box function does not /// verify, then the verification of the proof of the main ACIR program will /// ultimately fail. RecursiveAggregation, - /// Addition over the embedded curve on which - /// [`FieldElement`][acir_field::FieldElement] is defined. + /// Addition over the embedded curve on which the witness is defined. EmbeddedCurveAdd, /// BigInt addition @@ -219,9 +222,9 @@ pub enum BlackBoxFunc { Poseidon2Permutation, /// SHA256 compression function - /// - input: [(FieldElement, 32); 16] - /// - state: [(FieldElement, 32); 8] - /// - output: [(FieldElement, 32); 8] + /// - input: [(witness, 32); 16] + /// - state: [(witness, 32); 8] + /// - output: [(witness, 32); 8] Sha256Compression, } diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index d938baaaa67..984422c5e3a 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -63,8 +63,7 @@ pub enum Opcode { /// Some more advanced computations assume that the proving system has an /// 'embedded curve'. It is a curve that cycles with the main curve of the /// proving system, i.e the scalar field of the embedded curve is the base - /// field of the main one, and vice-versa. The curves used by the proving - /// system are dependent on the proving system (and/or its configuration). + /// field of the main one, and vice-versa. /// /// Aztec's Barretenberg uses BN254 as the main curve and Grumpkin as the /// embedded curve. @@ -79,7 +78,7 @@ pub enum Opcode { /// /// Directives will be replaced by Brillig opcodes in the future. Directive(Directive), - + /// Atomic operation on a block of memory /// /// ACIR is able to address any array of witnesses. Each array is assigned @@ -89,7 +88,8 @@ pub enum Opcode { /// ACIR arrays all have a known fixed length (given in the MemoryInit /// opcode below) /// - /// - predicate: an arithmetic expression that disable the opcode when it is null. + /// - predicate: an arithmetic expression that disables the execution of the + /// opcode when the expression evaluates to zero MemoryOp { /// identifier of the array block_id: BlockId, @@ -98,19 +98,15 @@ pub enum Opcode { /// Predicate of the memory operation - indicates if it should be skipped predicate: Option>, }, - + /// Initialize an ACIR array from a vector of witnesses. /// - block_id: identifier of the array /// - init: Vector of witnesses specifying the initial value of the array /// /// There must be only one MemoryInit per block_id, and MemoryOp opcodes must /// come after the MemoryInit. - MemoryInit { - block_id: BlockId, - init: Vec, - block_type: BlockType, - }, - + MemoryInit { block_id: BlockId, init: Vec, block_type: BlockType }, + /// Calls to unconstrained functions BrilligCall { /// Id for the function being called. It is the responsibility of the executor diff --git a/acvm-repo/acir/src/circuit/opcodes/memory_operation.rs b/acvm-repo/acir/src/circuit/opcodes/memory_operation.rs index 0678bef53e6..90e3ee0563a 100644 --- a/acvm-repo/acir/src/circuit/opcodes/memory_operation.rs +++ b/acvm-repo/acir/src/circuit/opcodes/memory_operation.rs @@ -29,4 +29,4 @@ impl MemOp { pub fn write_to_mem_index(index: Expression, value: Expression) -> Self { MemOp { operation: Expression::one(), index, value } } -} \ No newline at end of file +} From 8009721b056e56f933df44e9a3dbf0eb15227c34 Mon Sep 17 00:00:00 2001 From: "Michael J. Klein" Date: Mon, 3 Jun 2024 17:59:48 +0100 Subject: [PATCH 12/12] add 'homomorphic' to cspell --- cspell.json | 1 + 1 file changed, 1 insertion(+) diff --git a/cspell.json b/cspell.json index 4497d0bf9da..88cf6e4d4f0 100644 --- a/cspell.json +++ b/cspell.json @@ -97,6 +97,7 @@ "hexdigit", "higher-kinded", "Hindley-Milner", + "homomorphic", "idents", "ilog", "impls",