vOPRF-ID is a monorepo containing implementations for secure nullifier generation based on verifiable Oblivious Pseudorandom Functions (vOPRF).
You can read more about the protocol in our docs
This monorepo contains implementation of all necessary components:
- vOPRF MPC Node implementation
- Client Side zk Circuits for verifiability
- Registry smart-contract for OPRF nodes
- Optional check script for OPRF nodes
You can run a vOPRF MPC node either locally or in a docker container.
This step is optional, as you can reuse an already deployed contract, where OPRF nodes can store their public keys.
If you want to deploy your own contract:
cd packages/registry
Then create the .env file, and fill it as described in .env.example.
To deploy, run:
forge script script/Registry.s.sol:RegistryScript --rpc-url "<YOUR_RPC_URL>" --broadcast --private-key "<YOUR_PRIVATE_KEY>" -vvvv
Get the deployed contract address, as we'll use it to run OPRF nodes.
First, you need to create an .env file as described in .env.example. For the "REGISTRY_ADDRESS" field - you can use one of the deployed contracts. You should create the .env file in the project root (as well as run other commands).
cargo run --release -- initialize # This will create an OPRF node private key, store the public key in the registry, and save the private key to a file
To run the node:
cargo run --release -- serve # This will run a vOPRF node
docker build -t voprf . --no-cache
docker run -it --cap-add=NET_ADMIN --name=party1 -p 8081:8080 voprf
Even if you run in the Docker - you'll still need to set a Registry contract, and initialize the node.
ZK gives us verifiability of OPRF output. You can see how it works in a protocol overview. The project contains two separate zk circuits as it's described in the protocol. To run the first one you have to fill the Prover.toml file first. Then, to generate witness, vkey and zk proof:
cd packages/zk/oprf_commitment
nargo execute
bb prove -b ./target/oprf_commitment.json -w ./target/oprf_commitment.gz -o ./target/proof
bb write_vk -b ./target/oprf_commitment.json -o ./target
bb verify -k ./target/vk -p ./target/proof
You have to put vkey to the /generated dir, so that OPRF nodes can verify the first circuit.
You can send the generated proof to the vOPRF node using the testing script:
cd packages/scripts
python3 -m venv .venv
source .venv/bin/activate
pip3 install requests
python3 test_api.py --address localhost --port 8080
--
To generate a final zk proof that contains nullifier
- you have to fill the inputs in the Prover.toml file.
And run:
cd packages/zk/oprf_nullifier
nargo execute
bb prove -b ./target/oprf_nullifier.json -w ./target/oprf_nullifier.gz -o ./target/proof
bb write_vk -b ./target/oprf_nullifier.json -o ./target
bb verify -k ./target/vk -p ./target/proof
Current version slightly differs from the specification, for example - using Secp256k1 instead of BabyJubJub. In subsequent versions, the implementation will be updated and improved for usability (as well as benchmarks).