Skip to content

Commit

Permalink
added the scripts to merge the signups and the messages
Browse files Browse the repository at this point in the history
  • Loading branch information
yashgo0018 committed Apr 17, 2024
1 parent 9c8d406 commit af70db4
Show file tree
Hide file tree
Showing 3 changed files with 297 additions and 21 deletions.
53 changes: 32 additions & 21 deletions packages/nextjs/app/admin/_components/PollStatusModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import PollAbi from "~~/abi/Poll";
import Modal from "~~/components/Modal";
import { useScaffoldContractRead } from "~~/hooks/scaffold-eth";
import { Poll } from "~~/types/poll";
import { mergeSignups } from "~~/utils/mergeSignups";
import { useMergeMessages } from "~~/utils/useMergeMessages";
import { useMergeSignups } from "~~/utils/useMergeSignups";

const stepNames = ["Merge SignUps", "Merge Main Roots", "Compute Main Root"];

Expand Down Expand Up @@ -38,7 +39,6 @@ export default function PollStatusModal({
functionName: "treeDepths",
});
const [, , messageTreeDepth] = treeDepths || [undefined, undefined, undefined, undefined];
console.log(messageTreeDepth);
const { data: extContracts, refetch: refetchExtContracts } = useContractRead({
abi: PollAbi,
address: poll?.pollContracts.poll,
Expand All @@ -58,8 +58,6 @@ export default function PollStatusModal({
// check if the main root was not already computed
// const mainRoot = (await accQueueContract.getMainRoot(messageTreeDepth.toString())).toString();

console.log(mainRoot1, mainRoot2);

function refetch() {
refetchStateTreeDepth();
refetchTreeDepths();
Expand All @@ -76,11 +74,11 @@ export default function PollStatusModal({
}
}

async function mergeSignupStep() {
if (!poll?.pollContracts.poll) return;

await mergeSignups({ pollContractAddress: poll?.pollContracts.poll });
}
const { merge: mergeSignups } = useMergeSignups({ pollContractAddress: poll?.pollContracts.poll, refresh: refetch });
const { merge: mergeMessages } = useMergeMessages({
pollContractAddress: poll?.pollContracts.poll,
refresh: refetch,
});

return (
<Modal show={show} setOpen={setOpen}>
Expand All @@ -96,22 +94,35 @@ export default function PollStatusModal({
{step === 1 && (
<div className="text-center">
<div className="text-sm">Merge the signup subtrees of the accumulator queue</div>
<div className="mockup-code bg-primary text-primary-content text-left mt-5">
<pre data-prefix="$">
<code>node build/ts/index.js mergeSignups -o {poll?.maciPollId.toString()}</code>
</pre>
</div>
</div>
)}

{step === 2 && (
<div className="text-center">
<div className="text-sm">Merge the signup subtrees of the accumulator queue</div>
</div>
)}

<div className="mt-5 sm:mt-6 sm:grid sm:grid-flow-row-dense sm:grid-cols-2 sm:gap-3">
<button
type="button"
className="inline-flex w-full justify-center rounded-md bg-primary text-primary-content px-3 py-2 font-semibold shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 sm:col-start-2"
onClick={refetch}
>
Refresh
</button>
{step === 1 && (
<button
type="button"
className="inline-flex w-full justify-center rounded-md bg-primary text-primary-content px-3 py-2 font-semibold shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 sm:col-start-2"
onClick={mergeSignups}
>
Merge Signups
</button>
)}

{step === 2 && (
<button
type="button"
className="inline-flex w-full justify-center rounded-md bg-primary text-primary-content px-3 py-2 font-semibold shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 sm:col-start-2"
onClick={mergeMessages}
>
Merge Messages
</button>
)}
<button
type="button"
className="mt-3 inline-flex w-full justify-center rounded-md bg-white px-3 py-2 font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 sm:col-start-1 sm:mt-0"
Expand Down
134 changes: 134 additions & 0 deletions packages/nextjs/utils/useMergeMessages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import { DEFAULT_SR_QUEUE_OPS } from "./useMergeSignups";
import { getContract } from "viem";
import { useContractRead, useContractWrite, usePublicClient } from "wagmi";
import AccQueueAbi from "~~/abi/AccQueue";
import PollAbi from "~~/abi/Poll";
import { useScaffoldContractRead } from "~~/hooks/scaffold-eth";

export function useMergeMessages({
pollContractAddress,
numQueueOps,
refresh,
}: {
pollContractAddress?: string;
numQueueOps?: number;
refresh: () => void;
}) {
const { data: dd, isFetched: deployTimeFetched } = useContractRead({
abi: PollAbi,
address: pollContractAddress,
functionName: "getDeployTimeAndDuration",
});

const { data: extContracts, isFetched: extContractsFetched } = useContractRead({
abi: PollAbi,
address: pollContractAddress,
functionName: "extContracts",
});

const { data: pollId, isFetched: pollIdFetched } = useScaffoldContractRead({
contractName: "MACI",
functionName: "getPollId",
args: [pollContractAddress],
});

const messageAqContractAddr = extContracts?.[1];

const { writeAsync: mergeMessageAqSubRoots, isLoading: mergeMessageAqSubRootsLoading } = useContractWrite({
abi: PollAbi,
address: pollContractAddress,
functionName: "mergeMessageAqSubRoots",
args: [BigInt(numQueueOps || DEFAULT_SR_QUEUE_OPS)],
});
const { writeAsync: mergeMessageAq, isLoading: mergeMessageAqLoading } = useContractWrite({
abi: PollAbi,
address: pollContractAddress,
functionName: "mergeMessageAq",
});

const publicClient = usePublicClient();

async function merge() {
if (!pollContractAddress || pollId === undefined || !dd || !messageAqContractAddr || !publicClient) {
return;
}

// check if it's time to merge the message AQ
const deadline = Number(dd[0]) + Number(dd[1]);
const { timestamp: now } = await publicClient.getBlock();

if (now < deadline) {
console.error("Voting period is not over");
return;
}

const pollContract = getContract({
abi: PollAbi,
address: pollContractAddress,
publicClient,
});

const accQueueContract = getContract({
abi: AccQueueAbi,
address: messageAqContractAddr,
publicClient,
});

let subTreesMerged = false;

console.log("I am here");

// infinite loop to merge the sub trees
while (!subTreesMerged) {
// eslint-disable-next-line no-await-in-loop
subTreesMerged = await accQueueContract.read.subTreesMerged();

if (subTreesMerged) {
console.log("All message subtrees have been merged.");
} else {
// eslint-disable-next-line no-await-in-loop
await accQueueContract.read
.getSrIndices()
.then(data => data.map(x => Number(x)))
.then(indices => {
console.log(`Merging message subroots ${indices[0] + 1} / ${indices[1] + 1}`);
});

// eslint-disable-next-line no-await-in-loop
const { hash: tx } = await mergeMessageAqSubRoots();
// eslint-disable-next-line no-await-in-loop

console.log(`Transaction hash: ${tx}`);
}
}

// check if the message AQ has been fully merged
const messageTreeDepth = (await pollContract.read.treeDepths())[2];

// check if the main root was not already computed
const mainRoot = await accQueueContract.read.getMainRoot([BigInt(messageTreeDepth)]);
if (mainRoot === 0n) {
// go and merge the message tree

console.log("Merging subroots to a main message root...");
const { hash: tx } = await mergeMessageAq();

console.log(`Executed mergeMessageAq(); Transaction hash: ${tx}`);
console.log("The message tree has been merged.");
} else {
console.log("The message tree has already been merged.");
}

refresh();
}

const loadingData = {
deployTimeFetched,
extContractsFetched,
pollIdFetched,
mergeMessageAqLoading,
mergeMessageAqSubRootsLoading,
};

return { merge, loadingData };
}
131 changes: 131 additions & 0 deletions packages/nextjs/utils/useMergeSignups.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import { useState } from "react";
import { getContract } from "viem";
import { useContractRead, useContractWrite, usePublicClient } from "wagmi";
import AccQueueAbi from "~~/abi/AccQueue";
import PollAbi from "~~/abi/Poll";
import { useScaffoldContract, useScaffoldContractRead } from "~~/hooks/scaffold-eth";

export const DEFAULT_SR_QUEUE_OPS = 4;

export function useMergeSignups({
pollContractAddress,
numQueueOps,
refresh,
}: {
pollContractAddress?: string;
numQueueOps?: number;
refresh: () => void;
}) {
const { data: dd, isFetched: deployTimeFetched } = useContractRead({
abi: PollAbi,
address: pollContractAddress,
functionName: "getDeployTimeAndDuration",
});
const { data: pollId, isFetched: pollIdFetched } = useScaffoldContractRead({
contractName: "MACI",
functionName: "getPollId",
args: [pollContractAddress],
});
const { data: accQueueContractAddress, isFetched: accQueueContractAddressFetched } = useScaffoldContractRead({
contractName: "MACI",
functionName: "stateAq",
});
const publicClient = usePublicClient();
const { data: maci } = useScaffoldContract({ contractName: "MACI" });
const { writeAsync: mergeMaciStateAqSubRoots, isLoading: mergeMaciStateAqSubRootsLoading } = useContractWrite({
abi: PollAbi,
address: pollContractAddress,
functionName: "mergeMaciStateAqSubRoots",
args: pollId !== undefined ? [BigInt(numQueueOps || DEFAULT_SR_QUEUE_OPS), pollId] : undefined,
});
const { writeAsync: mergeMaciStateAq, isLoading: mergeMaciStateAqLoading } = useContractWrite({
abi: PollAbi,
address: pollContractAddress,
functionName: "mergeMaciStateAq",
args: pollId !== undefined ? [pollId] : undefined,
});

const [mergeLoading, setMergeLoading] = useState(false);

async function merge() {
if (!pollContractAddress || pollId === undefined || !dd || !accQueueContractAddress || !maci) {
return;
}

const deadline = Number(dd[0]) + Number(dd[1]);
const { timestamp: now } = await publicClient.getBlock();

if (now < deadline) {
console.error("Voting period is not over");
return;
}

setMergeLoading(true);

const accQueueContract = getContract({
abi: AccQueueAbi,
address: accQueueContractAddress,
publicClient,
});

let subTreesMerged = false;

// infinite loop to merge the sub trees
while (!subTreesMerged) {
// eslint-disable-next-line no-await-in-loop
subTreesMerged = await accQueueContract.read.subTreesMerged();

if (subTreesMerged) {
console.log("All state subtrees have been merged.");
} else {
// eslint-disable-next-line no-await-in-loop
await accQueueContract.read
.getSrIndices()
.then(data => data.map(x => Number(x)))
.then(indices => {
console.log(`Merging state subroots ${indices[0] + 1} / ${indices[1] + 1}`);
});

// first merge the subroots
// eslint-disable-next-line no-await-in-loop
const { hash: tx } = await mergeMaciStateAqSubRoots();

console.log(`Transaction hash: ${tx}`);
}
}

const stateTreeDepth = await maci.read.stateTreeDepth();

const mainRoot = await accQueueContract.read.getMainRoot([BigInt(stateTreeDepth)]);

if (mainRoot !== 0n && !pollId) {
console.log("The state tree has already been merged.");
return;
}

// go and merge the state tree
console.log("Merging subroots to a main state root...");
try {
const { hash: tx } = await mergeMaciStateAq();

console.log(`Transaction hash: ${tx}`);
} catch (err) {
console.log("error here");
}

setMergeLoading(false);

refresh();
}

const loadingData = {
deployTimeFetched,
pollIdFetched,
accQueueContractAddressFetched,
mergeMaciStateAqSubRootsLoading,
mergeMaciStateAqLoading,
mergeLoading,
};

return { merge, loadingData };
}

0 comments on commit af70db4

Please sign in to comment.