Code Monkey home page Code Monkey logo

circom-2-arithc's Introduction

Circom To Arithmetic Circuit

MIT licensed Build Status codecov

This library enables the creation of arithmetic circuits from circom programs.

Supported Circom Features

Category Type Supported
Statements InitializationBlock
Block
Substitution
Declaration
IfThenElse
While
Return
MultSubstitution
UnderscoreSubstitution
ConstraintEquality
LogCall
Assert
Expressions Call
InfixOp
Number
Variable
PrefixOp
InlineSwitchOp
ParallelOp
AnonymousComp
ArrayInLine
Tuple
UniformArray

Circomlib

WIP

Requirements

  • Rust: To install, follow the instructions found here.

Getting Started

  • Write your circom program in the input directory under the circuit.circom name.

  • Build the program

cargo build --release
  • Run the compilation
cargo run --release

The compiled circuit and circuit report can be found in the ./output directory.

ZK/MPC/FHE backends:

Contributing

Contributions are welcome!

License

This project is licensed under the MIT License - see the LICENSE file for details.

circom-2-arithc's People

Contributors

brech1 avatar namnc avatar voltrevo avatar curryrasul avatar vuvoth avatar

Stargazers

Evan Coats avatar  avatar  avatar sintayew gashaw avatar Tony Riemer avatar  avatar Daehyun Paik avatar Andrey Labe  avatar Alex Kuzmin avatar  avatar  avatar Daniel Kales avatar Hins avatar Jack Lloyd avatar Mamy Ratsimbazafy avatar Amrith Nayak avatar zakaria  avatar sudo rm -rf --no-preserve-root / avatar Bob Niu avatar  avatar Harry Chen avatar  avatar Suning Yao avatar JernKunpittaya avatar saham avatar Sigrid Jin (ง'̀-'́)ง oO avatar Lyron Co Ting Keh avatar Paul avatar Kurt Pan avatar Sora Suegami avatar enrico.eth avatar dungexn avatar Kevin Mai-Husan Chia avatar Soowon Jeong avatar  avatar 0xumarkhatab avatar Erhan avatar  avatar V.O.T avatar  avatar  avatar  avatar

Watchers

 avatar

circom-2-arithc's Issues

CircuitError(Inconsistency ...) error

CircuitError(Inconsistency ...) error when trying to compile Keras2Circom generated circuit

pragma circom 2.0.0;

include "../circuits/Dense.circom";
include "../circuits/Flatten2D.circom";
include "../circuits/ArgMax.circom";

template Model() {
signal input in[2][1][1];
signal input flatten_11_out[2];
signal input dense_23_weights[2][10];
signal input dense_23_bias[10];
signal input dense_23_out[10];
signal input dense_23_softmax_out[1];
signal output out[1];

component flatten_11 = Flatten2D(2, 1, 1);
component dense_23 = Dense(2, 10, 10);
component dense_23_softmax = ArgMax(10);

for (var i0 = 0; i0 < 2; i0++) {
    for (var i1 = 0; i1 < 1; i1++) {
        for (var i2 = 0; i2 < 1; i2++) {
            flatten_11.in[i0][i1][i2] <== in[i0][i1][i2];
}}}
for (var i0 = 0; i0 < 2; i0++) {
    flatten_11.out[i0] <== flatten_11_out[i0];
}
for (var i0 = 0; i0 < 2; i0++) {
    dense_23.in[i0] <== flatten_11.out[i0];
}
for (var i0 = 0; i0 < 2; i0++) {
    for (var i1 = 0; i1 < 10; i1++) {
        dense_23.weights[i0][i1] <== dense_23_weights[i0][i1];
}}
for (var i0 = 0; i0 < 10; i0++) {
    dense_23.bias[i0] <== dense_23_bias[i0];
}
for (var i0 = 0; i0 < 10; i0++) {
    dense_23.out[i0] <== dense_23_out[i0];
}
for (var i0 = 0; i0 < 10; i0++) {
    dense_23_softmax.in[i0] <== dense_23.out[i0];
}
dense_23_softmax.out <== dense_23_softmax_out[0];
out[0] <== dense_23_softmax.out;

}

