wip
This commit is contained in:
parent
3046f21e26
commit
7fb5cf01ef
6 changed files with 358 additions and 339 deletions
|
@ -68,8 +68,8 @@ impl ProgEnum {
|
||||||
|
|
||||||
pub fn curve(&self) -> &'static str {
|
pub fn curve(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
ProgEnum::Bls12_381Program(_) => Bls12_377Field::name(),
|
|
||||||
ProgEnum::Bn128Program(_) => Bn128Field::name(),
|
ProgEnum::Bn128Program(_) => Bn128Field::name(),
|
||||||
|
ProgEnum::Bls12_381Program(_) => Bls12_381Field::name(),
|
||||||
ProgEnum::Bls12_377Program(_) => Bls12_377Field::name(),
|
ProgEnum::Bls12_377Program(_) => Bls12_377Field::name(),
|
||||||
ProgEnum::Bw6_761Program(_) => Bw6_761Field::name(),
|
ProgEnum::Bw6_761Program(_) => Bw6_761Field::name(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,5 +18,5 @@ zokrates_field = { path = "../zokrates_field", default-features = false, feature
|
||||||
zokrates_abi = { path = "../zokrates_abi" }
|
zokrates_abi = { path = "../zokrates_abi" }
|
||||||
console_error_panic_hook = "0.1.6"
|
console_error_panic_hook = "0.1.6"
|
||||||
|
|
||||||
[package.metadata.wasm-pack.profile.release]
|
# [package.metadata.wasm-pack.profile.release]
|
||||||
wasm-opt = false
|
# wasm-opt = false
|
131
zokrates_js/index.d.ts
vendored
131
zokrates_js/index.d.ts
vendored
|
@ -1,5 +1,4 @@
|
||||||
declare module 'zokrates-js' {
|
declare module "zokrates-js" {
|
||||||
|
|
||||||
export type Curve = "bn128" | "bls12_381" | "bls12_377" | "bw6_761";
|
export type Curve = "bn128" | "bls12_381" | "bls12_377" | "bw6_761";
|
||||||
export type Backend = "bellman" | "ark";
|
export type Backend = "bellman" | "ark";
|
||||||
export type Scheme = "g16" | "gm17" | "marlin";
|
export type Scheme = "g16" | "gm17" | "marlin";
|
||||||
|
@ -11,79 +10,129 @@ declare module 'zokrates-js' {
|
||||||
export type G2Affine = [Fq2, Fq2];
|
export type G2Affine = [Fq2, Fq2];
|
||||||
export type ProvingKey = Uint8Array;
|
export type ProvingKey = Uint8Array;
|
||||||
|
|
||||||
export type ResolveCallback = (location: string, path: string) => ResolverResult;
|
export type ResolveCallback = (
|
||||||
|
location: string,
|
||||||
|
path: string
|
||||||
|
) => ResolverResult;
|
||||||
|
|
||||||
export interface CompileConfig {
|
export interface CompileConfig {
|
||||||
allow_unconstrained_variables?: boolean,
|
allow_unconstrained_variables?: boolean;
|
||||||
isolate_branches?: boolean
|
isolate_branches?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CompileOptions {
|
export interface CompileOptions {
|
||||||
location?: string,
|
location?: string;
|
||||||
resolveCallback?: ResolveCallback,
|
resolveCallback?: ResolveCallback;
|
||||||
config?: CompileConfig
|
config?: CompileConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface VerificationKey {
|
export interface VerificationKey {
|
||||||
alpha: G1Affine,
|
alpha: G1Affine;
|
||||||
beta: G2Affine,
|
beta: G2Affine;
|
||||||
gamma: G2Affine,
|
gamma: G2Affine;
|
||||||
delta: G2Affine,
|
delta: G2Affine;
|
||||||
gamma_abc: G1Affine[]
|
gamma_abc: G1Affine[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProofPoints {
|
export interface ProofPoints {
|
||||||
a: G1Affine,
|
a: G1Affine;
|
||||||
b: G2Affine,
|
b: G2Affine;
|
||||||
c: G1Affine
|
c: G1Affine;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Proof {
|
export interface Proof {
|
||||||
proof: ProofPoints,
|
proof: ProofPoints;
|
||||||
inputs: string[]
|
inputs: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ResolverResult {
|
export interface ResolverResult {
|
||||||
source: string,
|
source: string;
|
||||||
location: string
|
location: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ComputationResult {
|
export interface ComputationResult {
|
||||||
witness: string,
|
witness: string;
|
||||||
output: string
|
output: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CompilationArtifacts {
|
export interface CompilationArtifacts {
|
||||||
program: Uint8Array,
|
program: Uint8Array;
|
||||||
abi: string,
|
abi: string;
|
||||||
}
|
|
||||||
|
|
||||||
export interface SetupKeypair {
|
|
||||||
vk: VerificationKey,
|
|
||||||
pk: ProvingKey,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Options = {
|
export interface SetupKeypair {
|
||||||
curve: Scheme,
|
vk: VerificationKey;
|
||||||
backend: Backend,
|
pk: ProvingKey;
|
||||||
scheme: Curve,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Options = {
|
||||||
|
curve: Scheme;
|
||||||
|
backend: Backend;
|
||||||
|
scheme: Curve;
|
||||||
|
};
|
||||||
|
|
||||||
type AtLeast<T, K extends keyof T> = Partial<T> & Pick<T, K>;
|
type AtLeast<T, K extends keyof T> = Partial<T> & Pick<T, K>;
|
||||||
|
|
||||||
|
export type SpecializedZoKratesProvider = {
|
||||||
|
compile(
|
||||||
|
source: string,
|
||||||
|
compileOptions?: CompileOptions
|
||||||
|
): CompilationArtifacts;
|
||||||
|
computeWitness(
|
||||||
|
artifacts: CompilationArtifacts,
|
||||||
|
args: any[]
|
||||||
|
): ComputationResult;
|
||||||
|
setup(program: Uint8Array): SetupKeypair;
|
||||||
|
universalSetup(size: number): Uint8Array;
|
||||||
|
setupWithSrs(srs: Uint8Array, program: Uint8Array): SetupKeypair;
|
||||||
|
generateProof(
|
||||||
|
program: Uint8Array,
|
||||||
|
witness: string,
|
||||||
|
provingKey: Uint8Array
|
||||||
|
): Proof;
|
||||||
|
verify(verificationKey: VerificationKey, proof: Proof): boolean;
|
||||||
|
exportSolidityVerifier(verificationKey: VerificationKey): string;
|
||||||
|
};
|
||||||
|
|
||||||
export interface ZoKratesProvider {
|
export interface ZoKratesProvider {
|
||||||
compile(source: string, options?: CompileOptions): CompilationArtifacts;
|
withOptions(options: Options): SpecializedZoKratesProvider;
|
||||||
computeWitness(artifacts: CompilationArtifacts, args: any[]): ComputationResult;
|
compile(
|
||||||
setup(program: Uint8Array, options: AtLeast<Options, "backend" | "scheme">): SetupKeypair;
|
source: string,
|
||||||
setupWithSrs(srs: Uint8Array, program: Uint8Array, options: AtLeast<Options, "backend" | "scheme">): SetupKeypair;
|
compileOptions?: CompileOptions
|
||||||
|
): CompilationArtifacts;
|
||||||
|
computeWitness(
|
||||||
|
artifacts: CompilationArtifacts,
|
||||||
|
args: any[]
|
||||||
|
): ComputationResult;
|
||||||
|
setup(
|
||||||
|
program: Uint8Array,
|
||||||
|
options: AtLeast<Options, "backend" | "scheme">
|
||||||
|
): SetupKeypair;
|
||||||
universalSetup(curve: Curve, size: number): Uint8Array;
|
universalSetup(curve: Curve, size: number): Uint8Array;
|
||||||
exportSolidityVerifier(verificationKey: VerificationKey, options: AtLeast<Options, "curve" | "scheme">): string;
|
setupWithSrs(
|
||||||
generateProof(program: Uint8Array, witness: string, provingKey: Uint8Array, options: AtLeast<Options, "backend" | "scheme">): Proof;
|
srs: Uint8Array,
|
||||||
verify(verificationKey: VerificationKey, proof: Proof, options: Options): boolean;
|
program: Uint8Array,
|
||||||
|
options: AtLeast<Options, "backend" | "scheme">
|
||||||
|
): SetupKeypair;
|
||||||
|
generateProof(
|
||||||
|
program: Uint8Array,
|
||||||
|
witness: string,
|
||||||
|
provingKey: Uint8Array,
|
||||||
|
options: AtLeast<Options, "backend" | "scheme">
|
||||||
|
): Proof;
|
||||||
|
verify(
|
||||||
|
verificationKey: VerificationKey,
|
||||||
|
proof: Proof,
|
||||||
|
options: Options
|
||||||
|
): boolean;
|
||||||
|
exportSolidityVerifier(
|
||||||
|
verificationKey: VerificationKey,
|
||||||
|
options: AtLeast<Options, "curve" | "scheme">
|
||||||
|
): string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Metadata {
|
export interface Metadata {
|
||||||
version: string
|
version: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initialize(): Promise<ZoKratesProvider>;
|
export function initialize(): Promise<ZoKratesProvider>;
|
||||||
|
|
|
@ -67,14 +67,14 @@ impl<'a> Resolver<Error> for JsResolver<'a> {
|
||||||
)
|
)
|
||||||
.map_err(|_| {
|
.map_err(|_| {
|
||||||
Error::new(format!(
|
Error::new(format!(
|
||||||
"Error thrown in JS callback: could not resolve {}",
|
"Error thrown in JS callback: could not resolve `{}`",
|
||||||
import_location.display()
|
import_location.display()
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if value.is_null() || value.is_undefined() {
|
if value.is_null() || value.is_undefined() {
|
||||||
Err(Error::new(format!(
|
Err(Error::new(format!(
|
||||||
"Could not resolve {}",
|
"Could not resolve `{}`",
|
||||||
import_location.display()
|
import_location.display()
|
||||||
)))
|
)))
|
||||||
} else {
|
} else {
|
||||||
|
@ -210,15 +210,10 @@ pub fn compile(
|
||||||
location: JsValue,
|
location: JsValue,
|
||||||
resolve_callback: &js_sys::Function,
|
resolve_callback: &js_sys::Function,
|
||||||
config: JsValue,
|
config: JsValue,
|
||||||
options: JsValue,
|
curve: JsValue,
|
||||||
) -> Result<JsValue, JsValue> {
|
) -> Result<JsValue, JsValue> {
|
||||||
let options: serde_json::Value = options.into_serde().unwrap();
|
let curve = CurveParameter::try_from(curve.as_string().unwrap().as_str())
|
||||||
let curve = CurveParameter::try_from(
|
.map_err(|e| JsValue::from_str(&e))?;
|
||||||
options["curve"]
|
|
||||||
.as_str()
|
|
||||||
.ok_or_else(|| JsValue::from_str("missing field `curve` in `options` object"))?,
|
|
||||||
)
|
|
||||||
.map_err(|e| JsValue::from_str(&e))?;
|
|
||||||
|
|
||||||
match curve {
|
match curve {
|
||||||
CurveParameter::Bn128 => {
|
CurveParameter::Bn128 => {
|
||||||
|
@ -358,7 +353,7 @@ pub fn universal_setup(curve: JsValue, size: u32) -> Result<Vec<u8>, JsValue> {
|
||||||
Ok(internal::universal_setup_of_size::<Bw6_761Field, Marlin, Ark>(size))
|
Ok(internal::universal_setup_of_size::<Bw6_761Field, Marlin, Ark>(size))
|
||||||
}
|
}
|
||||||
c => Err(JsValue::from_str(&format!(
|
c => Err(JsValue::from_str(&format!(
|
||||||
"Unsupported curve `{:?}` provided in universal setup",
|
"Unsupported curve `{:?}` provided to universal setup",
|
||||||
c
|
c
|
||||||
))),
|
))),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,234 +1,166 @@
|
||||||
const assert = require('assert');
|
const assert = require("assert");
|
||||||
const { initialize } = require('../node/index.js');
|
const { initialize } = require("../node/index.js");
|
||||||
|
|
||||||
describe('tests', function() {
|
describe("tests", function () {
|
||||||
let zokrates;
|
let zokrates;
|
||||||
|
|
||||||
|
// initialize once before running tests
|
||||||
|
before((done) => {
|
||||||
|
initialize().then((provider) => {
|
||||||
|
zokrates = provider;
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("compilation", () => {
|
||||||
|
it("should compile", () => {
|
||||||
|
assert.doesNotThrow(() => {
|
||||||
|
const artifacts = zokrates.compile("def main() -> field: return 42");
|
||||||
|
assert.ok(artifacts !== undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should throw on invalid code", () => {
|
||||||
|
assert.throws(() => zokrates.compile(":-)"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should resolve stdlib module", () => {
|
||||||
|
const stdlib = require("../stdlib.json");
|
||||||
|
assert.doesNotThrow(() => {
|
||||||
|
const code = `import "${
|
||||||
|
Object.keys(stdlib)[0]
|
||||||
|
}" as func\ndef main(): return`;
|
||||||
|
zokrates.compile(code);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should resolve user module", () => {
|
||||||
|
assert.doesNotThrow(() => {
|
||||||
|
const code =
|
||||||
|
'import "test" as test\ndef main() -> field: return test()';
|
||||||
|
const options = {
|
||||||
|
resolveCallback: (_, path) => {
|
||||||
|
return {
|
||||||
|
source: "def main() -> (field): return 1",
|
||||||
|
location: path,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
zokrates.compile(code, options);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should throw on unresolved module", () => {
|
||||||
|
assert.throws(() => {
|
||||||
|
const code =
|
||||||
|
'import "test" as test\ndef main() -> field: return test()';
|
||||||
|
zokrates.compile(code);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("computation", () => {
|
||||||
|
it("should compute with valid inputs", () => {
|
||||||
|
assert.doesNotThrow(() => {
|
||||||
|
const code = "def main(private field a) -> field: return a * a";
|
||||||
|
const artifacts = zokrates.compile(code);
|
||||||
|
|
||||||
|
const result = zokrates.computeWitness(artifacts, ["2"]);
|
||||||
|
const output = JSON.parse(result.output);
|
||||||
|
assert.deepEqual(output, ["4"]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should throw on invalid input count", () => {
|
||||||
|
assert.throws(() => {
|
||||||
|
const code = "def main(private field a) -> field: return a * a";
|
||||||
|
const artifacts = zokrates.compile(code);
|
||||||
|
zokrates.computeWitness(artifacts, ["1", "2"]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should throw on invalid input type", () => {
|
||||||
|
assert.throws(() => {
|
||||||
|
const code = "def main(private field a) -> field: return a * a";
|
||||||
|
const artifacts = zokrates.compile(code);
|
||||||
|
zokrates.computeWitness(artifacts, [true]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const runWithOptions = (options) => {
|
||||||
|
let artifacts;
|
||||||
|
let computationResult;
|
||||||
|
let keypair;
|
||||||
|
let proof;
|
||||||
|
|
||||||
// initialize once before running tests
|
|
||||||
before((done) => {
|
before((done) => {
|
||||||
initialize().then((provider) => {
|
const code = "def main(private field a) -> field: return a + a";
|
||||||
zokrates = provider;
|
artifacts = zokrates.compile(code, { curve: options.curve });
|
||||||
done();
|
computationResult = zokrates.computeWitness(artifacts, ["2"]);
|
||||||
});
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("compilation", () => {
|
it("setup", () => {
|
||||||
it('should compile', () => {
|
assert.doesNotThrow(() => {
|
||||||
assert.doesNotThrow(() => {
|
if (options.scheme === "marlin") {
|
||||||
const artifacts = zokrates.compile("def main() -> field: return 42");
|
const srs = zokrates.universalSetup(options.curve, 2);
|
||||||
assert.ok(artifacts !== undefined);
|
keypair = zokrates.setupWithSrs(srs, artifacts.program, options);
|
||||||
})
|
} else {
|
||||||
});
|
keypair = zokrates.setup(artifacts.program, options);
|
||||||
|
}
|
||||||
it('should throw on invalid code', () => {
|
});
|
||||||
assert.throws(() => zokrates.compile(":-)"));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should resolve stdlib module', () => {
|
|
||||||
const stdlib = require('../stdlib.json');
|
|
||||||
assert.doesNotThrow(() => {
|
|
||||||
const code = `import "${Object.keys(stdlib)[0]}" as func\ndef main(): return`;
|
|
||||||
zokrates.compile(code);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should resolve user module', () => {
|
|
||||||
assert.doesNotThrow(() => {
|
|
||||||
const code = 'import "test" as test\ndef main() -> field: return test()';
|
|
||||||
const options = {
|
|
||||||
resolveCallback: (_, path) => {
|
|
||||||
return {
|
|
||||||
source: "def main() -> (field): return 1",
|
|
||||||
location: path
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
zokrates.compile(code, options);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw on unresolved module', () => {
|
|
||||||
assert.throws(() => {
|
|
||||||
const code = 'import "test" as test\ndef main() -> field: return test()';
|
|
||||||
zokrates.compile(code);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("computation", () => {
|
it("generate proof", () => {
|
||||||
it('should compute with valid inputs', () => {
|
assert.doesNotThrow(() => {
|
||||||
assert.doesNotThrow(() => {
|
proof = zokrates.generateProof(
|
||||||
const code = 'def main(private field a) -> field: return a * a';
|
artifacts.program,
|
||||||
const artifacts = zokrates.compile(code);
|
computationResult.witness,
|
||||||
|
keypair.pk,
|
||||||
const result = zokrates.computeWitness(artifacts, ["2"]);
|
options
|
||||||
const output = JSON.parse(result.output);
|
);
|
||||||
assert.deepEqual(output, ["4"]);
|
assert.ok(proof !== undefined);
|
||||||
});
|
assert.ok(proof.proof.hasOwnProperty("a"));
|
||||||
});
|
assert.ok(proof.proof.hasOwnProperty("b"));
|
||||||
|
assert.ok(proof.proof.hasOwnProperty("c"));
|
||||||
it('should throw on invalid input count', () => {
|
assert.equal(proof.inputs.length, 1);
|
||||||
assert.throws(() => {
|
});
|
||||||
const code = 'def main(private field a) -> field: return a * a';
|
|
||||||
const artifacts = zokrates.compile(code);
|
|
||||||
zokrates.computeWitness(artifacts, ["1", "2"]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw on invalid input type', () => {
|
|
||||||
assert.throws(() => {
|
|
||||||
const code = 'def main(private field a) -> field: return a * a';
|
|
||||||
const artifacts = zokrates.compile(code);
|
|
||||||
zokrates.computeWitness(artifacts, [true]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("bellman", () => {
|
it("verify with valid proof", () => {
|
||||||
describe("groth16", () => {
|
assert.doesNotThrow(() => {
|
||||||
const options = {
|
assert(zokrates.verify(keypair.vk, proof, options) === true);
|
||||||
backend: "bellman",
|
});
|
||||||
curve: "bn128",
|
|
||||||
scheme: "g16"
|
|
||||||
};
|
|
||||||
|
|
||||||
let artifacts;
|
|
||||||
let computationResult;
|
|
||||||
let keypair;
|
|
||||||
let proof;
|
|
||||||
|
|
||||||
before((done) => {
|
|
||||||
const code = 'def main(private field a) -> field: return a * a';
|
|
||||||
artifacts = zokrates.compile(code);
|
|
||||||
computationResult = zokrates.computeWitness(artifacts, ["2"]);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("setup", () => {
|
|
||||||
assert.doesNotThrow(() => {
|
|
||||||
keypair = zokrates.setup(artifacts.program, options);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("generate proof", () => {
|
|
||||||
assert.doesNotThrow(() => {
|
|
||||||
proof = zokrates.generateProof(artifacts.program, computationResult.witness, keypair.pk, options);
|
|
||||||
assert.ok(proof !== undefined);
|
|
||||||
assert.deepEqual(proof.inputs, ["0x0000000000000000000000000000000000000000000000000000000000000004"]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("export solidity verifier", () => {
|
|
||||||
let verifier = zokrates.exportSolidityVerifier(keypair.vk, options);
|
|
||||||
assert(verifier.length > 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("verify with valid proof", () => {
|
|
||||||
assert.doesNotThrow(() => {
|
|
||||||
assert(zokrates.verify(keypair.vk, proof, options) === true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("verify with invalid proof", () => {
|
|
||||||
// falsify proof
|
|
||||||
proof["proof"]["a"][0] = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
||||||
assert(zokrates.verify(keypair.vk, proof, options) === false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("ark", () => {
|
it("falsify proof", () => {
|
||||||
describe("gm17", () => {
|
let tmp = proof["proof"]["a"][0];
|
||||||
const options = {
|
proof["proof"]["a"][0] = proof["proof"]["a"][1];
|
||||||
backend: "ark",
|
proof["proof"]["a"][1] = tmp;
|
||||||
curve: "bn128",
|
assert(zokrates.verify(keypair.vk, proof, options) === false);
|
||||||
scheme: "gm17"
|
|
||||||
};
|
|
||||||
|
|
||||||
let artifacts;
|
|
||||||
let computationResult;
|
|
||||||
let keypair;
|
|
||||||
let proof;
|
|
||||||
|
|
||||||
before((done) => {
|
|
||||||
const code = 'def main(private field a) -> field: return a * a';
|
|
||||||
artifacts = zokrates.compile(code);
|
|
||||||
computationResult = zokrates.computeWitness(artifacts, ["2"]);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("setup", () => {
|
|
||||||
assert.doesNotThrow(() => {
|
|
||||||
keypair = zokrates.setup(artifacts.program, options);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("generate proof", () => {
|
|
||||||
assert.doesNotThrow(() => {
|
|
||||||
proof = zokrates.generateProof(artifacts.program, computationResult.witness, keypair.pk, options);
|
|
||||||
assert.ok(proof !== undefined);
|
|
||||||
assert.deepEqual(proof.inputs, ["0x0000000000000000000000000000000000000000000000000000000000000004"]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("verify with valid proof", () => {
|
|
||||||
assert.doesNotThrow(() => {
|
|
||||||
assert(zokrates.verify(keypair.vk, proof, options) === true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("verify with invalid proof", () => {
|
|
||||||
// falsify proof
|
|
||||||
proof["proof"]["a"][0] = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
||||||
assert(zokrates.verify(keypair.vk, proof, options) === false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("marlin", () => {
|
|
||||||
const options = {
|
|
||||||
backend: "ark",
|
|
||||||
curve: "bn128",
|
|
||||||
scheme: "marlin"
|
|
||||||
};
|
|
||||||
|
|
||||||
let artifacts;
|
|
||||||
let computationResult;
|
|
||||||
let keypair;
|
|
||||||
let proof;
|
|
||||||
|
|
||||||
before((done) => {
|
|
||||||
const code = 'def main(private field a, private field b) -> bool: return a * a == b';
|
|
||||||
artifacts = zokrates.compile(code);
|
|
||||||
computationResult = zokrates.computeWitness(artifacts, ["2", "4"]);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("setup", () => {
|
|
||||||
assert.doesNotThrow(() => {
|
|
||||||
const srs = zokrates.universalSetup("bn128", 4);
|
|
||||||
keypair = zokrates.setupWithSrs(srs, artifacts.program, options);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("generate proof", () => {
|
|
||||||
assert.doesNotThrow(() => {
|
|
||||||
proof = zokrates.generateProof(artifacts.program, computationResult.witness, keypair.pk, options);
|
|
||||||
assert.ok(proof !== undefined);
|
|
||||||
assert.deepEqual(proof.inputs, ["0x0000000000000000000000000000000000000000000000000000000000000001"]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("verify with valid proof", () => {
|
|
||||||
assert.doesNotThrow(() => {
|
|
||||||
assert(zokrates.verify(keypair.vk, proof, options) === true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("verify with invalid proof", () => {
|
|
||||||
// falsify proof
|
|
||||||
proof["inputs"][0] = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
||||||
assert(zokrates.verify(keypair.vk, proof, options) === false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
};
|
||||||
|
|
||||||
|
describe("bellman", () => {
|
||||||
|
describe("groth16", () => {
|
||||||
|
for (const curve of ["bn128", "bls12_381"]) {
|
||||||
|
describe(curve, () =>
|
||||||
|
runWithOptions({ backend: "bellman", scheme: "g16", curve })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("ark", () => {
|
||||||
|
for (const scheme of ["gm17", "marlin"]) {
|
||||||
|
describe(scheme, () => {
|
||||||
|
for (const curve of ["bn128", "bls12_377", "bw6_761"]) {
|
||||||
|
describe(curve, () =>
|
||||||
|
runWithOptions({ backend: "ark", scheme: "gm17", curve })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -1,71 +1,114 @@
|
||||||
const getAbsolutePath = (basePath, relativePath) => {
|
const getAbsolutePath = (basePath, relativePath) => {
|
||||||
if (relativePath[0] !== '.') {
|
if (relativePath[0] !== ".") {
|
||||||
return relativePath;
|
return relativePath;
|
||||||
}
|
}
|
||||||
var stack = basePath.split('/');
|
var stack = basePath.split("/");
|
||||||
var chunks = relativePath.split('/');
|
var chunks = relativePath.split("/");
|
||||||
stack.pop();
|
stack.pop();
|
||||||
|
|
||||||
for (var i = 0; i < chunks.length; i++) {
|
for (var i = 0; i < chunks.length; i++) {
|
||||||
if (chunks[i] == '.') {
|
if (chunks[i] == ".") {
|
||||||
continue;
|
continue;
|
||||||
} else if (chunks[i] == '..') {
|
} else if (chunks[i] == "..") {
|
||||||
stack.pop();
|
stack.pop();
|
||||||
} else {
|
} else {
|
||||||
stack.push(chunks[i]);
|
stack.push(chunks[i]);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return stack.join('/');
|
}
|
||||||
}
|
return stack.join("/");
|
||||||
|
};
|
||||||
|
|
||||||
const getImportPath = (currentLocation, importLocation) => {
|
const getImportPath = (currentLocation, importLocation) => {
|
||||||
let path = getAbsolutePath(currentLocation, importLocation);
|
let path = getAbsolutePath(currentLocation, importLocation);
|
||||||
const extension = path.slice((path.lastIndexOf(".") - 1 >>> 0) + 2);
|
const extension = path.slice(((path.lastIndexOf(".") - 1) >>> 0) + 2);
|
||||||
return extension ? path : path.concat('.zok');
|
return extension ? path : path.concat(".zok");
|
||||||
}
|
};
|
||||||
|
|
||||||
module.exports = (dep) => {
|
module.exports = (dep) => {
|
||||||
const { zokrates, stdlib } = dep;
|
const { zokrates, stdlib } = dep;
|
||||||
|
|
||||||
const resolveFromStdlib = (currentLocation, importLocation) => {
|
const resolveFromStdlib = (currentLocation, importLocation) => {
|
||||||
let key = getImportPath(currentLocation, importLocation);
|
let key = getImportPath(currentLocation, importLocation);
|
||||||
let source = stdlib[key];
|
let source = stdlib[key];
|
||||||
return source ? { source, location: key } : null;
|
return source ? { source, location: key } : null;
|
||||||
}
|
};
|
||||||
|
|
||||||
return {
|
const defaultProvider = {
|
||||||
compile: (source, options = {}) => {
|
compile: (source, compileOptions = {}) => {
|
||||||
const { curve = "bn128", location = "main.zok", resolveCallback = () => null, config = {} } = options;
|
const {
|
||||||
const callback = (currentLocation, importLocation) => {
|
curve = "bn128",
|
||||||
return resolveFromStdlib(currentLocation, importLocation) || resolveCallback(currentLocation, importLocation);
|
location = "main.zok",
|
||||||
};
|
resolveCallback = () => null,
|
||||||
const { program, abi } = zokrates.compile(source, location, callback, config, { curve });
|
config = {},
|
||||||
return {
|
} = compileOptions;
|
||||||
program: new Uint8Array(program),
|
const callback = (currentLocation, importLocation) => {
|
||||||
abi
|
return (
|
||||||
}
|
resolveFromStdlib(currentLocation, importLocation) ||
|
||||||
},
|
resolveCallback(currentLocation, importLocation)
|
||||||
computeWitness: (artifacts, args) => {
|
);
|
||||||
const { program, abi } = artifacts;
|
};
|
||||||
return zokrates.compute_witness(program, abi, JSON.stringify(Array.from(args)));
|
const { program, abi } = zokrates.compile(
|
||||||
},
|
source,
|
||||||
setup: (program, options) => {
|
location,
|
||||||
return zokrates.setup(program, options);
|
callback,
|
||||||
},
|
config,
|
||||||
universalSetup: (curve, size) => {
|
curve
|
||||||
return zokrates.universal_setup(curve, size);
|
);
|
||||||
},
|
return {
|
||||||
setupWithSrs: (srs, program, options) => {
|
program: new Uint8Array(program),
|
||||||
return zokrates.setup_with_srs(srs, program, options);
|
abi,
|
||||||
},
|
};
|
||||||
generateProof: (program, witness, provingKey, options) => {
|
},
|
||||||
return zokrates.generate_proof(program, witness, provingKey, options);
|
computeWitness: (artifacts, args) => {
|
||||||
},
|
const { program, abi } = artifacts;
|
||||||
verify: (vk, proof, options) => {
|
return zokrates.compute_witness(
|
||||||
return zokrates.verify(vk, proof, options);
|
program,
|
||||||
},
|
abi,
|
||||||
exportSolidityVerifier: (vk, options) => {
|
JSON.stringify(Array.from(args))
|
||||||
return zokrates.export_solidity_verifier(vk, options);
|
);
|
||||||
}
|
},
|
||||||
}
|
setup: (program, options) => {
|
||||||
};
|
return zokrates.setup(program, options);
|
||||||
|
},
|
||||||
|
universalSetup: (curve, size) => {
|
||||||
|
return zokrates.universal_setup(curve, size);
|
||||||
|
},
|
||||||
|
setupWithSrs: (srs, program, options) => {
|
||||||
|
return zokrates.setup_with_srs(srs, program, options);
|
||||||
|
},
|
||||||
|
generateProof: (program, witness, provingKey, options) => {
|
||||||
|
return zokrates.generate_proof(program, witness, provingKey, options);
|
||||||
|
},
|
||||||
|
verify: (vk, proof, options) => {
|
||||||
|
return zokrates.verify(vk, proof, options);
|
||||||
|
},
|
||||||
|
exportSolidityVerifier: (vk, options) => {
|
||||||
|
return zokrates.export_solidity_verifier(vk, options);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const withOptions = (options) => ({
|
||||||
|
compile: (source, compileOptions = {}) =>
|
||||||
|
defaultProvider.compile(source, {
|
||||||
|
...compileOptions,
|
||||||
|
curve: options.curve,
|
||||||
|
}),
|
||||||
|
computeWitness: (artifacts, args) =>
|
||||||
|
defaultProvider.computeWitness(artifacts, args),
|
||||||
|
setup: (program) => defaultProvider.setup(program, options),
|
||||||
|
universalSetup: (size) =>
|
||||||
|
defaultProvider.universalSetup(options.curve, size),
|
||||||
|
setupWithSrs: (srs, program) =>
|
||||||
|
defaultProvider.setupWithSrs(srs, program, options),
|
||||||
|
generateProof: (program, witness, provingKey) =>
|
||||||
|
defaultProvider.generateProof(program, witness, provingKey, options),
|
||||||
|
verify: (vk, proof) => defaultProvider.verify(vk, proof, options),
|
||||||
|
exportSolidityVerifier: (vk) =>
|
||||||
|
defaultProvider.exportSolidityVerifier(vk, options),
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
withOptions,
|
||||||
|
...defaultProvider,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in a new issue