Before generating an epoch key proof, we should generate a current user state to know the current global state tree s and the attestation histories.
DB
We should initialize a storage to save the state.
Copy 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.
Copy 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)
} ,
}
After clone the Unirep repository and run
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:
Copy 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.
Copy 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
}
Copy const userState = await genUserState (
provider ,
UNIREP_CONTRACT_ADDRESS ,
identity ,
db
)
Generate epoch key proof
Use the user state to generate epoch key proof.
Copy // genearte epoch key proof
const epochKeyNonce = 0
const proof = await userState .genVerifyEpochKeyProof (epochKeyNonce)
Submit epoch key proof
Copy const tx = await contract .submitEpochKeyProof (
proof .publicSignals ,
proof .proof
)
Get proof index
Then get the proof index with the proof hash
Copy const proofHash = proof .hash ()
const proofIdx = await contract .getProofIndex (proofHash)
console .log (proofIdx)
Verify epoch key proof
Verify the proof with UniRep smart contract
Copy const isValid = await contract .verifyEpochKeyValidity (
proof .publicSignals ,
proof .proof
)
console .log (isValid)
Verify the proof with local prover
Copy 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
Copy 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
}
Copy const unirepState = await genUnirepState (
provider ,
UNIREP_CONTRACT_ADDRESS ,
db
)
Then we can use the identity-free object to verify the global state tree root.
Copy const isGSTRootExisted = await unirepState .GSTRootExists (
proof .globalStateTree ,
proof .epoch
)
console .log (isGSTRootExisted) // false then the proof will be invalid