# #6 Circom: signal output

## <mark style="color:red;">`signal output`</mark>

Let's begin by reviewing the example from the previous article:

```rust
template Main() {
	// input signals
  signal input x1;
  signal input x2;
  signal input x3;
  signal input x4;
  signal output out;

	// intermediate signals
  signal y1;
  signal y2;

  // calc. intermediate values 
  y2 <-- y1 / x3;

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

component main = Main();
```

The reader would have two questions:

1. if we denote <mark style="color:red;">`out`</mark> as <mark style="color:red;">`signal out`</mark>, why did we group it with the other input signals?
2. does <mark style="color:red;">`signal output`</mark> output anything if at all?

## <mark style="color:red;">`signal output`</mark> is an input signal

Despite the "output" keyword, from the circuit's perspective, <mark style="color:red;">`out`</mark> is actually an input signal. The circuit creates a set of R1CS constraints, and <mark style="color:red;">`out`</mark> is simply part of this system.

The prover receives values of the witness vector, which must satisfy the circuit's constraints. In this case, the witness vector looks like: <mark style="color:red;">`[1, out, x1, x2, x3, x4, y1, y2]`</mark>.

> Remember, we are not computing anything - only verifying if a computation is correct. Hence, the outcome of the computation must be provided

This raises a question: if <mark style="color:red;">`out`</mark> is an input signal, shouldn't we be using <mark style="color:red;">`===`</mark> instead of <mark style="color:red;">`<==`</mark>?

### Why use `<==` and not `===` for `signal output`

The reason for constraining and assigning <mark style="color:red;">`out`</mark> is similar to why we use <mark style="color:red;">`<==`</mark> with intermediate signals, as explained previously. Although considered an input from the prover's perspective, <mark style="color:red;">`out`</mark> is still a value computed by the circuit.

Think of it this way: when defining the circuit, we're establishing relationships between inputs. From the circuit's viewpoint, <mark style="color:red;">`out`</mark> is simply another value calculated from the inputs.

The assignment operation (<mark style="color:red;">`<==`</mark>) is syntactic sugar—it instructs the compiler to include the necessary calculations in the witness generation artifacts for our convenience.

So why bother with the <mark style="color:red;">`output`</mark> designation at all?

### Does `signal output` output anything if at all?

Yes, it does serve a purpose.

* <mark style="color:red;">`out`</mark> is the output of this circuit
* A circuit can pass values to another circuit, to be used as input
* However, a circuit doesn't "output" data during execution in the traditional sense of programming

Therefore, a signal labelled <mark style="color:red;">`signal output`</mark> can be viewed as an input signal that we intend to pass along to another circuit. Circuits do not output anything to the world.

## Subcomponents

As circuits get more complex, Circom lets you break them into smaller, manageable pieces (subcomponents).

Input signals pass data to these subcomponents, while output signals relay data from one circuit to another.

#### **Example**

Two templates are defined in this example, **`Mul`** and **`Main`**. \
\&#xNAN;**`Mul`** serves to verify that of the supplied inputs, <mark style="color:red;">`a*b=c`</mark>. **`Main`** does the same repeatedly as seen below:

```rust
template Mul() {
	signal input a;
	signal input b;
	signal input c;
	
	c === a * b;
}

template Main() {
	signal input in[6];

	// instantiate subcomponents
	component mul1 = Mul();
	component mul2 = Mul();
	
	// check: in[0] * in[1] = in[2]
	mul1.a <== in[0];
	mul1.b <== in[1];
	mul1.c <== in[2];
	
	// check: in[3] * in[4] = in[5]
	mul2.a <== in[3];
	mul2.b <== in[4];
	mul2.c <== in[5];
}

component main = Main();
```

* Instantiations of sub-components are done using the keyword <mark style="color:red;">`component`</mark>; not unlike main.
* Instances of components cannot be reused - to use **`Mul`** twice, it must be instantiated twice. <mark style="color:red;">`mul1`</mark> cannot be reused with a different set if inputs.
* Inputs are passed into sub-components via dot notation. E.g., <mark style="color:red;">`mul1.`</mark>`a`

### Why use <mark style="color:red;">`<==`</mark> to pass inputs?

To explain this we examine the artifacts produced by the Circom compiler.

For simplicity we will focus on sub-component <mark style="color:red;">`mul1`</mark> only and ignore <mark style="color:red;">`mul2`</mark>; rest assured the same logic applies.

**Scenario 1: Inputs are assigned and constrained:**

