Skip to content

Commit

Permalink
upd contract types, implement registration with call data
Browse files Browse the repository at this point in the history
  • Loading branch information
lukachi committed Apr 9, 2024
1 parent a7fe92a commit 0c12447
Show file tree
Hide file tree
Showing 9 changed files with 466 additions and 175 deletions.
24 changes: 8 additions & 16 deletions src/api/modules/verify/helpers/voting.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,24 @@
import type { PublicSignals } from 'snarkjs'

import { api } from '@/api/clients'
import { RegistrationRemarkDetails, VotingRemarkDetails } from '@/api/modules/verify'
import { IVoting, VerifierHelper } from '@/types/contracts/Voting'
import { IVoting } from '@/types/contracts/Voting'
import { IRegistration } from '@/types/contracts/VotingRegistration'

export const signUpForVoting = async (votingAddress: string, callData: string) => {
return api.post('/verify-proof', {
export const signUpForVoting = async (txData: string) => {
return api.post('/integrations/proof-verification-relayer/v1/register', {
body: {
data: {
votingAddress,
callData,
tx_data: txData,
},
},
})
}

export const vote = async (
proof: VerifierHelper.ProofPointsStruct,
publicSignals: PublicSignals,
nullifierHash: string,
) => {
return api.post('/vote', {
export const vote = async (registrationAddress: string, txData: string) => {
return api.post('/integrations/proof-verification-relayer/v1/vote', {
body: {
data: {
...proof,
publicSignals,
nullifierHash,
registration: registrationAddress,
tx_data: txData,
},
},
})
Expand Down
47 changes: 7 additions & 40 deletions src/api/modules/verify/types/zkp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,12 @@ import { ClaimTypes } from '@/api/modules/verify/enums'

export type ProofRequestResponse = {
[ClaimTypes.Registration]: {
type: ClaimTypes.Registration
data: {
proveIdentityParams: {
issuingAuthority: string
documentNullifier: string
commitment: string
}
registerProofParams: {
a: string[]
b: [[string, string], [string, string]]
c: [string, string]
inputs: string[]
statesMerkleData: {
merkleProof: string[]
createdAtTimestamp: string
issuerState: string
issuerId: string
}
}
}
calldata: string
document_nullifier: string
}
[ClaimTypes.Voting]: {
type: ClaimTypes.Voting
data: {
proveIdentityParams: {
issuingAuthority: string
documentNullifier: string
commitment: string
}
registerProofParams: {
a: string[]
b: [[string, string], [string, string]]
c: [string, string]
inputs: string[]
statesMerkleData: {
merkleProof: string[]
createdAtTimestamp: string
issuerState: string
issuerId: string
}
}
}
calldata: string
document_nullifier: string
}
}

Expand All @@ -58,6 +22,9 @@ export type ClaimTypesMapOnChain = {
[ClaimTypes.Voting]: {
type: ClaimTypes.Voting
data: {
registration_address: string
voting_address: string
choice: string
metadata_url: string
// callback: string
}
Expand Down
11 changes: 2 additions & 9 deletions src/pages/Votings/hooks/app-voting-details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { AppVoting } from '@/api/modules/verify'
import { useWeb3Context } from '@/contexts'
import { formatDateDiff } from '@/helpers'
import { useVotingsContext } from '@/pages/Votings/contexts'
import { RegisterVerifier__factory, VotingRegistration__factory } from '@/types'
import { VotingRegistration__factory } from '@/types'

export const useAppVotingDetails = (pairIdOrInstance: string | AppVoting) => {
const { appVotings } = useVotingsContext()
Expand Down Expand Up @@ -109,14 +109,7 @@ export const useAppVotingDetails = (pairIdOrInstance: string | AppVoting) => {
provider.rawProvider as unknown as providers.JsonRpcProvider,
)

const registerVerifierContractAddress = await registrationInstance.registerVerifier()

const registerVerifierInstance = RegisterVerifier__factory.connect(
registerVerifierContractAddress,
provider.rawProvider as unknown as providers.JsonRpcProvider,
)

return registerVerifierInstance.isIdentityRegistered(documentNullifier)
return registrationInstance.isUserRegistered(documentNullifier)
},
[appVoting, provider?.rawProvider],
)
Expand Down
73 changes: 24 additions & 49 deletions src/pages/Votings/pages/VotingsId/components/VotingAlive/index.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,17 @@
import { alpha, Button, Paper, Stack, StackProps, Typography, useTheme } from '@mui/material'
import { providers } from 'ethers'
import { useCallback, useState } from 'react'

import {
AppVoting,
ClaimTypes,
getVoteZKP,
poseidonHash,
ProofRequestResponse,
vote,
} from '@/api/modules/verify'
import { AppVoting, ClaimTypes, ProofRequestResponse, vote } from '@/api/modules/verify'
import { NoDataViewer } from '@/common'
import { useWeb3Context } from '@/contexts'
import { ErrorHandler, formatDateDMY } from '@/helpers'
import { BusEvents } from '@/enums'
import { bus, ErrorHandler, formatDateDMY } from '@/helpers'
import { useAppRequest, useAppVotingDetails } from '@/pages/Votings/hooks'
import { AppRequestModal } from '@/pages/Votings/pages/VotingsId/components'
import { VotingProcessModal } from '@/pages/Votings/pages/VotingsId/components/VotingAlive/components'
import { VotingRegistration__factory } from '@/types'
import { UiTooltip } from '@/ui'

import { VotingProcessModal } from './components'

type Props = StackProps & {
appVoting: AppVoting
}
Expand All @@ -33,18 +26,21 @@ export default function VotingAlive({ appVoting, ...rest }: Props) {

const { getIsUserRegistered } = useAppVotingDetails(appVoting)

const [selectedCandidateHash, setSelectedCandidateHash] = useState<string>('')

const { request, start, cancelSubscription } = useAppRequest<ClaimTypes.Voting>({
type: ClaimTypes.Voting,
data: {
registration_address: appVoting.registration.contract_address,
voting_address: appVoting.voting!.contract_address,
choice: selectedCandidateHash,
metadata_url: appVoting.registration.remark,
// callbackUrl will be auto appended
},
})

const [selectedCandidateHash, setSelectedCandidateHash] = useState<string>('')

const voteForCandidate = useCallback(
async (proofResponse: ProofRequestResponse[ClaimTypes.Voting], candidateHash: string) => {
async (proofResponse: ProofRequestResponse[ClaimTypes.Voting]) => {
setIsPending(true)

try {
Expand All @@ -53,32 +49,14 @@ export default function VotingAlive({ appVoting, ...rest }: Props) {

if (!provider?.rawProvider) throw new TypeError('Provider is not connected')

if (
!(await getIsUserRegistered(proofResponse.data.proveIdentityParams.documentNullifier))
) {
if (!(await getIsUserRegistered(proofResponse.document_nullifier))) {
bus.emit(BusEvents.error, {
message: 'You are not not registered',
})
throw new Error('User is not registered') // TODO: add notification
}

const registrationInstance = VotingRegistration__factory.connect(
appVoting.registration?.contract_address,
provider.rawProvider as unknown as providers.JsonRpcProvider,
)

const commitmentIndex = poseidonHash(proofResponse.data.proveIdentityParams.commitment)

const root = await registrationInstance.getRoot()

const onchainProof = await registrationInstance.getProof(commitmentIndex)

const zkpProof = await getVoteZKP(
secrets,
root,
candidateHash,
appVoting.voting.contract_address,
onchainProof.siblings,
)

await vote(zkpProof.formattedProof, zkpProof.publicSignals, candidateHash)
await vote(appVoting.registration.contract_address, proofResponse.calldata)
} catch (error) {
ErrorHandler.process(error)
}
Expand All @@ -93,18 +71,15 @@ export default function VotingAlive({ appVoting, ...rest }: Props) {
],
)

const handleVote = useCallback(
async (candidateHash: string) => {
await start(async proofResponse => {
await voteForCandidate(proofResponse, candidateHash)
const handleVote = useCallback(async () => {
await start(async proofResponse => {
await voteForCandidate(proofResponse)

setIsAppRequestModalShown(false)
})
setIsAppRequestModalShown(false)
})

setIsAppRequestModalShown(true)
},
[start, voteForCandidate],
)
setIsAppRequestModalShown(true)
}, [start, voteForCandidate])

const isCandidateSelected = useCallback(
(hash: string) => selectedCandidateHash === hash,
Expand Down Expand Up @@ -187,7 +162,7 @@ export default function VotingAlive({ appVoting, ...rest }: Props) {
{appVoting?.voting?.candidates && (
<Button
sx={{ minWidth: spacing(40), alignSelf: 'flex-start' }}
onClick={() => handleVote(selectedCandidateHash)}
onClick={handleVote}
disabled={isPending || !selectedCandidateHash}
>
CONFIRM
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import { bus, ErrorHandler, sleep } from '@/helpers'
import { useAppRequest, useAppVotingDetails } from '@/pages/Votings/hooks'
import { AppRequestModal } from '@/pages/Votings/pages/VotingsId/components'
import { VotingProcessModal } from '@/pages/Votings/pages/VotingsId/components/VotingAlive/components'
import { VotingRegistration__factory } from '@/types'
import { IBaseVerifier, IRegisterVerifier } from '@/types/contracts/RegisterVerifier'
import { UiIcon } from '@/ui'

type Props = StackProps & {
Expand All @@ -35,59 +33,15 @@ export default function VotingRegistration({ appVoting, ...rest }: Props) {
const buildTxAndSignUpForVoting = useCallback(
async (proofResponse: ProofRequestResponse[ClaimTypes.Registration]) => {
try {
const proveIdentityParams: IBaseVerifier.ProveIdentityParamsStruct = {
statesMerkleData: {
issuerId: proofResponse.data.registerProofParams.statesMerkleData.issuerId,
issuerState: proofResponse.data.registerProofParams.statesMerkleData.issuerState,
createdAtTimestamp:
proofResponse.data.registerProofParams.statesMerkleData.createdAtTimestamp,
merkleProof: proofResponse.data.registerProofParams.statesMerkleData.merkleProof,
},
inputs: proofResponse.data.registerProofParams.inputs.map?.(el => BigInt(el)),
a: [
proofResponse.data.registerProofParams?.a[0],
proofResponse.data.registerProofParams.a[1],
],
b: [
[
proofResponse.data.registerProofParams.b[0][1],
proofResponse.data.registerProofParams.b[0][0],
],
[
proofResponse.data.registerProofParams.b[1][1],
proofResponse.data.registerProofParams.b[1][0],
],
],
c: [
proofResponse.data.registerProofParams.c[0],
proofResponse.data.registerProofParams.c[1],
],
}
const registerProofParams: IRegisterVerifier.RegisterProofParamsStruct = {
issuingAuthority: proofResponse.data.proveIdentityParams.issuingAuthority,
documentNullifier: proofResponse.data.proveIdentityParams.documentNullifier,
// TODO: handle 2 cases, when user signed before vote starts, and after
commitment: proofResponse.data.proveIdentityParams.commitment,
}
const transitStateParams: IBaseVerifier.TransitStateParamsStruct = {
newIdentitiesStatesRoot: '',
gistData: {
root: 0,
createdAtTimestamp: 0,
},
proof: '',
}
const isUserReg = await getIsUserRegistered(proofResponse.document_nullifier)

const contractInterface = VotingRegistration__factory.createInterface()
if (isUserReg) {
setIsUserRegistered(true)

const callData = contractInterface.encodeFunctionData('register', [
proveIdentityParams,
registerProofParams,
transitStateParams,
false,
])
return
}

await signUpForVoting(appVoting.registration.contract_address, callData)
await signUpForVoting(proofResponse.calldata)

bus.emit(BusEvents.success, {
message: 'You have successfully signed up for voting',
Expand All @@ -98,7 +52,7 @@ export default function VotingRegistration({ appVoting, ...rest }: Props) {

await sleep(10_000)
},
[appVoting.registration.contract_address],
[getIsUserRegistered],
)

const successHandler = useCallback(
Expand All @@ -111,9 +65,7 @@ export default function VotingRegistration({ appVoting, ...rest }: Props) {

await buildTxAndSignUpForVoting(proofResponse)

setIsUserRegistered(
await getIsUserRegistered(proofResponse.data.proveIdentityParams.documentNullifier),
)
setIsUserRegistered(await getIsUserRegistered(proofResponse.document_nullifier))

setIsPending(false)
},
Expand Down
Loading

0 comments on commit 0c12447

Please sign in to comment.