mirror of
https://github.com/arnaucube/circom.git
synced 2026-02-07 11:16:42 +01:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f604c31e0d | ||
|
|
a9c0593ec0 | ||
|
|
80cce0ccbb | ||
|
|
fcef4f5f32 | ||
|
|
3ef303593b | ||
|
|
16cf75c94b | ||
|
|
d79d59416d | ||
|
|
eae13a94fa | ||
|
|
7e41508860 | ||
|
|
5d374237e1 | ||
|
|
a18b603b22 | ||
|
|
f261992689 | ||
|
|
45e359aa35 | ||
|
|
da6cff2335 | ||
|
|
38b4a7a8b3 | ||
|
|
825f31b420 |
61
TUTORIAL.md
61
TUTORIAL.md
@@ -1,6 +1,6 @@
|
|||||||
# circom and snarkjs tutorial
|
# circom and snarkjs tutorial
|
||||||
|
|
||||||
This tutorial will guide you in creating your first Zero Knowledge zkSnark circuit. It will take you through the various techniques to write circuits, and will show you how to create proofs and verify them off-chain and on-chain on Ethereum.
|
This tutorial will guide you in creating your first zero-knowledge SNARK circuit. It will take you through the various techniques to write circuits and show you how to create and verify proofs off-chain and on-chain on Ethereum.
|
||||||
|
|
||||||
## 1. Installing the tools
|
## 1. Installing the tools
|
||||||
|
|
||||||
@@ -16,14 +16,13 @@ Run:
|
|||||||
|
|
||||||
```sh
|
```sh
|
||||||
npm install -g circom
|
npm install -g circom
|
||||||
npm install -g circom_runtime
|
|
||||||
npm install -g snarkjs
|
npm install -g snarkjs
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## 2. Working with a circuit
|
## 2. Working with a circuit
|
||||||
|
|
||||||
Let's create a circuit that tries to prove that you are able to factor a number!
|
Let's create a circuit that will allow you to prove that you are able to factor a number!
|
||||||
|
|
||||||
### 2.1 Create a circuit in a new directory
|
### 2.1 Create a circuit in a new directory
|
||||||
|
|
||||||
@@ -66,9 +65,11 @@ We are now ready to compile the circuit. Run the following command:
|
|||||||
circom circuit.circom --r1cs --wasm --sym
|
circom circuit.circom --r1cs --wasm --sym
|
||||||
```
|
```
|
||||||
|
|
||||||
The -r optin will generate `circuit.r1cs` ( The r1cs constraint system of the circuit in binary format)
|
The `--r1cs` option will generate `circuit.r1cs` (the r1cs constraint system of the circuit in binary format).
|
||||||
The -w will generate `circuit.wasm` (The wasm code to generate the witness)
|
|
||||||
The -s will generate `circuit.sym` (This is the symbols file, required for debugging or if you want to print the constraint system in an annotated mode)
|
The `--wasm` option will generate `circuit.wasm` (the wasm code to generate the witness).
|
||||||
|
|
||||||
|
The `--sym` option will generate `circuit.sym` (a symbols file required for debugging or if you want to print the constraint system in an annotated mode).
|
||||||
|
|
||||||
|
|
||||||
## 3. Taking the compiled circuit to *snarkjs*
|
## 3. Taking the compiled circuit to *snarkjs*
|
||||||
@@ -104,21 +105,21 @@ Ok, let's run a setup for our circuit:
|
|||||||
snarkjs setup
|
snarkjs setup
|
||||||
```
|
```
|
||||||
|
|
||||||
> By default `snarkjs` will look for and use `circuit.r1cs`. You can always specify a different circuit file by adding `-r <circuit R1CS file name>`
|
> By default `snarkjs` will look for and use `circuit.r1cs`. You can always specify a different circuit file by adding `-r <circuit R1CS file name>`.
|
||||||
|
|
||||||
The output of the setup will in the form of 2 files: `proving_key.json` and `verification_key.json`
|
The output of the setup will be in the form of 2 files: `proving_key.json` and `verification_key.json`.
|
||||||
|
|
||||||
### 3.3. Calculating a witness
|
### 3.3. Calculating a witness
|
||||||
|
|
||||||
Before creating any proof, we need to calculate all the signals of the circuit that match (all) the constrains of the circuit.
|
Before creating any proof, we need to calculate all the signals of the circuit that match (all) the constraints of the circuit.
|
||||||
|
|
||||||
`circom` generates a wasm module that calculates those for you. You need to provide a file with the inputs and it will execute the circuit and calculate all the intermediate signals and the output. This set of signals is the *witness*.
|
`circom` generates a wasm module that calculates those for you. You need to provide a file with the inputs and it will execute the circuit and calculate all the intermediate signals and the output. This set of signals is the *witness*.
|
||||||
|
|
||||||
The zero knowledge proofs prove that you know a set of signals (witness) that match all the constraints, without revealing any of the signals except the public inputs plus the outputs.
|
The zero-knowledge proofs prove that you know a set of signals (witness) that match all the constraints without revealing any of the signals except the public inputs and the outputs.
|
||||||
|
|
||||||
For example, imagine you want to prove you are able to factor 33. It means that you know two numbers `a` and `b` and when you multiply them, it results in 33.
|
For example, imagine you want to prove you are able to factor the number 33. It means that you know two numbers `a` and `b` that when you multiply them, it results in 33.
|
||||||
|
|
||||||
> Of course you can always use one and the same number as `a` or `b`. We will deal with this problem later.
|
> Of course you can always use the number one and the same number as `a` or `b`. We will deal with this problem later.
|
||||||
|
|
||||||
So you want to prove that you know 3 and 11.
|
So you want to prove that you know 3 and 11.
|
||||||
|
|
||||||
@@ -131,13 +132,9 @@ Let's create a file named `input.json`
|
|||||||
Now let's calculate the witness:
|
Now let's calculate the witness:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
snarkjs --wasm circuit.wasm --input input.json --witness witness.json
|
snarkjs calculatewitness --wasm circuit.wasm --input input.json --witness witness.json
|
||||||
```
|
```
|
||||||
|
|
||||||
`calcwit` is part of the circom_runtime package and it's just a wrapper in JS to call the wasm module.
|
|
||||||
|
|
||||||
You can use `circom_runtime` from your own project to calulate the witness.
|
|
||||||
|
|
||||||
You may want to take a look at `witness.json` file with all the signals.
|
You may want to take a look at `witness.json` file with all the signals.
|
||||||
|
|
||||||
### Create the proof
|
### Create the proof
|
||||||
@@ -150,7 +147,7 @@ snarkjs proof
|
|||||||
|
|
||||||
This command will use the `proving_key.json` and the `witness.json` files by default to generate `proof.json` and `public.json`
|
This command will use the `proving_key.json` and the `witness.json` files by default to generate `proof.json` and `public.json`
|
||||||
|
|
||||||
The `proof.json` file will contain the actual proof. And the `public.json` file will contain just the values of the public inputs and the outputs.
|
The `proof.json` file will contain the actual proof and the `public.json` file will contain just the values of the public inputs and the outputs.
|
||||||
|
|
||||||
|
|
||||||
### Verifying the proof
|
### Verifying the proof
|
||||||
@@ -180,7 +177,7 @@ You can take the code in `verifier.sol` and cut and paste it in remix.
|
|||||||
|
|
||||||
This code contains two contracts: Pairings and Verifier. You only need to deploy the `Verifier` contract.
|
This code contains two contracts: Pairings and Verifier. You only need to deploy the `Verifier` contract.
|
||||||
|
|
||||||
> You may want to use a test net like Rinkeby, Kovan or Ropsten. You can also use the Javascript VM, but in some browsers, the verification takes long and it may hang the page.
|
> You may want to use a test net like Rinkeby, Kovan or Ropsten. You can also use the Javascript VM, but in some browsers the verification takes long and it may hang the page.
|
||||||
|
|
||||||
|
|
||||||
### Verifying the proof on-chain
|
### Verifying the proof on-chain
|
||||||
@@ -189,7 +186,7 @@ The verifier contract deployed in the last step has a `view` function called `ve
|
|||||||
|
|
||||||
This function will return true if the proof and the inputs are valid.
|
This function will return true if the proof and the inputs are valid.
|
||||||
|
|
||||||
To facilitate the call, you can use snarkjs to generate the parameters of the call by typing:
|
To facilitate the call, you can use `snarkjs` to generate the parameters of the call by typing:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
snarkjs generatecall
|
snarkjs generatecall
|
||||||
@@ -204,15 +201,15 @@ If you change any bit in the parameters, the result will be verifiably false.
|
|||||||
|
|
||||||
## Bonus track
|
## Bonus track
|
||||||
|
|
||||||
We can fix the circuit to not accept one as any of the values by adding some extra constraints.
|
We can fix the circuit to not accept the number 1 as any of the input values by adding some extra constraints.
|
||||||
|
|
||||||
Here the trick is that we use the property that 0 has no inverse. So `(a-1)` should not have an inverse.
|
Here, the trick is that we use the property that 0 has no inverse. So `(a-1)` should not have an inverse.
|
||||||
|
|
||||||
That means that `(a-1)*inv = 1` will be inpossible to match if `a` is 1.
|
That means that `(a-1)*inv = 1` will be inpossible to match if `a` is 1.
|
||||||
|
|
||||||
We just calculate inv by `1/(a-1)`
|
We just calculate inv by `1/(a-1)`.
|
||||||
|
|
||||||
So let's modify the circuit:
|
So, let's modify the circuit:
|
||||||
|
|
||||||
```
|
```
|
||||||
template Multiplier() {
|
template Multiplier() {
|
||||||
@@ -234,22 +231,22 @@ template Multiplier() {
|
|||||||
component main = Multiplier();
|
component main = Multiplier();
|
||||||
```
|
```
|
||||||
|
|
||||||
A nice thing of the circom language is that you can split a <== into two independent actions: <-- and ===
|
A nice thing of the circom language is that you can split a `<==` into two independent actions: `<--` and `===`.
|
||||||
|
|
||||||
The <-- and --> operators assign a value to a signal without creating any constraints.
|
The `<--` and `-->` operators assign a value to a signal without creating any constraints.
|
||||||
|
|
||||||
The === operator adds a constraint without assigning any value to any signal.
|
The `===` operator adds a constraint without assigning any value to a signal.
|
||||||
|
|
||||||
The circuit also has another problem: the operation works in Zr, so we need to guarantee the multiplication does not overflow. This can be done by converting the inputs to binary and checking the ranges, but we will reserve it for future tutorials.
|
The circuit also has another problem: the operation works in `Z_r`, so we need to guarantee the multiplication does not overflow. This can be done by converting the inputs to binary and checking the ranges, but we will reserve it for future tutorials.
|
||||||
|
|
||||||
## Where to go from here:
|
## Where to go from here
|
||||||
|
|
||||||
You may want to read the [README](https://github.com/iden3/circom) to learn more features about circom.
|
You may want to read the [README](https://github.com/iden3/circom) to learn more features about `circom`.
|
||||||
|
|
||||||
You can also check a library with many basic circuits lib binarizations, comparators, eddsa, hashes, merkle trees etc [here](https://github.com/iden3/circomlib) (Work in progress).
|
You can also check a library with many basic circuits lib binarizations, comparators, eddsa, hashes, merkle trees etc [here](https://github.com/iden3/circomlib) (Work in progress).
|
||||||
|
|
||||||
|
|
||||||
Or a exponentiation in the Baby Jub curve [here](https://github.com/iden3/circomlib) (Work in progress).
|
Or a exponentiation in the Baby Jubjub curve [here](https://github.com/iden3/circomlib) (Work in progress).
|
||||||
|
|
||||||
|
|
||||||
# Final note
|
# Final note
|
||||||
@@ -258,4 +255,4 @@ There is nothing worse for a dev than working with a buggy compiler. This is a
|
|||||||
|
|
||||||
And please contact us for any isue you have. In general, a github issue with a small piece of code with the bug is very useful to us.
|
And please contact us for any isue you have. In general, a github issue with a small piece of code with the bug is very useful to us.
|
||||||
|
|
||||||
Enjoy zero knowledge proving!
|
Enjoy zero-knowledge proving!
|
||||||
|
|||||||
56
package-lock.json
generated
56
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "circom",
|
"name": "circom",
|
||||||
"version": "0.5.0",
|
"version": "0.5.4",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -221,9 +221,9 @@
|
|||||||
"integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII="
|
"integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII="
|
||||||
},
|
},
|
||||||
"circom_runtime": {
|
"circom_runtime": {
|
||||||
"version": "0.0.2",
|
"version": "0.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.0.3.tgz",
|
||||||
"integrity": "sha512-aJcQucUxrZ31O7JbY14l1oiP6ZlNAtPW+i8/CY4b9GAjgWPjts+D9pxtz/x2yC2Ei+ieaJY7LFjfCKFTOoHGDQ==",
|
"integrity": "sha512-z4ypbs9cTQn7+2FHZNTnccMj6kQCcKT2agYqCrm2kdLBJh9LDoxU1JVu5mSnVuOtgc7BclQ7r0xclG0zP2rxhw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"big-integer": "^1.6.48",
|
"big-integer": "^1.6.48",
|
||||||
"fnv-plus": "^1.3.1"
|
"fnv-plus": "^1.3.1"
|
||||||
@@ -592,30 +592,20 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ffjavascript": {
|
"ffjavascript": {
|
||||||
"version": "0.0.3",
|
"version": "0.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.0.4.tgz",
|
||||||
"integrity": "sha512-uXbiC7cNbFzNJCdkGlbQf2d7GciY1ICMcBeAA7+D8RHPr9Y5zYiDRWtU5etjAV8TplE7eZQ9Iqd9ieFi0ARJLA==",
|
"integrity": "sha512-6eiRvy+YuGCRjH4U8KdJbRel5VBW0zeuUL1FXQ+fFxTp5xv2ClqTfCYf5ClUtq0voGpd9XJAdUCvgIxHDbAQ0Q==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"big-integer": "^1.6.48"
|
"big-integer": "^1.6.48"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ffwasm": {
|
"ffwasm": {
|
||||||
"version": "0.0.5",
|
"version": "0.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/ffwasm/-/ffwasm-0.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/ffwasm/-/ffwasm-0.0.6.tgz",
|
||||||
"integrity": "sha512-biz1jK3TjxpwigoBLWzvBNtuQAC6WBVzlI1sw2BQp3RqTei66OhJ6E2G+zSk2SubUVWlrgTN+WfE+Fmn3qdtgg==",
|
"integrity": "sha512-bEBKYANozdyZBCGE6XLg4s/CaJRZdFGQgbthy7EZ4OhNCIpycgklS5mlf88Bw4fXSddlU1V9iYXI4JwfGO3BhQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"big-integer": "^1.6.48",
|
"big-integer": "^1.6.48",
|
||||||
"wasmbuilder": "0.0.8"
|
"wasmbuilder": "0.0.10"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"wasmbuilder": {
|
|
||||||
"version": "0.0.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/wasmbuilder/-/wasmbuilder-0.0.8.tgz",
|
|
||||||
"integrity": "sha512-d63cIsDmHnybA5hTlRRLadgys5r3Tl4W8SbcBRh13FauEPOo48dqjgzdL1xefpZkpKKybDRlFqgm+9cX04B3+w==",
|
|
||||||
"requires": {
|
|
||||||
"big-integer": "^1.6.43"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"figures": {
|
"figures": {
|
||||||
@@ -1133,9 +1123,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"r1csfile": {
|
"r1csfile": {
|
||||||
"version": "0.0.2",
|
"version": "0.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/r1csfile/-/r1csfile-0.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/r1csfile/-/r1csfile-0.0.3.tgz",
|
||||||
"integrity": "sha512-H1aR5NYRJ/RUrHWR/PNEivFEDkLV4R0+4SlKo2eq/fyiWxwgZNapOkjnJXsy5TZn40uFVrud0uOxGyVWgm9rDg==",
|
"integrity": "sha512-TNrodnbHw5yAMv2gj0Ezf22XS3q8zGEjdPHZLBmJauIPFxm6QmyzxlB92yZ5WNkjEtJiS7p1hvkO9/RsJXRDjw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"big-integer": "^1.6.48"
|
"big-integer": "^1.6.48"
|
||||||
}
|
}
|
||||||
@@ -1231,9 +1221,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"signal-exit": {
|
"signal-exit": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
|
||||||
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
|
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"slice-ansi": {
|
"slice-ansi": {
|
||||||
@@ -1456,9 +1446,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"wasmbuilder": {
|
"wasmbuilder": {
|
||||||
"version": "0.0.9",
|
"version": "0.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/wasmbuilder/-/wasmbuilder-0.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/wasmbuilder/-/wasmbuilder-0.0.10.tgz",
|
||||||
"integrity": "sha512-QJ550VwQvN6P4oW0d+/tCfo3i+1GBuuFX906r8QpDRryYXmXvdRZWJM0qkHgOfhg8G47SfgJVYNl3fyLfkxaPw==",
|
"integrity": "sha512-zQSvZ7d74d9OvN+mCN6ucNne4QS5/cBBYTHldX0Oe+u9gStY21orapvuX1ajisA7RVIpuFhYg+ZgdySsPfeh0A==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"big-integer": "^1.6.48"
|
"big-integer": "^1.6.48"
|
||||||
}
|
}
|
||||||
@@ -1531,9 +1521,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"yargs-parser": {
|
"yargs-parser": {
|
||||||
"version": "18.1.1",
|
"version": "18.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.2.tgz",
|
||||||
"integrity": "sha512-KRHEsOM16IX7XuLnMOqImcPNbLVXMNHYAoFc3BKR8Ortl5gzDbtXvvEoGx9imk5E+X1VeNKNlcHr8B8vi+7ipA==",
|
"integrity": "sha512-hlIPNR3IzC1YuL1c2UwwDKpXlNFBqD1Fswwh1khz5+d8Cq/8yc/Mn0i+rQXduu8hcrFKvO7Eryk+09NecTQAAQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"camelcase": "^5.0.0",
|
"camelcase": "^5.0.0",
|
||||||
"decamelize": "^1.2.0"
|
"decamelize": "^1.2.0"
|
||||||
|
|||||||
12
package.json
12
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "circom",
|
"name": "circom",
|
||||||
"version": "0.5.0",
|
"version": "0.5.4",
|
||||||
"description": "Language to generate logic circuits",
|
"description": "Language to generate logic circuits",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"directories": {
|
"directories": {
|
||||||
@@ -31,14 +31,14 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"big-integer": "^1.6.32",
|
"big-integer": "^1.6.32",
|
||||||
"chai": "^4.2.0",
|
"chai": "^4.2.0",
|
||||||
"circom_runtime": "0.0.2",
|
"circom_runtime": "0.0.3",
|
||||||
"ffiasm": "0.0.2",
|
"ffiasm": "0.0.2",
|
||||||
"ffjavascript": "0.0.3",
|
"ffjavascript": "0.0.4",
|
||||||
"ffwasm": "0.0.5",
|
"ffwasm": "0.0.6",
|
||||||
"fnv-plus": "^1.3.1",
|
"fnv-plus": "^1.3.1",
|
||||||
"r1csfile": "0.0.2",
|
"r1csfile": "0.0.3",
|
||||||
"tmp-promise": "^2.0.2",
|
"tmp-promise": "^2.0.2",
|
||||||
"wasmbuilder": "0.0.9"
|
"wasmbuilder": "0.0.10"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^6.8.0",
|
"eslint": "^6.8.0",
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ async function c_tester(circomFile, _options) {
|
|||||||
);
|
);
|
||||||
} else throw("Unsupported platform");
|
} else throw("Unsupported platform");
|
||||||
|
|
||||||
const cdir = path.join(__dirname, "..", "..", "node_modules", "circom_runtime", "c");
|
const cdir = path.join(path.dirname(require.resolve("circom_runtime")), "c");
|
||||||
|
|
||||||
await exec("g++" +
|
await exec("g++" +
|
||||||
` ${path.join(cdir, "main.cpp")}` +
|
` ${path.join(cdir, "main.cpp")}` +
|
||||||
|
|||||||
@@ -55,9 +55,8 @@ class WasmTester {
|
|||||||
await this.dir.cleanup();
|
await this.dir.cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
async calculateWitness(input) {
|
async calculateWitness(input, sanityCheck) {
|
||||||
|
return await this.witnessCalculator.calculateWitness(input, sanityCheck);
|
||||||
return await this.witnessCalculator.calculateWitness(input);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadSymbols() {
|
async loadSymbols() {
|
||||||
|
|||||||
@@ -624,6 +624,9 @@ function execReturn(ctx, ast) {
|
|||||||
function execVariable(ctx, ast) {
|
function execVariable(ctx, ast) {
|
||||||
|
|
||||||
const v = ctx.refs[ast.refId];
|
const v = ctx.refs[ast.refId];
|
||||||
|
if (!v) {
|
||||||
|
return ctx.throwError(ast, "Variable not defined: "+ast.name);
|
||||||
|
}
|
||||||
|
|
||||||
const sels = [];
|
const sels = [];
|
||||||
for (let i=0; i< ast.selectors.length; i++) {
|
for (let i=0; i< ast.selectors.length; i++) {
|
||||||
|
|||||||
@@ -175,17 +175,17 @@ function gen(ctx, ast) {
|
|||||||
} else if (ast.op == ">>") {
|
} else if (ast.op == ">>") {
|
||||||
return genOp(ctx, ast, "shr", 2);
|
return genOp(ctx, ast, "shr", 2);
|
||||||
} else if (ast.op == "<") {
|
} else if (ast.op == "<") {
|
||||||
return genOp(ctx, ast, "lt", 2);
|
return genOp(ctx, ast, "lt", 2, true);
|
||||||
} else if (ast.op == ">") {
|
} else if (ast.op == ">") {
|
||||||
return genOp(ctx, ast, "gt", 2);
|
return genOp(ctx, ast, "gt", 2, true);
|
||||||
} else if (ast.op == "<=") {
|
} else if (ast.op == "<=") {
|
||||||
return genOp(ctx, ast, "leq", 2);
|
return genOp(ctx, ast, "leq", 2, true);
|
||||||
} else if (ast.op == ">=") {
|
} else if (ast.op == ">=") {
|
||||||
return genOp(ctx, ast, "geq", 2);
|
return genOp(ctx, ast, "geq", 2, true);
|
||||||
} else if (ast.op == "==") {
|
} else if (ast.op == "==") {
|
||||||
return genOp(ctx, ast, "eq", 2);
|
return genOp(ctx, ast, "eq", 2, true);
|
||||||
} else if (ast.op == "!=") {
|
} else if (ast.op == "!=") {
|
||||||
return genOp(ctx, ast, "neq", 2);
|
return genOp(ctx, ast, "neq", 2, true);
|
||||||
} else if (ast.op == "?") {
|
} else if (ast.op == "?") {
|
||||||
return genTerCon(ctx, ast);
|
return genTerCon(ctx, ast);
|
||||||
} else {
|
} else {
|
||||||
@@ -1121,7 +1121,7 @@ function genOpOp(ctx, ast, op, lr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function genOp(ctx, ast, op, nOps) {
|
function genOp(ctx, ast, op, nOps, adjustBool) {
|
||||||
const vals = [];
|
const vals = [];
|
||||||
const valRefs = [];
|
const valRefs = [];
|
||||||
|
|
||||||
@@ -1159,7 +1159,8 @@ function genOp(ctx, ast, op, nOps) {
|
|||||||
for (let i=0; i<nOps; i++) {
|
for (let i=0; i<nOps; i++) {
|
||||||
params.push(vals[i].value[0]);
|
params.push(vals[i].value[0]);
|
||||||
}
|
}
|
||||||
rRef = newRef(ctx, "BIGINT", "_tmp", ctx.field[op](...params));
|
|
||||||
|
rRef = newRef(ctx, "BIGINT", "_tmp", adjustBool ? (ctx.field[op](...params)?bigInt.one:bigInt.zero) : ctx.field[op](...params));
|
||||||
}
|
}
|
||||||
return rRef;
|
return rRef;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,12 +85,6 @@ class LCAlgebra {
|
|||||||
const self = this;
|
const self = this;
|
||||||
this.field= aField;
|
this.field= aField;
|
||||||
[
|
[
|
||||||
["lt",2],
|
|
||||||
["leq",2],
|
|
||||||
["eq",2],
|
|
||||||
["neq",2],
|
|
||||||
["geq",2],
|
|
||||||
["gt",2],
|
|
||||||
["idiv",2],
|
["idiv",2],
|
||||||
["mod",2],
|
["mod",2],
|
||||||
["band",2],
|
["band",2],
|
||||||
@@ -102,12 +96,18 @@ class LCAlgebra {
|
|||||||
["lnot",2],
|
["lnot",2],
|
||||||
["shl",2],
|
["shl",2],
|
||||||
["shr",2],
|
["shr",2],
|
||||||
|
["lt",2, true],
|
||||||
|
["leq",2, true],
|
||||||
|
["eq",2, true],
|
||||||
|
["neq",2, true],
|
||||||
|
["geq",2, true],
|
||||||
|
["gt",2, true]
|
||||||
].forEach( (op) => {
|
].forEach( (op) => {
|
||||||
self._genNQOp(op[0], op[1]);
|
self._genNQOp(op[0], op[1], op[2]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_genNQOp(op, nOps) {
|
_genNQOp(op, nOps, adjustBool) {
|
||||||
const self=this;
|
const self=this;
|
||||||
self[op] = function() {
|
self[op] = function() {
|
||||||
const operands = [];
|
const operands = [];
|
||||||
@@ -118,7 +118,7 @@ class LCAlgebra {
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
t: "N",
|
t: "N",
|
||||||
v: self.field[op](...operands)
|
v: adjustBool ? ( self.field[op](...operands) ? bigInt.one: bigInt.zero) : self.field[op](...operands)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,7 +103,11 @@ async function buildR1cs(ctx, fileName) {
|
|||||||
|
|
||||||
async function writeU64(v, pos) {
|
async function writeU64(v, pos) {
|
||||||
const b = Buffer.allocUnsafe(8);
|
const b = Buffer.allocUnsafe(8);
|
||||||
b.writeBigUInt64LE(BigInt(v));
|
|
||||||
|
const LSB = v & 0xFFFFFFFF;
|
||||||
|
const MSB = Math.floor(v / 0x100000000);
|
||||||
|
b.writeInt32LE(LSB, 0);
|
||||||
|
b.writeInt32LE(MSB, 4);
|
||||||
|
|
||||||
await fd.write(b, 0, 8, pos);
|
await fd.write(b, 0, 8, pos);
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ function fnvHash(str) {
|
|||||||
|
|
||||||
|
|
||||||
function stringifyBigInts(o) {
|
function stringifyBigInts(o) {
|
||||||
if ((typeof(o) == "bigint") || o.isZero !== undefined) {
|
if ((typeof(o) == "bigint") || o.eq !== undefined) {
|
||||||
return o.toString(10);
|
return o.toString(10);
|
||||||
} else if (Array.isArray(o)) {
|
} else if (Array.isArray(o)) {
|
||||||
return o.map(stringifyBigInts);
|
return o.map(stringifyBigInts);
|
||||||
|
|||||||
Reference in New Issue
Block a user