<figure><img src="https://1983523492-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0nwEx8a60yETwfNYnenT%2Fuploads%2F7eay7zB4AfaE1MOnEdhP%2Fimage.png?alt=media&#x26;token=defaf1a1-ff1c-4088-986a-861f108946c3" alt="" width="527"><figcaption></figcaption></figure>

* Witness generation artifacts assign the circuit’s input signals to be inputs to <mark style="color:red;">`mul1`</mark>
* Low-level representation of constraints ensure that <mark style="color:red;">`mul1`</mark> inputs are constrained to the circuit’s input signals.
* Additionally, there is the <mark style="color:red;">`mul1`</mark> constraint that verifies that <mark style="color:red;">`a*b=c`</mark>.

When we feed this system of constraints to a zkSNARK generator (snarkJs), the generated prover and verifier will ensure that all these constraints are adhered to.

#### Scenario 2: Inputs are assigned, but not constrained

<figure><img src="https://1983523492-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0nwEx8a60yETwfNYnenT%2Fuploads%2FPDYHkaUCTA03AIZT12WM%2Fimage.png?alt=media&#x26;token=2bc7a330-f909-4d42-9217-7fa2029bf658" alt=""><figcaption></figcaption></figure>

* Witness generation remains unchanged.
* But there are is only a single constraint that verifies that <mark style="color:red;">`a*b=c`</mark>.

When we feed this system of constraints to a zkSNARK generator, the generated prover and verifier will only look to verify that <mark style="color:red;">`a*b=c`</mark>.

The input signals to the Main circuit, <mark style="color:red;">`in[6]`</mark>, are disregarded.

The prover will not check and generate a proof that is based on <mark style="color:red;">`in[6]`</mark> - an attacker could pass arbitrary values (differing from <mark style="color:red;">`in[6]`</mark>) to the subcomponent to achieve verification.

We will explore practical methods of achieving this in the exercise section.

In the next article we will see how outputs are used in foundational circuits found within Circomlib (primarily in **comparators.circom**).

***

## Exercise

This exercise will serve to illustrate the importance of using the <mark style="color:red;">`<==`</mark> operator when passing inputs to subcomponents.

We begin by illustrating what happens under the hood when we use <mark style="color:red;">`<==`</mark>.

### Positive Example

```jsx
pragma circom 2.1.8;

template Mul() {
	signal input a;
	signal input b;
	signal input c;
	
	c === a * b;
}

template Main() {
    
	signal input in[3];

	// instantiate subcomponents
	component mul = Mul();
	
	// assign & constraints inputs
	mul.a <== in[0];
	mul.b <== in[1];
	mul.c <== in[2];
	
}

component main = Main();
```

**Compile the circuit**

* **`circom positive.circom --r1cs --sym --wasm --O0`**
* Sanity check on terminal output:
  * `non-linear constraints: 1`
  * `linear constraints: 3`

<figure><img src="https://1983523492-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0nwEx8a60yETwfNYnenT%2Fuploads%2FBDXD3yWgDdRlVFBUe4Kt%2Fimage.png?alt=media&#x26;token=62ac1421-9c1a-48ca-848e-935c70696356" alt=""><figcaption></figcaption></figure>

This checks out.

* one non-linear constraint accounting for `a*b===c`.
* three linear constraints cover the subcomponent inputs’ constraints

**Examine the R1CS file**

* **`snarkjs r1cs print positive.r1cs`**
* Terminal prints all 3 constraints

<figure><img src="https://1983523492-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0nwEx8a60yETwfNYnenT%2Fuploads%2FEZcja74gnRCISwCjRFSx%2Fimage.png?alt=media&#x26;token=78d5aef3-3eb0-42cf-abb0-bdec5faca1b9" alt=""><figcaption></figcaption></figure>

**Generate the witness**

* create `inputs.json` file in `./positive_js` directory
* values passed will be as below

{% code title="inputs.json" %}

```json
{"in": ["1", "2", "2"]}
```

{% endcode %}

* run: `node generate_witness.js positive.wasm inputs.json witness.wtns`
* export to json: `snarkjs wtns export json witness.wtns`
* `cat witness.json` should output the following:

```jsx
[
 "1",     // 1
 "1",     // in[0]
 "2",     // in[1]
 "2",     // in[2]
 "1",     // a
 "2",     // b
 "2"      // c
]
```

The witness produced follows the expected layout.

Next, we check if a malicious witness would be accepted in this scenario.

***

#### *Informational: **`--O0`\*\*\*\* \*\*\*\*flag***