component main = Model();

Implement component connections in the arithmetic circuit

So far the gates are created independently when a template is executed (as a component).

But these templates have defined input and output signals, which are wired when setting up the component, these connections are currently only stored in each component but are not being part of the actual circuit.

The idea of this issue is to implement this connections.

  • Components inputs and outputs should be declared in the AC.
  • Circuit signal identifiers should be updated following the wiring maps of the components.

Support `UniformArray` expressions.

Add support for handling UniformArray expressions, expressions like:

var x[2][3];

will halt the circuit generation and return the ExpressionNotImplemented error.

Implement `circomlib-mpc` 0.1

Implement our version of circomlib in order to support basic functions.

This is needed due to circomlib being done to work with R1CS, not working for execution.

Support signal arrays assignment

We should add support for the assignment of whole signal arrays. Example:

template fc (width, height) {
    signal input weights[height][width];
    signal output out[height];
}

template network() {
    signal input in;
    signal output out;

    component l0 = fc(3, 5);

    signal input w0[5][3];
    signal input b0[5];

    l0.weights <== w0;
    ...
}

Handle compound assignment operators

Eg when running this program:

template network() {
    signal input x;
    signal output y;

    var z = 3;
    z += x; // <----- compound assignment

    y <== z;
}

component main = network();

We get:

Error: RuntimeError(ItemNotDeclared("get_variable_value: DataAccess { name: \"random_3750075181\", access: [] }"))

Compound assignment doesn't need to be implemented for signals, that's handled as an error by circom, eg:

error[T2000]: Typing error found
    ┌─ "./src/assets/circuit.circom":173:5
    │
173 │     y += x;
    │     ^^^^^^ The operator does not match the types of the assigned elements.
 Assignments to signals do not allow the operator =, try using <== or <-- instead

Error: AnalysisError

Compiler doesn't show error to a bad circuit

I tried to compile the circuit with out of bounds error:

pragma circom 2.1.0;

template circuit() {
   signal arr[10];

   for (var i = 0; i < 100; i++) {
      arr[i] <== 1;
   }
}

component main = circuit();

The compiler doesn't show the error; original Circom does show the out of bounds error, so something wrong with circom-2-arithc

Move all the integration tests into one SUPERtest

We have a lot of small integration tests files - it's not good, cause each of them is a different crate, therefore it generates separate binary; each of them is relinked with the library crate separately, etc.

You can read about it here

It's better to create one big integration test crate that'll contain all the tests we have as separate modules

Compiler outputs a different file after every run

On each compilation the circuit output is slightly different. This could be problematic for a backend, or some verification step if you're comparing compiled files. Here's an example:

First run:

4 12
8 1 1 1 1 1 1 1 1
4 1 1 1 1

2 1 2 4 10 AMul
2 1 7 0 9 AMul
2 1 3 5 8 AMul
2 1 6 1 11 AMul

Second run:

4 12
8 1 1 1 1 1 1 1 1
4 1 1 1 1

2 1 2 5 8 AMul
2 1 0 4 9 AMul
2 1 1 7 11 AMul
2 1 3 6 10 AMul

The change is in the input and output signal ids.

Support different number systems

At the moment we assume a traditional arithmetic over u32.

Instead we should define a Number trait and allow the user to specify the number system they are using. Additionally we can provide implementations of common number systems.

trait Number {
    fn op(&self, op: Operation, rhs: &Self) -> Self;
    // note: we may want to separate this as prefix_op, infix_op, but that's a separate issue
}

then anything implementing this trait can be used by using it as the constraint on a generic, like this:

fn execute<N: Number>(&self, inputs: &[N]) -> Result<Vec<N>, CircuitError>

Execute `ExpressionInfixOpcode` directly when dealing with integers

