# circom-MP-SPDZ
[ToC]
## Abstract
circom-MP-SPDZ allows parties to perform Multi-Party Computation (MPC) by writing Circom code using the MP-SPDZ framework. Circom code is converted to an arithmetic circuit and then gate by gate translated to the corresponding MP-SPDZ operators.
In the current structure, input files are not limited to MP-SPDZ and can be applied to other MPC frameworks. We can adapt `generate_mpspdz_circuit` and `generate_mpspdz_inputs_for_party` to support other MPC frameworks.
## Input files
### Computation
A computation is defined by two files: `circuit.circom` and `mpc_settings.json`.
- `circuit.circom` is an extended circom syntax, which supports more operators than the original circom. The list of supported operators can be found [here](https://github.com/namnc/circom-2-arithc/blob/e41f4bfa3b95010fe713a352b4df8e6af1e7c0ae/src/circuit.rs#L25-L37). For example, it could be
```circom
pragma circom 2.0.0;
template Main() {
signal input a;
signal input b;
signal input c <== 3;
signal output a_add_b <== a + b;
signal output a_mul_c <== a * c;
}
component main = Main();
```
- `mpc_settings.json` specifies which inputs a party should supply and which outputs a party can learn. It is an array of entries where the first entry is for party 0, the second entry is for party 1, etc. For example, it could be:
```json
[
{
"name": "alice",
"inputs": ["a"],
"outputs": ["a_add_b", "a_mul_c"]
},
{
"name": "bob",
"inputs": ["b"],
"outputs": ["a_add_b", "a_mul_c"]
}
]
```
This indicates that
- party 0
- name is `alice`
- should supply input `a`.
- should learn the value of outputs `a_add_b` and `a_mul_c` from the computation
- party 1
- name is `bob`
- should supply input `b`
- should learn the value of outputs `a_add_b` and `a_mul_c` from the computation
For a computation to be successfully carried out, parties must use the same `circuit.circom` and `mpc_settings.json` in order to generate the same MP-SPDZ circuit.
### Input values
- `inputs.json`: each party has an input file, containing all the values of the inputs they should supply according to `mpc_settings.json`.
For example, in `mpc_settings.json` party 0 is assigned to supply `a` and party 1 assigned to supply `b`.
`inputs.json` for party 0 should contain the value of `a`
```json
{
"a": 1
}
```
`inputs.json` for party 1 should contain the value of `b`
```json
{
"b": 2
}
```
## Workflow
Each party follows the following steps to perform a computation:
- [1. Generate MP-SPDZ circuit](#1-Generate-MP-SPDZ-circuit)
- [2. Generate MP-SPDZ inputs](#2-Generate-MP-SPDZ-inputs)
- [3. Run MPC with MP-SPDZ circuits and inputs](#3-Run-MPC-with-MP-SPDZ-circuits-and-inputs)
### 1. Generate MP-SPDZ circuit

#### 1.1. Circom to bristol fashion circuit
[circom-2-arithc](https://github.com/namnc/circom-2-arithc) converts `circuit.circom` to `circuit.txt`, a bristol fashion circuit with gates sorted in topological order. With this order, all inputs to a gate are available when the gate is executed. We can safely execute gates in this order. For example, `circuit.txt` would look like this:
```
# {num_gates} {num_wires}
2 5
# {num_inputs} {'1' * num_inputs}
3 1 1 1
# {num_outputs} {'1' * num_outputs}
2 1 1
# Below are {num_gates} lines.
# Each line is "{num_inputs} {num_outputs} {input_wire_index_0} {input_wire_index_1} {output_wire} {gate_type}"
2 1 1 0 3 AAdd
2 1 1 2 4 AMul
```
Another file `circuit_info.json` is also generated. It tells us how to interpret the wires in the bristol fashion circuit - which wires the inputs and outputs correspond to, and which wires are constants and can be assigned with values directly. For example,
```json
{
"input_name_to_wire_index": {
"a": 1,
"b": 0
},
"constants": {
"0.c": {
"value": 3,
"wire_index": 2
}
},
"output_name_to_wire_index": {
"a_add_b": 3,
"a_mul_c": 4
}
}
```
This means that the wire with index 1 is the input `a`, the wire with index 0 is the input `b`, the wire with index 2 is the constant `c` with value `3`, the wire with index 3 is the output `a_add_b`, and the wire with index 4 is the output `a_mul_c`.
#### 1.2. Bristol fashion circuit to MP-SPDZ circuit
[`generate_mpspdz_circuit`](https://github.com/mhchia/MP-SPDZ/blob/19018f1cfbba8641f005cdc8fa07aa3e14434db0/arithc_executor.py#L59-L142) generates a MP-SPDZ circuit `Circuits/circuit.mpc` under the MP-SPDZ project root. It translates each gate to their corresponding MP-SPDZ operator. For example, the above bristol fashion circuit is converted to the following MP-SPDZ circuit:
```python
wires = [sint.get_input_from(1), sint.get_input_from(0), cint(3), None, None]
# wires[3] = a_add_b (2 1 1 0 3 AAdd) and is translated to + operator in MP-SPDZ
wires[3] = wires[1] + wires[0]
# wires[4] = a_mul_c (2 1 1 2 4 AMul) and is translated to * operator in MP-SPDZ
wires[4] = wires[1] * wires[2]
# Print outputs according to mpc_settings.json
print_ln_to(0, 'outputs[0]: a_add_b=%s', wires[3].reveal_to(0))
print_ln_to(0, 'outputs[1]: a_mul_c=%s', wires[4].reveal_to(0))
print_ln_to(1, 'outputs[0]: a_add_b=%s', wires[3].reveal_to(1))
print_ln_to(1, 'outputs[1]: a_mul_c=%s', wires[4].reveal_to(1))
```
In the code above,
- `wires` is a list with 5 elements. According to `circuit_info.json` and `mpc_settings.json`,
- `wires[0]` is `b` and it should be supplied by party 1
- `wires[1]` is `a` and it should be supplied by party 0
- `wires[2]` is `c` and it's a constant with value `3`
- `wires[3]` is `a_add_b` and it is `None` because it should be computed in the following gates
- `wires[4]` is `a_mul_c` and it is `None` because it should be computed in the following gates
- `wires[3] = wires[1] + wires[0]` is the translation of the `AAdd` gate to the `+` operator in MP-SPDZ. `wires[4] = wires[1] * wires[2]` is the translation of the `AMul` gate to the `*` operator in MP-SPDZ.
- `print_ln_to(0, 'outputs[0]: a_add_b=%s', wires[3].reveal_to(0))` prints the value of `a_add_b` to party 0, as defined in `mpc_settings.json`, etc.
### 2. Generate MP-SPDZ inputs
Each party translates their `inputs.json` to the format MP-SPDZ requires by running [`generate_mpspdz_inputs_for_party`](https://github.com/mhchia/MP-SPDZ/blob/19018f1cfbba8641f005cdc8fa07aa3e14434db0/arithc_executor.py#L205-L246) with `circuit_info.json` and `mpc_settings.json` as inputs. The generated input file is stored in `Player-Data/Input-P{party}-0` under the MP-SPDZ project root.

For example, the above `inputs.json` for party 0 is converted to `Player-Data/Input-P0-0`
```bash
1
```
and the above `inputs.json` for party 1 is converted to `Player-Data/Input-P1-0`
```bash
2
```
### 3. Run MPC with MP-SPDZ circuits and inputs
With the generated circuit and inputs for MP-SPDZ, parties can run MP-SPDZ and get the computation result.

For testing, you can run all parties in your local machine. Or, each party can run on different machines and interact with each other through the network.
#### 1. Run all parties in the same machine
First, go to the project root of MP-SPDZ.
```bash
cd /path/to/MP-SPDZ
```
Run all parties in your local machine with the script
```bash
./Scripts/compile-run.py -E {mpc_protocol} {circuit_name}
```
where `{mpc_protocol}` is a protocol supported by MP-SPDZ you want to use (e.g., `semi`, `mascot`, [etc](https://mp-spdz.readthedocs.io/en/latest/readme.html#protocols)). `{circuit_name}` is the name of the circuit you want to run. For example, to run `circuit.mpc` with `semi` protocol:
```bash
./Scripts/compile-run.py -E semi circuit
```
#### 2: Run parties in different machines
For each party, run the following commands in the MP-SPDZ project root:
**Step 1:** Compile the VM for `semi` protocol
```bash
make -j8 semi-party.x
```
**Step 2:** Compile the circuit `circuit.mpc` to bytecode
```bash
./compile.py circuit
```
**Step 3:** Create a file with the IP addresses of all parties. For example, a file `hosts` with the following content:
```
18.183.238.119:3000
43.207.105.60:4000
```
it means party 0 will listen to `18.183.238.119:3000` and party 1 to `43.207.105.60:4000`. Note that all parties must use the same file.
**Step 4:** Run the party with the VM and bytecode. For example, to run party 0 with `circuit.mpc`:
```bash
./semi-party.x -N 2 -p 0 -OF . circuit -ip hosts
```
and party 1:
```bash
./semi-party.x -N 2 -p 1 -OF . circuit -ip hosts
```
where
- `-N 2`: there are two parties
- `-p 1`: this is party 0
- `-OF .`: outputs are printed to stdout
Outputs are printed to the console. For example, both party 0 and 1 will see the outputs`a_add_b` and `a_mul_c`:
```
outputs[0]: a_add_b=3
outputs[1]: a_mul_c=3
```
due to the settings we have in `mpc_settings.json`.
<!--
Old content of circom-2-arithc

#### 1.1. Circom to arithmetic circuit
[circom-2-arithc](https://github.com/namnc/circom-2-arithc) converts `circuit.circom` to `circuit.json`, which is an arithmetic representation of the circuit and is easier to work with than circom. For example, the above circom code is converted to:
```json
{
...,
"gates": [
{
"id": 0,
"gate_type": "AAdd",
"lh_input": 339827882353457231733281877774418513,
"rh_input": 261273425065800872138523378011643318856,
"output": 230661140909065778448104897333394910284
},
{
"id": 1,
"gate_type": "AMul",
"lh_input": 339827882353457231733281877774418513,
"rh_input": 224358152556191904480812644829082501076,
"output": 176538014183051407881132466597081583306
}
]
}
```
#### 1.2. Arithmetic circuit to bristol fashion circuit
Inputs to a gate can be outputs from other gates. Executing gates in the order listed in `circuit.json` might lead to errors if a gate's inputs have not yet been computed. The script [json_abristol.py](https://github.com/mhchia/MP-SPDZ/blob/19018f1cfbba8641f005cdc8fa07aa3e14434db0/json_abristol.py) converts `circuit.json` to `circuit.txt`, a bristol fashion circuit with gates sorted in topological order. With this order, all inputs to a gate are available when the gate is executed. We can safely execute gates in this order. For example, `circuit.txt` would look like this:
```
# {num_gates} {num_wires}
2 5
# {num_inputs} {'1' * num_inputs}
3 1 1 1
# {num_outputs} {'1' * num_outputs}
2 1 1
# Below are {num_gates} lines.
# Each line is "{num_inputs} {num_outputs} {input_wire_index_0} {input_wire_index_1} {output_wire} {gate_type}"
2 1 1 0 3 AAdd
2 1 1 2 4 AMul
```
Another file `circuit_info.json` is also generated. It tells us how to interpret the wires in the bristol fashion circuit - which wires the inputs and outputs correspond to, and which wires are constants and can be assigned with values directly. For example, we have the following `circuit_info.json` generated from the `circuit.json` above:
```json
{
"input_name_to_wire_index": {
"a": 1,
"b": 0
},
"constants": {
"0.c": {
"value": 3,
"wire_index": 2
}
},
"output_name_to_wire_index": {
"a_add_b": 3,
"a_mul_c": 4
}
}
```
This means that the wire with index 1 is the input `a`, the wire with index 0 is the input `b`, the wire with index 2 is the constant `c` with value `3`, the wire with index 3 is the output `a_add_b`, and the wire with index 4 is the output `a_mul_c`.
-->