*If we had compiled without the **`--O0`** flag, in the terminal output linear constraints would list linear constraints as **0** and this would subsequently affect the structure of the witness later on.*

<figure><img src="https://1983523492-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0nwEx8a60yETwfNYnenT%2Fuploads%2FO8dRt4w7wKqrz4bbBWQG%2Fimage.png?alt=media&#x26;token=49dc9847-f969-4f82-9537-c5ca73d89d2a" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1983523492-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0nwEx8a60yETwfNYnenT%2Fuploads%2Fh0xPupFFonSqK2ROlAxQ%2Fimage.png?alt=media&#x26;token=3f9f66f2-49df-4a03-8c63-41eb55e2b948" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1983523492-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0nwEx8a60yETwfNYnenT%2Fuploads%2FY5fhNDgi5qQ9Z5hmTw9Q%2Fimage.png?alt=media&#x26;token=66dd65ee-9217-4495-a0f4-b42c124c7692" alt=""><figcaption></figcaption></figure>

*The reader is welcome to repeat the entire process with and without the **`--O0`** flag as a learning exercise.*

***

### Exploiting the circuit

We will attempt to exploit the circuit by creating a malicious witness and verifying it. The malicious witness will be created by modifying the valid `witness.wtns` file.

**Create `view.js` in the same directory as `witness.wtns` with the following code:**

{% code title="view\.js" %}

```rust
const fs = require('fs');
const path = require('path');

const witnessPath = path.join(__dirname, 'witness.wtns');

try {
    const witness = fs.readFileSync(witnessPath);
    
    let data_arr = new Uint8Array(witness);
    console.dir(data_arr, {'maxArrayLength': null});
  
} catch (error) {

    console.error(`Error reading witness file: ${error.message}`);
}
```

{% endcode %}

Running view\.js will give us the following output in terminal:

<figure><img src="https://1983523492-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0nwEx8a60yETwfNYnenT%2Fuploads%2FwlXFrsszXYJ79COBi7eW%2Fimage.png?alt=media&#x26;token=a0d8e8c4-3b2b-4719-bd0d-a9ab417abc94" alt=""><figcaption></figcaption></figure>

Observe that the values of our witness are laid out in the same sequential order as witness.json.

<figure><img src="https://1983523492-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0nwEx8a60yETwfNYnenT%2Fuploads%2FJXVTdouvAGtwRfn7JX3F%2Fimage.png?alt=media&#x26;token=37555b20-aa2f-4cc0-bb80-98433f0c711a" alt="" width="563"><figcaption></figcaption></figure>

#### Modify witness values

* Overwrite `witness.wtns` where the values for signals `a`, `b`, `c` are stored.
* Create `edit.js` file in the same directory:

{% code title="edit.js" %}

```jsx
const fs = require('fs');
const path = require('path');

// Use path.join to create a full path to the witness.wtns file
const witnessPath = path.join(__dirname, 'witness.wtns');

try {
    const witness = fs.readFileSync(witnessPath);
    
    let data_arr = new Uint8Array(witness);

    console.log("Before");
    console.dir(data_arr, {'maxArrayLength': null});

    data_arr[204] = 4;  // `a`
    data_arr[236] = 5;  // `b`
    data_arr[268] = 20; // `c`

    console.log("After");
    console.dir(data_arr, {'maxArrayLength': null});
		
    // create exploit witness 
    const exploitWitnessPath = path.join(__dirname, 'exploit_witness.wtns');
    fs.writeFileSync(exploitWitnessPath, data_arr);

} catch (error) {

    console.error(`Error reading witness file: ${error.message}`);
}
```

{% endcode %}

The <mark style="color:red;">`After`</mark> output should be like so:

<figure><img src="https://1983523492-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0nwEx8a60yETwfNYnenT%2Fuploads%2FabHqcyAMYilL3nXlKQ3g%2Fimage.png?alt=media&#x26;token=bc9adc32-9c1d-4031-9de4-8f5048fbb966" alt="" width="546"><figcaption></figcaption></figure>

Observe that only signals a, b, c are modified; the rest remain unchanged.

**Verify `exploit_witness.wtns` against the circuit:**

* `snarkjs wtns check positive.r1cs exploit_witness.wtns`

<figure><img src="https://1983523492-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0nwEx8a60yETwfNYnenT%2Fuploads%2FOfUTK0mOs9v1an9uVqVU%2Fimage.png?alt=media&#x26;token=7c880186-c13f-4521-9d52-cc62b013fa00" alt=""><figcaption></figcaption></figure>

