circom-MP-SPDZ

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. For example, it could be
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:
[
    {
        "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

{
    "a": 1
}

inputs.json for party 1 should contain the value of b

{
    "b": 2
}

Workflow

Each party follows the following steps to perform a computation:

1. Generate MP-SPDZ circuit

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

1.1. Circom to bristol fashion circuit

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,

{
    "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 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:

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 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.

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

For example, the above inputs.json for party 0 is converted to Player-Data/Input-P0-0

1

and the above inputs.json for party 1 is converted to Player-Data/Input-P1-0

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.

3_run_mpc_and_get_result.drawio

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.

cd /path/to/MP-SPDZ

Run all parties in your local machine with the script

./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). {circuit_name} is the name of the circuit you want to run. For example, to run circuit.mpc with semi protocol:

./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

make -j8 semi-party.x

Step 2: Compile the circuit circuit.mpc to bytecode

./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:

./semi-party.x -N 2 -p 0 -OF . circuit -ip hosts

and party 1:

./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 outputsa_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.