mirror of
https://github.com/personaelabs/spartan-ecdsa.git
synced 2026-01-10 06:28:01 -05:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4bf236a1a5 | ||
|
|
ede2b29cac | ||
|
|
cb273002c0 | ||
|
|
a08876d1ff | ||
|
|
8b0529f868 | ||
|
|
3827e5de67 | ||
|
|
53049c8cbe | ||
|
|
2fab170a15 | ||
|
|
82518aabc3 | ||
|
|
e8c95a975b | ||
|
|
4cf4b36efd |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -23,6 +23,7 @@ circom_witness.wtns
|
||||
*.ptau
|
||||
|
||||
build/
|
||||
dist/
|
||||
|
||||
*.r1cs
|
||||
*.sym
|
||||
@@ -33,7 +34,7 @@ packages/prover/test_circuit/test_circuit_js/
|
||||
packages/prover/test_circuit/*.json
|
||||
|
||||
|
||||
wasm_bytes.ts
|
||||
wasmBytes.ts
|
||||
**/sage/*.sage.py
|
||||
packages/lib/src/circuits/
|
||||
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
"eslint-plugin-react": "7.32.1",
|
||||
"eslint-plugin-react-hooks": "4.6.0",
|
||||
"eslint-plugin-security": "1.7.0",
|
||||
"lerna": "^6.4.0",
|
||||
"snarkjs": "^0.5.0"
|
||||
"lerna": "^6.4.0"
|
||||
},
|
||||
"workspaces": [
|
||||
"packages/lib",
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
"next": "13.0.0",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"readline": "^1.3.0",
|
||||
"snarkjs": "^0.5.0"
|
||||
"readline": "^1.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "18.11.7",
|
||||
|
||||
@@ -12,7 +12,7 @@ const embedWasmBytes = async () => {
|
||||
export const wasmBytes = new Uint8Array([${bytes.toString()}]);
|
||||
`;
|
||||
|
||||
fs.writeFileSync("./src/wasm/wasm_bytes.ts", file);
|
||||
fs.writeFileSync("./src/wasm/wasmBytes.ts", file);
|
||||
};
|
||||
|
||||
embedWasmBytes();
|
||||
@@ -3,7 +3,10 @@ module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
transform: {
|
||||
"^.+\\.js?$": "ts-jest"
|
||||
"^.+\\.(ts|js)?$": "ts-jest"
|
||||
},
|
||||
moduleNameMapper: {
|
||||
"@src/(.*)$": "<rootDir>/src/$1",
|
||||
},
|
||||
testTimeout: 600000,
|
||||
};
|
||||
@@ -1,17 +1,32 @@
|
||||
{
|
||||
"name": "@personaelabs/spartan-ecdsa",
|
||||
"version": "2.3.0",
|
||||
"main": "./build/lib.js",
|
||||
"types": "./build/lib.d.ts",
|
||||
"version": "2.3.1",
|
||||
"description": "Spartan-ecdsa (which to our knowledge) is the fastest open-source method to verify ECDSA (secp256k1) signatures in zero-knowledge.",
|
||||
"keywords": [
|
||||
"spartan",
|
||||
"spartan-ecdsa",
|
||||
"zk",
|
||||
"efficient-ecdsa"
|
||||
],
|
||||
"author": "Personae Labs",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/personaelabs/spartan-ecdsa/issues/new"
|
||||
},
|
||||
"homepage": "https://github.com/personaelabs/spartan-ecdsa",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"files": [
|
||||
"build/**/*"
|
||||
"dist/**/*"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "rm -rf ./build && yarn embedWasmBytes && tsc",
|
||||
"build": "rm -rf ./dist && yarn embedWasmBytes && tsc --project tsconfig.build.json",
|
||||
"prepublishOnly": "yarn build",
|
||||
"prepare": "yarn embedWasmBytes",
|
||||
"embedWasmBytes": "ts-node ./embed_wasm_bytes.ts",
|
||||
"embedWasmBytes": "ts-node ./embedWasmBytes.ts",
|
||||
"test": "jest"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -25,6 +40,6 @@
|
||||
"@ethereumjs/util": "^8.0.3",
|
||||
"@zk-kit/incremental-merkle-tree": "^1.0.0",
|
||||
"elliptic": "^6.5.4",
|
||||
"snarkjs": "^0.5.0"
|
||||
"snarkjs": "^0.7.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import { ProverConfig, VerifyConfig } from "./types";
|
||||
|
||||
// Default configs for pubkey membership proving/verifying
|
||||
export const defaultPubkeyMembershipPConfig: ProverConfig = {
|
||||
witnessGenWasm:
|
||||
"https://storage.googleapis.com/personae-proving-keys/membership/pubkey_membership.wasm",
|
||||
circuit:
|
||||
"https://storage.googleapis.com/personae-proving-keys/membership/pubkey_membership.circuit"
|
||||
};
|
||||
|
||||
export const defaultPubkeyMembershipVConfig: VerifyConfig = {
|
||||
circuit: defaultPubkeyMembershipPConfig.circuit
|
||||
};
|
||||
|
||||
// Default configs for address membership proving/verifyign
|
||||
export const defaultAddressMembershipPConfig: ProverConfig = {
|
||||
witnessGenWasm:
|
||||
"https://storage.googleapis.com/personae-proving-keys/membership/addr_membership.wasm",
|
||||
circuit:
|
||||
"https://storage.googleapis.com/personae-proving-keys/membership/addr_membership.circuit"
|
||||
};
|
||||
|
||||
export const defaultAddressMembershipVConfig: VerifyConfig = {
|
||||
circuit: defaultAddressMembershipPConfig.circuit
|
||||
};
|
||||
25
packages/lib/src/config/index.ts
Normal file
25
packages/lib/src/config/index.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { ProverConfig, VerifyConfig } from "@src/types";
|
||||
|
||||
// Default configs for pubkey membership proving/verifying
|
||||
export const defaultPubkeyProverConfig: ProverConfig = {
|
||||
witnessGenWasm:
|
||||
"https://storage.googleapis.com/personae-proving-keys/membership/pubkey_membership.wasm",
|
||||
circuit:
|
||||
"https://storage.googleapis.com/personae-proving-keys/membership/pubkey_membership.circuit"
|
||||
};
|
||||
|
||||
export const defaultPubkeyVerifierConfig: VerifyConfig = {
|
||||
circuit: defaultPubkeyProverConfig.circuit
|
||||
};
|
||||
|
||||
// Default configs for address membership proving/verifyign
|
||||
export const defaultAddressProverConfig: ProverConfig = {
|
||||
witnessGenWasm:
|
||||
"https://storage.googleapis.com/personae-proving-keys/membership/addr_membership.wasm",
|
||||
circuit:
|
||||
"https://storage.googleapis.com/personae-proving-keys/membership/addr_membership.circuit"
|
||||
};
|
||||
|
||||
export const defaultAddressVerifierConfig: VerifyConfig = {
|
||||
circuit: defaultAddressProverConfig.circuit
|
||||
};
|
||||
@@ -1,16 +1,16 @@
|
||||
import { Profiler } from "../helpers/profiler";
|
||||
import { IProver, MerkleProof, NIZK, ProverConfig } from "../types";
|
||||
import { loadCircuit, fromSig, snarkJsWitnessGen } from "../helpers/utils";
|
||||
import { Profiler } from "@src/helpers/profiler";
|
||||
import { IProver, MerkleProof, NIZK, ProveArgs, ProverConfig } from "@src/types";
|
||||
import { loadCircuit, fromSig, snarkJsWitnessGen } from "@src/helpers/utils";
|
||||
import {
|
||||
PublicInput,
|
||||
computeEffEcdsaPubInput,
|
||||
CircuitPubInput
|
||||
} from "../helpers/public_input";
|
||||
import wasm, { init } from "../wasm";
|
||||
} from "@src/helpers/publicInputs";
|
||||
import { init, wasm } from "@src/wasm";
|
||||
import {
|
||||
defaultPubkeyMembershipPConfig,
|
||||
defaultAddressMembershipPConfig
|
||||
} from "../config";
|
||||
defaultPubkeyProverConfig,
|
||||
defaultAddressProverConfig
|
||||
} from "@src/config";
|
||||
|
||||
/**
|
||||
* ECDSA Membership Prover
|
||||
@@ -20,15 +20,20 @@ export class MembershipProver extends Profiler implements IProver {
|
||||
witnessGenWasm: string;
|
||||
useRemoteCircuit: boolean;
|
||||
|
||||
constructor(options: ProverConfig) {
|
||||
super({ enabled: options?.enableProfiler });
|
||||
constructor({
|
||||
enableProfiler,
|
||||
circuit,
|
||||
witnessGenWasm,
|
||||
useRemoteCircuit
|
||||
}: ProverConfig) {
|
||||
super({ enabled: enableProfiler });
|
||||
|
||||
if (
|
||||
options.circuit === defaultPubkeyMembershipPConfig.circuit ||
|
||||
options.witnessGenWasm ===
|
||||
defaultPubkeyMembershipPConfig.witnessGenWasm ||
|
||||
options.circuit === defaultAddressMembershipPConfig.circuit ||
|
||||
options.witnessGenWasm === defaultAddressMembershipPConfig.witnessGenWasm
|
||||
circuit === defaultPubkeyProverConfig.circuit ||
|
||||
witnessGenWasm ===
|
||||
defaultPubkeyProverConfig.witnessGenWasm ||
|
||||
circuit === defaultAddressProverConfig.circuit ||
|
||||
witnessGenWasm === defaultAddressProverConfig.witnessGenWasm
|
||||
) {
|
||||
console.warn(`
|
||||
Spartan-ecdsa default config warning:
|
||||
@@ -38,21 +43,16 @@ export class MembershipProver extends Profiler implements IProver {
|
||||
`);
|
||||
}
|
||||
|
||||
this.circuit = options.circuit;
|
||||
this.witnessGenWasm = options.witnessGenWasm;
|
||||
this.useRemoteCircuit = options.useRemoteCircuit ?? false;
|
||||
this.circuit = circuit;
|
||||
this.witnessGenWasm = witnessGenWasm;
|
||||
this.useRemoteCircuit = useRemoteCircuit ?? false;
|
||||
}
|
||||
|
||||
async initWasm() {
|
||||
await init();
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
async prove(
|
||||
sig: string,
|
||||
msgHash: Buffer,
|
||||
merkleProof: MerkleProof
|
||||
): Promise<NIZK> {
|
||||
async prove({ sig, msgHash, merkleProof }: ProveArgs): Promise<NIZK> {
|
||||
const { r, s, v } = fromSig(sig);
|
||||
|
||||
const effEcdsaPubInput = computeEffEcdsaPubInput(r, v, msgHash);
|
||||
@@ -80,7 +80,7 @@ export class MembershipProver extends Profiler implements IProver {
|
||||
|
||||
this.time("Load circuit");
|
||||
const useRemoteCircuit =
|
||||
this.useRemoteCircuit ?? typeof window !== "undefined";
|
||||
this.useRemoteCircuit || typeof window !== "undefined";
|
||||
const circuitBin = await loadCircuit(this.circuit, useRemoteCircuit);
|
||||
this.timeEnd("Load circuit");
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import {
|
||||
defaultAddressMembershipVConfig,
|
||||
defaultPubkeyMembershipVConfig
|
||||
} from "../config";
|
||||
import { Profiler } from "../helpers/profiler";
|
||||
import { loadCircuit } from "../helpers/utils";
|
||||
import { IVerifier, VerifyConfig } from "../types";
|
||||
import wasm, { init } from "../wasm";
|
||||
import { PublicInput, verifyEffEcdsaPubInput } from "../helpers/public_input";
|
||||
defaultAddressVerifierConfig,
|
||||
defaultPubkeyVerifierConfig
|
||||
} from "@src/config";
|
||||
import { Profiler } from "@src/helpers/profiler";
|
||||
import { loadCircuit } from "@src/helpers/utils";
|
||||
import { IVerifier, VerifyArgs, VerifyConfig } from "@src/types";
|
||||
import { init, wasm } from "@src/wasm";
|
||||
import { PublicInput, verifyEffEcdsaPubInput } from "@src/helpers/publicInputs";
|
||||
|
||||
/**
|
||||
* ECDSA Membership Verifier
|
||||
@@ -15,12 +15,16 @@ export class MembershipVerifier extends Profiler implements IVerifier {
|
||||
circuit: string;
|
||||
useRemoteCircuit: boolean;
|
||||
|
||||
constructor(options: VerifyConfig) {
|
||||
super({ enabled: options?.enableProfiler });
|
||||
constructor({
|
||||
circuit,
|
||||
enableProfiler,
|
||||
useRemoteCircuit
|
||||
}: VerifyConfig) {
|
||||
super({ enabled: enableProfiler });
|
||||
|
||||
if (
|
||||
options.circuit === defaultAddressMembershipVConfig.circuit ||
|
||||
options.circuit === defaultPubkeyMembershipVConfig.circuit
|
||||
circuit === defaultAddressVerifierConfig.circuit ||
|
||||
circuit === defaultPubkeyVerifierConfig.circuit
|
||||
) {
|
||||
console.warn(`
|
||||
Spartan-ecdsa default config warning:
|
||||
@@ -30,19 +34,16 @@ export class MembershipVerifier extends Profiler implements IVerifier {
|
||||
`);
|
||||
}
|
||||
|
||||
this.circuit = options.circuit;
|
||||
this.circuit = circuit;
|
||||
this.useRemoteCircuit =
|
||||
options.useRemoteCircuit ?? typeof window !== "undefined";
|
||||
useRemoteCircuit || typeof window !== "undefined";
|
||||
}
|
||||
|
||||
async initWasm() {
|
||||
await init();
|
||||
}
|
||||
|
||||
async verify(
|
||||
proof: Uint8Array,
|
||||
publicInputSer: Uint8Array
|
||||
): Promise<boolean> {
|
||||
async verify({ proof, publicInputSer }: VerifyArgs): Promise<boolean> {
|
||||
this.time("Load circuit");
|
||||
const circuitBin = await loadCircuit(this.circuit, this.useRemoteCircuit);
|
||||
this.timeEnd("Load circuit");
|
||||
@@ -1,5 +1,5 @@
|
||||
import { init, wasm } from "@src/wasm";
|
||||
import { bigIntToLeBytes, bytesLeToBigInt } from "./utils";
|
||||
import wasm, { init } from "../wasm";
|
||||
|
||||
export class Poseidon {
|
||||
hash(inputs: bigint[]): bigint {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
var EC = require("elliptic").ec;
|
||||
const BN = require("bn.js");
|
||||
|
||||
import { EffECDSAPubInput } from "@src/types";
|
||||
import { bytesToBigInt, bigIntToBytes } from "./utils";
|
||||
import { EffECDSAPubInput } from "../types";
|
||||
|
||||
const ec = new EC("secp256k1");
|
||||
|
||||
@@ -144,15 +144,18 @@ export const computeEffEcdsaPubInput = (
|
||||
/**
|
||||
* Verify the public values of the efficient ECDSA circuit
|
||||
*/
|
||||
export const verifyEffEcdsaPubInput = (pubInput: PublicInput): boolean => {
|
||||
export const verifyEffEcdsaPubInput = ({
|
||||
r,
|
||||
rV,
|
||||
msgHash,
|
||||
circuitPubInput
|
||||
}: PublicInput): boolean => {
|
||||
const expectedCircuitInput = computeEffEcdsaPubInput(
|
||||
pubInput.r,
|
||||
pubInput.rV,
|
||||
pubInput.msgHash
|
||||
r,
|
||||
rV,
|
||||
msgHash
|
||||
);
|
||||
|
||||
const circuitPubInput = pubInput.circuitPubInput;
|
||||
|
||||
const isValid =
|
||||
expectedCircuitInput.Tx === circuitPubInput.Tx &&
|
||||
expectedCircuitInput.Ty === circuitPubInput.Ty &&
|
||||
@@ -18,7 +18,10 @@ export const snarkJsWitnessGen = async (input: any, wasmFile: string) => {
|
||||
/**
|
||||
* Load a circuit from a file or URL
|
||||
*/
|
||||
export const loadCircuit = async (pathOrUrl: string, useRemoteCircuit: boolean): Promise<Uint8Array> => {
|
||||
export const loadCircuit = async (
|
||||
pathOrUrl: string,
|
||||
useRemoteCircuit: boolean
|
||||
): Promise<Uint8Array> => {
|
||||
if (useRemoteCircuit) {
|
||||
return await fetchCircuit(pathOrUrl);
|
||||
} else {
|
||||
|
||||
8
packages/lib/src/index.ts
Normal file
8
packages/lib/src/index.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export { MembershipProver } from "@src/core/prover";
|
||||
export { MembershipVerifier } from "@src/core/verifier";
|
||||
export { CircuitPubInput, PublicInput, computeEffEcdsaPubInput, verifyEffEcdsaPubInput } from "@src/helpers/publicInputs";
|
||||
export { Tree } from "@src/helpers/tree";
|
||||
export { Poseidon } from "@src/helpers/poseidon";
|
||||
export { init, wasm } from "@src/wasm/index";
|
||||
export { defaultPubkeyProverConfig as defaultPubkeyMembershipPConfig, defaultPubkeyVerifierConfig as defaultPubkeyMembershipVConfig, defaultAddressProverConfig as defaultAddressMembershipPConfig, defaultAddressVerifierConfig as defaultAddressMembershipVConfig } from "@src/config";
|
||||
export type { MerkleProof, EffECDSAPubInput, NIZK, ProverConfig, VerifyConfig, IProver, IVerifier } from "@src/types";
|
||||
@@ -1,8 +0,0 @@
|
||||
export * from "./types";
|
||||
export * from "./helpers/public_input";
|
||||
export * from "./core/membership_prover";
|
||||
export * from "./core/membership_verifier";
|
||||
export * from "./helpers/tree";
|
||||
export * from "./helpers/poseidon";
|
||||
export * from "./wasm/index";
|
||||
export * from "./config";
|
||||
@@ -1,47 +0,0 @@
|
||||
import { PublicInput } from "./helpers/public_input";
|
||||
|
||||
// The same structure as MerkleProof in @zk-kit/incremental-merkle-tree.
|
||||
// Not directly using MerkleProof defined in @zk-kit/incremental-merkle-tree so
|
||||
// library users can choose whatever merkle tree management method they want.
|
||||
export interface MerkleProof {
|
||||
root: bigint;
|
||||
siblings: [bigint][];
|
||||
pathIndices: number[];
|
||||
}
|
||||
export interface EffECDSAPubInput {
|
||||
Tx: bigint;
|
||||
Ty: bigint;
|
||||
Ux: bigint;
|
||||
Uy: bigint;
|
||||
}
|
||||
|
||||
export interface NIZK {
|
||||
proof: Uint8Array;
|
||||
publicInput: PublicInput;
|
||||
}
|
||||
|
||||
export interface ProverConfig {
|
||||
witnessGenWasm: string;
|
||||
circuit: string;
|
||||
enableProfiler?: boolean;
|
||||
useRemoteCircuit?: boolean;
|
||||
}
|
||||
|
||||
export interface VerifyConfig {
|
||||
circuit: string; // Path to circuit file compiled by Nova-Scotia
|
||||
enableProfiler?: boolean;
|
||||
useRemoteCircuit?: boolean;
|
||||
}
|
||||
|
||||
export interface IProver {
|
||||
circuit: string; // Path to circuit file compiled by Nova-Scotia
|
||||
witnessGenWasm: string; // Path to witness generator wasm file generated by Circom
|
||||
|
||||
prove(...args: any): Promise<NIZK>;
|
||||
}
|
||||
|
||||
export interface IVerifier {
|
||||
circuit: string; // Path to circuit file compiled by Nova-Scotia
|
||||
|
||||
verify(proof: Uint8Array, publicInput: Uint8Array): Promise<boolean>;
|
||||
}
|
||||
58
packages/lib/src/types/index.ts
Normal file
58
packages/lib/src/types/index.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { PublicInput } from "@src/helpers/publicInputs";
|
||||
|
||||
// The same structure as MerkleProof in @zk-kit/incremental-merkle-tree.
|
||||
// Not directly using MerkleProof defined in @zk-kit/incremental-merkle-tree so
|
||||
// library users can choose whatever merkle tree management method they want.
|
||||
export interface MerkleProof {
|
||||
root: bigint;
|
||||
siblings: [bigint][];
|
||||
pathIndices: number[];
|
||||
}
|
||||
export interface EffECDSAPubInput {
|
||||
Tx: bigint;
|
||||
Ty: bigint;
|
||||
Ux: bigint;
|
||||
Uy: bigint;
|
||||
}
|
||||
|
||||
export interface NIZK {
|
||||
proof: Uint8Array;
|
||||
publicInput: PublicInput;
|
||||
}
|
||||
|
||||
export interface ProverConfig {
|
||||
witnessGenWasm: string;
|
||||
circuit: string;
|
||||
enableProfiler?: boolean;
|
||||
useRemoteCircuit?: boolean;
|
||||
}
|
||||
|
||||
export interface ProveArgs {
|
||||
sig: string;
|
||||
msgHash: Buffer,
|
||||
merkleProof: MerkleProof;
|
||||
}
|
||||
|
||||
export interface VerifyArgs {
|
||||
proof: Uint8Array,
|
||||
publicInputSer: Uint8Array
|
||||
}
|
||||
|
||||
export interface VerifyConfig {
|
||||
circuit: string; // Path to circuit file compiled by Nova-Scotia
|
||||
enableProfiler?: boolean;
|
||||
useRemoteCircuit?: boolean;
|
||||
}
|
||||
|
||||
export interface IProver {
|
||||
circuit: string; // Path to circuit file compiled by Nova-Scotia
|
||||
witnessGenWasm: string; // Path to witness generator wasm file generated by Circom
|
||||
|
||||
prove({ sig, msgHash, merkleProof }: ProveArgs): Promise<NIZK>;
|
||||
}
|
||||
|
||||
export interface IVerifier {
|
||||
circuit: string; // Path to circuit file compiled by Nova-Scotia
|
||||
|
||||
verify({ proof, publicInputSer }: VerifyArgs): Promise<boolean>;
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
import * as wasm from "./wasm";
|
||||
|
||||
import { wasmBytes } from "./wasm_bytes";
|
||||
import { wasmBytes } from "./wasmBytes";
|
||||
|
||||
export const init = async () => {
|
||||
await wasm.initSync(wasmBytes.buffer);
|
||||
wasm.init_panic_hook();
|
||||
};
|
||||
|
||||
export default wasm;
|
||||
export { wasm };
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { hashPersonalMessage } from "@ethereumjs/util";
|
||||
|
||||
import {
|
||||
CircuitPubInput,
|
||||
PublicInput,
|
||||
verifyEffEcdsaPubInput
|
||||
} from "../src/helpers/public_input";
|
||||
import { hashPersonalMessage } from "@ethereumjs/util";
|
||||
} from "../src/helpers/publicInputs";
|
||||
|
||||
describe("public_input", () => {
|
||||
/**
|
||||
@@ -1,19 +1,20 @@
|
||||
import {
|
||||
MembershipProver,
|
||||
MembershipVerifier,
|
||||
Tree,
|
||||
Poseidon,
|
||||
NIZK
|
||||
} from "../src/lib";
|
||||
import {
|
||||
hashPersonalMessage,
|
||||
ecsign,
|
||||
privateToAddress,
|
||||
privateToPublic
|
||||
} from "@ethereumjs/util";
|
||||
var EC = require("elliptic").ec;
|
||||
|
||||
import * as path from "path";
|
||||
|
||||
import {
|
||||
MembershipProver,
|
||||
MembershipVerifier,
|
||||
Tree,
|
||||
Poseidon,
|
||||
NIZK
|
||||
} from "../src";
|
||||
|
||||
describe("membership prove and verify", () => {
|
||||
// Init prover
|
||||
const treeDepth = 20;
|
||||
@@ -25,7 +26,6 @@ describe("membership prove and verify", () => {
|
||||
// Sign (Use privKeys[0] for proving)
|
||||
const proverIndex = 0;
|
||||
const proverPrivKey = privKeys[proverIndex];
|
||||
let proverAddress: bigint;
|
||||
|
||||
let msg = Buffer.from("harry potter");
|
||||
const msgHash = hashPersonalMessage(msg);
|
||||
@@ -84,11 +84,14 @@ describe("membership prove and verify", () => {
|
||||
const index = pubKeyTree.indexOf(proverPubKeyHash as bigint);
|
||||
const merkleProof = pubKeyTree.createProof(index);
|
||||
|
||||
nizk = await pubKeyMembershipProver.prove(sig, msgHash, merkleProof);
|
||||
nizk = await pubKeyMembershipProver.prove({ sig, msgHash, merkleProof });
|
||||
|
||||
const { proof, publicInput } = nizk;
|
||||
expect(
|
||||
await pubKeyMembershipVerifier.verify(proof, publicInput.serialize())
|
||||
await pubKeyMembershipVerifier.verify({
|
||||
proof,
|
||||
publicInputSer: publicInput.serialize()
|
||||
})
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
@@ -97,17 +100,23 @@ describe("membership prove and verify", () => {
|
||||
let proof = nizk.proof;
|
||||
proof[0] = proof[0] += 1;
|
||||
expect(
|
||||
await pubKeyMembershipVerifier.verify(proof, publicInput.serialize())
|
||||
await pubKeyMembershipVerifier.verify({
|
||||
proof,
|
||||
publicInputSer: publicInput.serialize()
|
||||
})
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("should assert invalid public input", async () => {
|
||||
const { proof } = nizk;
|
||||
let publicInput = nizk.publicInput.serialize();
|
||||
publicInput[0] = publicInput[0] += 1;
|
||||
expect(await pubKeyMembershipVerifier.verify(proof, publicInput)).toBe(
|
||||
false
|
||||
);
|
||||
let publicInputSer = nizk.publicInput.serialize();
|
||||
publicInputSer[0] = publicInputSer[0] += 1;
|
||||
expect(
|
||||
await pubKeyMembershipVerifier.verify({
|
||||
proof,
|
||||
publicInputSer
|
||||
})
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -154,14 +163,14 @@ describe("membership prove and verify", () => {
|
||||
|
||||
await addressMembershipProver.initWasm();
|
||||
|
||||
nizk = await addressMembershipProver.prove(sig, msgHash, merkleProof);
|
||||
nizk = await addressMembershipProver.prove({ sig, msgHash, merkleProof });
|
||||
await addressMembershipVerifier.initWasm();
|
||||
|
||||
expect(
|
||||
await addressMembershipVerifier.verify(
|
||||
nizk.proof,
|
||||
nizk.publicInput.serialize()
|
||||
)
|
||||
await addressMembershipVerifier.verify({
|
||||
proof: nizk.proof,
|
||||
publicInputSer: nizk.publicInput.serialize()
|
||||
})
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
@@ -170,17 +179,23 @@ describe("membership prove and verify", () => {
|
||||
let proof = nizk.proof;
|
||||
proof[0] = proof[0] += 1;
|
||||
expect(
|
||||
await addressMembershipVerifier.verify(proof, publicInput.serialize())
|
||||
await addressMembershipVerifier.verify({
|
||||
proof,
|
||||
publicInputSer: publicInput.serialize()
|
||||
})
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("should assert invalid public input", async () => {
|
||||
const { proof } = nizk;
|
||||
let publicInput = nizk.publicInput.serialize();
|
||||
publicInput[0] = publicInput[0] += 1;
|
||||
expect(await addressMembershipVerifier.verify(proof, publicInput)).toBe(
|
||||
false
|
||||
);
|
||||
let publicInputSer = nizk.publicInput.serialize();
|
||||
publicInputSer[0] = publicInputSer[0] += 1;
|
||||
expect(
|
||||
await addressMembershipVerifier.verify({
|
||||
proof,
|
||||
publicInputSer
|
||||
})
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Tree, Poseidon } from "../src/lib";
|
||||
import { Tree, Poseidon } from "../src";
|
||||
|
||||
describe("Merkle tree prove and verify", () => {
|
||||
let poseidon: Poseidon;
|
||||
|
||||
6
packages/lib/tsconfig.build.json
Normal file
6
packages/lib/tsconfig.build.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"exclude": [
|
||||
"./tests/**/*"
|
||||
],
|
||||
}
|
||||
@@ -1,25 +1,31 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"rootDir": ".",
|
||||
"outDir": "./dist",
|
||||
"declaration": true,
|
||||
"target": "ES6",
|
||||
"module": "CommonJS",
|
||||
"moduleResolution": "node",
|
||||
"allowJs": true,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"paths": {
|
||||
"@src/*": [
|
||||
"src/*"
|
||||
]
|
||||
},
|
||||
},
|
||||
"include": [
|
||||
"./src/**/*",
|
||||
"./src/**/*.wasm",
|
||||
"./tests/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"./jest.config.js",
|
||||
"./node_modules",
|
||||
"./tests",
|
||||
"./build"
|
||||
"./dist"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"target": "ES6",
|
||||
"module": "CommonJS",
|
||||
"rootDir": "./src",
|
||||
"moduleResolution": "node",
|
||||
"allowJs": true,
|
||||
"outDir": "./build",
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true
|
||||
}
|
||||
}
|
||||
55
yarn.lock
55
yarn.lock
@@ -2058,12 +2058,12 @@
|
||||
node-gyp-build "^4.3.0"
|
||||
|
||||
"@personaelabs/spartan-ecdsa@file:./packages/lib":
|
||||
version "2.1.2"
|
||||
version "2.3.0"
|
||||
dependencies:
|
||||
"@ethereumjs/util" "^8.0.3"
|
||||
"@zk-kit/incremental-merkle-tree" "^1.0.0"
|
||||
elliptic "^6.5.4"
|
||||
snarkjs "^0.5.0"
|
||||
snarkjs "^0.7.1"
|
||||
|
||||
"@phenomnomnominal/tsquery@4.1.1":
|
||||
version "4.1.1"
|
||||
@@ -3144,6 +3144,13 @@ circom_runtime@0.1.21:
|
||||
dependencies:
|
||||
ffjavascript "0.2.56"
|
||||
|
||||
circom_runtime@0.1.24:
|
||||
version "0.1.24"
|
||||
resolved "https://registry.yarnpkg.com/circom_runtime/-/circom_runtime-0.1.24.tgz#60ca8a31c3675802fbab5a0bcdeb02556e510733"
|
||||
integrity sha512-H7/7I2J/cBmRnZm9docOCGhfxzS61BEm4TMCWcrZGsWNBQhePNfQq88Oj2XpUfzmBTCd8pRvRb3Mvazt3TMrJw==
|
||||
dependencies:
|
||||
ffjavascript "0.2.60"
|
||||
|
||||
circom_tester@^0.0.19:
|
||||
version "0.0.19"
|
||||
resolved "https://registry.npmjs.org/circom_tester/-/circom_tester-0.0.19.tgz"
|
||||
@@ -4308,6 +4315,15 @@ ffjavascript@0.2.56:
|
||||
wasmcurves "0.2.0"
|
||||
web-worker "^1.2.0"
|
||||
|
||||
ffjavascript@0.2.60:
|
||||
version "0.2.60"
|
||||
resolved "https://registry.yarnpkg.com/ffjavascript/-/ffjavascript-0.2.60.tgz#4d8ae613d6bf4e98b3cc29ba10c626f5853854cf"
|
||||
integrity sha512-T/9bnEL5xAZRDbQoEMf+pM9nrhK+C3JyZNmqiWub26EQorW7Jt+jR54gpqDhceA4Nj0YctPQwYnl8xa52/A26A==
|
||||
dependencies:
|
||||
wasmbuilder "0.0.16"
|
||||
wasmcurves "0.2.2"
|
||||
web-worker "^1.2.0"
|
||||
|
||||
ffjavascript@^0.2.45, ffjavascript@^0.2.48, ffjavascript@^0.2.56, ffjavascript@^0.2.57:
|
||||
version "0.2.57"
|
||||
resolved "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.57.tgz"
|
||||
@@ -7078,6 +7094,16 @@ r1csfile@0.0.41, r1csfile@^0.0.41:
|
||||
fastfile "0.0.20"
|
||||
ffjavascript "0.2.56"
|
||||
|
||||
r1csfile@0.0.47:
|
||||
version "0.0.47"
|
||||
resolved "https://registry.yarnpkg.com/r1csfile/-/r1csfile-0.0.47.tgz#ed95a0dc8e910e9c070253906f7a31bd8c5333c8"
|
||||
integrity sha512-oI4mAwuh1WwuFg95eJDNDDL8hCaZkwnPuNZrQdLBWvDoRU7EG+L/MOHL7SwPW2Y+ZuYcTLpj3rBkgllBQZN/JA==
|
||||
dependencies:
|
||||
"@iden3/bigarray" "0.0.2"
|
||||
"@iden3/binfileutils" "0.0.11"
|
||||
fastfile "0.0.20"
|
||||
ffjavascript "0.2.60"
|
||||
|
||||
react-dom@18.2.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz"
|
||||
@@ -7454,7 +7480,7 @@ smart-buffer@^4.2.0:
|
||||
resolved "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz"
|
||||
integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==
|
||||
|
||||
snarkjs@0.5.0, snarkjs@^0.5.0:
|
||||
snarkjs@0.5.0:
|
||||
version "0.5.0"
|
||||
resolved "https://registry.npmjs.org/snarkjs/-/snarkjs-0.5.0.tgz"
|
||||
integrity sha512-KWz8mZ2Y+6wvn6GGkQo6/ZlKwETdAGohd40Lzpwp5TUZCn6N6O4Az1SuX1rw/qREGL6Im+ycb19suCFE8/xaKA==
|
||||
@@ -7470,6 +7496,22 @@ snarkjs@0.5.0, snarkjs@^0.5.0:
|
||||
logplease "^1.2.15"
|
||||
r1csfile "0.0.41"
|
||||
|
||||
snarkjs@^0.7.1:
|
||||
version "0.7.1"
|
||||
resolved "https://registry.yarnpkg.com/snarkjs/-/snarkjs-0.7.1.tgz#c96ecaf4db8c2eb44d60b17ee02f37ed39c821bb"
|
||||
integrity sha512-Qs1oxssa135WZkzfARgEp5SuKHKvKNtcspeJbE5je6MurUpBylD1rzcAzQSTGWA/EH/BV/TmUyTaTD64xScvbA==
|
||||
dependencies:
|
||||
"@iden3/binfileutils" "0.0.11"
|
||||
bfj "^7.0.2"
|
||||
blake2b-wasm "^2.4.0"
|
||||
circom_runtime "0.1.24"
|
||||
ejs "^3.1.6"
|
||||
fastfile "0.0.20"
|
||||
ffjavascript "0.2.60"
|
||||
js-sha3 "^0.8.0"
|
||||
logplease "^1.2.15"
|
||||
r1csfile "0.0.47"
|
||||
|
||||
socks-proxy-agent@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz"
|
||||
@@ -8141,6 +8183,13 @@ wasmcurves@0.2.0:
|
||||
dependencies:
|
||||
wasmbuilder "0.0.16"
|
||||
|
||||
wasmcurves@0.2.2:
|
||||
version "0.2.2"
|
||||
resolved "https://registry.yarnpkg.com/wasmcurves/-/wasmcurves-0.2.2.tgz#ca444f6a6f6e2a5cbe6629d98ff478a62b4ccb2b"
|
||||
integrity sha512-JRY908NkmKjFl4ytnTu5ED6AwPD+8VJ9oc94kdq7h5bIwbj0L4TDJ69mG+2aLs2SoCmGfqIesMWTEJjtYsoQXQ==
|
||||
dependencies:
|
||||
wasmbuilder "0.0.16"
|
||||
|
||||
wcwidth@^1.0.0, wcwidth@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz"
|
||||
|
||||
Reference in New Issue
Block a user