daily claim prove test done

This commit is contained in:
Tihe
2024-12-03 21:37:54 +08:00
committed by TI-HE CHEN
parent bc5d02be2e
commit 6ad93c431c
17 changed files with 384 additions and 32 deletions

5
.gitmodules vendored
View File

@@ -1,5 +0,0 @@
[submodule "circomlib"]
path = packages/circuits/circuits/circomlib
url = https://github.com/iden3/circomlib.git
shallow = true
active = true

View File

@@ -16,4 +16,8 @@ zksnarkBuild/*
!*/reportIdentityProof.vkey.json
!*/reportIdentityProof.wasm
!*/reportIdentityProof.zkey
!*/reportIdentityProof.circom
!*/reportIdentityProof.circom
!*/dailyClaimProof.vkey.json
!*/dailyClaimProof.wasm
!*/dailyClaimProof.zkey
!*/dailyClaimProof.circom

View File

@@ -1,7 +1,7 @@
pragma circom 2.1.0;
include "./circomlib/circuits/comparators.circom";
include "../../../node_modules/@unirep/circuits/circuits/circomlib/circuits/reputation.circom";
include "../../../node_modules/@unirep/circuits/circuits/circomlib/circuits/comparators.circom";
include "../../../node_modules/@unirep/circuits/circuits/reputation.circom";
template DailyClaimProof(STATE_TREE_DEPTH, EPOCH_KEY_NONCE_PER_EPOCH, SUM_FIELD_COUNT, FIELD_COUNT, REPL_NONCE_BITS) {
// Identity and daily epoch
@@ -60,5 +60,6 @@ template DailyClaimProof(STATE_TREE_DEPTH, EPOCH_KEY_NONCE_PER_EPOCH, SUM_FIELD_
max_rep_check === 1;
// Step 2: check daily nullifier
daily_nullifier === Poseidon(2)([identity_secret, daily_epoch]);
signal cal_daily_nullifier <== Poseidon(2)([identity_secret, daily_epoch]);
daily_nullifier === cal_daily_nullifier;
}

View File

@@ -1,8 +1,8 @@
import { stringifyBigInts } from '@unirep/utils'
import child_process from 'child_process'
import fs from 'fs'
import path from 'path'
import * as snarkjs from 'snarkjs'
import child_process from 'child_process'
import { circuitContents, ptauName } from './circuits'
import { downloadPtau } from './downloadPtau'

View File

@@ -7,25 +7,10 @@ import { UnirepSocialCircuit } from './types'
*/
export class DailyClaimProof extends BaseProof {
readonly input = {
identitySecret: 0,
dailyEpoch: 1,
dailyNullifier: 2,
stateTreeIndices: 3,
stateTreeElements: 4,
data: 5,
proveGraffiti: 6,
graffiti: 7,
revealNonce: 8,
attesterId: 9,
epoch: 10,
nonce: 11,
chainId: 12,
sigData: 13,
minRep: 14,
maxRep: 15,
proveMinRep: 16,
proveMaxRep: 17,
proveZeroRep: 18,
dailyEpoch: 0,
dailyNullifier: 1,
attesterId: 2,
epoch: 3,
}
public dailyNullifier: bigint

View File

@@ -1,3 +1,4 @@
export { DailyClaimProof } from './DailyClaimProof'
export { DataProof } from './DataProof'
export { ReportIdentityProof } from './ReportIdentityProof'
export { ReportNonNullifierProof } from './ReportNonNullifierProof'

View File

@@ -0,0 +1,160 @@
import { CircuitConfig } from '@unirep/circuits'
import * as utils from '@unirep/utils'
import { IncrementalMerkleTree as zkIncrementalMerkleTree } from '@zk-kit/incremental-merkle-tree'
import { expect } from 'chai'
import { poseidon2 } from 'poseidon-lite'
import { DailyClaimProof } from '../src'
import { UnirepSocialCircuit } from '../src/types'
import { ProofGenerationError } from './error'
import {
createRandomUserIdentity,
genDailyClaimCircuitInput,
genNullifier,
genProofAndVerify,
genReputationCircuitInput,
} from './utils'
const circuit = UnirepSocialCircuit.dailyClaimProof
describe('Prove report identity in Unirep Social-TW', function () {
this.timeout(300000)
/**
* 1. should succeed with valid inputs
* 2. should revert with reputation > 0
* 3. should revert with wrong reputation proof
*/
const chainId = 31337
const user = createRandomUserIdentity()
const { STATE_TREE_DEPTH, FIELD_COUNT } = CircuitConfig.default
const attesterId = BigInt(10210)
const epoch = BigInt(120958)
const tree: zkIncrementalMerkleTree = new utils.IncrementalMerkleTree(
STATE_TREE_DEPTH
)
const data = [...Array(FIELD_COUNT).fill(0)]
const leaf = utils.genStateTreeLeaf(
user.id.secret,
attesterId,
epoch,
data,
chainId
)
tree.insert(leaf)
const leafIndex = tree.indexOf(leaf)
const leafProof = tree.createProof(leafIndex)
it('should succeed with valid inputs', async () => {
const identitySecret = user.id.secret
const dailyEpoch = 0
const dailyNullifier = genNullifier(user.id, dailyEpoch)
const reputationCircuitInput = genReputationCircuitInput({
identitySecret,
epoch: epoch,
nonce: 0,
attesterId: attesterId,
stateTreeIndices: leafProof.pathIndices,
stateTreeElements: leafProof.siblings,
data: data,
maxRep: 1,
chainId: chainId,
})
const circuitInputs = genDailyClaimCircuitInput({
dailyEpoch,
dailyNullifier,
identitySecret,
reputationCircuitInput,
})
const { isValid, proof, publicSignals } = await genProofAndVerify(
circuit,
circuitInputs
)
const dailyClaimProof = new DailyClaimProof(publicSignals, proof)
expect(isValid).to.be.true
expect(dailyClaimProof.dailyNullifier.toString()).to.be.equal(
poseidon2([identitySecret, dailyEpoch]).toString()
)
expect(dailyClaimProof.attesterId).to.be.equal(attesterId)
expect(dailyClaimProof.epoch).to.be.equal(epoch)
})
it('should revert with reputation > 0', async () => {
const identitySecret = user.id.secret
const dailyEpoch = 0
const dailyNullifier = genNullifier(user.id, dailyEpoch)
const reputationCircuitInput = genReputationCircuitInput({
identitySecret,
epoch: epoch,
nonce: 0,
attesterId: attesterId,
stateTreeIndices: leafProof.pathIndices,
stateTreeElements: leafProof.siblings,
data: data,
minRep: 1,
chainId: chainId,
})
const circuitInputs = genDailyClaimCircuitInput({
dailyEpoch,
dailyNullifier,
identitySecret,
reputationCircuitInput,
})
try {
await genProofAndVerify(circuit, circuitInputs)
} catch (error: unknown) {
expect?.(error).to.be.an.instanceof(ProofGenerationError)
expect?.(error).to.have.property(
'message',
'Error: Assert Failed. Error in template DailyClaimProof_97 line: 60\n'
)
}
})
it('should revert with wrong reputation proof', async () => {
const identitySecret = user.id.secret
const dailyEpoch = 0
const dailyNullifier = genNullifier(user.id, dailyEpoch)
const wrongAttesterId =
BigInt(2) ** CircuitConfig.default.ATTESTER_ID_BITS
const reputationCircuitInput = genReputationCircuitInput({
identitySecret,
epoch: epoch,
nonce: 0,
attesterId: attesterId,
stateTreeIndices: leafProof.pathIndices,
stateTreeElements: leafProof.siblings,
data: data,
maxRep: 1,
chainId: chainId,
})
reputationCircuitInput.attester_id = wrongAttesterId
const circuitInputs = genDailyClaimCircuitInput({
dailyEpoch,
dailyNullifier,
identitySecret,
reputationCircuitInput,
})
try {
await genProofAndVerify(circuit, circuitInputs)
} catch (error: unknown) {
expect?.(error).to.be.an.instanceof(ProofGenerationError)
expect?.(error).to.have.property(
'message',
'Error: Assert Failed. Error in template Num2Bits_3 line: 38\nError in template Reputation_93 line: 111\nError in template DailyClaimProof_97 line: 39\n'
)
}
})
})

View File

@@ -122,7 +122,7 @@ describe('Prove report non nullifier in Unirep Social-TW', function () {
expect?.(error).to.be.an.instanceof(ProofGenerationError)
expect?.(error).to.have.property(
'message',
'Error: Assert Failed. Error in template ReportNonNullifierProof_79 line: 42\n'
'Error: Assert Failed. Error in template ReportNonNullifierProof_79 line: 40\n'
)
}
})
@@ -160,7 +160,7 @@ describe('Prove report non nullifier in Unirep Social-TW', function () {
expect?.(error).to.be.an.instanceof(ProofGenerationError)
expect?.(error).to.have.property(
'message',
'Error: Assert Failed. Error in template ReportNonNullifierProof_79 line: 42\n'
'Error: Assert Failed. Error in template ReportNonNullifierProof_79 line: 40\n'
)
}
})
@@ -190,7 +190,7 @@ describe('Prove report non nullifier in Unirep Social-TW', function () {
expect?.(error).to.be.an.instanceof(ProofGenerationError)
expect?.(error).to.have.property(
'message',
'Error: Assert Failed. Error in template ReportNonNullifierProof_79 line: 42\n'
'Error: Assert Failed. Error in template ReportNonNullifierProof_79 line: 40\n'
)
}
})

