1
0
Fork 0
mirror of synced 2025-09-24 04:40:05 +00:00

fix conflicts

This commit is contained in:
schaeff 2020-08-04 17:34:23 +02:00
commit 2605559f4c
17 changed files with 258 additions and 188 deletions

View file

@ -233,12 +233,6 @@ err() {
exit 1 exit 1
} }
need() {
if ! command -v $1 > /dev/null 2>&1; then
err "need $1 (command not found)"
fi
}
main() { main() {
need_cmd curl need_cmd curl
@ -259,12 +253,11 @@ main() {
done done
# Dependencies # Dependencies
need basename need_cmd curl
need curl need_cmd install
need install need_cmd mkdir
need mkdir need_cmd mktemp
need mktemp need_cmd tar
need tar
git="ZoKrates/ZoKrates" git="ZoKrates/ZoKrates"

View file

@ -1,51 +1,33 @@
# zokrates.js # zokrates.js
You can get JavaScript bindings for ZoKrates by running JavaScript bindings for [ZoKrates](https://github.com/Zokrates/ZoKrates).
```bash ```bash
npm install zokrates-js npm install zokrates-js
``` ```
## API ## Importing
| Function | Description | ##### Bundlers
| ------ | ------ | **Note:** As this library uses a model where the wasm module itself is natively an ES module, you will need a bundler of some form.
| initialize | Loads binding wasm module and returns a promise with ZoKrates provider | Currently the only known bundler known to be fully compatible with `zokrates-js` is [Webpack](https://webpack.js.org/).
| compile | Compiles source code into ZoKrates internal representation of arithmetic circuits | The choice of this default was done to reflect the trends of the JS ecosystem.
| computeWitness | Computes a valid assignment of the variables, which include the results of the computation |
| setup | Generates a trusted setup for the compiled program |
| exportSolidityVerifier | Generates a Solidity contract which contains the generated verification key and a public function to verify a solution to the compiled program |
| generateProof | Generates a proof for a computation of the compiled program |
## Usage
### Importing
Bundlers
```js ```js
import { initialize } from 'zokrates-js'; import { initialize } from 'zokrates-js';
``` ```
Node ##### Node
```js ```js
const { initialize } = require('zokrates-js/node'); const { initialize } = require('zokrates-js/node');
``` ```
### Example ## Example
```js ```js
function importResolver(currentLocation, importLocation) {
// implement your resolving logic here
return {
source: "def main(): return",
location: importLocation
};
}
initialize().then((zokratesProvider) => { initialize().then((zokratesProvider) => {
const source = "def main(private field a) -> field: return a * a"; const source = "def main(private field a) -> field: return a * a";
// compilation // compilation
const artifacts = zokratesProvider.compile(source, "main", importResolver); const artifacts = zokratesProvider.compile(source);
// computation // computation
const { witness, output } = zokratesProvider.computeWitness(artifacts, ["2"]); const { witness, output } = zokratesProvider.computeWitness(artifacts, ["2"]);
@ -60,3 +42,103 @@ initialize().then((zokratesProvider) => {
const verifier = zokratesProvider.exportSolidityVerifier(keypair.vk, "v1"); const verifier = zokratesProvider.exportSolidityVerifier(keypair.vk, "v1");
}); });
``` ```
## API
##### initialize()
Returns an initialized `ZoKratesProvider` as a promise.
```js
initialize().then(zokratesProvider => {
// call api functions here
});
```
Returns: `Promise<ZoKratesProvider>`
##### compile(source[, options])
Compiles source code into ZoKrates internal representation of arithmetic circuits.
Parameters:
* `source` - Source code to compile
* `options` - Compilation options
Returns: `CompilationArtifacts`
**Examples:**
Compilation:
```js
const artifacts = zokratesProvider.compile("def main() -> (): return");
```
Compilation with custom options:
```js
const source = "...";
const options = {
location: "main.zok", // location of the root module
resolveCallback: (currentLocation, importLocation) => {
console.log(currentLocation + ' is importing ' + importLocation);
return {
source: "def main() -> (): return",
location: importLocation
};
},
config: {
is_release: true
}
};
const artifacts = zokratesProvider.compile(source, options);
```
**Note:** The `resolveCallback` function is used to resolve dependencies.
This callback receives the current module location and the import location of the module which is being imported.
The callback must synchronously return either an error, `null` or a valid `ResolverResult` object like shown in the example above.
##### computeWitness(artifacts, args)
Computes a valid assignment of the variables, which include the results of the computation.
Parameters:
* `artifacts` - Compilation artifacts
* `args` - Array of arguments (eg. `["1", "2", true]`)
Returns: `ComputationResult`
**Example:**
```js
const code = 'def main(private field a) -> (field): return a * a';
const artifacts = zokratesProvider.compile(code);
const { witness, output } = zokratesProvider.computeWitness(artifacts, ["2"]);
console.log(witness); // Resulting witness which can be used to generate a proof
console.log(output); // Computation output: ["4"]
```
##### setup(program)
Generates a trusted setup for the compiled program.
Parameters:
* `program` - Compiled program
Returns: `SetupKeypair`
##### exportSolidityVerifier(verificationKey, abi)
Generates a Solidity contract which contains the generated verification key and a public function to verify proofs of computation of the compiled program.
Parameters:
* `verificationKey` - Verification key from the setup keypair
* `abi` - Abi version (`"v1"` | `"v2"`)
Returns: `string`
##### generateProof(program, witness, provingKey)
Generates a proof for a computation of the compiled program.
Parameters:
* `program` - Compiled program
* `witness` - Witness (valid assignment of the variables) from the computation result
* `provingKey` - Proving key from the setup keypair
Returns: `Proof`

View file

@ -409,23 +409,13 @@ impl<'ast, T: Field> From<pest::Spread<'ast>> for absy::SpreadNode<'ast, T> {
} }
} }
impl<'ast, T: Field> From<pest::Range<'ast>> for absy::RangeNode<T> { impl<'ast, T: Field> From<pest::Range<'ast>> for absy::RangeNode<'ast, T> {
fn from(range: pest::Range<'ast>) -> absy::RangeNode<T> { fn from(range: pest::Range<'ast>) -> absy::RangeNode<'ast, T> {
use absy::NodeValue; use absy::NodeValue;
let from = range let from = range.from.map(|e| absy::ExpressionNode::from(e.0));
.from
.map(|e| match absy::ExpressionNode::from(e.0).value {
absy::Expression::FieldConstant(n) => n,
e => unimplemented!("Range bounds should be constants, found {}", e),
});
let to = range let to = range.to.map(|e| absy::ExpressionNode::from(e.0));
.to
.map(|e| match absy::ExpressionNode::from(e.0).value {
absy::Expression::FieldConstant(n) => n,
e => unimplemented!("Range bounds should be constants, found {}", e),
});
absy::Range { from, to }.span(range.span) absy::Range { from, to }.span(range.span)
} }

View file

@ -395,7 +395,7 @@ impl<'ast, T: fmt::Debug> fmt::Debug for SpreadOrExpression<'ast, T> {
/// The index in an array selector. Can be a range or an expression. /// The index in an array selector. Can be a range or an expression.
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
pub enum RangeOrExpression<'ast, T> { pub enum RangeOrExpression<'ast, T> {
Range(RangeNode<T>), Range(RangeNode<'ast, T>),
Expression(ExpressionNode<'ast, T>), Expression(ExpressionNode<'ast, T>),
} }
@ -439,14 +439,14 @@ pub struct Spread<'ast, T> {
/// A range /// A range
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
pub struct Range<T> { pub struct Range<'ast, T> {
pub from: Option<T>, pub from: Option<ExpressionNode<'ast, T>>,
pub to: Option<T>, pub to: Option<ExpressionNode<'ast, T>>,
} }
pub type RangeNode<T> = Node<Range<T>>; pub type RangeNode<'ast, T> = Node<Range<'ast, T>>;
impl<'ast, T: fmt::Display> fmt::Display for Range<T> { impl<'ast, T: fmt::Display> fmt::Display for Range<'ast, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!( write!(
f, f,
@ -463,7 +463,7 @@ impl<'ast, T: fmt::Display> fmt::Display for Range<T> {
} }
} }
impl<'ast, T: fmt::Debug> fmt::Debug for Range<T> { impl<'ast, T: fmt::Debug> fmt::Debug for Range<'ast, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Range({:?}, {:?})", self.from, self.to) write!(f, "Range({:?}, {:?})", self.from, self.to)
} }

