# \[ZK Learning Group 2] Circom workshop #1

#### Circom serves 2 primary purposes:&#x20;

1. Lets you define a set of constraints that implicitly is equivalent to some function.
2. Define at proving-time, how you should fill in the nodes of your Arithemtic circuit - intermediate variables. (witness generation).

```rust
pragma circom 2.0.3;

template Main() {
  //private 
  signal input x; 
  signal x_squared;
  signal x_cubed;
  signal output out;
  
  // witness generation: IR gen
  x_squared <-- x * x;
  x_cubed <-- x_squared * x;
  out <-- x_cubed - x + 7;

  // constraint definition
  x_squared === x * x;
  x_cubed === x_squared * x;
  out === x_cubed - x + 7;
}

component main = Main();
```

#### On signals

* they are not bits.&#x20;
* they are prime field elements. modulo p, where p is the babyjubjub prime.

#### On witness generation&#x20;

* You know some `x` that results in some public `out`, such that `f(x) = y` (y = out)&#x20;
* For convenience, circom allows you to generate the intermediate witnesses, as opposed to having the user to supply them.&#x20;
* This is done with the `<--` notation

#### Constraints

* constraints are done with `===` notation
* can only use `*` or `+` operators
* must look like either"

```
a * b === c;
d === f + e;
```

### Compilation

Comilation gives up a number of files, including the .r1cs file.

#### **R1CS**

* Compiling the circuit gives us an R1CS file, that can be used with different toolstacks, that implement the Groth16 protocol.&#x20;
* Think of it as a IR representation; like your compiled bytecode.

#### **.wasm file**

* a wasm exceutable program that implements the single arrow stuff - witness generation.&#x20;
* witness generation program that allows derivation of the intermediate signals (`x_squared, x_cubed`) just from the single input, `x`.

#### vkey: verification key

* goes into your smart contract for verification.&#x20;
* a .sol file is also created, whjich is a contract based on the vk that serves as the verification component.&#x20;
* .sol file would expose a `verifyProof` function

#### .zkey: proving key

* goes into your client, Dapp Front-end.
* used in proof generation.

### When can't you simply just `<==` for all constraints/intermediates?

```
// I know some x1,x2,x3,x4 such tt
Eq: f(x) = (x1 + x2)/ x3 - x4 

Intermediate Rep: 
y1 / x3 - x4 
y2 - x4

y1 = (x1 + x2)
y2 = y1/x3
```

* Input signals: x1,..x4&#x20;
* Intermediates : y1, y2

```solidity
pragma circom 2.0.3;

template Main() {
  signal input x1;
  signal input x2;
  signal input x3;
  signal input x4;

  signal y1;
  signal y2;

  signal output out;

//witness generation
  y1 <-- x1 + x2;
  y2 <-- y1 / x3;
  out <-- y2 - x4;

// constraints can only have quadratic expressions
// can only use + or *
  y1 === x1 + x2;
  y1 === y2 * x3;
  out === y2 - x4;
}

component main { public [ x2 ] } = Main();
```

Notice that in this example we cannot simply use `<===` to combine out witness generation and constraint definition.&#x20;

The reason we have to seperate is cos' of the **`y2 <-- y1 / x3;`**

* In witness generation you are **allowed** to use **arbitrary operations** like division.&#x20;
* But in defining constraints, we can only use quadratic expressions.&#x20;
* So instead of `y2 <-- y1 / x3;` >>> it becomes `y1 === y2 * x3;`&#x20;

```solidity
// the following would be a valid circuit:
  y1 <== x1 + x2;

  y2 <-- y1 / x3;
  y1 === y2 * x3;

  out <== y2 - x4;
```

{% hint style="info" %}
You are only allowed quadratic constraints: a+b\*c

* can't do x\*x\*x&#x20;
  {% endhint %}

### Include

```circom
pragma circom 2.0.3;

include "../node_modules/circomlib/circuits/mimcsponge.circom";

template Main() {
  signal input x;
  // signal input hash;

  signal output out;

  component mimc = MiMCSponge(1, 220, 1);
  mimc.ins[0] <== x;
  mimc.k <== 0;

  out <== mimc.outs[0];

  // out === hash;
}

component main = Main();
```

```circom
// include for importing
// be it dir or direct from github
// allows re-use of circuits to build larger circuits
```

### Paranthesis

Allows you to enter values that are params

* params are for dynamic parts of the circuit
* like counter of a for loop
* must be specified by compile time. cos the compiled circuit cannot have such dynamic parts like loops.

<figure><img src="/files/GuEbnI0LOgJsY8cA2GRJ" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}

* At compile time, circuits must be bounded.
* n must be known at compile time.
* For loops just serve as a kind of syntatic sugar - they get unrolled into individuals lines of code.&#x20;
  {% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://calnix.gitbook.io/zk-notes/0xparc-zk-learning-group/zk-learning-group-2-circom-workshop-1.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