The execute_op function is called whenever we need to operate on two integers (not signals). Transforming to our set of gates is limiting us to perform some operations, and is not really needed, we could operate any opcode directly.

/// Executes an operation, performing the specified arithmetic or logical computation.
pub fn execute_op(lhs: &u32, rhs: &u32, op: &ExpressionInfixOpcode) -> u32 {
    match op {
     ...
    }
}

Create `examples` folder.

The current assets directory should be removed and replaced by an examples directory in the project root.

This new dir should contain single file circuit examples for the different supported features.

The ArgMax circuit doesn't work with MP-SPDZ

The compiled ArgMax circuit doesn't work with MP-SPDZ, because of the errors with constants:

/MP-SPDZ ((704049e1)) ~> PLAYERS=2 Scripts/compile-run.py -E semi circuit -M          Wed Jun 26 12:47:40 2024
Default bit length for compilation: 64
Default security parameter for compilation: 40
Compiling file Programs/Source/circuit.mpc
Traceback (most recent call last):
  File "/MP-SPDZ/Scripts/compile-run.py", line 14, in <module>
    prog = compiler.compile_file()
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "/MP-SPDZ/Scripts/../Compiler/compilerLib.py", line 452, in compile_file
    exec(compile(infile.read(), infile.name, "exec"), self.VARS)
  File "Programs/Source/circuit.mpc", line 6, in <module>
    wires[10] = wires[9] - wires[7]
                ~~~~~~~~~^~~~~~~~~~
TypeError: unsupported operand type(s) for -: 'NoneType' and 'sint'

Assign Constant to different signals

Currently constants are being assigned to the same signal. This means that it's not possible to assign the same constant to multiple circuit outputs.

Reassigning signal returns error

This doesn't work without doing + 0 for out signal

pragma circom 2.0.0;

// Flatten layer with that accepts a 2D input
template Flatten2D (nRows, nCols, nChannels) {
    signal input in[nRows][nCols][nChannels];
    signal output out[nRows*nCols*nChannels];

    var idx = 0;

    for (var i=0; i<nRows; i++) {
        for (var j=0; j<nCols; j++) {
            for (var k=0; k<nChannels; k++) {
                // TODO: remove a need to create a gate
                out[idx] <== in[i][j][k] + 0;
                idx++;
            }
        }
    }
}

Improve template processing

Right now there seems to be a linear scan for adding connections between caller and callee, may be we can:

  • measure the current cost to see if it significantly slowdown circuit generation
  • and if it does, improve it in someway

Merge `traverse` and `execute` functions

Restructure the codebase to reduce redundant code and improve navigation by merging:

  • execute_statement
  • traverse_statement
  • execute_expression
  • traverse_expression

Into two functions to handle statements and expressions in a single way.

Assigning the value to an intermediate signal returns error

I tried the circuit:

pragma circom 2.1.0;

template temp() {
    signal input a;
    signal output out;

    signal intermediate <== 0;
}

component main = temp();

It finishes with error:

thread 'main' panicked at src/compiler.rs:520:51:
no entry found for key
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Add default project config and enable CLI configuration

This issue is related to the Project Usability item in the project overview.

To improve usability we need to create our own CLI argument parsing and remove the existent one in the circom directory. This one has been built around regular circom usage and needs to be removed, along with any configuration we're not using or planning to.

A project configuration struct has to be made, starting from:

struct CompilerConfig {
    /// Circuit input file.
    input: String,
    /// Circuit and report output paths.
    output: String,
}

This will be helpful when using our project as an executable from a command line interface, but can also serve as inspiration if the project is used as a library.

This will also allow us to update the clap dependency.

Tasks

  • Removal of all code in the circom directory related to CLI arguments parsing or project configuration.
  • Implementation of our own CLI, with a compile command.
  • Implementation of a new CompilerConfig struct that holds all necessary optional data related to project compilation. Keep in mind this would only be related to the compile command on the CLI.
  • Update clap dependency.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.