View file

@ -91,7 +91,7 @@ impl<'ast> NodeValue for Variable<'ast> {}
impl<'ast> NodeValue for Parameter<'ast> {} impl<'ast> NodeValue for Parameter<'ast> {}
impl<'ast> NodeValue for Import<'ast> {} impl<'ast> NodeValue for Import<'ast> {}
impl<'ast, T: fmt::Display + fmt::Debug + PartialEq> NodeValue for Spread<'ast, T> {} impl<'ast, T: fmt::Display + fmt::Debug + PartialEq> NodeValue for Spread<'ast, T> {}
impl<T: fmt::Display + fmt::Debug + PartialEq> NodeValue for Range<T> {} impl<'ast, T: fmt::Display + fmt::Debug + PartialEq> NodeValue for Range<'ast, T> {}
impl<T: PartialEq> PartialEq for Node<T> { impl<T: PartialEq> PartialEq for Node<T> {
fn eq(&self, other: &Node<T>) -> bool { fn eq(&self, other: &Node<T>) -> bool {

View file

@ -1659,17 +1659,50 @@ impl<'ast> Checker<'ast> {
let array_size = array.size(); let array_size = array.size();
let inner_type = array.inner_type().clone(); let inner_type = array.inner_type().clone();
// check that the bounds are valid expressions
let from = r let from = r
.value .value
.from .from
.map(|v| v.to_dec_string().parse::<usize>().unwrap()) .map(|e| self.check_expression(e, module_id, &types))
.unwrap_or(0); .unwrap_or(Ok(FieldElementExpression::Number(T::from(0)).into()))?;
let to = r let to = r
.value .value
.to .to
.map(|v| v.to_dec_string().parse::<usize>().unwrap()) .map(|e| self.check_expression(e, module_id, &types))
.unwrap_or(array_size); .unwrap_or(Ok(FieldElementExpression::Number(T::from(
array_size,
))
.into()))?;
// check the bounds are field constants
// Note: it would be nice to allow any field expression, and check it's a constant after constant propagation,
// but it's tricky from a type perspective: the size of the slice changes the type of the resulting array,
// which doesn't work well with our static array approach. Enabling arrays to have unknown size introduces a lot
// of complexity in the compiler, as function selection in inlining requires knowledge of the array size, but
// determining array size potentially requires inlining and propagating. This suggests we would need semantic checking
// to happen iteratively with inlining and propagation, which we can't do now as we go from absy to typed_absy
let from = match from {
TypedExpression::FieldElement(FieldElementExpression::Number(n)) => Ok(n.to_dec_string().parse::<usize>().unwrap()),
e => Err(ErrorInner {
pos: Some(pos),
message: format!(
"Expected the lower bound of the range to be a constant field, found {}",
e
),
})
}?;
let to = match to {
TypedExpression::FieldElement(FieldElementExpression::Number(n)) => Ok(n.to_dec_string().parse::<usize>().unwrap()),
e => Err(ErrorInner {
pos: Some(pos),
message: format!(
"Expected the higher bound of the range to be a constant field, found {}",
e
),
})
}?;
match (from, to, array_size) { match (from, to, array_size) {
(f, _, s) if f > s => Err(ErrorInner { (f, _, s) if f > s => Err(ErrorInner {

View file

@ -5,3 +5,4 @@ pkg
wasm-pack.log wasm-pack.log
stdlib stdlib
stdlib.json stdlib.json
metadata.json

View file

@ -6,57 +6,4 @@ JavaScript bindings for [ZoKrates](https://github.com/Zokrates/ZoKrates) project
npm install zokrates-js npm install zokrates-js
``` ```
## API Check the offical [ZoKrates documentation](https://zokrates.github.io/zokrates_js.html) for more details.
| Function | Description |
| ------ | ------ |
| initialize | Loads binding wasm module and returns a promise with ZoKrates provider |
| compile | Compiles source code into ZoKrates internal representation of arithmetic circuits |
| computeWitness | Computes a valid assignment of the variables, which include the results of the computation |
| setup | Generates a trusted setup for the compiled program |
| exportSolidityVerifier | Generates a Solidity contract which contains the generated verification key and a public function to verify a solution to the compiled program |
| generateProof | Generates a proof for a computation of the compiled program |
## Usage
### Importing
Bundlers
```js
import { initialize } from 'zokrates-js';
```
Node
```js
const { initialize } = require('zokrates-js/node');
```
### Example
```js
function importResolver(currentLocation, importLocation) {
// implement your resolving logic here
return {
source: "def main(): return",
location: importLocation
};
}
initialize().then((zokratesProvider) => {
const source = "def main(private field a) -> field: return a * a";
// compilation
const artifacts = zokratesProvider.compile(source, "main", importResolver);
// computation
const { witness, output } = zokratesProvider.computeWitness(artifacts, ["2"]);
// run setup
const keypair = zokratesProvider.setup(artifacts.program);
// generate proof
const proof = zokratesProvider.generateProof(artifacts.program, witness, keypair.pk);
// export solidity verifier
const verifier = zokratesProvider.exportSolidityVerifier(keypair.vk, "v1");
});
```

View file

@ -3,10 +3,11 @@ const gulp = require('gulp');
const dree = require('dree'); const dree = require('dree');
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const toml = require('toml');
/** stdlib constants */ /** stdlib constants */
const stdlibRoot = '../zokrates_stdlib/stdlib'; const stdlibRoot = '../zokrates_stdlib/stdlib';
const output = 'stdlib.json'; const stdlibOutput = 'stdlib.json';
const options = { const options = {
extensions: ['zok'] extensions: ['zok']
@ -22,6 +23,17 @@ gulp.task('stdlib', (done) => {
stdlib[file.relativePath] = content; stdlib[file.relativePath] = content;
}); });
fs.writeFileSync(path.resolve(__dirname, output), JSON.stringify(stdlib)); fs.writeFileSync(path.resolve(__dirname, stdlibOutput), JSON.stringify(stdlib));
done(); done();
}); });
gulp.task('metadata', (done) => {
const config = toml.parse(fs.readFileSync('../zokrates_cli/Cargo.toml').toString());
const metadata = JSON.stringify({
version: config.package.version
});
fs.writeFileSync(path.resolve(__dirname, 'metadata.json'), metadata);
done();
});
gulp.task('setup', gulp.parallel('stdlib', 'metadata'));

View file

@ -4,10 +4,19 @@ declare module 'zokrates-js' {
export type G2Affine = [G1Affine, G1Affine]; export type G2Affine = [G1Affine, G1Affine];
export type ProvingKey = Uint8Array; export type ProvingKey = Uint8Array;
export type SolidityAbi = "v1" | "v2";
export type ResolveCallback = (location: string, path: string) => ResolverResult;
export interface CompileConfig { export interface CompileConfig {
is_release: boolean is_release: boolean
} }
export interface CompileOptions {
location?: string,
resolveCallback?: ResolveCallback,
config?: CompileConfig
}
export interface VerificationKey { export interface VerificationKey {
alpha: G1Affine, alpha: G1Affine,
beta: G2Affine, beta: G2Affine,
@ -49,16 +58,18 @@ declare module 'zokrates-js' {
pk: ProvingKey, pk: ProvingKey,
} }
export type SolidityAbi = "v1" | "v2";
export type ResolveCallback = (location: string, path: string) => ResolverResult;
export interface ZoKratesProvider { export interface ZoKratesProvider {
compile(source: string, location: string, callback: ResolveCallback, config?: CompileConfig): CompilationArtifacts; compile(source: string, options?: CompileOptions): CompilationArtifacts;
setup(program: Uint8Array): SetupKeypair; setup(program: Uint8Array): SetupKeypair;
computeWitness(artifacts: CompilationArtifacts, args: any[]): ComputationResult; computeWitness(artifacts: CompilationArtifacts, args: any[]): ComputationResult;
exportSolidityVerifier(verifyingKey: VerificationKey, abi: SolidityAbi): string; exportSolidityVerifier(verifyingKey: VerificationKey, abi: SolidityAbi): string;
generateProof(program: Uint8Array, witness: string, provingKey: Uint8Array): Proof; generateProof(program: Uint8Array, witness: string, provingKey: Uint8Array): Proof;
} }
export interface Metadata {
version: string
}
export function initialize(): Promise<ZoKratesProvider>; export function initialize(): Promise<ZoKratesProvider>;
export var metadata: Metadata;
} }

View file

@ -1,9 +1,10 @@
import wrapper from './wrapper'; import wrapper from './wrapper';
import stdlib from './stdlib.json'; import stdlib from './stdlib.json';
import metadata from './metadata.json';
const initialize = async () => { const initialize = async () => {
const zokrates = await import('./pkg/index.js'); const zokrates = await import('./pkg/index.js');
return wrapper({ zokrates, stdlib }); return wrapper({ zokrates, stdlib });
} }
export { initialize }; export { initialize, metadata };

View file

@ -1,5 +1,6 @@
const wrapper = require('../wrapper.js'); const wrapper = require('../wrapper.js');
const stdlib = require('../stdlib.json'); const stdlib = require('../stdlib.json');
const metadata = require('../metadata.json');
const initialize = async () => { const initialize = async () => {
return wrapper({ return wrapper({
@ -8,4 +9,4 @@ const initialize = async () => {
}); });
} }
module.exports = { initialize }; module.exports = { initialize, metadata };

View file

@ -4572,6 +4572,12 @@
"through2": "^2.0.3" "through2": "^2.0.3"
} }
}, },
"toml": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz",
"integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==",
"dev": true
},
"type": { "type": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",

View file

@ -16,12 +16,13 @@
"index.d.ts", "index.d.ts",
"wrapper.js", "wrapper.js",
"stdlib.json", "stdlib.json",
"metadata.json",
"README.md" "README.md"
], ],
"types": "index.d.ts", "types": "index.d.ts",
"scripts": { "scripts": {
"wasm-pack": "wasm-pack build --out-name index --release", "wasm-pack": "wasm-pack build --out-name index --release",
"setup": "npm install && gulp stdlib", "setup": "npm install && gulp setup",
"prebuild": "npm run setup", "prebuild": "npm run setup",
"build": "npm run build:bundler && npm run build:node", "build": "npm run build:bundler && npm run build:node",
"build:bundler": "rimraf pkg && npm run wasm-pack -- --target bundler && npm run clean-pkg", "build:bundler": "rimraf pkg && npm run wasm-pack -- --target bundler && npm run clean-pkg",
@ -39,7 +40,8 @@
"mocha": "^7.1.1", "mocha": "^7.1.1",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"serve": "^11.3.2", "serve": "^11.3.2",
"text-encoding": "^0.7.0" "text-encoding": "^0.7.0",
"toml": "^3.0.0"
}, },
"dependencies": {} "dependencies": {}
} }

View file

@ -98,22 +98,13 @@ impl<'a> Resolver<Error> for JsResolver<'a> {
pub fn compile( pub fn compile(
source: JsValue, source: JsValue,
location: JsValue, location: JsValue,
resolve: &js_sys::Function, resolve_callback: &js_sys::Function,
config: JsValue, config: JsValue,
) -> Result<JsValue, JsValue> { ) -> Result<JsValue, JsValue> {
let resolver = JsResolver::new(resolve_callback);
let config: CompileConfig = config.into_serde().unwrap_or(CompileConfig::default());
let fmt_error = |e: &CompileError| format!("{}:{}", e.file().display(), e.value()); let fmt_error = |e: &CompileError| format!("{}:{}", e.file().display(), e.value());
let resolver = JsResolver::new(resolve);
let config: CompileConfig = {
if config.is_object() {
config
.into_serde()
.map_err(|e| JsValue::from_str(&format!("Invalid config format: {}", e)))?
} else {
CompileConfig::default()
}
};
let artifacts: CompilationArtifacts<Bn128Field> = core_compile( let artifacts: CompilationArtifacts<Bn128Field> = core_compile(
source.as_string().unwrap(), source.as_string().unwrap(),
PathBuf::from(location.as_string().unwrap()), PathBuf::from(location.as_string().unwrap()),
@ -208,8 +199,6 @@ pub fn generate_proof(program: JsValue, witness: JsValue, pk: JsValue) -> Result
#[wasm_bindgen(start)] #[wasm_bindgen(start)]
pub fn main_js() -> Result<(), JsValue> { pub fn main_js() -> Result<(), JsValue> {
#[cfg(debug_assertions)]
console_error_panic_hook::set_once(); console_error_panic_hook::set_once();
Ok(()) Ok(())
} }

View file

@ -14,112 +14,113 @@ describe('tests', function() {
describe("compilation", () => { describe("compilation", () => {
it('should compile', function() { it('should compile', function() {
assert.doesNotThrow(() => { assert.doesNotThrow(() => {
const artifacts = this.zokrates.compile("def main() -> field: return 42", "main"); const artifacts = this.zokrates.compile("def main() -> field: return 42");
assert.ok(artifacts !== undefined); assert.ok(artifacts !== undefined);
}) })
}); });
it('should throw on invalid code', function() { it('should throw on invalid code', function() {
assert.throws(() => this.zokrates.compile(":-)", "main")); assert.throws(() => this.zokrates.compile(":-)"));
}); });
it('should resolve stdlib module', function() { it('should resolve stdlib module', function() {
const stdlib = require('../stdlib.json');
assert.doesNotThrow(() => { assert.doesNotThrow(() => {
const code = ` const code = `import "${Object.keys(stdlib)[0]}" as func\ndef main(): return`;
def main(): this.zokrates.compile(code);
return });
`;
this.zokrates.compile(code, "main");
})
}); });
it('should resolve user module', function() { it('should resolve user module', function() {
assert.doesNotThrow(() => { assert.doesNotThrow(() => {
const code = 'import "test" as test\ndef main() -> field: return test()'; const code = 'import "test" as test\ndef main() -> field: return test()';
this.zokrates.compile(code, "main", (_, path) => { const options = {
resolveCallback: (_, path) => {
return { return {
source: "def main() -> field: return 1", source: "def main() -> (field): return 1",
location: path location: path
} }
}
};
this.zokrates.compile(code, options);
}); });
})
}); });
it('should throw on invalid module', function() { it('should throw on unresolved module', function() {
assert.throws(() => { assert.throws(() => {
const code = 'import "test" as test\ndef main() -> field: return test()'; const code = 'import "test" as test\ndef main() -> field: return test()';
this.zokrates.compile(code, "main", (_loc, _path) => null); this.zokrates.compile(code);
}) });
});
}); });
})
describe("computation", () => { describe("computation", () => {
it('should compute with valid inputs', function() { it('should compute with valid inputs', function() {
assert.doesNotThrow(() => { assert.doesNotThrow(() => {
const code = 'def main(private field a) -> field: return a * a'; const code = 'def main(private field a) -> field: return a * a';
const artifacts = this.zokrates.compile(code, "main", null); const artifacts = this.zokrates.compile(code);
const result = this.zokrates.computeWitness(artifacts, ["2"]) const result = this.zokrates.computeWitness(artifacts, ["2"]);
const output = JSON.parse(result.output); const output = JSON.parse(result.output);
assert.deepEqual(output, ["4"]); assert.deepEqual(output, ["4"]);
}) });
}); });
it('should throw on invalid input count', function() { it('should throw on invalid input count', function() {
assert.throws(() => { assert.throws(() => {
const code = 'def main(private field a) -> field: return a * a'; const code = 'def main(private field a) -> field: return a * a';
const artifacts = this.zokrates.compile(code, "main", null); const artifacts = this.zokrates.compile(code);
this.zokrates.computeWitness(artifacts, ["1", "2"]) this.zokrates.computeWitness(artifacts, ["1", "2"]);
}) });
}); });
it('should throw on invalid input type', function() { it('should throw on invalid input type', function() {
assert.throws(() => { assert.throws(() => {
const code = 'def main(private field a) -> field: return a * a'; const code = 'def main(private field a) -> field: return a * a';
const artifacts = this.zokrates.compile(code, "main", null); const artifacts = this.zokrates.compile(code);
this.zokrates.computeWitness(artifacts, [true]) this.zokrates.computeWitness(artifacts, [true]);
}) });
});
}); });
})
describe("setup", () => { describe("setup", () => {
it('should run setup', function() { it('should run setup', function() {
assert.doesNotThrow(() => { assert.doesNotThrow(() => {
const code = 'def main(private field a) -> field: return a * a'; const code = 'def main(private field a) -> field: return a * a';
const artifacts = this.zokrates.compile(code, "main", null); const artifacts = this.zokrates.compile(code);
this.zokrates.setup(artifacts.program); this.zokrates.setup(artifacts.program);
})
}); });
}) });
});
describe("export-verifier", () => { describe("export-verifier", () => {
it('should export solidity verifier', function() { it('should export solidity verifier', function() {
assert.doesNotThrow(() => { assert.doesNotThrow(() => {
const code = 'def main(private field a) -> field: return a * a'; const code = 'def main(private field a) -> field: return a * a';
const artifacts = this.zokrates.compile(code, "main", null); const artifacts = this.zokrates.compile(code);
const keypair = this.zokrates.setup(artifacts.program); const keypair = this.zokrates.setup(artifacts.program);
const verifier = this.zokrates.exportSolidityVerifier(keypair.vk, "v1"); const verifier = this.zokrates.exportSolidityVerifier(keypair.vk, "v1");
assert.ok(verifier.length > 0) assert.ok(verifier.length > 0);
}) });
});
}); });
})
describe("generate-proof", () => { describe("generate-proof", () => {
it('should generate proof', function() { it('should generate proof', function() {
assert.doesNotThrow(() => { assert.doesNotThrow(() => {
const code = 'def main(private field a) -> field: return a * a'; const code = 'def main(private field a) -> field: return a * a';
const artifacts = this.zokrates.compile(code, "main", null); const artifacts = this.zokrates.compile(code);
const computationResult = this.zokrates.computeWitness(artifacts, ["2"]) const computationResult = this.zokrates.computeWitness(artifacts, ["2"])
const keypair = this.zokrates.setup(artifacts.program); const keypair = this.zokrates.setup(artifacts.program);
const proof = this.zokrates.generateProof(artifacts.program, computationResult.witness, keypair.pk); const proof = this.zokrates.generateProof(artifacts.program, computationResult.witness, keypair.pk);
assert.ok(proof !== undefined); assert.ok(proof !== undefined);
assert.deepEqual(proof.inputs, ["0x0000000000000000000000000000000000000000000000000000000000000004"]) assert.deepEqual(proof.inputs, ["0x0000000000000000000000000000000000000000000000000000000000000004"]);
}) })
}); });
}); });

View file

@ -35,11 +35,12 @@ module.exports = (dep) => {
} }
return { return {
compile: (source, location, callback) => { compile: (source, options = {}) => {
let importCallback = (currentLocation, importLocation) => { const { location = "main.zok", resolveCallback = () => null, config } = options;
return resolveFromStdlib(currentLocation, importLocation) || callback(currentLocation, importLocation); const callback = (currentLocation, importLocation) => {
return resolveFromStdlib(currentLocation, importLocation) || resolveCallback(currentLocation, importLocation);
}; };
const { program, abi } = zokrates.compile(source, location, importCallback); const { program, abi } = zokrates.compile(source, location, callback, config);
return { return {
program: Array.from(program), program: Array.from(program),
abi abi