Files
social-tw-website/packages/contracts/test/ClaimReportPosRep.test.ts
2024-12-12 01:22:46 +08:00

498 lines
16 KiB
TypeScript

// @ts-ignore
import { expect } from 'chai'
import { ethers } from 'hardhat'
import { deployApp } from '../scripts/utils/deployUnirepSocialTw'
import { Unirep, UnirepApp } from '../typechain-types'
import { ProofGenerationError } from './error'
import { IdentityObject } from './types'
import {
createMultipleUserIdentity,
flattenProof,
genNullifier,
genProofAndVerify,
genReportNonNullifierCircuitInput,
genReportNullifierCircuitInput,
genUserState,
genVHelperIdentifier,
userStateTransition,
} from './utils'
describe('Claim Report Positive Reputation Test', function () {
this.timeout(1000000)
let unirep: Unirep
let app: UnirepApp
let chainId: number
let upvoter: IdentityObject
let reporter: IdentityObject
let reporterEpochKey: bigint
let reporterEpoch: number
let snapshot: any
const epochLength = 300
const posReputation = 3
const nullifierCircuit = 'reportNullifierProof'
const nonNullifierCircuit = 'reportNonNullifierProof'
const nullifierIdentifier = genVHelperIdentifier(
'reportNullifierProofVerifierHelper'
)
const nonNullifierIdentifier = genVHelperIdentifier(
'reportNonNullifierProofVerifierHelper'
)
let usedPublicSig: any
let usedProof: any
{
before(async function () {
snapshot = await ethers.provider.send('evm_snapshot', [])
})
after(async function () {
await ethers.provider.send('evm_revert', [snapshot])
})
}
before(async function () {
try {
const [deployer] = await ethers.getSigners()
const contracts = await deployApp(deployer, epochLength)
unirep = contracts.unirep
app = contracts.app
const users = createMultipleUserIdentity(2)
upvoter = users[0]
reporter = users[1]
chainId = await unirep.chainid()
const upvoterState = await genUserState(upvoter.id, app)
const { publicSignals: upvoterSig, proof: upvoterPf } =
await upvoterState.genUserSignUpProof()
await app.userSignUp(
upvoterSig,
upvoterPf,
upvoter.hashUserId,
false
)
await app
.userRegistry(upvoter.hashUserId)
.then((res) => expect(res).to.be.true)
console.log('upvoter register success...')
upvoterState.stop()
const reporterState = await genUserState(reporter.id, app)
const { publicSignals: reporterSig, proof: reporterPf } =
await reporterState.genUserSignUpProof()
await app.userSignUp(
reporterSig,
reporterPf,
reporter.hashUserId,
false
)
await app
.userRegistry(reporter.hashUserId)
.then((res) => expect(res).to.be.true)
console.log('reporter register success...')
reporterState.stop()
} catch (err) {
console.error(err)
}
})
/**
* 1. succeed to claim rep to upvoter
* 2. revert with used proof
* 3. succeed to claim rep to reporter
* 4. revert with used proof
* 5. revert with invalid reportNullifierProof
* 6. revert with wrong epoch for reportNullifierProof
* 7. revert with invalid attesterId for reportNullifierProof
* 8. revert with invalid reportNonNullifierProof
* 9. revert with wrong epoch for reportNonNullifierProof
* 10. revert with invalid attesterId for reportNonNullifierProof
*/
it('should succeed to claim reputation to upvoter', async () => {
const reportId = 0
const currentNonce = 0
const identitySecret = upvoter.id.secret
const attesterId = BigInt(app.address)
const upvoterState = await genUserState(upvoter.id, app)
// elapsing 5 epoch
await ethers.provider.send('evm_increaseTime', [epochLength * 5])
await ethers.provider.send('evm_mine', [])
// userState Transition
await userStateTransition(upvoterState, unirep, app)
const currentEpoch = await upvoterState.sync.loadCurrentEpoch()
const reportNullifier = genNullifier(upvoter.id, reportId)
const reportNullifierCircuitInputs = genReportNullifierCircuitInput({
reportNullifier,
identitySecret,
reportId,
currentEpoch,
currentNonce,
attesterId,
chainId,
})
const { publicSignals, proof } = await genProofAndVerify(
nullifierCircuit,
reportNullifierCircuitInputs
)
usedPublicSig = publicSignals
usedProof = flattenProof(proof)
const tx = await app.claimReportPosRep(
usedPublicSig,
usedProof,
nullifierIdentifier,
posReputation
)
await expect(tx)
.to.emit(app, 'ClaimPosRep')
.withArgs(publicSignals[1], currentEpoch)
// userState Transition
await userStateTransition(upvoterState, unirep, app)
// check if reputation is claimed
const data = await upvoterState.getData()
expect(data[0]).to.be.equal(BigInt(posReputation))
upvoterState.stop()
})
it('should revert with not owner', async () => {
const notOwner = await ethers.getSigners().then((signers) => signers[1])
await expect(
app
.connect(notOwner)
.claimReportPosRep(
usedPublicSig,
usedProof,
nullifierIdentifier,
posReputation
)
).to.be.reverted
})
it('should revert with used proof', async () => {
await expect(
app.claimReportPosRep(
usedPublicSig,
usedProof,
nullifierIdentifier,
posReputation
)
).to.be.revertedWithCustomError(app, 'ProofHasUsed')
})
before(async () => {
// reporter report the poster at this moment
const reporterState = await genUserState(reporter.id, app)
const { publicSignals: reporterPubSig } =
await reporterState.genEpochKeyProof()
reporterEpochKey = reporterPubSig[0]
reporterEpoch = await reporterState.sync.loadCurrentEpoch()
})
it('should succeed to claim reputation to reporter', async () => {
const reporterState = await genUserState(reporter.id, app)
// elapsing 5 epoch
await ethers.provider.send('evm_increaseTime', [epochLength * 5])
await ethers.provider.send('evm_mine', [])
// userState Transition
await userStateTransition(reporterState, unirep, app)
const identitySecret = reporter.id.secret
const attesterId = BigInt(app.address)
const currentNonce = 0
const currentEpoch = await reporterState.sync.loadCurrentEpoch()
const reportNonNullifierCircuitInputs =
genReportNonNullifierCircuitInput({
reportedEpochKey: reporterEpochKey,
identitySecret,
reportedEpoch: reporterEpoch,
currentEpoch,
currentNonce,
chainId,
attesterId,
})
const { publicSignals, proof } = await genProofAndVerify(
nonNullifierCircuit,
reportNonNullifierCircuitInputs
)
usedPublicSig = publicSignals
usedProof = flattenProof(proof)
const tx = await app.claimReportPosRep(
usedPublicSig,
usedProof,
nonNullifierIdentifier,
posReputation
)
await expect(tx)
.to.emit(app, 'ClaimPosRep')
.withArgs(publicSignals[1], currentEpoch)
// userState Transition
await userStateTransition(reporterState, unirep, app)
// check if reputation is claimed
const data = await reporterState.getData()
expect(data[0]).to.be.equal(BigInt(posReputation))
reporterState.stop()
})
it('should revert with used proof', async () => {
await expect(
app.claimReportPosRep(
usedPublicSig,
usedProof,
nullifierIdentifier,
posReputation
)
).to.be.revertedWithCustomError(app, 'ProofHasUsed')
})
it('should revert with used proof', async () => {
await expect(
app.claimReportPosRep(
usedPublicSig,
usedProof,
nullifierIdentifier,
posReputation
)
).to.be.revertedWithCustomError(app, 'ProofHasUsed')
})
it('should revert with wrong reportNullifierProof', async () => {
const reportId = 1
const currentNonce = 0
const identitySecret = upvoter.id.secret
const attesterId = BigInt(app.address)
const upvoterState = await genUserState(upvoter.id, app)
const currentEpoch = await upvoterState.sync.loadCurrentEpoch()
const reportNullifier = genNullifier(upvoter.id, reportId)
const reportNullifierCircuitInputs = genReportNullifierCircuitInput({
reportNullifier,
identitySecret,
reportId,
currentEpoch,
currentNonce,
attesterId,
chainId,
})
const { publicSignals, proof } = await genProofAndVerify(
nullifierCircuit,
reportNullifierCircuitInputs
)
const flattenedProof = flattenProof(proof)
flattenedProof[0] = BigInt(0)
await expect(
app.claimReportPosRep(
publicSignals,
flattenedProof,
nullifierIdentifier,
posReputation
)
).to.be.reverted
upvoterState.stop()
})
it('should revert with wrong epoch for reportNullifierProof', async () => {
const reportId = 1
const currentNonce = 0
const identitySecret = upvoter.id.secret
const attesterId = BigInt(app.address)
const upvoterState = await genUserState(upvoter.id, app)
const currentEpoch = 444
const reportNullifier = genNullifier(upvoter.id, reportId)
const reportNullifierCircuitInputs = genReportNullifierCircuitInput({
reportNullifier,
identitySecret,
reportId,
currentEpoch,
currentNonce,
attesterId,
chainId,
})
const { publicSignals, proof } = await genProofAndVerify(
nullifierCircuit,
reportNullifierCircuitInputs
)
const flattenedProof = flattenProof(proof)
await expect(
app.claimReportPosRep(
publicSignals,
flattenedProof,
nullifierIdentifier,
posReputation
)
).to.be.revertedWithCustomError(app, 'InvalidEpoch')
upvoterState.stop()
})
it('should revert with wrong attester for reportNullifierProof', async () => {
const reportId = 1
const currentNonce = 0
const identitySecret = upvoter.id.secret
const wrongAttester = BigInt(44444)
const upvoterState = await genUserState(upvoter.id, app)
const currentEpoch = await upvoterState.sync.loadCurrentEpoch()
const reportNullifier = genNullifier(upvoter.id, reportId)
const reportNullifierCircuitInputs = genReportNullifierCircuitInput({
reportNullifier,
identitySecret,
reportId,
currentEpoch,
currentNonce,
attesterId: wrongAttester,
chainId,
})
const { publicSignals, proof } = await genProofAndVerify(
nullifierCircuit,
reportNullifierCircuitInputs
)
const flattenedProof = flattenProof(proof)
await expect(
app.claimReportPosRep(
publicSignals,
flattenedProof,
nullifierIdentifier,
posReputation
)
).to.be.reverted
upvoterState.stop()
})
it('should revert with invalid reportNonNullifierProof', async () => {
const reporterState = await genUserState(reporter.id, app)
const identitySecret = reporter.id.secret
const attesterId = BigInt(app.address)
const currentNonce = 0
const currentEpoch = await reporterState.sync.loadCurrentEpoch()
const reportNonNullifierCircuitInputs =
genReportNonNullifierCircuitInput({
reportedEpochKey: reporterEpochKey,
identitySecret,
reportedEpoch: reporterEpoch,
currentEpoch,
currentNonce,
chainId,
attesterId,
})
const { publicSignals, proof } = await genProofAndVerify(
nonNullifierCircuit,
reportNonNullifierCircuitInputs
)
const flattenedProof = flattenProof(proof)
flattenedProof[0] = BigInt(0)
await expect(
app.claimReportPosRep(
publicSignals,
flattenedProof,
nonNullifierIdentifier,
posReputation
)
).to.be.reverted
reporterState.stop()
})
it('should revert with wrong reported epoch and wrong for reportNonNullifierProof', async () => {
const identitySecret = reporter.id.secret
const attesterId = BigInt(app.address)
const wrongEpoch = BigInt(44444)
const reportNonNullifierCircuitInputs =
genReportNonNullifierCircuitInput({
reportedEpochKey: reporterEpochKey,
identitySecret,
reportedEpoch: reporterEpoch,
currentEpoch: wrongEpoch,
currentNonce: 0,
chainId,
attesterId,
})
const { publicSignals, proof } = await genProofAndVerify(
nonNullifierCircuit,
reportNonNullifierCircuitInputs
)
const flattenedProof = flattenProof(proof)
await expect(
app.claimReportPosRep(
publicSignals,
flattenedProof,
nonNullifierIdentifier,
posReputation
)
).to.be.reverted
})
it('should revert with wrong attester for reportNonNullifierProof', async () => {
const reporterState = await genUserState(reporter.id, app)
const identitySecret = reporter.id.secret
const attesterId = BigInt(13131)
const currentNonce = 0
const currentEpoch = await reporterState.sync.loadCurrentEpoch()
const reportNonNullifierCircuitInputs =
genReportNonNullifierCircuitInput({
reportedEpochKey: reporterEpochKey,
identitySecret,
reportedEpoch: reporterEpoch,
currentEpoch,
currentNonce,
chainId,
attesterId,
})
// this will not generate a proof since the attesterId would change the epochkey
try {
await genProofAndVerify(
nonNullifierCircuit,
reportNonNullifierCircuitInputs
)
} catch (error: unknown) {
expect?.(error).to.be.an.instanceof(ProofGenerationError)
expect?.(error).to.have.property(
'message',
'Error: Assert Failed. Error in template ReportNonNullifierProof_79 line: 42\n'
)
}
})
})