fix conflicts
This commit is contained in:
commit
2605559f4c
17 changed files with 258 additions and 188 deletions
|
@ -233,12 +233,6 @@ err() {
|
|||
exit 1
|
||||
}
|
||||
|
||||
need() {
|
||||
if ! command -v $1 > /dev/null 2>&1; then
|
||||
err "need $1 (command not found)"
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
need_cmd curl
|
||||
|
||||
|
@ -259,12 +253,11 @@ main() {
|
|||
done
|
||||
|
||||
# Dependencies
|
||||
need basename
|
||||
need curl
|
||||
need install
|
||||
need mkdir
|
||||
need mktemp
|
||||
need tar
|
||||
need_cmd curl
|
||||
need_cmd install
|
||||
need_cmd mkdir
|
||||
need_cmd mktemp
|
||||
need_cmd tar
|
||||
|
||||
git="ZoKrates/ZoKrates"
|
||||
|
||||
|
|
|
@ -1,51 +1,33 @@
|
|||
# zokrates.js
|
||||
|
||||
You can get JavaScript bindings for ZoKrates by running
|
||||
JavaScript bindings for [ZoKrates](https://github.com/Zokrates/ZoKrates).
|
||||
|
||||
```bash
|
||||
npm install zokrates-js
|
||||
```
|
||||
|
||||
## API
|
||||
## Importing
|
||||
|
||||
| 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
|
||||
##### 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.
|
||||
Currently the only known bundler known to be fully compatible with `zokrates-js` is [Webpack](https://webpack.js.org/).
|
||||
The choice of this default was done to reflect the trends of the JS ecosystem.
|
||||
```js
|
||||
import { initialize } from 'zokrates-js';
|
||||
```
|
||||
|
||||
Node
|
||||
##### Node
|
||||
```js
|
||||
const { initialize } = require('zokrates-js/node');
|
||||
```
|
||||
|
||||
### Example
|
||||
## 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);
|
||||
const artifacts = zokratesProvider.compile(source);
|
||||
|
||||
// computation
|
||||
const { witness, output } = zokratesProvider.computeWitness(artifacts, ["2"]);
|
||||
|
@ -60,3 +42,103 @@ initialize().then((zokratesProvider) => {
|
|||
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`
|
||||
|
|
|
@ -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> {
|
||||
fn from(range: pest::Range<'ast>) -> absy::RangeNode<T> {
|
||||
impl<'ast, T: Field> From<pest::Range<'ast>> for absy::RangeNode<'ast, T> {
|
||||
fn from(range: pest::Range<'ast>) -> absy::RangeNode<'ast, T> {
|
||||
use absy::NodeValue;
|
||||
|
||||
let from = range
|
||||
.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 from = range.from.map(|e| absy::ExpressionNode::from(e.0));
|
||||
|
||||
let to = range
|
||||
.to
|
||||
.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.to.map(|e| absy::ExpressionNode::from(e.0));
|
||||
|
||||
absy::Range { from, to }.span(range.span)
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum RangeOrExpression<'ast, T> {
|
||||
Range(RangeNode<T>),
|
||||
Range(RangeNode<'ast, T>),
|
||||
Expression(ExpressionNode<'ast, T>),
|
||||
}
|
||||
|
||||
|
@ -439,14 +439,14 @@ pub struct Spread<'ast, T> {
|
|||
|
||||
/// A range
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct Range<T> {
|
||||
pub from: Option<T>,
|
||||
pub to: Option<T>,
|
||||
pub struct Range<'ast, T> {
|
||||
pub from: Option<ExpressionNode<'ast, 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 {
|
||||
write!(
|
||||
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 {
|
||||
write!(f, "Range({:?}, {:?})", self.from, self.to)
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ impl<'ast> NodeValue for Variable<'ast> {}
|
|||
impl<'ast> NodeValue for Parameter<'ast> {}
|
||||
impl<'ast> NodeValue for Import<'ast> {}
|
||||
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> {
|
||||
fn eq(&self, other: &Node<T>) -> bool {
|
||||
|
|
|
@ -1659,17 +1659,50 @@ impl<'ast> Checker<'ast> {
|
|||
let array_size = array.size();
|
||||
let inner_type = array.inner_type().clone();
|
||||
|
||||
// check that the bounds are valid expressions
|
||||
let from = r
|
||||
.value
|
||||
.from
|
||||
.map(|v| v.to_dec_string().parse::<usize>().unwrap())
|
||||
.unwrap_or(0);
|
||||
.map(|e| self.check_expression(e, module_id, &types))
|
||||
.unwrap_or(Ok(FieldElementExpression::Number(T::from(0)).into()))?;
|
||||
|
||||
let to = r
|
||||
.value
|
||||
.to
|
||||
.map(|v| v.to_dec_string().parse::<usize>().unwrap())
|
||||
.unwrap_or(array_size);
|
||||
.map(|e| self.check_expression(e, module_id, &types))
|
||||
.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) {
|
||||
(f, _, s) if f > s => Err(ErrorInner {
|
||||
|
|
1
zokrates_js/.gitignore
vendored
1
zokrates_js/.gitignore
vendored
|
@ -5,3 +5,4 @@ pkg
|
|||
wasm-pack.log
|
||||
stdlib
|
||||
stdlib.json
|
||||
metadata.json
|
|
@ -6,57 +6,4 @@ JavaScript bindings for [ZoKrates](https://github.com/Zokrates/ZoKrates) project
|
|||
npm install zokrates-js
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
| 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");
|
||||
});
|
||||
```
|
||||
Check the offical [ZoKrates documentation](https://zokrates.github.io/zokrates_js.html) for more details.
|
||||
|
|
|
@ -3,10 +3,11 @@ const gulp = require('gulp');
|
|||
const dree = require('dree');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const toml = require('toml');
|
||||
|
||||
/** stdlib constants */
|
||||
const stdlibRoot = '../zokrates_stdlib/stdlib';
|
||||
const output = 'stdlib.json';
|
||||
const stdlibOutput = 'stdlib.json';
|
||||
|
||||
const options = {
|
||||
extensions: ['zok']
|
||||
|
@ -22,6 +23,17 @@ gulp.task('stdlib', (done) => {
|
|||
stdlib[file.relativePath] = content;
|
||||
});
|
||||
|
||||
fs.writeFileSync(path.resolve(__dirname, output), JSON.stringify(stdlib));
|
||||
fs.writeFileSync(path.resolve(__dirname, stdlibOutput), JSON.stringify(stdlib));
|
||||
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'));
|
19
zokrates_js/index.d.ts
vendored
19
zokrates_js/index.d.ts
vendored
|
@ -4,10 +4,19 @@ declare module 'zokrates-js' {
|
|||
export type G2Affine = [G1Affine, G1Affine];
|
||||
export type ProvingKey = Uint8Array;
|
||||
|
||||
export type SolidityAbi = "v1" | "v2";
|
||||
export type ResolveCallback = (location: string, path: string) => ResolverResult;
|
||||
|
||||
export interface CompileConfig {
|
||||
is_release: boolean
|
||||
}
|
||||
|
||||
export interface CompileOptions {
|
||||
location?: string,
|
||||
resolveCallback?: ResolveCallback,
|
||||
config?: CompileConfig
|
||||
}
|
||||
|
||||
export interface VerificationKey {
|
||||
alpha: G1Affine,
|
||||
beta: G2Affine,
|
||||
|
@ -49,16 +58,18 @@ declare module 'zokrates-js' {
|
|||
pk: ProvingKey,
|
||||
}
|
||||
|
||||
export type SolidityAbi = "v1" | "v2";
|
||||
export type ResolveCallback = (location: string, path: string) => ResolverResult;
|
||||
|
||||
export interface ZoKratesProvider {
|
||||
compile(source: string, location: string, callback: ResolveCallback, config?: CompileConfig): CompilationArtifacts;
|
||||
compile(source: string, options?: CompileOptions): CompilationArtifacts;
|
||||
setup(program: Uint8Array): SetupKeypair;
|
||||
computeWitness(artifacts: CompilationArtifacts, args: any[]): ComputationResult;
|
||||
exportSolidityVerifier(verifyingKey: VerificationKey, abi: SolidityAbi): string;
|
||||
generateProof(program: Uint8Array, witness: string, provingKey: Uint8Array): Proof;
|
||||
}
|
||||
|
||||
export interface Metadata {
|
||||
version: string
|
||||
}
|
||||
|
||||
export function initialize(): Promise<ZoKratesProvider>;
|
||||
export var metadata: Metadata;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import wrapper from './wrapper';
|
||||
import stdlib from './stdlib.json';
|
||||
import metadata from './metadata.json';
|
||||
|
||||
const initialize = async () => {
|
||||
const zokrates = await import('./pkg/index.js');
|
||||
return wrapper({ zokrates, stdlib });
|
||||
}
|
||||
|
||||
export { initialize };
|
||||
export { initialize, metadata };
|
|
@ -1,5 +1,6 @@
|
|||
const wrapper = require('../wrapper.js');
|
||||
const stdlib = require('../stdlib.json');
|
||||
const metadata = require('../metadata.json');
|
||||
|
||||
const initialize = async () => {
|
||||
return wrapper({
|
||||
|
@ -8,4 +9,4 @@ const initialize = async () => {
|
|||
});
|
||||
}
|
||||
|
||||
module.exports = { initialize };
|
||||
module.exports = { initialize, metadata };
|
6
zokrates_js/package-lock.json
generated
6
zokrates_js/package-lock.json
generated
|
@ -4572,6 +4572,12 @@
|
|||
"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": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
|
||||
|
|
|
@ -16,12 +16,13 @@
|
|||
"index.d.ts",
|
||||
"wrapper.js",
|
||||
"stdlib.json",
|
||||
"metadata.json",
|
||||
"README.md"
|
||||
],
|
||||
"types": "index.d.ts",
|
||||
"scripts": {
|
||||
"wasm-pack": "wasm-pack build --out-name index --release",
|
||||
"setup": "npm install && gulp stdlib",
|
||||
"setup": "npm install && gulp setup",
|
||||
"prebuild": "npm run setup",
|
||||
"build": "npm run build:bundler && npm run build:node",
|
||||
"build:bundler": "rimraf pkg && npm run wasm-pack -- --target bundler && npm run clean-pkg",
|
||||
|
@ -39,7 +40,8 @@
|
|||
"mocha": "^7.1.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"serve": "^11.3.2",
|
||||
"text-encoding": "^0.7.0"
|
||||
"text-encoding": "^0.7.0",
|
||||
"toml": "^3.0.0"
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
|
|
|
@ -98,22 +98,13 @@ impl<'a> Resolver<Error> for JsResolver<'a> {
|
|||
pub fn compile(
|
||||
source: JsValue,
|
||||
location: JsValue,
|
||||
resolve: &js_sys::Function,
|
||||
resolve_callback: &js_sys::Function,
|
||||
config: 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 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(
|
||||
source.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)]
|
||||
pub fn main_js() -> Result<(), JsValue> {
|
||||
#[cfg(debug_assertions)]
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -14,112 +14,113 @@ describe('tests', function() {
|
|||
describe("compilation", () => {
|
||||
it('should compile', function() {
|
||||
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);
|
||||
})
|
||||
});
|
||||
|
||||
it('should throw on invalid code', function() {
|
||||
assert.throws(() => this.zokrates.compile(":-)", "main"));
|
||||
assert.throws(() => this.zokrates.compile(":-)"));
|
||||
});
|
||||
|
||||
it('should resolve stdlib module', function() {
|
||||
const stdlib = require('../stdlib.json');
|
||||
assert.doesNotThrow(() => {
|
||||
const code = `
|
||||
def main():
|
||||
return
|
||||
`;
|
||||
this.zokrates.compile(code, "main");
|
||||
})
|
||||
const code = `import "${Object.keys(stdlib)[0]}" as func\ndef main(): return`;
|
||||
this.zokrates.compile(code);
|
||||
});
|
||||
});
|
||||
|
||||
it('should resolve user module', function() {
|
||||
assert.doesNotThrow(() => {
|
||||
const code = 'import "test" as test\ndef main() -> field: return test()';
|
||||
this.zokrates.compile(code, "main", (_, path) => {
|
||||
const options = {
|
||||
resolveCallback: (_, path) => {
|
||||
return {
|
||||
source: "def main() -> field: return 1",
|
||||
source: "def main() -> (field): return 1",
|
||||
location: path
|
||||
}
|
||||
}
|
||||
};
|
||||
this.zokrates.compile(code, options);
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
it('should throw on invalid module', function() {
|
||||
it('should throw on unresolved module', function() {
|
||||
assert.throws(() => {
|
||||
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", () => {
|
||||
it('should compute with valid inputs', function() {
|
||||
assert.doesNotThrow(() => {
|
||||
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);
|
||||
|
||||
assert.deepEqual(output, ["4"]);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw on invalid input count', function() {
|
||||
assert.throws(() => {
|
||||
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() {
|
||||
assert.throws(() => {
|
||||
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", () => {
|
||||
it('should run setup', function() {
|
||||
assert.doesNotThrow(() => {
|
||||
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);
|
||||
})
|
||||
});
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe("export-verifier", () => {
|
||||
it('should export solidity verifier', function() {
|
||||
assert.doesNotThrow(() => {
|
||||
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 verifier = this.zokrates.exportSolidityVerifier(keypair.vk, "v1");
|
||||
assert.ok(verifier.length > 0)
|
||||
})
|
||||
assert.ok(verifier.length > 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
describe("generate-proof", () => {
|
||||
it('should generate proof', function() {
|
||||
assert.doesNotThrow(() => {
|
||||
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 keypair = this.zokrates.setup(artifacts.program);
|
||||
const proof = this.zokrates.generateProof(artifacts.program, computationResult.witness, keypair.pk);
|
||||
|
||||
assert.ok(proof !== undefined);
|
||||
assert.deepEqual(proof.inputs, ["0x0000000000000000000000000000000000000000000000000000000000000004"])
|
||||
assert.deepEqual(proof.inputs, ["0x0000000000000000000000000000000000000000000000000000000000000004"]);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
|
|
@ -35,11 +35,12 @@ module.exports = (dep) => {
|
|||
}
|
||||
|
||||
return {
|
||||
compile: (source, location, callback) => {
|
||||
let importCallback = (currentLocation, importLocation) => {
|
||||
return resolveFromStdlib(currentLocation, importLocation) || callback(currentLocation, importLocation);
|
||||
compile: (source, options = {}) => {
|
||||
const { location = "main.zok", resolveCallback = () => null, config } = options;
|
||||
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 {
|
||||
program: Array.from(program),
|
||||
abi
|
||||
|
|
Loading…
Reference in a new issue