feat: create semaphore proofs, test
This commit is contained in:
parent
9ec26069f0
commit
1224edffb9
|
@ -1,11 +1,17 @@
|
|||
import { utils } from "ethers";
|
||||
import { Signer, utils } from "ethers";
|
||||
import createIdentity from "@interep/identity";
|
||||
import { Group, Member } from "@semaphore-protocol/group";
|
||||
import { generateProof, packToSolidityProof } from "@semaphore-protocol/proof";
|
||||
import type { Identity } from "@semaphore-protocol/identity";
|
||||
// import createProof from '@interep/proof'
|
||||
import type { SnarkArtifacts } from "@interep/proof/dist/types/types";
|
||||
|
||||
export const sToBytes32 = (str: string): string => {
|
||||
return utils.formatBytes32String(str);
|
||||
};
|
||||
|
||||
// zerokit can only use 15, 19, and 20 depth
|
||||
export const merkleTreeDepth = 15;
|
||||
export const merkleTreeDepth = 20;
|
||||
|
||||
export const SNARK_SCALAR_FIELD = BigInt(
|
||||
"21888242871839275222246405745257275088548364400416034343698204186575808495617"
|
||||
|
@ -43,3 +49,59 @@ export const getGroups = () => {
|
|||
export const getValidGroups = () => {
|
||||
return getGroups().filter((group) => group.name !== sToBytes32("bronze"));
|
||||
};
|
||||
|
||||
export const createInterepIdentity = (signer: Signer, provider: string) => {
|
||||
if (!providers.includes(provider))
|
||||
throw new Error(`Invalid provider: ${provider}`);
|
||||
|
||||
const sign = (message: string) => signer.signMessage(message);
|
||||
return createIdentity(sign, provider);
|
||||
};
|
||||
|
||||
interface ProofCreationArgs {
|
||||
identity: Identity;
|
||||
members: Member[];
|
||||
groupProvider: typeof providers[0];
|
||||
groupTier: typeof tiers[0];
|
||||
externalNullifier: number;
|
||||
signal: string;
|
||||
snarkArtifacts: SnarkArtifacts;
|
||||
}
|
||||
|
||||
// Similar to https://github.com/interep-project/interep.js/blob/ae7d19f560a63fef08b71ecba7a926729538011c/packages/proof/src/createProof.ts#L21,
|
||||
// but without the api interactions
|
||||
// Note: An aribitrary set of members is passed in, without validation
|
||||
// when this function is called, ensure that the membership set passed in is a valid representation of onchain membership
|
||||
export const createInterepProof = async (args: ProofCreationArgs) => {
|
||||
const group = new Group(merkleTreeDepth);
|
||||
|
||||
const idCommitment = args.identity.getCommitment();
|
||||
|
||||
group.addMembers(args.members);
|
||||
|
||||
const memberIndex = group.indexOf(idCommitment);
|
||||
if (memberIndex === -1) {
|
||||
throw new Error("The semaphore identity is not yet verifiable onchain");
|
||||
}
|
||||
|
||||
const merkleProof = group.generateProofOfMembership(memberIndex);
|
||||
|
||||
const { publicSignals, proof } = await generateProof(
|
||||
args.identity,
|
||||
merkleProof,
|
||||
BigInt(args.externalNullifier),
|
||||
args.signal,
|
||||
args.snarkArtifacts
|
||||
);
|
||||
|
||||
const solidityProof = packToSolidityProof(proof);
|
||||
const groupId = createGroupId(args.groupProvider, args.groupTier).toString();
|
||||
|
||||
return {
|
||||
groupId,
|
||||
signal: args.signal,
|
||||
publicSignals,
|
||||
proof,
|
||||
solidityProof,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
"@nomiclabs/hardhat-etherscan": "^3.1.0",
|
||||
"@nomiclabs/hardhat-waffle": "^2.0.3",
|
||||
"@semaphore-protocol/contracts": "2.0.0",
|
||||
"@interep/identity": "0.3.0",
|
||||
"@interep/proof": "0.7.0",
|
||||
"@types/mocha": "^9.1.1",
|
||||
"chai": "^4.3.6",
|
||||
"ethereum-waffle": "^3.4.4",
|
||||
|
|
33
test/rln.ts
33
test/rln.ts
|
@ -1,7 +1,12 @@
|
|||
import { expect, assert } from "chai";
|
||||
import { BigNumber } from "ethers";
|
||||
import { ethers, deployments } from "hardhat";
|
||||
import { createGroupId, sToBytes32 } from "../common";
|
||||
import {
|
||||
createGroupId,
|
||||
createInterepIdentity,
|
||||
createInterepProof,
|
||||
sToBytes32,
|
||||
} from "../common";
|
||||
|
||||
describe("RLN", () => {
|
||||
beforeEach(async () => {
|
||||
|
@ -134,6 +139,32 @@ describe("RLN", () => {
|
|||
expect(pubkey.toHexString() === dummyPubkey.toHexString());
|
||||
});
|
||||
|
||||
it.only("[interep] should generate proof for registration", async () => {
|
||||
const signer = ethers.provider.getSigner(0);
|
||||
const identity = await createInterepIdentity(signer, "github");
|
||||
|
||||
// create a proof to test
|
||||
const proof = await createInterepProof({
|
||||
identity,
|
||||
members: [identity.getCommitment()],
|
||||
groupProvider: "github",
|
||||
groupTier: "silver",
|
||||
signal: "foo",
|
||||
externalNullifier: 1,
|
||||
snarkArtifacts: {
|
||||
wasmFilePath: "./test/snarkArtifacts/semaphore.wasm",
|
||||
zkeyFilePath: "./test/snarkArtifacts/semaphore.zkey",
|
||||
},
|
||||
});
|
||||
|
||||
expect(proof.groupId).to.eql(
|
||||
"19580063316323634959827976785370507245708993886389832860880129572471638471998"
|
||||
);
|
||||
expect(proof.publicSignals.merkleRoot).to.eql(
|
||||
"10738127364751233254031334835017982823925916365031589705155005906674724477907"
|
||||
);
|
||||
});
|
||||
|
||||
it("[interep] should withdraw membership", () => {
|
||||
// TODO
|
||||
});
|
||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue