From 4c560b66989ef6e73762bf4e14b463cdc61ae3f3 Mon Sep 17 00:00:00 2001 From: Tom French Date: Fri, 3 Feb 2023 20:03:16 +0000 Subject: [PATCH 1/3] feat(ci): add CSpell --- .github/workflows/rust.yml | 11 +++++++++++ cspell.json | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 cspell.json diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index d1ea0251b..d70c4cf68 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -22,3 +22,14 @@ jobs: run: cargo clippy --verbose - name: Run tests run: cargo test --verbose + + spellcheck: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: streetsidesoftware/cspell-action@v2 + with: + files: | + **/*.{md,rs} + incremental_files_only : false # Run this action on files which have changed in PR + strict: false # Do not fail, if a spelling mistake is found (This can be annoying for contributors) diff --git a/cspell.json b/cspell.json new file mode 100644 index 000000000..152e653aa --- /dev/null +++ b/cspell.json @@ -0,0 +1,35 @@ +{ + "version": "0.2", + "words": [ + "blackbox", + "decomp", + "finalise", + "generalises", + "optimise", + "optimisation", + "optimisations", + "optimised", + "optimiser", + "arithmetisation", + // In code + // + "acir", + "ACIR", + "ACVM", + "coeff", + "consts", + "hasher", + "OddRange", + "PLONKC", + "prehashed", + "pubkey", + "secp", + "Shleft", + "Shright", + "stdlib", + "typenum" + // Dependencies + // + "thiserror" + ] +} From ccb92c3e19397c5b782b680035431b24a23c5713 Mon Sep 17 00:00:00 2001 From: Tom French Date: Fri, 3 Feb 2023 20:16:18 +0000 Subject: [PATCH 2/3] chore: fix up spellings --- CHANGELOG.md | 2 +- README.md | 4 +- acir/src/circuit/directives.rs | 4 +- acir/src/circuit/mod.rs | 10 +-- acir/src/circuit/opcodes.rs | 6 +- acir/src/lib.rs | 2 +- acir/src/native_types/arithmetic.rs | 8 +- acir/src/native_types/witness.rs | 2 +- .../{serialisation.rs => serialization.rs} | 2 +- acir_field/src/generic_ark.rs | 6 +- acvm/src/compiler.rs | 36 ++++---- acvm/src/compiler/optimiser/mod.rs | 7 -- .../csat_optimizer.rs} | 84 +++++++++---------- .../general_optimizer.rs} | 6 +- acvm/src/compiler/optimizer/mod.rs | 7 ++ .../r1cs_optimizer.rs} | 18 ++-- .../range_optimizer.rs} | 16 ++-- acvm/src/lib.rs | 2 +- acvm/src/pwg/arithmetic.rs | 2 +- cspell.json | 31 ++++--- stdlib/src/fallback.rs | 4 +- stdlib/src/helpers.rs | 2 +- 22 files changed, 135 insertions(+), 126 deletions(-) rename acir/src/{serialisation.rs => serialization.rs} (95%) delete mode 100644 acvm/src/compiler/optimiser/mod.rs rename acvm/src/compiler/{optimiser/csat_optimiser.rs => optimizer/csat_optimizer.rs} (88%) rename acvm/src/compiler/{optimiser/general_optimiser.rs => optimizer/general_optimizer.rs} (87%) create mode 100644 acvm/src/compiler/optimizer/mod.rs rename acvm/src/compiler/{optimiser/r1cs_optimiser.rs => optimizer/r1cs_optimizer.rs} (70%) rename acvm/src/compiler/{optimiser/range_optimiser.rs => optimizer/range_optimizer.rs} (54%) diff --git a/CHANGELOG.md b/CHANGELOG.md index e64cad60c..c6b4f98fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,7 +42,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - XOR, Range and AND gates are no longer special case. They are now another opcode in the GadgetCall - Move fallback module to `stdlib` -- optimiser code and any other passes will live in acvm. acir is solely for defining the IR now. +- Optimizer code and any other passes will live in acvm. acir is solely for defining the IR now. - ACIR passes now live under the compiler parent module - Moved opcode module in acir crate to circuit/opcode - Rename GadgetCall to BlackBoxFuncCall diff --git a/README.md b/README.md index 7b38a27a0..49154bdc3 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # ACIR - Abstract Circuit Intermediate Representation -ACIR is an NP complete language that generalises R1CS and arithmetic circuits while not losing proving system specific optimisations through the use of black box functions. +ACIR is an NP complete language that generalizes R1CS and arithmetic circuits while not losing proving system specific optimizations through the use of black box functions. # ACVM - Abstract Circuit Virtual Machine This can be seen as the ACIR compiler. It will take an ACIR instance and convert it to the format required -by a particular proving system to create a proof. \ No newline at end of file +by a particular proving system to create a proof. diff --git a/acir/src/circuit/directives.rs b/acir/src/circuit/directives.rs index c3d8e2cd0..019179804 100644 --- a/acir/src/circuit/directives.rs +++ b/acir/src/circuit/directives.rs @@ -2,7 +2,7 @@ use std::io::{Read, Write}; use crate::{ native_types::{Expression, Witness}, - serialisation::{read_n, read_u16, read_u32, write_bytes, write_u16, write_u32}, + serialization::{read_n, read_u16, read_u32, write_bytes, write_u16, write_u32}, }; use serde::{Deserialize, Serialize}; @@ -185,7 +185,7 @@ impl Directive { } #[test] -fn serialisation_roundtrip() { +fn serialization_roundtrip() { fn read_write(directive: Directive) -> (Directive, Directive) { let mut bytes = Vec::new(); directive.write(&mut bytes).unwrap(); diff --git a/acir/src/circuit/mod.rs b/acir/src/circuit/mod.rs index 5d7c8260e..fa72763d6 100644 --- a/acir/src/circuit/mod.rs +++ b/acir/src/circuit/mod.rs @@ -4,7 +4,7 @@ pub mod opcodes; pub use opcodes::Opcode; use crate::native_types::Witness; -use crate::serialisation::{read_u32, write_u32}; +use crate::serialization::{read_u32, write_u32}; use rmp_serde; use serde::{Deserialize, Serialize}; @@ -27,7 +27,7 @@ impl Circuit { } #[deprecated( - note = "we want to use a serialisation strategy that is easy to implement in many languages (without ffi). use `read` instead" + note = "we want to use a serialization strategy that is easy to implement in many languages (without ffi). use `read` instead" )] pub fn from_bytes(bytes: &[u8]) -> Circuit { let mut deflater = DeflateDecoder::new(bytes); @@ -37,7 +37,7 @@ impl Circuit { } #[deprecated( - note = "we want to use a serialisation strategy that is easy to implement in many languages (without ffi).use `write` instead" + note = "we want to use a serialization strategy that is easy to implement in many languages (without ffi).use `write` instead" )] pub fn to_bytes(&self) -> Vec { let buf = rmp_serde::to_vec(&self).unwrap(); @@ -69,7 +69,7 @@ impl Circuit { // TODO (Note): we could use semver versioning from the Cargo.toml // here and then reject anything that has a major bump // - // We may also not want to do that if we do not want to couple serialisation + // We may also not want to do that if we do not want to couple serialization // with other breaking changes if version_number != VERSION_NUMBER { return Err(std::io::ErrorKind::InvalidData.into()); @@ -178,7 +178,7 @@ mod test { } #[test] - fn serialisation_roundtrip() { + fn serialization_roundtrip() { let circuit = Circuit { current_witness_index: 5, opcodes: vec![and_opcode(), range_opcode()], diff --git a/acir/src/circuit/opcodes.rs b/acir/src/circuit/opcodes.rs index 37017adde..b4e279ffa 100644 --- a/acir/src/circuit/opcodes.rs +++ b/acir/src/circuit/opcodes.rs @@ -2,7 +2,7 @@ use std::io::{Read, Write}; use super::directives::Directive; use crate::native_types::{Expression, Witness}; -use crate::serialisation::{read_n, read_u16, read_u32, write_bytes, write_u16, write_u32}; +use crate::serialization::{read_n, read_u16, read_u32, write_bytes, write_u16, write_u32}; use crate::BlackBoxFunc; use serde::{Deserialize, Serialize}; @@ -25,7 +25,7 @@ impl Opcode { } // We have three types of opcodes allowed in the IR // Expression, BlackBoxFuncCall and Directives - // When we serialise these opcodes, we use the index + // When we serialize these opcodes, we use the index // to uniquely identify which category of opcode we are dealing with. pub(crate) fn to_index(&self) -> u8 { match self { @@ -326,7 +326,7 @@ impl std::fmt::Debug for BlackBoxFuncCall { } #[test] -fn serialisation_roundtrip() { +fn serialization_roundtrip() { fn read_write(opcode: Opcode) -> (Opcode, Opcode) { let mut bytes = Vec::new(); opcode.write(&mut bytes).unwrap(); diff --git a/acir/src/lib.rs b/acir/src/lib.rs index ff1f4a951..7738b9210 100644 --- a/acir/src/lib.rs +++ b/acir/src/lib.rs @@ -2,7 +2,7 @@ pub mod circuit; pub mod native_types; -mod serialisation; +mod serialization; pub use acir_field::FieldElement; pub use circuit::blackbox_functions::BlackBoxFunc; diff --git a/acir/src/native_types/arithmetic.rs b/acir/src/native_types/arithmetic.rs index 56621919a..342a70819 100644 --- a/acir/src/native_types/arithmetic.rs +++ b/acir/src/native_types/arithmetic.rs @@ -1,5 +1,5 @@ use crate::native_types::{Linear, Witness}; -use crate::serialisation::{read_field_element, read_u32, write_bytes, write_u32}; +use crate::serialization::{read_field_element, read_u32, write_bytes, write_u32}; use acir_field::FieldElement; use serde::{Deserialize, Serialize}; use std::cmp::Ordering; @@ -17,7 +17,7 @@ use super::witness::UnknownWitness; // XXX: If we allow the degree of the quotient polynomial to be arbitrary, then we will need a vector of wire values #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct Expression { - // To avoid having to create intermediate variables pre-optimisation + // To avoid having to create intermediate variables pre-optimization // We collect all of the multiplication terms in the arithmetic gate // A multiplication term if of the form q_M * wL * wR // Hence this vector represents the following sum: q_M1 * wL1 * wR1 + q_M2 * wL2 * wR2 + .. + @@ -448,7 +448,7 @@ impl Expression { // A polynomial whose mul terms are non zero which do not match up with two terms in the fan-in cannot fit into one gate // An example of this is: Axy + Bx + Cy + ... // Notice how the bivariate monomial xy has two univariate monomials with their respective coefficients - // XXX: note that if x or y is zero, then we could apply a further optimisation, but this would be done in another algorithm. + // XXX: note that if x or y is zero, then we could apply a further optimization, but this would be done in another algorithm. // It would be the same as when we have zero coefficients - Can only work if wire is constrained to be zero publicly let mul_term = &self.mul_terms[0]; @@ -478,7 +478,7 @@ impl Expression { } #[test] -fn serialisation_roundtrip() { +fn serialization_roundtrip() { // Empty expression // let expr = Expression::default(); diff --git a/acir/src/native_types/witness.rs b/acir/src/native_types/witness.rs index 8bcc62a72..d7753ec7c 100644 --- a/acir/src/native_types/witness.rs +++ b/acir/src/native_types/witness.rs @@ -55,7 +55,7 @@ impl Witness { // We use this, so that they are pushed to the beginning of the array // // When they are pushed to the beginning of the array, they are less likely to be used in an intermediate gate -// by the optimiser, which would mean two unknowns in an equation. +// by the optimizer, which would mean two unknowns in an equation. // See Issue #20 // TODO: can we find a better solution to this? pub struct UnknownWitness(pub u32); diff --git a/acir/src/serialisation.rs b/acir/src/serialization.rs similarity index 95% rename from acir/src/serialisation.rs rename to acir/src/serialization.rs index 838e01667..1fe719936 100644 --- a/acir/src/serialisation.rs +++ b/acir/src/serialization.rs @@ -43,7 +43,7 @@ pub fn read_field_element( let bytes = read_n::(&mut r)?; - // TODO: We should not reduce here, we want the serialisation to be + // TODO: We should not reduce here, we want the serialization to be // TODO canonical let field_element = FieldElement::from_be_bytes_reduce(&bytes); diff --git a/acir_field/src/generic_ark.rs b/acir_field/src/generic_ark.rs index fb3722ea7..76518d3ca 100644 --- a/acir_field/src/generic_ark.rs +++ b/acir_field/src/generic_ark.rs @@ -51,7 +51,7 @@ impl std::fmt::Display for FieldElement { // we usually have numbers in the form 2^t * q + r // We focus on 2^64, 2^32, 2^16, 2^8, 2^4 because // they are common. We could extend this to a more - // general factorisation strategy, but we pay in terms of CPU time + // general factorization strategy, but we pay in terms of CPU time let mul_sign = "×"; for power in [64, 32, 16, 8, 4] { let power_of_two = BigUint::from(2_u128).pow(power); @@ -226,7 +226,7 @@ impl FieldElement { } /// Computes the inverse or returns zero if the inverse does not exist - /// Before using this FieldElement, please ensure that this behaviour is necessary + /// Before using this FieldElement, please ensure that this behavior is necessary pub fn inverse(&self) -> FieldElement { let inv = self.0.inverse().unwrap_or_else(F::zero); FieldElement(inv) @@ -297,7 +297,7 @@ impl FieldElement { let num_elements = num_bytes / 8; let mut bytes = self.to_be_bytes(); - bytes.reverse(); // put it in big endian format. XXX(next refactor): we should be explicit about endianess. + bytes.reverse(); // put it in big endian format. XXX(next refactor): we should be explicit about endianness. bytes[0..num_elements].to_vec() } diff --git a/acvm/src/compiler.rs b/acvm/src/compiler.rs index 15df5f1ed..e4e389ce7 100644 --- a/acvm/src/compiler.rs +++ b/acvm/src/compiler.rs @@ -1,6 +1,6 @@ // The various passes that we can use over ACIR pub mod fallback; -pub mod optimiser; +pub mod optimizer; use crate::Language; use acir::{ @@ -9,10 +9,10 @@ use acir::{ BlackBoxFunc, }; use indexmap::IndexMap; -use optimiser::{CSatOptimiser, GeneralOptimiser}; +use optimizer::{CSatOptimizer, GeneralOptimizer}; use thiserror::Error; -use self::{fallback::IsBlackBoxSupported, optimiser::R1CSOptimiser}; +use self::{fallback::IsBlackBoxSupported, optimizer::R1CSOptimizer}; #[derive(PartialEq, Eq, Debug, Error)] pub enum CompileError { @@ -25,28 +25,28 @@ pub fn compile( np_language: Language, is_blackbox_supported: IsBlackBoxSupported, ) -> Result { - // Instantiate the optimiser. - // Currently the optimiser and reducer are one in the same + // Instantiate the optimizer. + // Currently the optimizer and reducer are one in the same // for CSAT // Fallback pass let fallback = fallback::fallback(acir, is_blackbox_supported)?; - let optimiser = match &np_language { + let optimizer = match &np_language { crate::Language::R1CS => { - let optimiser = R1CSOptimiser::new(fallback); - return Ok(optimiser.optimise()); + let optimizer = R1CSOptimizer::new(fallback); + return Ok(optimizer.optimize()); } - crate::Language::PLONKCSat { width } => CSatOptimiser::new(*width), + crate::Language::PLONKCSat { width } => CSatOptimizer::new(*width), }; - // TODO: the code below is only for CSAT optimiser + // TODO: the code below is only for CSAT optimizer // TODO it may be possible to refactor it in a way that we do not need to return early from the r1cs - // TODO or at the very least, we could put all of it inside of CSATOptimiser pass + // TODO or at the very least, we could put all of it inside of CSatOptimizer pass - // Optimise the arithmetic gates by reducing them into the correct width and + // Optimize the arithmetic gates by reducing them into the correct width and // creating intermediate variables when necessary - let mut optimised_gates = Vec::new(); + let mut optimized_gates = Vec::new(); let mut next_witness_index = fallback.current_witness_index + 1; for opcode in fallback.opcodes { @@ -55,7 +55,7 @@ pub fn compile( let mut intermediate_variables: IndexMap = IndexMap::new(); let arith_expr = - optimiser.optimise(arith_expr, &mut intermediate_variables, next_witness_index); + optimizer.optimize(arith_expr, &mut intermediate_variables, next_witness_index); // Update next_witness counter next_witness_index += intermediate_variables.len() as u32; @@ -67,10 +67,10 @@ pub fn compile( new_gates.push(arith_expr); new_gates.sort(); for gate in new_gates { - optimised_gates.push(Opcode::Arithmetic(gate)); + optimized_gates.push(Opcode::Arithmetic(gate)); } } - other_gate => optimised_gates.push(other_gate), + other_gate => optimized_gates.push(other_gate), } } @@ -78,7 +78,7 @@ pub fn compile( Ok(Circuit { current_witness_index, - opcodes: optimised_gates, - public_inputs: fallback.public_inputs, // The optimiser does not add public inputs + opcodes: optimized_gates, + public_inputs: fallback.public_inputs, // The optimizer does not add public inputs }) } diff --git a/acvm/src/compiler/optimiser/mod.rs b/acvm/src/compiler/optimiser/mod.rs deleted file mode 100644 index 02b03c0bc..000000000 --- a/acvm/src/compiler/optimiser/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod csat_optimiser; -mod general_optimiser; -mod r1cs_optimiser; - -pub use csat_optimiser::Optimiser as CSatOptimiser; -pub use general_optimiser::GeneralOpt as GeneralOptimiser; -pub use r1cs_optimiser::R1CSOptimiser; diff --git a/acvm/src/compiler/optimiser/csat_optimiser.rs b/acvm/src/compiler/optimizer/csat_optimizer.rs similarity index 88% rename from acvm/src/compiler/optimiser/csat_optimiser.rs rename to acvm/src/compiler/optimizer/csat_optimizer.rs index 94126b89f..454bcde42 100644 --- a/acvm/src/compiler/optimiser/csat_optimiser.rs +++ b/acvm/src/compiler/optimizer/csat_optimizer.rs @@ -6,53 +6,53 @@ use acir::{ }; use indexmap::IndexMap; -use super::general_optimiser::GeneralOpt; -// Optimiser struct with all of the related optimisations to the arithmetic gate +use super::general_optimizer::GeneralOpt; +// Optimizer struct with all of the related optimizations to the arithmetic gate -// Is this more of a Reducer than an optimiser? +// Is this more of a Reducer than an optimizer? // Should we give it all of the gates? -// Have a single optimiser that you instantiate with a width, then pass many gates through -pub struct Optimiser { +// Have a single optimizer that you instantiate with a width, then pass many gates through +pub struct Optimizer { width: usize, } -impl Optimiser { - // Configure the width for the optimiser - pub fn new(width: usize) -> Optimiser { +impl Optimizer { + // Configure the width for the Optimizer + pub fn new(width: usize) -> Optimizer { assert!(width > 2); - Optimiser { width } + Optimizer { width } } - // Still missing dead witness optimisation. + // Still missing dead witness optimization. // To do this, we will need the whole set of arithmetic gates - // I think it can also be done before the local optimisation seen here, as dead variables will come from the user - pub fn optimise( + // I think it can also be done before the local optimization seen here, as dead variables will come from the user + pub fn optimize( &self, gate: Expression, intermediate_variables: &mut IndexMap, num_witness: u32, ) -> Expression { - let gate = GeneralOpt::optimise(gate); + let gate = GeneralOpt::optimize(gate); // Here we create intermediate variables and constrain them to be equal to any subset of the polynomial that can be represented as a full gate - let gate = self.full_gate_scan_optimisation(gate, intermediate_variables, num_witness); - // The last optimisation to do is to create intermediate variables in order to flatten the fan-in and the amount of mul terms + let gate = self.full_gate_scan_optimization(gate, intermediate_variables, num_witness); + // The last optimization to do is to create intermediate variables in order to flatten the fan-in and the amount of mul terms // If a gate has more than one mul term. We may need an intermediate variable for each one. Since not every variable will need to link to // the mul term, we could possibly do it that way. - // We wil call this a partial gate scan optimisation which will result in the gates being able to fit into the correct width + // We wil call this a partial gate scan optimization which will result in the gates being able to fit into the correct width let mut gate = - self.partial_gate_scan_optimisation(gate, intermediate_variables, num_witness); + self.partial_gate_scan_optimization(gate, intermediate_variables, num_witness); gate.sort(); gate } - // This optimisation will search for combinations of terms which can be represented in a single arithmetic gate + // This optimization will search for combinations of terms which can be represented in a single arithmetic gate // Case 1 : qM * wL * wR + qL * wL + qR * wR + qO * wO + qC - // This polynomial does not require any further optimisations, it can be safely represented in one gate + // This polynomial does not require any further optimizations, it can be safely represented in one gate // ie a polynomial with 1 mul(bi-variate) term and 3 (univariate) terms where 2 of those terms match the bivariate term // wL and wR, we can represent it in one gate - // GENERALISED for WIDTH: instead of the number 3, we use `WIDTH` + // GENERALIZED for WIDTH: instead of the number 3, we use `WIDTH` // // // Case 2: qM * wL * wR + qL * wL + qR * wR + qO * wO + qC + qM2 * wL2 * wR2 + qL * wL2 + qR * wR2 + qO * wO2 + qC2 @@ -70,7 +70,7 @@ impl Optimiser { // The polynomial now looks like so t + t2 // We can no longer extract another full gate, hence the algorithm terminates. Creating two intermediate variables t and t2. // This stage of preprocessing does not guarantee that all polynomials can fit into a gate. It only guarantees that all full gates have been extracted from each polynomial - fn full_gate_scan_optimisation( + fn full_gate_scan_optimization( &self, mut gate: Expression, intermediate_variables: &mut IndexMap, @@ -79,11 +79,11 @@ impl Optimiser { // We pass around this intermediate variable IndexMap, so that we do not create intermediate variables that we have created before // One instance where this might happen is t1 = wL * wR and t2 = wR * wL - // First check that this is not a simple gate which does not need optimisation + // First check that this is not a simple gate which does not need optimization // - // If the gate only has one mul term, then this algorithm cannot optimise it any further + // If the gate only has one mul term, then this algorithm cannot optimize it any further // Either it can be represented in a single arithmetic equation or it's fan-in is too large and we need intermediate variables for those - // large-fan-in optimisation is not this algorithms purpose. + // large-fan-in optimization is not this algorithms purpose. // If the gate has 0 mul terms, then it is an add gate and similarly it can either fit into a single arithmetic gate or it has a large fan-in if gate.mul_terms.len() <= 1 { return gate; @@ -103,7 +103,7 @@ impl Optimiser { // Check if this pair is present in the simplified fan-in // We are assuming that the fan-in/fan-out has been simplified. - // Note this function is not public, and can only be called within the optimise method, so this guarantee will always hold + // Note this function is not public, and can only be called within the optimize method, so this guarantee will always hold let index_wl = gate .linear_combinations .iter() @@ -162,15 +162,15 @@ impl Optimiser { // Add this element into the new gate intermediate_gate.linear_combinations.push(wire_term); } else { - // Nomore elements left in the old gate, we could stop the whole function - // We could alternative let it keep going, as it will never reach this branch again since there are nomore elements left - // XXX: Future optimisation - // nomoreleft = true + // No more elements left in the old gate, we could stop the whole function + // We could alternative let it keep going, as it will never reach this branch again since there are no more elements left + // XXX: Future optimization + // no_more_left = true } } // Constraint this intermediate_gate to be equal to the temp variable by adding it into the IndexMap // We need a unique name for our intermediate variable - // XXX: Another optimisation, which could be applied in another algorithm + // XXX: Another optimization, which could be applied in another algorithm // If two gates have a large fan-in/out and they share a few common terms, then we should create intermediate variables for them // Do some sort of subset matching algorithm for this on the terms of the polynomial let inter_var = Witness(intermediate_variables.len() as u32 + num_witness); @@ -202,16 +202,16 @@ impl Optimiser { new_gate } - // A partial gate scan optimisation aim to create intermediate variables in order to compress the polynomial + // A partial gate scan optimization aim to create intermediate variables in order to compress the polynomial // So that it fits within the given width - // Note that this gate follows the full gate scan optimisation. + // Note that this gate follows the full gate scan optimization. // We define the partial width as equal to the full width - 2. // This is because two of our variables cannot be used as they are linked to the multiplication terms // Example: qM1 * wL1 * wR2 + qL1 * wL3 + qR1 * wR4+ qR2 * wR5 + qO1 * wO5 + qC // One thing to note is that the multiplication wires do not match any of the fan-in/out wires. This is guaranteed as we have - // just completed the full gate optimisation algorithm. + // just completed the full gate optimization algorithm. // - //Actually we can optimise in two ways here: We can create an intermediate variable which is equal to the fan-in terms + //Actually we can optimize in two ways here: We can create an intermediate variable which is equal to the fan-in terms // t = qL1 * wL3 + qR1 * wR4 -> width = 3 // This `t` value can only use width - 1 terms // The gate now looks like: qM1 * wL1 * wR2 + t + qR2 * wR5+ qO1 * wO5 + qC @@ -234,12 +234,12 @@ impl Optimiser { // The gate now looks like: t2 + qR1 * wR4+ qR2 * wR5 + qO1 * wO5 + qC // t3 = t2 + qR1 * wR4 // The gate now looks like: t3 + qR2 * wR5 + qO1 * wO5 + qC - // This took the same amount of gates, but which one is better when the width increases? Compute this and maybe do both optimisations + // This took the same amount of gates, but which one is better when the width increases? Compute this and maybe do both optimizations // naming : partial_gate_mul_first_opt and partial_gate_fan_first_opt // Also remember that since we did full gate scan, there is no way we can have a non-zero mul term along with the wL and wR terms being non-zero // // Cases, a lot of mul terms, a lot of fan-in terms, 50/50 - fn partial_gate_scan_optimisation( + fn partial_gate_scan_optimization( &self, mut gate: Expression, intermediate_variables: &mut IndexMap, @@ -248,7 +248,7 @@ impl Optimiser { // We will go for the easiest route, which is to convert all multiplications into additions using intermediate variables // Then use intermediate variables again to squash the fan-in, so that it can fit into the appropriate width - // First check if this polynomial actually needs a partial gate optimisation + // First check if this polynomial actually needs a partial gate optimization // There is the chance that it fits perfectly within the arithmetic gate if gate.fits_in_one_identity(self.width) { return gate; @@ -321,7 +321,7 @@ impl Optimiser { // keep consistency with the original equation. gate.linear_combinations.extend(added); - self.partial_gate_scan_optimisation(gate, intermediate_variables, num_witness) + self.partial_gate_scan_optimization(gate, intermediate_variables, num_witness) } } @@ -348,8 +348,8 @@ fn simple_reduction_smoke_test() { let num_witness = 4; - let optimiser = Optimiser::new(3); - let got_optimised_gate_a = optimiser.optimise(gate_a, &mut intermediate_variables, num_witness); + let optimizer = Optimizer::new(3); + let got_optimized_gate_a = optimizer.optimize(gate_a, &mut intermediate_variables, num_witness); // a = b + c + d => a - b - c - d = 0 // For width3, the result becomes: @@ -358,7 +358,7 @@ fn simple_reduction_smoke_test() { // // a - b + e = 0 let e = Witness(4); - let expected_optimised_gate_a = Expression { + let expected_optimized_gate_a = Expression { mul_terms: vec![], linear_combinations: vec![ (FieldElement::one(), a), @@ -367,7 +367,7 @@ fn simple_reduction_smoke_test() { ], q_c: FieldElement::zero(), }; - assert_eq!(expected_optimised_gate_a, got_optimised_gate_a); + assert_eq!(expected_optimized_gate_a, got_optimized_gate_a); assert_eq!(intermediate_variables.len(), 1); diff --git a/acvm/src/compiler/optimiser/general_optimiser.rs b/acvm/src/compiler/optimizer/general_optimizer.rs similarity index 87% rename from acvm/src/compiler/optimiser/general_optimiser.rs rename to acvm/src/compiler/optimizer/general_optimizer.rs index 65e95e13b..6f81c896e 100644 --- a/acvm/src/compiler/optimiser/general_optimiser.rs +++ b/acvm/src/compiler/optimizer/general_optimizer.rs @@ -6,8 +6,8 @@ use indexmap::IndexMap; pub struct GeneralOpt; impl GeneralOpt { - pub fn optimise(gate: Expression) -> Expression { - // XXX: Perhaps this optimisation can be done on the fly + pub fn optimize(gate: Expression) -> Expression { + // XXX: Perhaps this optimization can be done on the fly let gate = remove_zero_coefficients(gate); simplify_mul_terms(gate) } @@ -27,7 +27,7 @@ pub fn remove_zero_coefficients(mut gate: Expression) -> Expression { pub fn simplify_mul_terms(mut gate: Expression) -> Expression { let mut hash_map: IndexMap<(Witness, Witness), FieldElement> = IndexMap::new(); - // Canonicalise the ordering of the multiplication, lets just order by variable name + // Canonicalize the ordering of the multiplication, lets just order by variable name for (scale, w_l, w_r) in gate.mul_terms.clone().into_iter() { let mut pair = vec![w_l, w_r]; // Sort using rust sort algorithm diff --git a/acvm/src/compiler/optimizer/mod.rs b/acvm/src/compiler/optimizer/mod.rs new file mode 100644 index 000000000..e84d7cb79 --- /dev/null +++ b/acvm/src/compiler/optimizer/mod.rs @@ -0,0 +1,7 @@ +mod csat_optimizer; +mod general_optimizer; +mod r1cs_optimizer; + +pub use csat_optimizer::Optimizer as CSatOptimizer; +pub use general_optimizer::GeneralOpt as GeneralOptimizer; +pub use r1cs_optimizer::R1CSOptimizer; diff --git a/acvm/src/compiler/optimiser/r1cs_optimiser.rs b/acvm/src/compiler/optimizer/r1cs_optimizer.rs similarity index 70% rename from acvm/src/compiler/optimiser/r1cs_optimiser.rs rename to acvm/src/compiler/optimizer/r1cs_optimizer.rs index f76562164..01ecaffa1 100644 --- a/acvm/src/compiler/optimiser/r1cs_optimiser.rs +++ b/acvm/src/compiler/optimizer/r1cs_optimizer.rs @@ -1,34 +1,34 @@ -use crate::compiler::GeneralOptimiser; +use crate::compiler::GeneralOptimizer; use acir::circuit::{Circuit, Opcode}; -pub struct R1CSOptimiser { +pub struct R1CSOptimizer { acir: Circuit, } -impl R1CSOptimiser { +impl R1CSOptimizer { pub fn new(acir: Circuit) -> Self { Self { acir } } - // R1CS optimisations uses the general optimiser. + // R1CS optimizations uses the general optimizer. // TODO: We could possibly make sure that all polynomials are at most degree-2 - pub fn optimise(self) -> Circuit { - let optimised_arith_gates: Vec<_> = self + pub fn optimize(self) -> Circuit { + let optimized_arith_gates: Vec<_> = self .acir .opcodes .into_iter() .map(|gate| match gate { - Opcode::Arithmetic(arith) => Opcode::Arithmetic(GeneralOptimiser::optimise(arith)), + Opcode::Arithmetic(arith) => Opcode::Arithmetic(GeneralOptimizer::optimize(arith)), other_gates => other_gates, }) .collect(); Circuit { - // The general optimiser may remove enough gates that a witness is no longer used + // The general optimizer may remove enough gates that a witness is no longer used // however, we cannot decrement the number of witnesses, as that // would require a linear scan over all gates in order to decrement all witness indices // above the witness which was removed current_witness_index: self.acir.current_witness_index, - opcodes: optimised_arith_gates, + opcodes: optimized_arith_gates, public_inputs: self.acir.public_inputs, } } diff --git a/acvm/src/compiler/optimiser/range_optimiser.rs b/acvm/src/compiler/optimizer/range_optimizer.rs similarity index 54% rename from acvm/src/compiler/optimiser/range_optimiser.rs rename to acvm/src/compiler/optimizer/range_optimizer.rs index 6d733cdb6..9bfa86d08 100644 --- a/acvm/src/compiler/optimiser/range_optimiser.rs +++ b/acvm/src/compiler/optimizer/range_optimizer.rs @@ -1,19 +1,19 @@ // XXX: We could alleviate a runtime check from noir // By casting directly // Example: -// priv z1 = x as u32 -// priv z2 = x as u16 +// priv z1 = x as u32 +// priv z2 = x as u16 // // The IR would see both casts and replace it with -// -// +// +// // priv z1 = x as u16; // priv z2 = x as u16; // -// -// Then maybe another optimisation could be done so that it transforms into +// +// Then maybe another optimization could be done so that it transforms into // // priv z1 = x as u16 // priv z2 = z1 -// This is what I would call a general optimisation, so it could live inside of the IR module -// A more specific optimisation would be to have z2 = z1 not use a gate (copy_from_to), this is more specific to plonk-aztec and would not live in this module \ No newline at end of file +// This is what I would call a general optimization, so it could live inside of the IR module +// A more specific optimization would be to have z2 = z1 not use a gate (copy_from_to), this is more specific to plonk-aztec and would not live in this module diff --git a/acvm/src/lib.rs b/acvm/src/lib.rs index c44fd9632..c709e1241 100644 --- a/acvm/src/lib.rs +++ b/acvm/src/lib.rs @@ -180,7 +180,7 @@ pub enum Language { pub fn hash_constraint_system(cs: &Circuit) -> [u8; 32] { let mut bytes = Vec::new(); - cs.write(&mut bytes).expect("could not serialise circuit"); + cs.write(&mut bytes).expect("could not serialize circuit"); use sha2::{digest::FixedOutput, Digest, Sha256}; let mut hasher = Sha256::new(); diff --git a/acvm/src/pwg/arithmetic.rs b/acvm/src/pwg/arithmetic.rs index 7ac522413..6b6182ff1 100644 --- a/acvm/src/pwg/arithmetic.rs +++ b/acvm/src/pwg/arithmetic.rs @@ -124,7 +124,7 @@ impl ArithmeticSolver { witness_assignments: &BTreeMap, ) -> MulTerm { // First note that the mul term can only contain one/zero term - // We are assuming it has been optimised. + // We are assuming it has been optimized. match arith_gate.mul_terms.len() { 0 => MulTerm::Solved(FieldElement::zero()), 1 => { diff --git a/cspell.json b/cspell.json index 152e653aa..8a4bf70c6 100644 --- a/cspell.json +++ b/cspell.json @@ -2,34 +2,43 @@ "version": "0.2", "words": [ "blackbox", - "decomp", - "finalise", - "generalises", - "optimise", - "optimisation", - "optimisations", - "optimised", - "optimiser", - "arithmetisation", // In code // "acir", "ACIR", "ACVM", + "Axyz", + "arithmetization", + "bivariate", + "canonicalize", "coeff", "consts", + "csat", + "decomp", + "deflater", + "endianness", + "euclidian", "hasher", + "Merkle", "OddRange", + "Pedersen", "PLONKC", "prehashed", "pubkey", + "repr", "secp", + "Schnorr", "Shleft", "Shright", "stdlib", - "typenum" + "struct", + "TORADIX", // Dependencies // - "thiserror" + "bufread", + "flate", + "indexmap", + "thiserror", + "typenum" ] } diff --git a/stdlib/src/fallback.rs b/stdlib/src/fallback.rs index 818c8b874..9aaaa2c37 100644 --- a/stdlib/src/fallback.rs +++ b/stdlib/src/fallback.rs @@ -68,7 +68,7 @@ pub(crate) fn bit_decomposition( bit_decomp_constraint.sort(); // TODO: we have an issue open to check if this is needed. Ideally, we remove it. new_gates.push(Opcode::Arithmetic(bit_decomp_constraint)); - (new_gates, bit_vector, variables.finalise()) + (new_gates, bit_vector, variables.finalize()) } // Range constraint @@ -140,7 +140,7 @@ pub fn xor( let two = FieldElement::from(2_i128); // Build an xor expression - // TODO: check this is the correct arithmetisation + // TODO: check this is the correct arithmetization let mut xor_expr = Expression::default(); for (a_bit, b_bit) in a_bits.into_iter().zip(b_bits) { xor_expr.term_addition(two_pow, a_bit); diff --git a/stdlib/src/helpers.rs b/stdlib/src/helpers.rs index 4eea6a518..5ab258368 100644 --- a/stdlib/src/helpers.rs +++ b/stdlib/src/helpers.rs @@ -17,7 +17,7 @@ impl<'a> VariableStore<'a> { witness } - pub fn finalise(self) -> u32 { + pub fn finalize(self) -> u32 { *self.witness_index } } From 944c842816f17d9a1c567fbf89cbfcb4a99318cc Mon Sep 17 00:00:00 2001 From: Tom French Date: Fri, 3 Feb 2023 20:26:52 +0000 Subject: [PATCH 3/3] chore: make CI incremental --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index d70c4cf68..935d6e471 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -31,5 +31,5 @@ jobs: with: files: | **/*.{md,rs} - incremental_files_only : false # Run this action on files which have changed in PR + incremental_files_only : true # Run this action on files which have changed in PR strict: false # Do not fail, if a spelling mistake is found (This can be annoying for contributors)