From 1ad99cc36f7a54889416d0593aefa23ef8f1452e Mon Sep 17 00:00:00 2001 From: yuetloo Date: Wed, 13 Mar 2024 05:08:23 -0400 Subject: [PATCH] fix reallocation error due to changes in SignUp and publishMessage changes --- docs/tally-verify.md | 4 +- subgraph/abis/MACI.json | 89 ++++++++++------------- subgraph/config/arbitrum-sepolia.json | 6 +- subgraph/generated/ClrFund/MACI.ts | 80 +++++++------------- subgraph/generated/schema.ts | 74 +++++++++++++++++++ subgraph/generated/templates/MACI/MACI.ts | 80 +++++++------------- subgraph/schema.graphql | 9 ++- subgraph/src/ClrFundMapping.ts | 6 ++ subgraph/src/MACIMapping.ts | 8 +- subgraph/src/PollMapping.ts | 23 ++++-- subgraph/subgraph.template.yaml | 2 +- subgraph/subgraph.yaml | 2 +- 12 files changed, 211 insertions(+), 172 deletions(-) diff --git a/docs/tally-verify.md b/docs/tally-verify.md index 28b165c02..7f96663f6 100644 --- a/docs/tally-verify.md +++ b/docs/tally-verify.md @@ -93,4 +93,6 @@ Also, lack of memory can also cause `core dump`, try to work around it by settin export NODE_OPTIONS=--max-old-space-size=4096 ``` -If you notice `Error at message index 0 - failed decryption due to either wrong encryption public key or corrupted ciphertext` while running the tally script, don't worry, it's just a warning. This issue is tracked [here](https://github.com/privacy-scaling-explorations/maci/issues/1134) \ No newline at end of file +If you notice `Error at message index 0 - failed decryption due to either wrong encryption public key or corrupted ciphertext` while running the tally script, don't worry, it's just a warning. This issue is tracked [here](https://github.com/privacy-scaling-explorations/maci/issues/1134) + +`Error at message index n - invalid nonce` is also a warning, not an error. This error occurs when users reallocated their contribution. \ No newline at end of file diff --git a/subgraph/abis/MACI.json b/subgraph/abis/MACI.json index cb7060c0e..4a09120f9 100644 --- a/subgraph/abis/MACI.json +++ b/subgraph/abis/MACI.json @@ -93,6 +93,11 @@ "name": "PreviousPollNotCompleted", "type": "error" }, + { + "inputs": [], + "name": "SignupTemporaryBlocked", + "type": "error" + }, { "inputs": [], "name": "TooManySignups", @@ -108,22 +113,16 @@ "type": "uint256" }, { - "components": [ - { - "internalType": "uint256", - "name": "x", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "y", - "type": "uint256" - } - ], - "indexed": false, - "internalType": "struct DomainObjs.PubKey", - "name": "_pubKey", - "type": "tuple" + "indexed": true, + "internalType": "uint256", + "name": "_coordinatorPubKeyX", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "_coordinatorPubKeyY", + "type": "uint256" }, { "components": [ @@ -186,22 +185,16 @@ "type": "uint256" }, { - "components": [ - { - "internalType": "uint256", - "name": "x", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "y", - "type": "uint256" - } - ], - "indexed": false, - "internalType": "struct DomainObjs.PubKey", - "name": "_userPubKey", - "type": "tuple" + "indexed": true, + "internalType": "uint256", + "name": "_userPubKeyX", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "_userPubKeyY", + "type": "uint256" }, { "indexed": false, @@ -649,25 +642,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "numStateLeaves", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "owner", @@ -884,6 +858,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "subtreesMerged", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "tallyFactory", diff --git a/subgraph/config/arbitrum-sepolia.json b/subgraph/config/arbitrum-sepolia.json index 53c80a2a6..82727f44c 100644 --- a/subgraph/config/arbitrum-sepolia.json +++ b/subgraph/config/arbitrum-sepolia.json @@ -1,6 +1,6 @@ { "network": "arbitrum-sepolia", - "address": "0x9E43d48513FDe2701288bDCEd1057109E592f048", - "clrFundStartBlock": 20200250, - "recipientRegistryStartBlock": 20200250 + "address": "0xEd7dD059294dE1B053B2B50Fb6A73a559219F678", + "clrFundStartBlock": 22697290, + "recipientRegistryStartBlock": 22697290 } diff --git a/subgraph/generated/ClrFund/MACI.ts b/subgraph/generated/ClrFund/MACI.ts index b4644bdef..b1b8238e1 100644 --- a/subgraph/generated/ClrFund/MACI.ts +++ b/subgraph/generated/ClrFund/MACI.ts @@ -27,29 +27,21 @@ export class DeployPoll__Params { return this._event.parameters[0].value.toBigInt(); } - get _pubKey(): DeployPoll_pubKeyStruct { - return changetype( - this._event.parameters[1].value.toTuple(), - ); + get _coordinatorPubKeyX(): BigInt { + return this._event.parameters[1].value.toBigInt(); + } + + get _coordinatorPubKeyY(): BigInt { + return this._event.parameters[2].value.toBigInt(); } get pollAddr(): DeployPollPollAddrStruct { return changetype( - this._event.parameters[2].value.toTuple(), + this._event.parameters[3].value.toTuple(), ); } } -export class DeployPoll_pubKeyStruct extends ethereum.Tuple { - get x(): BigInt { - return this[0].toBigInt(); - } - - get y(): BigInt { - return this[1].toBigInt(); - } -} - export class DeployPollPollAddrStruct extends ethereum.Tuple { get poll(): Address { return this[0].toAddress(); @@ -107,28 +99,20 @@ export class SignUp__Params { return this._event.parameters[0].value.toBigInt(); } - get _userPubKey(): SignUp_userPubKeyStruct { - return changetype( - this._event.parameters[1].value.toTuple(), - ); + get _userPubKeyX(): BigInt { + return this._event.parameters[1].value.toBigInt(); } - get _voiceCreditBalance(): BigInt { + get _userPubKeyY(): BigInt { return this._event.parameters[2].value.toBigInt(); } - get _timestamp(): BigInt { + get _voiceCreditBalance(): BigInt { return this._event.parameters[3].value.toBigInt(); } -} - -export class SignUp_userPubKeyStruct extends ethereum.Tuple { - get x(): BigInt { - return this[0].toBigInt(); - } - get y(): BigInt { - return this[1].toBigInt(); + get _timestamp(): BigInt { + return this._event.parameters[4].value.toBigInt(); } } @@ -663,29 +647,6 @@ export class MACI extends ethereum.SmartContract { return ethereum.CallResult.fromValue(value[0].toBigInt()); } - numStateLeaves(param0: BigInt): BigInt { - let result = super.call( - "numStateLeaves", - "numStateLeaves(uint256):(uint256)", - [ethereum.Value.fromUnsignedBigInt(param0)], - ); - - return result[0].toBigInt(); - } - - try_numStateLeaves(param0: BigInt): ethereum.CallResult { - let result = super.tryCall( - "numStateLeaves", - "numStateLeaves(uint256):(uint256)", - [ethereum.Value.fromUnsignedBigInt(param0)], - ); - if (result.reverted) { - return new ethereum.CallResult(); - } - let value = result.value; - return ethereum.CallResult.fromValue(value[0].toBigInt()); - } - owner(): Address { let result = super.call("owner", "owner():(address)", []); @@ -889,6 +850,21 @@ export class MACI extends ethereum.SmartContract { return ethereum.CallResult.fromValue(value[0].toAddress()); } + subtreesMerged(): boolean { + let result = super.call("subtreesMerged", "subtreesMerged():(bool)", []); + + return result[0].toBoolean(); + } + + try_subtreesMerged(): ethereum.CallResult { + let result = super.tryCall("subtreesMerged", "subtreesMerged():(bool)", []); + if (result.reverted) { + return new ethereum.CallResult(); + } + let value = result.value; + return ethereum.CallResult.fromValue(value[0].toBoolean()); + } + tallyFactory(): Address { let result = super.call("tallyFactory", "tallyFactory():(address)", []); diff --git a/subgraph/generated/schema.ts b/subgraph/generated/schema.ts index 0cc9e7c47..97e62f0d3 100644 --- a/subgraph/generated/schema.ts +++ b/subgraph/generated/schema.ts @@ -434,6 +434,23 @@ export class Message extends Entity { } } + get poll(): string | null { + let value = this.get("poll"); + if (!value || value.kind == ValueKind.NULL) { + return null; + } else { + return value.toString(); + } + } + + set poll(value: string | null) { + if (!value) { + this.unset("poll"); + } else { + this.set("poll", Value.fromString(value)); + } + } + get submittedBy(): Bytes | null { let value = this.get("submittedBy"); if (!value || value.kind == ValueKind.NULL) { @@ -620,6 +637,63 @@ export class PublicKey extends Entity { } } +export class Poll extends Entity { + constructor(id: string) { + super(); + this.set("id", Value.fromString(id)); + } + + save(): void { + let id = this.get("id"); + assert(id != null, "Cannot save Poll entity without an ID"); + if (id) { + assert( + id.kind == ValueKind.STRING, + `Entities of type Poll must have an ID of type String but the id '${id.displayData()}' is of type ${id.displayKind()}`, + ); + store.set("Poll", id.toString(), this); + } + } + + static loadInBlock(id: string): Poll | null { + return changetype(store.get_in_block("Poll", id)); + } + + static load(id: string): Poll | null { + return changetype(store.get("Poll", id)); + } + + get id(): string { + let value = this.get("id"); + if (!value || value.kind == ValueKind.NULL) { + throw new Error("Cannot return null for a required field."); + } else { + return value.toString(); + } + } + + set id(value: string) { + this.set("id", Value.fromString(value)); + } + + get fundingRound(): string { + let value = this.get("fundingRound"); + if (!value || value.kind == ValueKind.NULL) { + throw new Error("Cannot return null for a required field."); + } else { + return value.toString(); + } + } + + set fundingRound(value: string) { + this.set("fundingRound", Value.fromString(value)); + } + + get messages(): MessageLoader { + return new MessageLoader("Poll", this.get("id")!.toString(), "messages"); + } +} + export class FundingRound extends Entity { constructor(id: string) { super(); diff --git a/subgraph/generated/templates/MACI/MACI.ts b/subgraph/generated/templates/MACI/MACI.ts index b4644bdef..b1b8238e1 100644 --- a/subgraph/generated/templates/MACI/MACI.ts +++ b/subgraph/generated/templates/MACI/MACI.ts @@ -27,29 +27,21 @@ export class DeployPoll__Params { return this._event.parameters[0].value.toBigInt(); } - get _pubKey(): DeployPoll_pubKeyStruct { - return changetype( - this._event.parameters[1].value.toTuple(), - ); + get _coordinatorPubKeyX(): BigInt { + return this._event.parameters[1].value.toBigInt(); + } + + get _coordinatorPubKeyY(): BigInt { + return this._event.parameters[2].value.toBigInt(); } get pollAddr(): DeployPollPollAddrStruct { return changetype( - this._event.parameters[2].value.toTuple(), + this._event.parameters[3].value.toTuple(), ); } } -export class DeployPoll_pubKeyStruct extends ethereum.Tuple { - get x(): BigInt { - return this[0].toBigInt(); - } - - get y(): BigInt { - return this[1].toBigInt(); - } -} - export class DeployPollPollAddrStruct extends ethereum.Tuple { get poll(): Address { return this[0].toAddress(); @@ -107,28 +99,20 @@ export class SignUp__Params { return this._event.parameters[0].value.toBigInt(); } - get _userPubKey(): SignUp_userPubKeyStruct { - return changetype( - this._event.parameters[1].value.toTuple(), - ); + get _userPubKeyX(): BigInt { + return this._event.parameters[1].value.toBigInt(); } - get _voiceCreditBalance(): BigInt { + get _userPubKeyY(): BigInt { return this._event.parameters[2].value.toBigInt(); } - get _timestamp(): BigInt { + get _voiceCreditBalance(): BigInt { return this._event.parameters[3].value.toBigInt(); } -} - -export class SignUp_userPubKeyStruct extends ethereum.Tuple { - get x(): BigInt { - return this[0].toBigInt(); - } - get y(): BigInt { - return this[1].toBigInt(); + get _timestamp(): BigInt { + return this._event.parameters[4].value.toBigInt(); } } @@ -663,29 +647,6 @@ export class MACI extends ethereum.SmartContract { return ethereum.CallResult.fromValue(value[0].toBigInt()); } - numStateLeaves(param0: BigInt): BigInt { - let result = super.call( - "numStateLeaves", - "numStateLeaves(uint256):(uint256)", - [ethereum.Value.fromUnsignedBigInt(param0)], - ); - - return result[0].toBigInt(); - } - - try_numStateLeaves(param0: BigInt): ethereum.CallResult { - let result = super.tryCall( - "numStateLeaves", - "numStateLeaves(uint256):(uint256)", - [ethereum.Value.fromUnsignedBigInt(param0)], - ); - if (result.reverted) { - return new ethereum.CallResult(); - } - let value = result.value; - return ethereum.CallResult.fromValue(value[0].toBigInt()); - } - owner(): Address { let result = super.call("owner", "owner():(address)", []); @@ -889,6 +850,21 @@ export class MACI extends ethereum.SmartContract { return ethereum.CallResult.fromValue(value[0].toAddress()); } + subtreesMerged(): boolean { + let result = super.call("subtreesMerged", "subtreesMerged():(bool)", []); + + return result[0].toBoolean(); + } + + try_subtreesMerged(): ethereum.CallResult { + let result = super.tryCall("subtreesMerged", "subtreesMerged():(bool)", []); + if (result.reverted) { + return new ethereum.CallResult(); + } + let value = result.value; + return ethereum.CallResult.fromValue(value[0].toBoolean()); + } + tallyFactory(): Address { let result = super.call("tallyFactory", "tallyFactory():(address)", []); diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index e6fae8d30..147b3225f 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -27,7 +27,8 @@ type Message @entity { data: [BigInt!] msgType: BigInt! publicKey: PublicKey - fundingRound: FundingRound + fundingRound: FundingRound + poll: Poll submittedBy: Bytes timestamp: String blockNumber: BigInt! @@ -44,6 +45,12 @@ type PublicKey @entity { voiceCreditBalance: BigInt } +type Poll @entity { + id: ID! + fundingRound: FundingRound! + messages: [Message!] @derivedFrom(field: "poll") +} + type FundingRound @entity { id: ID! clrFund: ClrFund diff --git a/subgraph/src/ClrFundMapping.ts b/subgraph/src/ClrFundMapping.ts index 719480475..f26e32586 100644 --- a/subgraph/src/ClrFundMapping.ts +++ b/subgraph/src/ClrFundMapping.ts @@ -35,6 +35,7 @@ import { RecipientRegistry, ContributorRegistry, Token, + Poll, } from '../generated/schema' function createContributorRegistry( @@ -264,6 +265,11 @@ export function handleRoundStarted(event: RoundStarted): void { fundingRound.pollAddress = pollAddress PollTemplate.create(pollAddress) + let pollEntityId = pollAddress.toHexString() + let pollEntity = new Poll(pollEntityId) + pollEntity.fundingRound = fundingRoundId + pollEntity.save() + let pollContract = PollContract.bind(pollAddress) let deployTimeAndDuration = pollContract.try_getDeployTimeAndDuration() if (!deployTimeAndDuration.reverted) { diff --git a/subgraph/src/MACIMapping.ts b/subgraph/src/MACIMapping.ts index 2b8e98a0f..75da4929b 100644 --- a/subgraph/src/MACIMapping.ts +++ b/subgraph/src/MACIMapping.ts @@ -26,8 +26,8 @@ export function handleSignUp(event: SignUp): void { let publicKeyId = makePublicKeyId( fundingRoundId, - event.params._userPubKey.x, - event.params._userPubKey.y + event.params._userPubKeyX, + event.params._userPubKeyY ) let publicKey = PublicKey.load(publicKeyId) @@ -35,8 +35,8 @@ export function handleSignUp(event: SignUp): void { if (publicKey == null) { publicKey = new PublicKey(publicKeyId) } - publicKey.x = event.params._userPubKey.x - publicKey.y = event.params._userPubKey.y + publicKey.x = event.params._userPubKeyX + publicKey.y = event.params._userPubKeyY publicKey.stateIndex = event.params._stateIndex publicKey.voiceCreditBalance = event.params._voiceCreditBalance diff --git a/subgraph/src/PollMapping.ts b/subgraph/src/PollMapping.ts index 867d023a1..b3a4a6a86 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 { FundingRound, Message, PublicKey } from '../generated/schema' +import { FundingRound, Poll, Message, PublicKey } from '../generated/schema' import { makePublicKeyId } from './PublicKey' export function handlePublishMessage(event: PublishMessage): void { @@ -13,12 +13,21 @@ export function handlePublishMessage(event: PublishMessage): void { return } - let fundingRoundId = event.transaction.to!.toHex() - let fundingRound = FundingRound.load(fundingRoundId) - if (fundingRound == null) { + let pollEntityId = event.transaction.to!.toHex() + let poll = Poll.load(pollEntityId) + if (poll == null) { log.error( - 'Error: handlePublishMessage failed fundingRound not registered', - [] + 'Error: handlePublishMessage failed poll not found {}', + [pollEntityId] + ) + return + } + + let fundingRoundId = poll.fundingRound + if (!fundingRoundId) { + log.error( + 'Error: handlePublishMessage failed poll {} missing funding round', + [pollEntityId] ) return } @@ -55,6 +64,8 @@ export function handlePublishMessage(event: PublishMessage): void { message.publicKey = publicKeyId message.timestamp = timestamp + + message.poll = pollEntityId message.fundingRound = fundingRoundId message.save() log.info('handlePublishMessage', []) diff --git a/subgraph/subgraph.template.yaml b/subgraph/subgraph.template.yaml index 984cc41da..2e084d44f 100644 --- a/subgraph/subgraph.template.yaml +++ b/subgraph/subgraph.template.yaml @@ -179,7 +179,7 @@ templates: - name: FundingRound file: ./abis/FundingRound.json eventHandlers: - - event: SignUp(uint256,(uint256,uint256),uint256,uint256) + - event: SignUp(uint256,indexed uint256,indexed uint256,uint256,uint256) handler: handleSignUp file: ./src/MACIMapping.ts - name: Poll diff --git a/subgraph/subgraph.yaml b/subgraph/subgraph.yaml index ec0e082d4..20f0ab44d 100644 --- a/subgraph/subgraph.yaml +++ b/subgraph/subgraph.yaml @@ -179,7 +179,7 @@ templates: - name: FundingRound file: ./abis/FundingRound.json eventHandlers: - - event: SignUp(uint256,(uint256,uint256),uint256,uint256) + - event: SignUp(uint256,indexed uint256,indexed uint256,uint256,uint256) handler: handleSignUp file: ./src/MACIMapping.ts - name: Poll