This indicates that the malicious witness will not be accepted, as there input constraints to ensure that the circuit’s top-level signals match the inputs to **Mul()**.

Observe that the unmodified witness is accepted: <mark style="color:red;">`snarkjs wtns check positive.r1cs witness.wtns`</mark>

<figure><img src="https://1983523492-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0nwEx8a60yETwfNYnenT%2Fuploads%2FPaTdEYY5dBsoCJPiutCA%2Fimage.png?alt=media&#x26;token=979debf7-e056-43a9-8f89-efcf31d702fd" alt=""><figcaption></figcaption></figure>

Next, the negative example of using <mark style="color:red;">`<--`</mark>.

### Negative Example

```jsx
pragma circom 2.1.8;

template Mul() {
	signal input a;
	signal input b;
	signal input c;
	
	c === a * b;
}

template Main() {
    
	signal input in[3];

	// instantiate subcomponents
	component mul = Mul();
	
	// assign inputs
	mul.a <-- in[0];
	mul.b <-- in[1];
	mul.c <-- in[2];
	
}

component main = Main();
```

**Compile**

* <mark style="color:red;">**`circom negative.circom --r1cs --sym --wasm --O0`**</mark>
* Sanity check on terminal output:
  * <mark style="color:red;">`non-linear constraints: 1`</mark>
  * <mark style="color:red;">`linear constraints: 0`</mark>
  * <mark style="color:red;">**`private inputs: 3 (none belong to witness)`**</mark>

<figure><img src="https://1983523492-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0nwEx8a60yETwfNYnenT%2Fuploads%2FfOpzio5x54sZoi4FZpIA%2Fimage.png?alt=media&#x26;token=5df5d8c5-d749-4c5f-bfeb-88ffc986a552" alt=""><figcaption></figcaption></figure>

The above comment is a warning that there are 3 private inputs as per `in[3]`, however none of them are in the witness vector. This will be made apparent as we go along.

The other point of note, is that we no longer have 3 linear constraints, as we do not have input constraints in this scenario.

**Examine the R1CS file**

* <mark style="color:red;">**`snarkjs r1cs print negative.r1cs`**</mark>
* Terminal prints a single constraint: <mark style="color:red;">`main.add1.a + main.add1.b = main.add1.c`</mark>

<figure><img src="https://1983523492-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0nwEx8a60yETwfNYnenT%2Fuploads%2FMrxWSzJOlBPcOYBbPjVm%2Fimage.png?alt=media&#x26;token=98ca64ab-c9d8-4736-9f9f-eab435f58c14" alt=""><figcaption></figcaption></figure>

**Generate the witness**

* create `inputs.json` file in `./negative_js` directory:

{% code title="inputs.json" %}

```json
{"in": ["1", "2", "2"]}
```

{% endcode %}

* run: <mark style="color:red;">`node generate_witness.js negative.wasm inputs.json witness.wtns`</mark>
* export to json: <mark style="color:red;">`snarkjs wtns export json witness.wtns`</mark>
* <mark style="color:red;">`cat witness.json`</mark> should output the following:
* run: <mark style="color:red;">`node generate_witness.js negative.wasm inputs.json witness.wtns`</mark>
* export to json: <mark style="color:red;">`snarkjs wtns export json witness.wtns`</mark>
* <mark style="color:red;">`cat witness.json`</mark> should output the following:

```jsx
[
 "1",     // 1
 "1",     // in[0]
 "2",     // in[1]
 "2",     // in[2]
 "1",     // a
 "2",     // b
 "2"      // c
]
```

The witness produced follows the expected layout.\
Let’s check if a malicious witness would be accepted in this scenario.

### Exploiting the circuit

* create and run `edit.js` file in the same directory as `witness.wtns`
* layout of the witness variables are the same, and so the same modifications will work
* verify `exploit_witness.wtns` against the circuit:`snarkjs wtns check negative.r1cs exploit_witness.wtns`

<figure><img src="https://1983523492-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0nwEx8a60yETwfNYnenT%2Fuploads%2FWMqF0PjE70hdZSEW8B6D%2Fimage.png?alt=media&#x26;token=35b180ba-570a-4239-a6e2-f6d6744e626b" alt=""><figcaption></figcaption></figure>

The exploit works because we passed values \[`a=4`, `b=5`, `c=20`] to the subcomponent, satisfying its constraint, while `in[3]` held different values.

We successfully exploited the circuit by passing inconsistent values, demonstrating that it's under-constrained. This vulnerability allows an attacker to craft a fake witness using unrelated data, highlighting the importance of constraining inputs when passing them to subcomponents.
