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
To reach a very large group of developers, a protocol needs to be extremely user-friendly, understandable and simple.
Achieve an excellent balance between simplicity and functionality through modularity, autonomy, and interoperability.
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
Enabling developers to focus on innovation by simplifying complexities while supporting diverse use cases.
Empowering individuals with knowledge, resources, and support, ensuring they're equipped to innovate and solve challenges.
Fostering spaces where collaboration thrives, ideas flourish, and diverse voices are celebrated.
Zero Knowledge: new cryptography
Zero-knowledge is a new field in cryptography that allows developers to build apps that allow users to share information with each other without revealing their identities or the contents of the information being shared.
Learn more
Characteristics
To reach a very large group of developers, a protocol needs to be extremely user-friendly, understandable and simple.
Achieve an excellent balance between simplicity and functionality through modularity, autonomy, and interoperability.
A protocol must not only work, it must also be extremely efficient if the goal is to support privacy by default for everyone.
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
})
Videos
Articles