Skip to content

Yoii-Inc/zk-mpc

Repository files navigation

This repositry is zk-mpc.

Directory Structure

The following is the main directory structure.

  • /circuits
    • This module contains various circuits.
    • circuit.rs
      • This file defines the circuit for MPC.
    • input_circuit.rs
      • This file defines the input circuit for prove the correctness of secret inputs sharing.
  • /she
  • input.rs
    • This file defines the input struct used in the corresponding circuit.
  • bin_werewolf.rs
    • This is the binary file for werewolf game.
  • main.rs
    • This file is the main binary file. Mainly, used for preprocessing phase.
  • online.rs
    • This file is the second binary file. Mainly, used for online phase.
  • preprocessing.rs
    • This file defines the preprocessing module.
    • MPC protocol requires preprocessing.

Build guide

Clone this repositry:

git clone https://github.com/Yoii-Inc/zk-mpc.git

and build:

cargo build

setup input file

cp ./inputs/inputs-template.json ./inputs/inputs.json

Preprocessing phase

setup output folder

mkdir ./outputs
mkdir ./outputs/0
mkdir ./outputs/1
mkdir ./outputs/2

run(by groth16):

cargo run --bin main groth16 ./inputs/inputs.json

or run(by marlin):

cargo run --bin main marlin ./inputs/inputs.json

Online phase

run online phase

./run_online.zsh

Tests

The tests performed by the following DOES NOT include MPC. Therefore, testing of the MPC itself is performed by executing preprocessing and online as described above.

cargo test --bin main

Usage

how to specify secret inputs

To specify secret inputs, follow these steps:

  1. In the inputs/inputs.json file, define the desired inputs using a JSON format. For example:

    {
        "arg1": 10,
        "arg2": -2,
        "arg3": "value3"
    }

    You can modify the number and types of arguments based on your requirements.

  2. In the main.rs file of your project, use the ArgInput struct to receive the specified arguments. Make sure to update the struct definition to match the number and types of arguments you specified in the inputs.json file. For example:

    struct ArgInput {
        arg1: u128,
        arg2: i32,
        arg3: String,
    }

    Modify the ArgInput struct as needed to accommodate the changes in the number and types of arguments.

By following these steps, you can specify secret inputs in the inputs.json file and receive them in your Rust program using the ArgInput struct.

how to specify constraints

Constraints are specified in input_circuit.rs. For example:

pub struct MySecretInputCircuit<F: PrimeField + LocalOrMPC<F>> {
    // private witness to the circuit
    x: Option<F>,
    input_bit: Option<Vec<F>>,
    open_bit: Option<Vec<F>>,
    params: Option<F::PedersenParam>,

    // public instance to the circuit
    h_x: Option<F::PedersenCommitment>,
    lower_bound: Option<F>,
    upper_bound: Option<F>,
}

This sturuct represents a circuit, and it requires to define the necessary witness and public instances.

In addition, the constraints in the circuit are defined as follows.

impl<F: PrimeField + LocalOrMPC<F>> ConstraintSynthesizer<F> for MySecretInputCircuit<F> {
    fn generate_constraints(self, cs: ConstraintSystemRef<F>) -> Result<(), SynthesisError> {
        self.verify_constraints(cs.clone())?;

        self.verify_commitment(cs.clone())?;

        Ok(())
    }
}

In addition to usual constraints, we also defines one here to calculate commitments.

Here we show the example of the former constraints:

impl<F: PrimeField + LocalOrMPC<F>> MySecretInputCircuit<F> {
    fn verify_constraints(&self, cs: ConstraintSystemRef<F>) -> Result<(), SynthesisError> {
        let x = FpVar::new_witness(cs.clone(), || {
            self.x.ok_or(SynthesisError::AssignmentMissing)
        })?;

        let lower_bound = FpVar::new_input(cs.clone(), || {
            self.lower_bound.ok_or(SynthesisError::AssignmentMissing)
        })?;

        let upper_bound = FpVar::new_input(cs.clone(), || {
            self.upper_bound.ok_or(SynthesisError::AssignmentMissing)
        })?;

        x.enforce_cmp(&lower_bound, Ordering::Greater, true)?;
        x.enforce_cmp(&upper_bound, Ordering::Less, false)?;

        Ok(())
    }
}

See this to learn more about how to specify constraints.

how to specify mpc calculation

online mpc calculations are specified in circuits/circuit.rs. Defaultly, MySimpleCircuit is used. Constraints is specified in same way as input_circuit.rs.

Example - Werewolf

Initialize werewolf game. The following command initializes the game with 3 players. Game files are generated in werewolf/ directory.

./run_werewolf.zsh init 3

Run the game. The following command runs the game in the night phase. The command is written in Default zsh file, that player allocated fortune teller get whether next player is werewolf or not and outputs the result to e.g. werewolf/0/divination_result.json.

./run_werewolf.zsh night

Technical Details

Generating secret sharing of inputs and ZKP verification

The additive secret sharing method is used in SPDZ, and the secret information $S$ is kept in the form of shares $S_i$ such that

$$S=\sum_{i=1}^nS_i$$

With respect to the input values of SPDZ, a participant's share of secret information $X$ is constructed as follows.

  1. Each participant has a share $r_i$ of a random number $r$. The value of $r$ is unknown to anyone at this point.
  2. The participant who wants to create a share of secret information $x$ recovers the value of $r$ and broadcasts $\varepsilon=x-r$.
  3. Each participant $P_i$ determines its share $x_i$ of $x$ as $x_1=r_1+\varepsilon, x_i=r_i(i\neq 1)$. In this case, $x=\sum x_i$ holds.

The share $x_i$ is created by such a procedure, but it is not generally known whether each participant has composed the share according to the protocol, or whether the original secret information $x$ satisfies certain conditions.

Therefore, for each conditional secret input $x$, we use zkp to prove that each person's share of $x$ has been correctly created.

  • Secret input
    • $x$: secret information
    • $randomenesss$: randomness for commitment.
  • Public input
    • $h_x$: commitment of secret value $x$.

For these, the participant who has secret inputs creates a proof so that the following relation is satisfied.

$$ \begin{align*} C(x)&=0\\ Commitment(x, randomeness)&=h_x \end{align*} $$

where the 1st equation is the condition that $x$ must satisfy.

Requirement for $r$ and $\varepsilon$ isn't necessary, since SPDZ protocol has MAC verification for authenticated shares.s

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages