UniRep: Universal Reputation

Using zero knowledge, UniRep allows users to voluntarily prove their membership of a group and reputation or data in the group without revealing their original identity. The goal is to make UniRep a standard for anonymous reputation and group membership proving.

Principles

Accessibility

To reach a very large group of developers, a protocol needs to be extremely user-friendly, understandable and simple.

Composability

Achieve an excellent balance between simplicity and functionality through modularity, autonomy, and interoperability.

Efficiency

A protocol must not only work, it must also be extremely efficient if the goal is to support privacy by default for everyone.

Main focus

Developer experience

Enabling developers to focus on innovation by simplifying complexities while supporting diverse use cases.

Education

Empowering individuals with knowledge, resources, and support, ensuring they're equipped to innovate and solve challenges.

Community

Fostering spaces where collaboration thrives, ideas flourish, and diverse voices are celebrated.

Attesters

Attesters are responsible for attesting to the reputation of users. They can be Ethereum accounts, multi-sig wallets or smart contracts.

Design an attester

pragma solidity ^0.8.0; import {Unirep} from '@unirep/contracts/Unirep.sol'; contract Attester { Unirep public unirep; constructor( Unirep _unirep, uint48 _epochLength ) { // set UniRep address unirep = _unirep; // sign up as an attester unirep.attesterSignUp(_epochLength); } }

Users

Users in UniRep protocol can choose to signup in one or more attesters. Once users signup, they can start to be attested by attesters and generate reputation or data proofs.

Generate User State

import { UserState } from '@unirep/core' import { defaultProver } from '@unirep/circuits/provers/defaultProver' import { Identity } from '@semaphore-protocol/identity' const id = new Identity() const userState = new UserState({ prover: defaultProver, // a circuit prover unirepAddress: '0xaabbccaabbccaabbccaabbccaabbccaabbccaaaa', provider, // an ethers.js provider id, }) // start the synchoronizer deamon await userState.start() await userState.waitForSync()

Data

UniRep protocol supports two types of data field: addition data field and replacement data field. The elements in addition field are combined with addition. The elements in replacement field are combined by replacement.

Learn more about data fields

// addition data field old_data[0] = 3 new_data[0] = 5 final_data[0] = old_data[0] + new_data[0] = 8 // replacement data field old_data[0] = 3 new_data[0] = 5 final_data[0] = new_data[0] = 5

Epoch Key

Epoch key is used to receive data from attesters. It works like an Ethereum address to receive tokens, but each user can generate multiple epoch keys per epoch, and each epoch key cannot be linked to the same user.

Generate an epoch key to receive data

import { genEpochKey } from '@unirep/utils' // get epoch from contract const epoch = await unirepContract.attesterCurrentEpoch(attester.address) // define nonce const nonce = 0 // it could be 0 to (NUM_EPOCH_KEY_NONCE - 1) per user // get chainId from ethers.js provider const { chainId } = await provider.getNetwork() // generate an epoch key const epochKey = genEpochKey( identity.secret, BigInt(attester.address), epoch, nonce, chainId, )

Attest

The attesters are responsible for attesting to the epoch key of the users. The attester can define the attest rules and execute it in the smart contract.

Define Attest Rules

function attest( uint epochKey, uint48 epoch, ) public { // only attest to field index = 0 uint fieldIndex = 0; // only attest with value = 5 uint val = 5; unirep.attest(epochKey, epoch, fieldIndex, val); }

User State Transition

After receiving data from attesters, users should perform a user state transition to update the user state on-chain. It should be called after an epoch finishes.

Perform Transition

// call to make sure the state is updated await userState.waitForSync() // generate the user state transition proof const { proof, publicSignals } = await userState.genUserStateTransitionProof() // sends the tx const tx = await unirepContract.userStateTransition( publicSignals, proof ) await tx.wait()

Prove Reputation

After user state is updated in the latest epoch, the users can generate reputation proofs to prove their reputation in the group.

Generate Reputation Proof

// call to make sure the state is updated await userState.waitForSync() // the data that the user wants to prove // If the user has 5, they can choose to prove they have more than 3 const repProof = await userState.genProveReputationProof({ minRep: 3 })
UniRep logo

Discord community

Give feedback & discuss ideas

Copyright © 2023 Ethereum Foundation