Merge branch 'develop' of github.com:Zokrates/ZoKrates into update-book
This commit is contained in:
commit
14d4ac4379
19 changed files with 3032 additions and 215 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`
|
||||
|
|
1
zokrates_cli/tests/contract/.gitignore
vendored
Normal file
1
zokrates_cli/tests/contract/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
node_modules
|
2746
zokrates_cli/tests/contract/package-lock.json
generated
Normal file
2746
zokrates_cli/tests/contract/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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 {
|
||||
|
|
|
@ -1644,17 +1644,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 {
|
||||
|
|
3
zokrates_js/.gitignore
vendored
3
zokrates_js/.gitignore
vendored
|
@ -4,4 +4,5 @@ target
|
|||
pkg
|
||||
wasm-pack.log
|
||||
stdlib
|
||||
stdlib.json
|
||||
stdlib.json
|
||||
metadata.json
|
|
@ -1,62 +1,9 @@
|
|||
# zokrates.js
|
||||
|
||||
JavaScript bindings for [ZoKrates](https://github.com/Zokrates/ZoKrates) project.
|
||||
JavaScript bindings for [ZoKrates](https://github.com/Zokrates/ZoKrates) project.
|
||||
|
||||
```bash
|
||||
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 };
|
58
zokrates_js/package-lock.json
generated
58
zokrates_js/package-lock.json
generated
|
@ -140,9 +140,9 @@
|
|||
}
|
||||
},
|
||||
"arch": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/arch/-/arch-2.1.1.tgz",
|
||||
"integrity": "sha512-BLM56aPo9vLLFVa8+/+pJLnrZ7QGGTVHWsCwieAWT9o9K8UeGaQbzZbGoabWLOo2ksBCztoXdqBZBplqLDDCSg==",
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/arch/-/arch-2.1.2.tgz",
|
||||
"integrity": "sha512-NTBIIbAfkJeIletyABbVtdPgeKfDafR+1mZV/AyyfC1UkVkp9iUjV+wwmqtUgphHYajbI86jejBJp5e+jkGTiQ==",
|
||||
"dev": true
|
||||
},
|
||||
"archy": {
|
||||
|
@ -2789,9 +2789,9 @@
|
|||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.15",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
|
||||
"version": "4.17.19",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
|
||||
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
|
||||
"dev": true
|
||||
},
|
||||
"log-symbols": {
|
||||
|
@ -2894,18 +2894,18 @@
|
|||
}
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.43.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
|
||||
"integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==",
|
||||
"version": "1.44.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
|
||||
"integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==",
|
||||
"dev": true
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.26",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz",
|
||||
"integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==",
|
||||
"version": "2.1.27",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
|
||||
"integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mime-db": "1.43.0"
|
||||
"mime-db": "1.44.0"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
|
@ -4012,9 +4012,9 @@
|
|||
}
|
||||
},
|
||||
"serve": {
|
||||
"version": "11.3.0",
|
||||
"resolved": "https://registry.npmjs.org/serve/-/serve-11.3.0.tgz",
|
||||
"integrity": "sha512-AU0g50Q1y5EVFX56bl0YX5OtVjUX1N737/Htj93dQGKuHiuLvVB45PD8Muar70W6Kpdlz8aNJfoUqTyAq9EE/A==",
|
||||
"version": "11.3.2",
|
||||
"resolved": "https://registry.npmjs.org/serve/-/serve-11.3.2.tgz",
|
||||
"integrity": "sha512-yKWQfI3xbj/f7X1lTBg91fXBP0FqjJ4TEi+ilES5yzH0iKJpN5LjNb1YzIfQg9Rqn4ECUS2SOf2+Kmepogoa5w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@zeit/schemas": "2.6.0",
|
||||
|
@ -4024,7 +4024,7 @@
|
|||
"chalk": "2.4.1",
|
||||
"clipboardy": "1.2.3",
|
||||
"compression": "1.7.3",
|
||||
"serve-handler": "6.1.2",
|
||||
"serve-handler": "6.1.3",
|
||||
"update-check": "1.5.2"
|
||||
},
|
||||
"dependencies": {
|
||||
|
@ -4075,9 +4075,9 @@
|
|||
}
|
||||
},
|
||||
"serve-handler": {
|
||||
"version": "6.1.2",
|
||||
"resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.2.tgz",
|
||||
"integrity": "sha512-RFh49wX7zJmmOVDcIjiDSJnMH+ItQEvyuYLYuDBVoA/xmQSCuj+uRmk1cmBB5QQlI3qOiWKp6p4DUGY+Z5AB2A==",
|
||||
"version": "6.1.3",
|
||||
"resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz",
|
||||
"integrity": "sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bytes": "3.0.0",
|
||||
|
@ -4152,9 +4152,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"signal-exit": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
|
||||
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
|
||||
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
|
||||
"dev": true
|
||||
},
|
||||
"snapdragon": {
|
||||
|
@ -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",
|
||||
|
@ -4957,9 +4963,9 @@
|
|||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "18.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.1.tgz",
|
||||
"integrity": "sha512-KRHEsOM16IX7XuLnMOqImcPNbLVXMNHYAoFc3BKR8Ortl5gzDbtXvvEoGx9imk5E+X1VeNKNlcHr8B8vi+7ipA==",
|
||||
"version": "18.1.3",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
|
||||
"integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"camelcase": "^5.0.0",
|
||||
|
|
|
@ -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",
|
||||
|
@ -38,8 +39,9 @@
|
|||
"gulp-cli": "^2.2.0",
|
||||
"mocha": "^7.1.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"serve": "^11.3.0",
|
||||
"text-encoding": "^0.7.0"
|
||||
"serve": "^11.3.2",
|
||||
"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) => {
|
||||
return {
|
||||
source: "def main() -> (field): return 1",
|
||||
location: path
|
||||
const options = {
|
||||
resolveCallback: (_, path) => {
|
||||
return {
|
||||
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