Unirep
  • 👏Welcome
  • 🧩Introduction
  • 🎮Getting Started
    • Install & build 🛠
    • Start with cli commands 🔌
      • 0. Install and build
      • 1. Spin up the testing chain
      • 2. Deploy Unirep contract
      • 3. User generates semaphore identity
      • 4. User signs up
      • 5. Attester signs up
      • 6. User generates epoch key and epoch key proof
      • 7. Attesters/Users verify epoch key proof
      • 8. Submit epoch key proof to Unirep smart contract
      • 9. Attester attest to epoch key
      • 10. Epoch transition
      • 11. User state transition
      • 12. User generates reputation proof
      • 13. Attesters/ Users verify the reputation proof
      • 14. User generates sign up proof
      • 15. Attesters/ Users verify the sign up proof
    • Start with Typescript 📠
      • 0. Install packages
      • 1. deploy
      • 2. User signs up
      • 3. Attester signs up
      • 4. Epoch key proof
      • 5. Attest
      • 6. Epoch transition
      • 7. User state transition
      • 8. Reputation proof
    • Computation happens off-chain â„šī¸
  • â˜€ī¸Protocol
    • Glossary
      • Users and Attesters
      • Epoch
      • Epoch Key
      • Reputation
      • Trees
      • Nullifiers
      • Epoch Transition
      • User State Transition
    • Circuits
      • Epoch Key Proof
      • Reputation Proof
      • User Sign Up Proof
      • User State Transition Proof
    • Contract
      • Sign up
      • Attestations
      • Epoch transition
      • User state transition
      • Verify proofs
  • 🌈Package usage
    • @unirep/crypto
    • @unirep/circuits
    • @unirep/contracts
    • @unirep/core
    • @unirep/subgraph
    • cli
      • Deploy Unirep Contract
      • User Identity
      • User Sign Up
      • Epoch Key And Proof
      • Attestation
      • Epoch transition
      • User state transition
      • Reputation Proof
      • Airdrop Reputation
      • Spend Reputation
  • đŸŒģApplications
    • Unirep Social
Powered by GitBook
On this page
  • DB
  • Prover
  • Identity
  • Generate current user state
  • Generate epoch key proof
  • Submit epoch key proof
  • Get proof index
  • Verify epoch key proof
  • Verify UniRep state

Was this helpful?

Edit on GitHub
  1. Getting Started
  2. Start with Typescript 📠

4. Epoch key proof

Previous3. Attester signs upNext5. Attest

Last updated 2 years ago

Was this helpful?

Before generating an epoch key proof, we should generate a current user state to know the current s and the attestation histories.

DB

We should initialize a storage to save the state.

import { DB, SQLiteConnector } from 'anondb/node'
import { schema } from '@unirep/core'

// construct a memory db
const db = await SQLiteConnector.create(schema, ':memory:')
// or construct a SQLite db
// const db = await SQLiteConnector.create(schema, 'test.sqlite')

Prover

Also we have to initialize a prover to generate proofs and verify proofs.

const snarkjs = require('snarkjs')
import { Circuit, Prover } from '@unirep/circuits'
import { SnarkProof, SnarkPublicSignals } from '@unirep/crypto'
const buildPath = 'PATH/TO/THE/KEYS/'

const prover: Prover = {
    genProofAndPublicSignals: async (
        proofType: string | Circuit,
        inputs: any
    ): Promise<{
        proof: any,
        publicSignals: any
    }> => {
        const circuitWasmPath = buildPath + `${proofType}.wasm`
        const zkeyPath = buildPath + `${proofType}.zkey`
        const { proof, publicSignals } = await snarkjs.groth16.fullProve(
            inputs,
            circuitWasmPath,
            zkeyPath
        )
        return { proof, publicSignals }
    },
    verifyProof: async (
        name: string | Circuit,
        publicSignals: SnarkPublicSignals,
        proof: SnarkProof
    ): Promise<boolean> => {
        const vkey = require(buildPath + `${name}.vkey.json`)
        return snarkjs.groth16.verify(vkey, publicSignals, proof)
    },
}

yarn && yarn build

The buildPath will be found at packages/circuits/zksnarkBuild

In the future it will be uploaded to a server to be downloaded.

Identity

Also, the ZkIdentity can be unserialized with a serialized identity, for example:

import { ZkIdentity, Strategy } from '@unirep/core'

const identity = new ZkIdentity(
    Strategy.SERIALIZED, 
    `{"identityNullifier":"27d1ae5c98aab64b851a9c668a7eec0d835867a17d4b9454a8bf9824836271d6","identityTrapdoor":"2596ecc2a1e1f6a8f279e097464e6edc3b18b946d934398dfe52a34c4e414e67","secret":["27d1ae5c98aab64b851a9c668a7eec0d835867a17d4b9454a8bf9824836271d6","2596ecc2a1e1f6a8f279e097464e6edc3b18b946d934398dfe52a34c4e414e67"]}`
)

Generate current user state

And then we can use a genUserState to perform synchronization.

const genUserState = async (
    provider: ethers.providers.Provider,
    address: string,
    userIdentity: ZkIdentity,
    db: DB
) => {
    const contract = getUnirepContract(address, provider)
    const userState = new UserState(
        db,
        prover,
        contract,
        userIdentity
    )
    await userState.start()
    await userState.waitForSync()
    return userState
}
const userState = await genUserState(
    provider,
    UNIREP_CONTRACT_ADDRESS,
    identity,
    db
)

Generate epoch key proof

Use the user state to generate epoch key proof.

// genearte epoch key proof
const epochKeyNonce = 0
const proof = await userState.genVerifyEpochKeyProof(epochKeyNonce)

Submit epoch key proof

const tx = await contract.submitEpochKeyProof(
    proof.publicSignals,
    proof.proof
)

Get proof index

Then get the proof index with the proof hash

const proofHash = proof.hash()
const proofIdx = await contract.getProofIndex(proofHash)
console.log(proofIdx)

Verify epoch key proof

Verify the proof with UniRep smart contract

const isValid = await contract.verifyEpochKeyValidity(
    proof.publicSignals,
    proof.proof
)
console.log(isValid)

Verify the proof with local prover

const isValid = await proof.verify()
console.log(isValid)

Verify UniRep state

Check if the global state tree exists in the current UniRep state.

It can be verified by either a Synchronizer or a UserState object. But the Synchronizer doesn't take ZkIdentity as an input. For example

const genUnirepState = async (
    provider: ethers.providers.Provider,
    address: string,
    db: DB
) => {
    const contract = getUnirepContract(address, provider)
    const unirepState = new Synchronizer(
        db,
        prover,
        contract,
    )
    await unirepState.start()
    await unirepState.waitForSync()
    return unirepState
}
const unirepState = await genUnirepState(
    provider,
    UNIREP_CONTRACT_ADDRESS,
    db
)

Then we can use the identity-free object to verify the global state tree root.

const isGSTRootExisted = await unirepState.GSTRootExists(
    proof.globalStateTree,
    proof.epoch
)
console.log(isGSTRootExisted) // false then the proof will be invalid

After clone the and run

🎮
Unirep repository
global state tree