Skip to content

Commit

Permalink
added multiplexing
Browse files Browse the repository at this point in the history
  • Loading branch information
erhant committed Dec 14, 2024
1 parent 7b804b0 commit d4f10ed
Show file tree
Hide file tree
Showing 11 changed files with 163 additions and 17 deletions.
5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,8 @@
"preliminary": "Custom",
"advanced": "Font"
},
"jestrunner.jestCommand": "bun test"
"jestrunner.jestCommand": "bun test",
"github.copilot.enable": {
"markdown": true
}
}
12 changes: 6 additions & 6 deletions book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@
- [Bits](./bits/README.md)
- [Logic Gates](./bits/logic-gates.md)
- [Comparators](./comparators/README.md)
- [Constant Comparisons](./comparators/constant.md)
- [Constant Comparisons 🚧](./comparators/constant.md)
- [Range Check](./comparators/range-check.md)
- [Control Flow](./control-flow/README.md)
- [Multiplexing](./control-flow/mux.md)
- [Multiplexing](./control-flow/multiplexing.md)
- [Arrays](./arrays/README.md)
- [Distinct](./arrays/distinct.md)
- [Sorted](./arrays/sorted.md)
- [Hashing](./hashing/README.md)
- [Poseidon](./hashing/poseidon.md)
- [MiMC](./hashing/mimc.md)
- [Hashing 🚧](./hashing/README.md)
- [Poseidon 🚧](./hashing/poseidon.md)
- [MiMC 🚧](./hashing/mimc.md)
- [Merkle Trees](./merkle-trees/README.md)
- [Sparse Merkle Tree](./merkle-trees/smt.md)
- [Sparse Merkle Tree 🚧](./merkle-trees/smt.md)
- [Advanced](./advanced/README.md)

# Examples
Expand Down
16 changes: 12 additions & 4 deletions book/src/arithmetic/multiplication.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,26 @@ There is really not much more to talk about in this circuit. It is simply a grea
## Soundness
Imagine that you would like to use the circuit above to prove that you know the prime factors $p_1, p_2, \ldots, p_n$ for some number:
Imagine that you would like to use the circuit above to prove that you know some factors $q_1, q_2, \ldots, q_n$ for some number:
$$
k = \prod_{i=1}^{n}p_i
k = \prod_{i=1}^{n}q_i
$$
Would it be okay to use the circuit above as given, with `out` as the only public signal?
If you think about this for a while, you will realize that the circuit does not care if a factor is 1 or not! Meaning that one can provide the same proof just by providing an array `[k, 1, ..., 1]` since:
$$
k = \prod_{i=1}^{n}p_i = k \times \prod_{i=2}^{n}1
k = \prod_{i=1}^{n}q_i = k \times \prod_{i=2}^{n}1
$$
The circuit author is responsible from checking these edge-cases, and writing the necessary constrains to prevent such soundness errors.
Even further, if $n$ is even one can do:
$$
k = k \times \prod_{i=2}^{n/2} r_i \times r_i^{-1}
$$
These are classified as soundness errors, as they allow creating of valid proofs without actually proving the intended statement.
> The circuit author is responsible from checking these edge-cases, and writing the necessary constrains to prevent soundness errors.
61 changes: 61 additions & 0 deletions book/src/control-flow/multiplexing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Multiplexing

Multiplexing is a technique to select one of many signals based on a control signal. It is often used to switch between different signals or to select a signal based on a condition.

## `Mux1`

```cs
template Mux1() {
signal input in[2];
signal input sel;
signal output out;

out <== (in[1] - in[0]) * sel + in[0];
}
```

`Mux1` is actually the same circuit as `IfElse` we defined in this section. Its just that the naming is a bit different, such that it is generalizable to higher multiplexers.

- `in[0]` is `ifFalse`
- `in[1]` is `ifTrue`
- `sel` is `cond`
- `out` is `out`

The main idea here is that `in` has number of values equal to the number of bits of `sel`, and `out = in[sel]`.

To compute this expression, on can construct the truth table and then its corresponding boolean expression. The truth table for `Mux1` is:

| sel | out |
| --- | ------- |
| 0 | `in[0]` |
| 1 | `in[1]` |

## `Mux2`

