diff --git a/contracts/tasks/helpers/ConstructorArguments.ts b/contracts/tasks/helpers/ConstructorArguments.ts index 3f77d336b..9997e9683 100644 --- a/contracts/tasks/helpers/ConstructorArguments.ts +++ b/contracts/tasks/helpers/ConstructorArguments.ts @@ -150,6 +150,7 @@ async function getTallyConstructorArguments( tallyContract.vkRegistry(), tallyContract.poll(), tallyContract.messageProcessor(), + tallyContract.mode(), ]) return args @@ -174,6 +175,7 @@ async function getMessageProcessorConstructorArguments( messageProcesor.verifier(), messageProcesor.vkRegistry(), messageProcesor.poll(), + messageProcesor.mode(), ]) return args diff --git a/contracts/tasks/runners/maciPubkey.ts b/contracts/tasks/runners/maciPubkey.ts index c69ff002a..dad72f66e 100644 --- a/contracts/tasks/runners/maciPubkey.ts +++ b/contracts/tasks/runners/maciPubkey.ts @@ -4,7 +4,6 @@ * * Usage: hardhat maci-pubkey --macisk */ -import { id } from 'ethers' import { task } from 'hardhat/config' import { PubKey, PrivKey, Keypair } from '@clrfund/common' @@ -26,8 +25,5 @@ task('maci-pubkey', 'Get the serialized MACI public key') } const pubKey = new PubKey([BigInt(x), BigInt(y)]) console.log(`Public Key: ${pubKey.serialize()}`) - - const subgraphId = id(x + '.' + y) - console.log(`Subgraph id: ${subgraphId}`) } }) diff --git a/contracts/tasks/runners/verifyAll.ts b/contracts/tasks/runners/verifyAll.ts index 74972fe0c..7aa910b72 100644 --- a/contracts/tasks/runners/verifyAll.ts +++ b/contracts/tasks/runners/verifyAll.ts @@ -16,6 +16,7 @@ import { BaseContract } from 'ethers' import { HardhatEthersHelpers } from '@nomicfoundation/hardhat-ethers/types' import { ZERO_ADDRESS } from '../../utils/constants' import { ConstructorArguments } from '../helpers/ConstructorArguments' +import { getContractAt } from '../../utils/contracts' type ContractInfo = { name: string @@ -138,6 +139,8 @@ async function getContractList( clrfund: string, ethers: HardhatEthersHelpers ): Promise { + const userRegistries = new Set() + const recipientRegistries = new Set() const contractList: ContractInfo[] = [ { name: EContracts.ClrFund, @@ -145,10 +148,11 @@ async function getContractList( }, ] - const clrfundContract = (await ethers.getContractAt( + const clrfundContract = await getContractAt( EContracts.ClrFund, - clrfund - )) as BaseContract as ClrFund + clrfund, + ethers + ) const fundingRoundFactoryAddress = await clrfundContract.roundFactory() if (fundingRoundFactoryAddress !== ZERO_ADDRESS) { @@ -192,6 +196,16 @@ async function getContractList( }) } + const userRegistryAddress = await clrfundContract.userRegistry() + if (userRegistryAddress !== ZERO_ADDRESS) { + userRegistries.add(userRegistryAddress) + } + + const recipientRegistryAddress = await clrfundContract.recipientRegistry() + if (recipientRegistryAddress !== ZERO_ADDRESS) { + recipientRegistries.add(recipientRegistryAddress) + } + const fundingRoundAddress = await clrfundContract.getCurrentRound() if (fundingRoundAddress !== ZERO_ADDRESS) { contractList.push({ @@ -255,27 +269,32 @@ async function getContractList( // User Registry const userRegistryAddress = await fundingRound.userRegistry() if (userRegistryAddress !== ZERO_ADDRESS) { - const name = await getUserRegistryName(userRegistryAddress, ethers) - contractList.push({ - name, - address: userRegistryAddress, - }) + userRegistries.add(userRegistryAddress) } // Recipient Registry const recipientRegistryAddress = await fundingRound.recipientRegistry() if (recipientRegistryAddress !== ZERO_ADDRESS) { - const name = await getRecipientRegistryName( - recipientRegistryAddress, - ethers - ) - contractList.push({ - name, - address: recipientRegistryAddress, - }) + recipientRegistries.add(recipientRegistryAddress) } } + for (const address of userRegistries) { + const name = await getUserRegistryName(address, ethers) + contractList.push({ + name, + address, + }) + } + + for (const address of recipientRegistries) { + const name = await getRecipientRegistryName(address, ethers) + contractList.push({ + name, + address, + }) + } + return contractList } diff --git a/contracts/utils/providers/EtherscanProvider.ts b/contracts/utils/providers/EtherscanProvider.ts index 8534156ae..047ccdbea 100644 --- a/contracts/utils/providers/EtherscanProvider.ts +++ b/contracts/utils/providers/EtherscanProvider.ts @@ -3,6 +3,7 @@ import { FetchRequest } from 'ethers' import { HardhatConfig } from 'hardhat/types' const EtherscanApiUrl: Record = { + sepolia: 'https://api-sepolia.etherscan.io', xdai: 'https://api.gnosisscan.io', arbitrum: 'https://api.arbiscan.io', 'arbitrum-goerli': 'https://api-goerli.arbiscan.io', diff --git a/subgraph/generated/schema.ts b/subgraph/generated/schema.ts index b3f92c01b..50ce4aecf 100644 --- a/subgraph/generated/schema.ts +++ b/subgraph/generated/schema.ts @@ -551,21 +551,17 @@ export class PublicKey extends Entity { this.set("id", Value.fromString(value)); } - get fundingRound(): string | null { - let value = this.get("fundingRound"); + get maci(): string { + let value = this.get("maci"); if (!value || value.kind == ValueKind.NULL) { - return null; + throw new Error("Cannot return null for a required field."); } else { return value.toString(); } } - set fundingRound(value: string | null) { - if (!value) { - this.unset("fundingRound"); - } else { - this.set("fundingRound", Value.fromString(value)); - } + set maci(value: string) { + this.set("maci", Value.fromString(value)); } get messages(): MessageLoader { diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index 3d9b3610a..2d779393a 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -37,7 +37,7 @@ type Message @entity { type PublicKey @entity { id: ID! - fundingRound: FundingRound + maci: String! messages: [Message!] @derivedFrom(field: "publicKey") x: BigInt! y: BigInt! diff --git a/subgraph/schema.template.graphql b/subgraph/schema.template.graphql index 44b3d2127..e8f1db50d 100644 --- a/subgraph/schema.template.graphql +++ b/subgraph/schema.template.graphql @@ -49,7 +49,7 @@ type Message @entity { type PublicKey @entity { id: ID! - fundingRound: FundingRound + maci: String! messages: [Message!] @derivedFrom(field: "publicKey") x: BigInt! y: BigInt! diff --git a/subgraph/src/MACIMapping.ts b/subgraph/src/MACIMapping.ts index e1cbdb28f..667822f48 100644 --- a/subgraph/src/MACIMapping.ts +++ b/subgraph/src/MACIMapping.ts @@ -21,11 +21,11 @@ import { makePublicKeyId } from './PublicKey' // - contract.verifier(...) export function handleSignUp(event: SignUp): void { - let fundingRoundAddress = event.address - let fundingRoundId = fundingRoundAddress.toHex() + let maciAddress = event.address + let maciId = maciAddress.toHex() let publicKeyId = makePublicKeyId( - fundingRoundId, + maciId, event.params._userPubKeyX, event.params._userPubKeyY ) @@ -39,14 +39,7 @@ export function handleSignUp(event: SignUp): void { publicKey.y = event.params._userPubKeyY publicKey.stateIndex = event.params._stateIndex publicKey.voiceCreditBalance = event.params._voiceCreditBalance - - let fundingRound = FundingRound.load(fundingRoundId) - if (fundingRound == null) { - log.error('Error: handleSignUp failed, fundingRound not registered', []) - return - } - - publicKey.fundingRound = fundingRoundId + publicKey.maci = maciId publicKey.save() log.info('SignUp', []) diff --git a/subgraph/src/PollMapping.ts b/subgraph/src/PollMapping.ts index e3c6fe043..e566813e6 100644 --- a/subgraph/src/PollMapping.ts +++ b/subgraph/src/PollMapping.ts @@ -1,7 +1,7 @@ import { log } from '@graphprotocol/graph-ts' import { PublishMessage } from '../generated/templates/Poll/Poll' -import { Poll, Message, PublicKey } from '../generated/schema' +import { FundingRound, Poll, Message, PublicKey } from '../generated/schema' import { makePublicKeyId } from './PublicKey' export function handlePublishMessage(event: PublishMessage): void { @@ -17,12 +17,24 @@ export function handlePublishMessage(event: PublishMessage): void { let fundingRoundId = poll.fundingRound if (!fundingRoundId) { log.error( - 'Error: handlePublishMessage failed poll {} missing funding round', + 'Error: handlePublishMessage failed poll {} missing funding round id', [pollEntityId] ) return } + let fundingRound = FundingRound.load(fundingRoundId) + if (!fundingRound) { + log.error( + 'Error: handlePublishMessage failed poll {} missing funding round entity', + [pollEntityId] + ) + return + } + + let maci = fundingRound.maci + let maciId = maci ? maci.toHex() : '' + let messageID = event.transaction.hash.toHexString() + '-' + @@ -37,7 +49,7 @@ export function handlePublishMessage(event: PublishMessage): void { message.submittedBy = event.transaction.from let publicKeyId = makePublicKeyId( - fundingRoundId, + maciId, event.params._encPubKey.x, event.params._encPubKey.y ) @@ -48,8 +60,7 @@ export function handlePublishMessage(event: PublishMessage): void { let publicKey = new PublicKey(publicKeyId) publicKey.x = event.params._encPubKey.x publicKey.y = event.params._encPubKey.y - publicKey.fundingRound = fundingRoundId - + publicKey.maci = maciId publicKey.save() } diff --git a/subgraph/src/PublicKey.ts b/subgraph/src/PublicKey.ts index d34f33706..d3edacbc0 100644 --- a/subgraph/src/PublicKey.ts +++ b/subgraph/src/PublicKey.ts @@ -2,15 +2,11 @@ import { ByteArray, crypto, BigInt } from '@graphprotocol/graph-ts' // Create the PublicKey entity id used in subgraph // using MACI public key x and y values -export function makePublicKeyId( - fundingRoundId: string, - x: BigInt, - y: BigInt -): string { +export function makePublicKeyId(maciId: string, x: BigInt, y: BigInt): string { let publicKeyX = x.toString() let publicKeyY = y.toString() let publicKeyXY = ByteArray.fromUTF8( - fundingRoundId + '.' + publicKeyX + '.' + publicKeyY + maciId + '.' + publicKeyX + '.' + publicKeyY ) let publicKeyId = crypto.keccak256(publicKeyXY).toHexString() return publicKeyId diff --git a/vue-app/src/api/cart.ts b/vue-app/src/api/cart.ts index c95993530..fd5c3ca62 100644 --- a/vue-app/src/api/cart.ts +++ b/vue-app/src/api/cart.ts @@ -17,15 +17,14 @@ export async function getCommittedCart( encryptionKey: string, contributorAddress: string, ): Promise { - const { coordinatorPubKey, fundingRoundAddress, voiceCreditFactor, nativeTokenDecimals, recipientRegistryAddress } = - round + const { coordinatorPubKey, maciAddress, voiceCreditFactor, nativeTokenDecimals, recipientRegistryAddress } = round const encKeypair = await Keypair.createFromSeed(encryptionKey) const sharedKey = Keypair.genEcdhSharedKey(encKeypair.privKey, coordinatorPubKey) const messages = await getContributorMessages({ - fundingRoundAddress, + maciAddress, contributorKey: encKeypair, coordinatorPubKey, contributorAddress, diff --git a/vue-app/src/api/contributions.ts b/vue-app/src/api/contributions.ts index 5e0618447..a6aed99ef 100644 --- a/vue-app/src/api/contributions.ts +++ b/vue-app/src/api/contributions.ts @@ -27,13 +27,13 @@ export interface Contributor { /** * get the id of the subgraph public key entity from the pubKey value - * @param fundingRoundAddress funding round address + * @param maciAddress MACI address * @param pubKey MACI public key * @returns the id for the subgraph public key entity */ -function getPubKeyId(fundingRoundAddress = '', pubKey: PubKey): string { +function getPubKeyId(maciAddress = '', pubKey: PubKey): string { const pubKeyPair = pubKey.asContractParam() - return id(fundingRoundAddress.toLowerCase() + '.' + pubKeyPair.x + '.' + pubKeyPair.y) + return id(maciAddress.toLowerCase() + '.' + pubKeyPair.x + '.' + pubKeyPair.y) } export function getCartStorageKey(roundAddress: string): string { @@ -141,17 +141,16 @@ export function isContributionAmountValid(value: string, currentRound: RoundInfo /** * Get the MACI contributor state index - * @param fundingRoundAddress Funding round contract address + * @param maciAddress MACI contract address * @param pubKey Contributor public key * @returns Contributor stateIndex returned from MACI */ -export async function getContributorIndex(fundingRoundAddress: string, pubKey: PubKey): Promise { - if (!fundingRoundAddress) { +export async function getContributorIndex(maciAddress: string, pubKey: PubKey): Promise { + if (!maciAddress) { return null } - const id = getPubKeyId(fundingRoundAddress, pubKey) + const id = getPubKeyId(maciAddress, pubKey) const data = await sdk.GetContributorIndex({ - fundingRoundAddress: fundingRoundAddress.toLowerCase(), publicKeyId: id, }) @@ -178,29 +177,28 @@ function getMaciMessage(type: any, data: any[] | null): Message { /** * Get the latest set of vote messages submitted by contributor - * @param fundingRoundAddress Funding round contract address + * @param maciAddress MACI contract address * @param contributorKey Contributor key used to encrypt messages * @param coordinatorPubKey Coordinator public key * @returns MACI messages */ export async function getContributorMessages({ - fundingRoundAddress, + maciAddress, contributorKey, coordinatorPubKey, contributorAddress, }: { - fundingRoundAddress: string + maciAddress: string contributorKey: Keypair coordinatorPubKey: PubKey contributorAddress: string }): Promise { - if (!fundingRoundAddress) { + if (!maciAddress) { return [] } - const key = getPubKeyId(fundingRoundAddress, contributorKey.pubKey) + const key = getPubKeyId(maciAddress, contributorKey.pubKey) const result = await sdk.GetContributorMessages({ - fundingRoundAddress: fundingRoundAddress.toLowerCase(), pubKey: key, contributorAddress: contributorAddress.toLowerCase(), }) diff --git a/vue-app/src/graphql/API.ts b/vue-app/src/graphql/API.ts index 72b5be6c3..36ba4ad46 100644 --- a/vue-app/src/graphql/API.ts +++ b/vue-app/src/graphql/API.ts @@ -1778,6 +1778,7 @@ export enum Message_OrderBy { PollId = 'poll__id', PublicKey = 'publicKey', PublicKeyId = 'publicKey__id', + PublicKeyMaci = 'publicKey__maci', PublicKeyStateIndex = 'publicKey__stateIndex', PublicKeyVoiceCreditBalance = 'publicKey__voiceCreditBalance', PublicKeyX = 'publicKey__x', @@ -1884,8 +1885,8 @@ export enum Poll_OrderBy { export type PublicKey = { __typename?: 'PublicKey'; - fundingRound: Maybe; id: Scalars['ID']; + maci: Scalars['String']; messages: Maybe>; stateIndex: Maybe; voiceCreditBalance: Maybe; @@ -1906,27 +1907,6 @@ export type PublicKey_Filter = { /** Filter for the block changed event. */ _change_block: InputMaybe; and: InputMaybe>>; - fundingRound: InputMaybe; - fundingRound_: InputMaybe; - fundingRound_contains: InputMaybe; - fundingRound_contains_nocase: InputMaybe; - fundingRound_ends_with: InputMaybe; - fundingRound_ends_with_nocase: InputMaybe; - fundingRound_gt: InputMaybe; - fundingRound_gte: InputMaybe; - fundingRound_in: InputMaybe>; - fundingRound_lt: InputMaybe; - fundingRound_lte: InputMaybe; - fundingRound_not: InputMaybe; - fundingRound_not_contains: InputMaybe; - fundingRound_not_contains_nocase: InputMaybe; - fundingRound_not_ends_with: InputMaybe; - fundingRound_not_ends_with_nocase: InputMaybe; - fundingRound_not_in: InputMaybe>; - fundingRound_not_starts_with: InputMaybe; - fundingRound_not_starts_with_nocase: InputMaybe; - fundingRound_starts_with: InputMaybe; - fundingRound_starts_with_nocase: InputMaybe; id: InputMaybe; id_gt: InputMaybe; id_gte: InputMaybe; @@ -1935,6 +1915,26 @@ export type PublicKey_Filter = { id_lte: InputMaybe; id_not: InputMaybe; id_not_in: InputMaybe>; + maci: InputMaybe; + maci_contains: InputMaybe; + maci_contains_nocase: InputMaybe; + maci_ends_with: InputMaybe; + maci_ends_with_nocase: InputMaybe; + maci_gt: InputMaybe; + maci_gte: InputMaybe; + maci_in: InputMaybe>; + maci_lt: InputMaybe; + maci_lte: InputMaybe; + maci_not: InputMaybe; + maci_not_contains: InputMaybe; + maci_not_contains_nocase: InputMaybe; + maci_not_ends_with: InputMaybe; + maci_not_ends_with_nocase: InputMaybe; + maci_not_in: InputMaybe>; + maci_not_starts_with: InputMaybe; + maci_not_starts_with_nocase: InputMaybe; + maci_starts_with: InputMaybe; + maci_starts_with_nocase: InputMaybe; messages_: InputMaybe; or: InputMaybe>>; stateIndex: InputMaybe; @@ -1972,38 +1972,8 @@ export type PublicKey_Filter = { }; export enum PublicKey_OrderBy { - FundingRound = 'fundingRound', - FundingRoundContributorCount = 'fundingRound__contributorCount', - FundingRoundContributorRegistryAddress = 'fundingRound__contributorRegistryAddress', - FundingRoundCoordinator = 'fundingRound__coordinator', - FundingRoundCoordinatorPubKeyX = 'fundingRound__coordinatorPubKeyX', - FundingRoundCoordinatorPubKeyY = 'fundingRound__coordinatorPubKeyY', - FundingRoundCreatedAt = 'fundingRound__createdAt', - FundingRoundId = 'fundingRound__id', - FundingRoundIsCancelled = 'fundingRound__isCancelled', - FundingRoundIsFinalized = 'fundingRound__isFinalized', - FundingRoundLastUpdatedAt = 'fundingRound__lastUpdatedAt', - FundingRoundMaci = 'fundingRound__maci', - FundingRoundMaciTxHash = 'fundingRound__maciTxHash', - FundingRoundMatchingPoolSize = 'fundingRound__matchingPoolSize', - FundingRoundMaxMessages = 'fundingRound__maxMessages', - FundingRoundMaxVoteOptions = 'fundingRound__maxVoteOptions', - FundingRoundMessageTreeDepth = 'fundingRound__messageTreeDepth', - FundingRoundNativeToken = 'fundingRound__nativeToken', - FundingRoundPollAddress = 'fundingRound__pollAddress', - FundingRoundPollId = 'fundingRound__pollId', - FundingRoundRecipientCount = 'fundingRound__recipientCount', - FundingRoundRecipientRegistryAddress = 'fundingRound__recipientRegistryAddress', - FundingRoundSignUpDeadline = 'fundingRound__signUpDeadline', - FundingRoundStartTime = 'fundingRound__startTime', - FundingRoundStateTreeDepth = 'fundingRound__stateTreeDepth', - FundingRoundTallyHash = 'fundingRound__tallyHash', - FundingRoundTotalSpent = 'fundingRound__totalSpent', - FundingRoundTotalVotes = 'fundingRound__totalVotes', - FundingRoundVoiceCreditFactor = 'fundingRound__voiceCreditFactor', - FundingRoundVoteOptionTreeDepth = 'fundingRound__voteOptionTreeDepth', - FundingRoundVotingDeadline = 'fundingRound__votingDeadline', Id = 'id', + Maci = 'maci', Messages = 'messages', StateIndex = 'stateIndex', VoiceCreditBalance = 'voiceCreditBalance', @@ -3170,7 +3140,6 @@ export type GetContributionsAmountQueryVariables = Exact<{ export type GetContributionsAmountQuery = { __typename?: 'Query', contributions: Array<{ __typename?: 'Contribution', amount: any | null }> }; export type GetContributorIndexQueryVariables = Exact<{ - fundingRoundAddress: Scalars['String']; publicKeyId: Scalars['ID']; }>; @@ -3178,7 +3147,6 @@ export type GetContributorIndexQueryVariables = Exact<{ export type GetContributorIndexQuery = { __typename?: 'Query', publicKeys: Array<{ __typename?: 'PublicKey', id: string, stateIndex: any | null }> }; export type GetContributorMessagesQueryVariables = Exact<{ - fundingRoundAddress: Scalars['String']; pubKey: Scalars['String']; contributorAddress: Scalars['Bytes']; }>; @@ -3303,17 +3271,17 @@ export const GetContributionsAmountDocument = gql` } `; export const GetContributorIndexDocument = gql` - query GetContributorIndex($fundingRoundAddress: String!, $publicKeyId: ID!) { - publicKeys(where: {id: $publicKeyId, fundingRound: $fundingRoundAddress}) { + query GetContributorIndex($publicKeyId: ID!) { + publicKeys(where: {id: $publicKeyId}) { id stateIndex } } `; export const GetContributorMessagesDocument = gql` - query GetContributorMessages($fundingRoundAddress: String!, $pubKey: String!, $contributorAddress: Bytes!) { + query GetContributorMessages($pubKey: String!, $contributorAddress: Bytes!) { messages( - where: {fundingRound: $fundingRoundAddress, publicKey: $pubKey, submittedBy: $contributorAddress} + where: {publicKey: $pubKey, submittedBy: $contributorAddress} first: 1000 orderBy: blockNumber orderDirection: desc diff --git a/vue-app/src/graphql/queries/GetContributorIndex.graphql b/vue-app/src/graphql/queries/GetContributorIndex.graphql index c3954dac6..d240e6b13 100644 --- a/vue-app/src/graphql/queries/GetContributorIndex.graphql +++ b/vue-app/src/graphql/queries/GetContributorIndex.graphql @@ -1,8 +1,7 @@ query GetContributorIndex( - $fundingRoundAddress: String! $publicKeyId: ID! ) { - publicKeys(where: {id: $publicKeyId, fundingRound: $fundingRoundAddress}) { + publicKeys(where: {id: $publicKeyId}) { id stateIndex } diff --git a/vue-app/src/graphql/queries/GetContributorMessages.graphql b/vue-app/src/graphql/queries/GetContributorMessages.graphql index d163b923b..5a3acbac4 100644 --- a/vue-app/src/graphql/queries/GetContributorMessages.graphql +++ b/vue-app/src/graphql/queries/GetContributorMessages.graphql @@ -1,11 +1,9 @@ query GetContributorMessages( - $fundingRoundAddress: String! $pubKey: String! $contributorAddress: Bytes! ) { messages( where: { - fundingRound: $fundingRoundAddress, publicKey: $pubKey, submittedBy: $contributorAddress }, diff --git a/vue-app/src/stores/app.ts b/vue-app/src/stores/app.ts index d977e04b7..65b7fc494 100644 --- a/vue-app/src/stores/app.ts +++ b/vue-app/src/stores/app.ts @@ -458,7 +458,7 @@ export const useAppStore = defineStore('app', { } const contributorKeypair = Keypair.createFromSeed(userStore.currentUser.encryptionKey) - const stateIndex = await getContributorIndex(this.currentRound.fundingRoundAddress, contributorKeypair.pubKey) + const stateIndex = await getContributorIndex(this.currentRound.maciAddress, contributorKeypair.pubKey) if (!stateIndex) { // if no contributor index, user has not contributed