View File

@@ -115,6 +115,71 @@ export const genReportNullifierCircuitInput = (config: {
return utils.stringifyBigInts(circuitInputs)
}
export const genReputationCircuitInput = (config: {
identitySecret: any
epoch: bigint
nonce: number
attesterId: number | bigint
stateTreeIndices: any[]
stateTreeElements: any
data: number[] | bigint[]
minRep?: number | bigint
maxRep?: number | bigint
proveMinRep?: number
proveMaxRep?: number
proveZeroRep?: number
proveGraffiti?: boolean | number
graffiti?: any
revealNonce?: number
chainId: number
}) => {
const {
identitySecret,
epoch,
nonce,
attesterId,
stateTreeIndices,
stateTreeElements,
data,
minRep,
proveGraffiti,
graffiti,
maxRep,
proveMinRep,
proveMaxRep,
proveZeroRep,
revealNonce,
chainId,
} = Object.assign(
{
minRep: 0,
maxRep: 0,
graffiti: 0,
},
config
)
const circuitInputs = {
identity_secret: identitySecret,
state_tree_indices: stateTreeIndices,
state_tree_elements: stateTreeElements,
data: data,
graffiti: graffiti,
epoch,
nonce,
attester_id: attesterId,
prove_graffiti: proveGraffiti ? proveGraffiti : 0,
min_rep: minRep,
max_rep: maxRep,
prove_max_rep: proveMaxRep ?? 0,
prove_min_rep: proveMinRep ?? 0,
prove_zero_rep: proveZeroRep ?? 0,
reveal_nonce: revealNonce ?? 0,
sig_data: 0,
chain_id: chainId,
}
return utils.stringifyBigInts(circuitInputs)
}
export const genReportIdentityCircuitInput = (config: {
reportNullifier: any
identitySecret: string | bigint
@@ -155,6 +220,44 @@ export const genReportIdentityCircuitInput = (config: {
return utils.stringifyBigInts(circuitInputs)
}
export const genDailyClaimCircuitInput = (config: {
identitySecret: any
dailyEpoch: number | bigint
dailyNullifier: number | bigint
reputationCircuitInput: any
}) => {
const {
identitySecret,
dailyEpoch,
dailyNullifier,
reputationCircuitInput,
} = Object.assign(config)
const circuitInputs = {
identity_secret: identitySecret,
daily_epoch: dailyEpoch,
daily_nullifier: dailyNullifier,
state_tree_indices: reputationCircuitInput.state_tree_indices,
state_tree_elements: reputationCircuitInput.state_tree_elements,
data: reputationCircuitInput.data,
prove_graffiti: reputationCircuitInput.prove_graffiti,
graffiti: reputationCircuitInput.graffiti,
reveal_nonce: reputationCircuitInput.reveal_nonce,
attester_id: reputationCircuitInput.attester_id,
epoch: reputationCircuitInput.epoch,
nonce: reputationCircuitInput.nonce,
chain_id: reputationCircuitInput.chain_id,
sig_data: reputationCircuitInput.sig_data,
min_rep: reputationCircuitInput.min_rep,
max_rep: reputationCircuitInput.max_rep,
prove_min_rep: reputationCircuitInput.prove_min_rep,
prove_max_rep: reputationCircuitInput.prove_max_rep,
prove_zero_rep: reputationCircuitInput.prove_zero_rep,
}
return utils.stringifyBigInts(circuitInputs)
}
export const randomData = () => [
...Array(CircuitConfig.default.SUM_FIELD_COUNT)
.fill(0)

View File

@@ -0,0 +1,3 @@
pragma circom 2.1.0; include "../circuits/dailyClaimProof.circom";
component main { public [ daily_nullifier, daily_epoch, epoch, attester_id ] } = DailyClaimProof(17, 3, 4, 6, 48);

View File

@@ -0,0 +1,100 @@
{
"protocol": "groth16",
"curve": "bn128",
"nPublic": 4,
"vk_alpha_1": [
"20491192805390485299153009773594534940189261866228447918068658471970481763042",
"9383485363053290200918347156157836566562967994039712273449902621266178545958",
"1"
],
"vk_beta_2": [
[
"6375614351688725206403948262868962793625744043794305715222011528459656738731",
"4252822878758300859123897981450591353533073413197771768651442665752259397132"
],
[
"10505242626370262277552901082094356697409835680220590971873171140371331206856",
"21847035105528745403288232691147584728191162732299865338377159692350059136679"
],
["1", "0"]
],
"vk_gamma_2": [
[
"10857046999023057135944570762232829481370756359578518086990519993285655852781",
"11559732032986387107991004021392285783925812861821192530917403151452391805634"
],
[
"8495653923123431417604973247489272438418190587263600148770280649306958101930",
"4082367875863433681332203403145435568316851327593401208105741076214120093531"
],
["1", "0"]
],
"vk_delta_2": [
[
"10857046999023057135944570762232829481370756359578518086990519993285655852781",
"11559732032986387107991004021392285783925812861821192530917403151452391805634"
],
[
"8495653923123431417604973247489272438418190587263600148770280649306958101930",
"4082367875863433681332203403145435568316851327593401208105741076214120093531"
],
["1", "0"]
],
"vk_alphabeta_12": [
[
[
"2029413683389138792403550203267699914886160938906632433982220835551125967885",
"21072700047562757817161031222997517981543347628379360635925549008442030252106"
],
[
"5940354580057074848093997050200682056184807770593307860589430076672439820312",
"12156638873931618554171829126792193045421052652279363021382169897324752428276"
],
[
"7898200236362823042373859371574133993780991612861777490112507062703164551277",
"7074218545237549455313236346927434013100842096812539264420499035217050630853"
]
],
[
[
"7077479683546002997211712695946002074877511277312570035766170199895071832130",
"10093483419865920389913245021038182291233451549023025229112148274109565435465"
],
[
"4595479056700221319381530156280926371456704509942304414423590385166031118820",
"19831328484489333784475432780421641293929726139240675179672856274388269393268"
],
[
"11934129596455521040620786944827826205713621633706285934057045369193958244500",
"8037395052364110730298837004334506829870972346962140206007064471173334027475"
]
]
],
"IC": [
[
"15502130539699483078353751900175217592043819558261990569338948999455916306859",
"14128759405766106444037936523299661649630861678576910740977015615466354043051",
"1"
],
[
"19180852455737178961419599821706870299145214554924087121339269074290474183076",
"4707992987307697395999371287169257767263545778251645658910300277427071960385",
"1"
],
[
"641400503886684557468999318299690693182057768279043286950515991129631171674",
"20248989105400872470670962912638907026376203009550626621642070696568817840364",
"1"
],
[
"14743727015456969719282516603276488302089351465310367630276116909517539240828",
"3965520222802372027491340839327530315899703930304769759858246890872360592794",
"1"
],
[
"4548392863595590044952621500430291560746345297682509109594036029465612105893",
"5377445044534648220891183013698926789281057030320833968044923000319563920987",
"1"
]
]
}

Binary file not shown.

Binary file not shown.