```cs
template Mux2() {
signal input in[4];
signal input sel[2];
signal output out;

// due to multiplication we need an auxiliary signal
signal sel_0_sel_1 <== sel[1] * sel[0];

signal a11 <== (in[3] - in[2] - in[1] + in[0]) * sel_0_sel_1;
signal a10 <== (in[2] - in[0]) * sel[1];
signal a01 <== (in[1] - in[0]) * sel[0];
signal a00 <== in[0];

out <== (a11 + a10 + a01 + a00);
}
```

One can actually construct a `Mux2` using three `Mux1` circuits.

- `inA <== Mux1(in[0], in[1], sel[0])`
- `inB <== Mux1(in[2], in[3], sel[0])`
- `out <== Mux1(inA, inB, sel[1])`

## Larger Multiplexers

There are larger multiplexing circuits, e.g. [`Mux3`](https://github.com/iden3/circomlib/blob/circomlib2/circuits/mux3.circom), [`Mux4`](https://github.com/iden3/circomlib/blob/circomlib2/circuits/mux4.circom), etc. but we will not cover them here.
3 changes: 0 additions & 3 deletions book/src/control-flow/mux.md

This file was deleted.

Binary file modified bun.lockb
Binary file not shown.
40 changes: 40 additions & 0 deletions circuits/control-flow/multiplexing.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// "2-to-1" multiplexer.
//
// Inputs:
// - in: inputs
// - sel: selector bit
//
// Outputs:
// - out: equals in[sel]
template Mux1() {
signal input in[2];
signal input sel;
signal output out;

out <== (in[1] - in[0]) * sel + in[0];
}

// "4-to-1" multiplexer.
//
// Inputs:
// - in: inputs
// - sel: selector bits
//
// Outputs:
// - out: equals in[2*sel[1] + sel[0]]
template Mux2() {
signal input in[4];
signal input sel[2];
signal output out;

// due to multiplication we need an auxiliary signal
signal sel_0_sel_1 <== sel[1] * sel[0];

signal a11 <== (in[3] - in[2] - in[1] + in[0]) * sel_0_sel_1;
signal a10 <== (in[2] - in[0]) * sel[1];
signal a01 <== (in[1] - in[0]) * sel[0];
signal a00 <== in[0];

out <== (a11 + a10 + a01 + a00);
}

2 changes: 1 addition & 1 deletion circuits/test/comparators/compconstant.circom
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ pragma circom 2.0.0;

include "../../comparators/constant.circom";

component main = CompConstant(1093);
component main = CompConstant(9900);
6 changes: 6 additions & 0 deletions circuits/test/control-flow/mux1.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// auto-generated by circomkit
pragma circom 2.0.0;

include "../../control-flow/multiplexing.circom";

component main = Mux2();
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
"book:build": "cd book && mdbook build"
},
"dependencies": {
"circomkit": "^0.2.1",
"circomlib": "^2.0.5"
"circomkit": "^0.3.1",
"circomlib": "^2.0.5",
"snarkjs": "^0.7.5"
},
"devDependencies": {
"@types/bun": "^1.1.0",
Expand Down
30 changes: 30 additions & 0 deletions tests/control-flow/multiplexing.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { circomkit } from "../common";
import { describe, beforeAll, it } from "bun:test";

describe("multiplexing", () => {
it("2-to-1 multiplex", async () => {
const circuit = await circomkit.WitnessTester<["in", "sel"], ["out"]>(`mux1`, {
file: "control-flow/multiplexing",
template: "Mux1",
dir: "test/control-flow",
});

const input = [101, 202];
await circuit.expectPass({ in: input, sel: 0 }, { out: input[0] });
await circuit.expectPass({ in: input, sel: 1 }, { out: input[1] });
});

it("4-to-1 multiplex", async () => {
const circuit = await circomkit.WitnessTester<["in", "sel"], ["out"]>(`mux1`, {
file: "control-flow/multiplexing",
template: "Mux2",
dir: "test/control-flow",
});

const input = [234, 678, 123, 987];
await circuit.expectPass({ in: input, sel: [0, 0] }, { out: input[0] });
await circuit.expectPass({ in: input, sel: [1, 0] }, { out: input[1] });
await circuit.expectPass({ in: input, sel: [0, 1] }, { out: input[2] });
await circuit.expectPass({ in: input, sel: [1, 1] }, { out: input[3] });
});
});

0 comments on commit d4f10ed

Please sign in to comment.