Compare commits
11 Commits
v0.2.4
...
tornado-tr
| Author | SHA1 | Date | |
|---|---|---|---|
| fdcb762030 | |||
| e9256fbf85 | |||
|
|
d20d53411d | ||
|
|
f4e209728e | ||
|
|
c90b18e93b | ||
|
|
5935ac69df | ||
|
|
45f190b445 | ||
|
|
8423282b8c | ||
|
|
1e04fc0325 | ||
|
|
1f9d0bd37f | ||
|
|
411a7d7576 |
1
.npmrc
Normal file
1
.npmrc
Normal file
@@ -0,0 +1 @@
|
||||
@tornado:registry=https://git.tornado.ws/api/packages/tornado-packages/npm/
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
- This repository contains a library of circuit templates.
|
||||
- All files are copyrighted under 2018 0KIMS association and part of the free software [circom](https://github.com/iden3/circom) (Zero Knowledge Circuit Compiler).
|
||||
- You can read more about the circom language in [the circom documentation webpage](https://docs.circom.io/).
|
||||
|
||||
## Organisation
|
||||
|
||||
@@ -14,4 +15,4 @@ This respository contains 5 folders:
|
||||
- `src`: it contains similar implementation of circuits in JavaScript.
|
||||
- `test`: tests.
|
||||
|
||||
A description of the specific circuit templates for the `circuit` folder will be soon updated.
|
||||
A description of the specific circuit templates for the `circuit` folder will be soon updated.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const bn128 = require("snarkjs").bn128;
|
||||
const bigInt = require("snarkjs").bigInt;
|
||||
const bn128 = require("@tornado/snarkjs").bn128;
|
||||
const bigInt = require("@tornado/snarkjs").bigInt;
|
||||
const createBlakeHash = require("blake-hash");
|
||||
const babyJub = require("../src/babyjub");
|
||||
|
||||
@@ -8,17 +8,17 @@ function getPoint(S) {
|
||||
const h = createBlakeHash("blake256").update(S).digest();
|
||||
|
||||
if (h.length != 32) {
|
||||
throw new Error("Invalid length")
|
||||
throw new Error("Invalid length");
|
||||
}
|
||||
|
||||
let sign = false;
|
||||
if (h[31] & 0x80) {
|
||||
h[31] = h[31] & 0x7F;
|
||||
h[31] = h[31] & 0x7f;
|
||||
sign = true;
|
||||
}
|
||||
|
||||
let y = bigInt(0);
|
||||
for (let i=0; i<32; i++) {
|
||||
for (let i = 0; i < 32; i++) {
|
||||
y = y.shl(8);
|
||||
y = y.add(bigInt(h[i]));
|
||||
}
|
||||
@@ -28,9 +28,7 @@ function getPoint(S) {
|
||||
|
||||
const y2 = F.square(y);
|
||||
|
||||
let x = F.sqrt(F.div(
|
||||
F.sub(F.one, y2),
|
||||
F.sub(a, F.mul(d, y2))));
|
||||
let x = F.sqrt(F.div(F.sub(F.one, y2), F.sub(a, F.mul(d, y2))));
|
||||
|
||||
if (x == null) return null;
|
||||
|
||||
@@ -43,41 +41,34 @@ function getPoint(S) {
|
||||
return p8;
|
||||
}
|
||||
|
||||
|
||||
function generatePoint(S) {
|
||||
let p= null;
|
||||
let p = null;
|
||||
let idx = 0;
|
||||
while (p==null) {
|
||||
while (p == null) {
|
||||
let sidx = "" + idx;
|
||||
while (sidx.length<16) sidx = "0"+sidx;
|
||||
p = getPoint(S+"_"+sidx);
|
||||
while (sidx.length < 16) sidx = "0" + sidx;
|
||||
p = getPoint(S + "_" + sidx);
|
||||
idx++;
|
||||
}
|
||||
if (!babyJub.inCurve(p)){
|
||||
if (!babyJub.inCurve(p)) {
|
||||
throw new Error("Point not in curve");
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const g = [
|
||||
bigInt("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
|
||||
bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203")];
|
||||
bigInt("16950150798460657717958625567821834550301663161624707787222815936182638968203"),
|
||||
];
|
||||
|
||||
// Sanity check
|
||||
if (!babyJub.inCurve(g)) {
|
||||
throw new Error("Generator not In curve -> Some thing goes wrong...");
|
||||
}
|
||||
|
||||
for (let i=0; i<25; i++) {
|
||||
let S = "" +i;
|
||||
while (S.length<16) S = "0"+S;
|
||||
const P = generatePoint("Iden3_PedersenGenerator_"+S);
|
||||
for (let i = 0; i < 25; i++) {
|
||||
let S = "" + i;
|
||||
while (S.length < 16) S = "0" + S;
|
||||
const P = generatePoint("Iden3_PedersenGenerator_" + S);
|
||||
console.log(`[${P[0].toString()}, ${P[1].toString()}]`);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -43,10 +43,9 @@ template Poseidon(nInputs) {
|
||||
// Using recommended parameters from whitepaper https://eprint.iacr.org/2019/458.pdf (table 2, table 8)
|
||||
// Generated by https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/calc_round_numbers.py
|
||||
// And rounded up to nearest integer that divides by t
|
||||
var N_ROUNDS_P[8] = [56, 57, 56, 60, 60, 63, 64, 63];
|
||||
var t = nInputs + 1;
|
||||
var nRoundsF = 8;
|
||||
var nRoundsP = N_ROUNDS_P[t - 2];
|
||||
var nRoundsP = 35;
|
||||
var C[t*(nRoundsF + nRoundsP)] = POSEIDON_C(t);
|
||||
var M[t][t] = POSEIDON_M(t);
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -22,6 +22,8 @@ include "t1.circom";
|
||||
include "t2.circom";
|
||||
include "../binsum.circom";
|
||||
include "sigmaplus.circom";
|
||||
include "sha256compression_function.circom";
|
||||
|
||||
|
||||
template Sha256compression() {
|
||||
signal input hin[256];
|
||||
@@ -37,7 +39,11 @@ template Sha256compression() {
|
||||
signal h[65][32];
|
||||
signal w[64][32];
|
||||
|
||||
|
||||
var outCalc[256] = sha256compression(hin, inp);
|
||||
|
||||
var i;
|
||||
for (i=0; i<256; i++) out[i] <-- outCalc[i];
|
||||
|
||||
component sigmaPlus[48];
|
||||
for (i=0; i<48; i++) sigmaPlus[i] = SigmaPlus();
|
||||
@@ -147,13 +153,13 @@ template Sha256compression() {
|
||||
}
|
||||
|
||||
for (k=0; k<32; k++) {
|
||||
out[31-k] <== fsum[0].out[k];
|
||||
out[32+31-k] <== fsum[1].out[k];
|
||||
out[64+31-k] <== fsum[2].out[k];
|
||||
out[96+31-k] <== fsum[3].out[k];
|
||||
out[128+31-k] <== fsum[4].out[k];
|
||||
out[160+31-k] <== fsum[5].out[k];
|
||||
out[192+31-k] <== fsum[6].out[k];
|
||||
out[224+31-k] <== fsum[7].out[k];
|
||||
out[31-k] === fsum[0].out[k];
|
||||
out[32+31-k] === fsum[1].out[k];
|
||||
out[64+31-k] === fsum[2].out[k];
|
||||
out[96+31-k] === fsum[3].out[k];
|
||||
out[128+31-k] === fsum[4].out[k];
|
||||
out[160+31-k] === fsum[5].out[k];
|
||||
out[192+31-k] === fsum[6].out[k];
|
||||
out[224+31-k] === fsum[7].out[k];
|
||||
}
|
||||
}
|
||||
|
||||
112
circuits/sha256/sha256compression_function.circom
Normal file
112
circuits/sha256/sha256compression_function.circom
Normal file
@@ -0,0 +1,112 @@
|
||||
// signal input hin[256];
|
||||
// signal input inp[512];
|
||||
// signal output out[256];
|
||||
|
||||
|
||||
function rrot(x, n) {
|
||||
return ((x >> n) | (x << (32-n))) & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
function bsigma0(x) {
|
||||
return rrot(x,2) ^ rrot(x,13) ^ rrot(x,22);
|
||||
}
|
||||
|
||||
function bsigma1(x) {
|
||||
return rrot(x,6) ^ rrot(x,11) ^ rrot(x,25);
|
||||
}
|
||||
|
||||
function ssigma0(x) {
|
||||
return rrot(x,7) ^ rrot(x,18) ^ (x >> 3);
|
||||
}
|
||||
|
||||
function ssigma1(x) {
|
||||
return rrot(x,17) ^ rrot(x,19) ^ (x >> 10);
|
||||
}
|
||||
|
||||
function Maj(x, y, z) {
|
||||
return (x&y) ^ (x&z) ^ (y&z);
|
||||
}
|
||||
|
||||
function Ch(x, y, z) {
|
||||
return (x & y) ^ ((0xFFFFFFFF ^x) & z);
|
||||
}
|
||||
|
||||
function sha256K(i) {
|
||||
var k[64] = [
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||
];
|
||||
return k[i];
|
||||
}
|
||||
|
||||
function sha256compression(hin, inp) {
|
||||
var H[8];
|
||||
var a;
|
||||
var b;
|
||||
var c;
|
||||
var d;
|
||||
var e;
|
||||
var f;
|
||||
var g;
|
||||
var h;
|
||||
var out[256];
|
||||
for (var i=0; i<8; i++) {
|
||||
H[i] = 0;
|
||||
for (var j=0; j<32; j++) {
|
||||
H[i] += hin[i*32+j] << j;
|
||||
}
|
||||
}
|
||||
a=H[0];
|
||||
b=H[1];
|
||||
c=H[2];
|
||||
d=H[3];
|
||||
e=H[4];
|
||||
f=H[5];
|
||||
g=H[6];
|
||||
h=H[7];
|
||||
var w[64];
|
||||
var T1;
|
||||
var T2;
|
||||
for (var i=0; i<64; i++) {
|
||||
if (i<16) {
|
||||
w[i]=0;
|
||||
for (var j=0; j<32; j++) {
|
||||
w[i] += inp[i*32+31-j]<<j;
|
||||
}
|
||||
} else {
|
||||
w[i] = (ssigma1(w[i-2]) + w[i-7] + ssigma0(w[i-15]) + w[i-16]) & 0xFFFFFFFF;
|
||||
}
|
||||
T1 = (h + bsigma1(e) + Ch(e,f,g) + sha256K(i) + w[i]) & 0xFFFFFFFF;
|
||||
T2 = (bsigma0(a) + Maj(a,b,c)) & 0xFFFFFFFF;
|
||||
|
||||
h=g;
|
||||
g=f;
|
||||
f=e;
|
||||
e=(d+T1) & 0xFFFFFFFF;
|
||||
d=c;
|
||||
c=b;
|
||||
b=a;
|
||||
a=(T1+T2) & 0xFFFFFFFF;
|
||||
|
||||
}
|
||||
H[0] = H[0] + a;
|
||||
H[1] = H[1] + b;
|
||||
H[2] = H[2] + c;
|
||||
H[3] = H[3] + d;
|
||||
H[4] = H[4] + e;
|
||||
H[5] = H[5] + f;
|
||||
H[6] = H[6] + g;
|
||||
H[7] = H[7] + h;
|
||||
for (var i=0; i<8; i++) {
|
||||
for (var j=0; j<32; j++) {
|
||||
out[i*32+31-j] = (H[i] >> j) & 1;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
12564
package-lock.json
generated
12564
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
73
package.json
73
package.json
@@ -1,38 +1,39 @@
|
||||
{
|
||||
"name": "circomlib",
|
||||
"version": "0.2.4",
|
||||
"description": "Basic circuits library for Circom",
|
||||
"main": "index.js",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha --max-old-space-size=4000"
|
||||
},
|
||||
"keywords": [
|
||||
"pedersen",
|
||||
"hash",
|
||||
"ethereum",
|
||||
"circuit",
|
||||
"circom",
|
||||
"zksnark"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/iden3/circomlib.git"
|
||||
},
|
||||
"author": "0Kims",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"blake-hash": "^1.1.0",
|
||||
"blake2b": "^2.1.3",
|
||||
"circom": "0.5.21",
|
||||
"ffjavascript": "0.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^6.8.0",
|
||||
"ganache-cli": "^6.10.1",
|
||||
"mocha": "^7.1.1",
|
||||
"web3": "^1.2.11"
|
||||
}
|
||||
"name": "@tornado/circomlib",
|
||||
"version": "0.4.1",
|
||||
"description": "Basic circuits library for Circom",
|
||||
"main": "index.js",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha --max-old-space-size=4000"
|
||||
},
|
||||
"keywords": [
|
||||
"pedersen",
|
||||
"hash",
|
||||
"ethereum",
|
||||
"circuit",
|
||||
"circom",
|
||||
"zksnark"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.tornado.ws/tornado-packages/circomlib.git"
|
||||
},
|
||||
"author": "0Kims",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"@tornado/snarkjs": "0.1.20",
|
||||
"blake-hash": "^1.1.0",
|
||||
"blake2b": "^2.1.3",
|
||||
"circom": "0.5.33",
|
||||
"ffjavascript": "0.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^6.8.0",
|
||||
"ganache-cli": "^6.12.1",
|
||||
"mocha": "^7.1.1",
|
||||
"web3": "^1.3.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,23 +3,21 @@
|
||||
//
|
||||
|
||||
const Contract = require("./evmasm");
|
||||
const G2 = require("snarkjs").bn128.G2;
|
||||
|
||||
const G2 = require("@tornado/snarkjs").bn128.G2;
|
||||
|
||||
function toHex256(a) {
|
||||
let S = a.toString(16);
|
||||
while (S.length < 64) S="0"+S;
|
||||
while (S.length < 64) S = "0" + S;
|
||||
return "0x" + S;
|
||||
}
|
||||
|
||||
function createCode(P, w) {
|
||||
|
||||
const C = new Contract();
|
||||
|
||||
const NPOINTS = 1 << (w-1);
|
||||
const NPOINTS = 1 << (w - 1);
|
||||
|
||||
const VAR_POS = C.allocMem(32);
|
||||
const VAR_POINTS = C.allocMem( (NPOINTS)*4*32);
|
||||
const VAR_POINTS = C.allocMem(NPOINTS * 4 * 32);
|
||||
const savedP = C.allocMem(32);
|
||||
const savedZ3 = C.allocMem(32);
|
||||
|
||||
@@ -37,7 +35,7 @@ function createCode(P, w) {
|
||||
|
||||
storeVals();
|
||||
|
||||
C.push( Math.floor(255/w)*w ); // pos := 255
|
||||
C.push(Math.floor(255 / w) * w); // pos := 255
|
||||
C.push(VAR_POS);
|
||||
C.mstore();
|
||||
|
||||
@@ -49,38 +47,38 @@ function createCode(P, w) {
|
||||
C.push(0);
|
||||
C.push(0);
|
||||
|
||||
C.label("begin_loop"); // ACC_X ACC_Y ACC_Z q
|
||||
C.label("begin_loop"); // ACC_X ACC_Y ACC_Z q
|
||||
|
||||
C.internalCall("double");
|
||||
|
||||
// g = (e>>pos)&MASK
|
||||
C.push(4);
|
||||
C.calldataload(); // e ACC_X ACC_Y ACC_Z q
|
||||
C.calldataload(); // e ACC_X ACC_Y ACC_Z q
|
||||
|
||||
C.push(VAR_POS);
|
||||
C.mload(); // pos e ACC_X ACC_Y ACC_Z q
|
||||
C.mload(); // pos e ACC_X ACC_Y ACC_Z q
|
||||
C.shr();
|
||||
|
||||
C.push(NPOINTS-1);
|
||||
C.and(); // g ACC_X ACC_Y ACC_Z q
|
||||
C.push(NPOINTS - 1);
|
||||
C.and(); // g ACC_X ACC_Y ACC_Z q
|
||||
|
||||
C.internalCall("add"); // acc_x acc_y acc_z
|
||||
C.internalCall("add"); // acc_x acc_y acc_z
|
||||
|
||||
C.push(VAR_POS);
|
||||
C.mload(); // pos acc_x acc_y acc_z
|
||||
C.dup(0); // pos pos acc_x acc_y acc_z
|
||||
C.push(0); // 0 pos pos acc_x acc_y acc_z
|
||||
C.eq(); // eq pos acc_x acc_y acc_z
|
||||
C.jmpi("after_loop"); // pos acc_x acc_y acc_z
|
||||
C.push(w); // 5 pos acc_x acc_y acc_z
|
||||
C.sub(); // pos acc_x acc_y acc_z
|
||||
C.mload(); // pos acc_x acc_y acc_z
|
||||
C.dup(0); // pos pos acc_x acc_y acc_z
|
||||
C.push(0); // 0 pos pos acc_x acc_y acc_z
|
||||
C.eq(); // eq pos acc_x acc_y acc_z
|
||||
C.jmpi("after_loop"); // pos acc_x acc_y acc_z
|
||||
C.push(w); // 5 pos acc_x acc_y acc_z
|
||||
C.sub(); // pos acc_x acc_y acc_z
|
||||
C.push(VAR_POS);
|
||||
C.mstore(); // acc_x acc_y acc_z
|
||||
C.mstore(); // acc_x acc_y acc_z
|
||||
C.jmp("begin_loop");
|
||||
C.label("after_loop"); // pos acc_x acc_y acc_z
|
||||
C.pop(); // acc_x acc_y acc_z
|
||||
C.label("after_loop"); // pos acc_x acc_y acc_z
|
||||
C.pop(); // acc_x acc_y acc_z
|
||||
|
||||
C.internalCall("affine"); // acc_x acc_y
|
||||
C.internalCall("affine"); // acc_x acc_y
|
||||
|
||||
C.push(0);
|
||||
C.mstore();
|
||||
@@ -95,17 +93,16 @@ function createCode(P, w) {
|
||||
C.push("0x00");
|
||||
C.return();
|
||||
|
||||
|
||||
double();
|
||||
addPoint();
|
||||
affine();
|
||||
|
||||
return C.createTxData();
|
||||
|
||||
function add(a,b,q) {
|
||||
function add(a, b, q) {
|
||||
C.dup(q);
|
||||
C.dup(a+1 + 1);
|
||||
C.dup(b+1 + 2);
|
||||
C.dup(a + 1 + 1);
|
||||
C.dup(b + 1 + 2);
|
||||
C.addmod();
|
||||
C.dup(q + 1);
|
||||
C.dup(a + 2);
|
||||
@@ -113,73 +110,73 @@ function createCode(P, w) {
|
||||
C.addmod();
|
||||
}
|
||||
|
||||
function sub(a,b,q) {
|
||||
C.dup(q); // q
|
||||
C.dup(a+1 + 1); // ai q
|
||||
C.dub(q + 2); // q ai q
|
||||
C.dup(b+1 + 3); // bi q ai q
|
||||
C.sub(); // -bi ai q
|
||||
C.addmod(); // ci
|
||||
C.dup(q + 1); // q ci
|
||||
C.dup(a + 2); // ar q ci
|
||||
C.dup(q + 3); // q ar q ci
|
||||
C.dup(b + 4); // br q ar q ci
|
||||
C.sub(); // -br ar q ci
|
||||
C.addmod(); // cr ci
|
||||
function sub(a, b, q) {
|
||||
C.dup(q); // q
|
||||
C.dup(a + 1 + 1); // ai q
|
||||
C.dub(q + 2); // q ai q
|
||||
C.dup(b + 1 + 3); // bi q ai q
|
||||
C.sub(); // -bi ai q
|
||||
C.addmod(); // ci
|
||||
C.dup(q + 1); // q ci
|
||||
C.dup(a + 2); // ar q ci
|
||||
C.dup(q + 3); // q ar q ci
|
||||
C.dup(b + 4); // br q ar q ci
|
||||
C.sub(); // -br ar q ci
|
||||
C.addmod(); // cr ci
|
||||
}
|
||||
|
||||
function mul(a, b, q) {
|
||||
C.dup(q); // q
|
||||
C.dup(q + 1); // q q
|
||||
C.dup(a + 2); // ar q q
|
||||
C.dup(b+1 + 3); // bi ar q q
|
||||
C.mulmod(); // ci1 q
|
||||
C.dup(q + 2); // q ci1 q
|
||||
C.dup(a+1 + 3); // ai q ci1 q
|
||||
C.dup(b + 4); // ar ai q ci1 q
|
||||
C.mulmod(); // ci2 ci1 q
|
||||
C.addmod(); // ci
|
||||
C.dup(q + 1); // q ci
|
||||
C.dup(q + 2); // q q ci
|
||||
C.dup(q + 3); // q q q ci
|
||||
C.dup(a+1 + 4); // ai q q ci
|
||||
C.dup(b+1 + 5); // bi ai q q ci
|
||||
C.mulmod(); // cr2 q q ci
|
||||
C.sub(); // -cr2 q ci
|
||||
C.dup(q + 3); // q -cr2 q ci
|
||||
C.dup(a + 4); // ar q -cr2 q ci
|
||||
C.dup(b + 5); // br ar q -cr2 q ci
|
||||
C.mulmod(); // cr1 -cr2 q ci
|
||||
C.addmod(); // cr ci
|
||||
C.dup(q); // q
|
||||
C.dup(q + 1); // q q
|
||||
C.dup(a + 2); // ar q q
|
||||
C.dup(b + 1 + 3); // bi ar q q
|
||||
C.mulmod(); // ci1 q
|
||||
C.dup(q + 2); // q ci1 q
|
||||
C.dup(a + 1 + 3); // ai q ci1 q
|
||||
C.dup(b + 4); // ar ai q ci1 q
|
||||
C.mulmod(); // ci2 ci1 q
|
||||
C.addmod(); // ci
|
||||
C.dup(q + 1); // q ci
|
||||
C.dup(q + 2); // q q ci
|
||||
C.dup(q + 3); // q q q ci
|
||||
C.dup(a + 1 + 4); // ai q q ci
|
||||
C.dup(b + 1 + 5); // bi ai q q ci
|
||||
C.mulmod(); // cr2 q q ci
|
||||
C.sub(); // -cr2 q ci
|
||||
C.dup(q + 3); // q -cr2 q ci
|
||||
C.dup(a + 4); // ar q -cr2 q ci
|
||||
C.dup(b + 5); // br ar q -cr2 q ci
|
||||
C.mulmod(); // cr1 -cr2 q ci
|
||||
C.addmod(); // cr ci
|
||||
}
|
||||
|
||||
function square(a, q) {
|
||||
C.dup(q); // q
|
||||
C.dup(q + 1); // q q
|
||||
C.dup(a + 2); // ar q q
|
||||
C.dup(a+1 + 3); // ai ar q q
|
||||
C.mulmod(); // arai q
|
||||
C.dup(0); // arai arai q
|
||||
C.addmod(); // ci
|
||||
C.dup(q + 1); // q ci
|
||||
C.dup(q + 2); // q q ci
|
||||
C.dup(q + 3); // q q q ci
|
||||
C.dup(a+1 + 4); // ai q q ci
|
||||
C.dup(a+1 + 5); // ai ai q q ci
|
||||
C.mulmod(); // cr2 q q ci
|
||||
C.sub(); // -cr2 q ci
|
||||
C.dup(q + 3); // q -cr2 q ci
|
||||
C.dup(a + 4); // ar q -cr2 q ci
|
||||
C.dup(a + 5); // br ar q -cr2 q ci
|
||||
C.mulmod(); // cr1 -cr2 q ci
|
||||
C.addmod(); // cr ci
|
||||
C.dup(q); // q
|
||||
C.dup(q + 1); // q q
|
||||
C.dup(a + 2); // ar q q
|
||||
C.dup(a + 1 + 3); // ai ar q q
|
||||
C.mulmod(); // arai q
|
||||
C.dup(0); // arai arai q
|
||||
C.addmod(); // ci
|
||||
C.dup(q + 1); // q ci
|
||||
C.dup(q + 2); // q q ci
|
||||
C.dup(q + 3); // q q q ci
|
||||
C.dup(a + 1 + 4); // ai q q ci
|
||||
C.dup(a + 1 + 5); // ai ai q q ci
|
||||
C.mulmod(); // cr2 q q ci
|
||||
C.sub(); // -cr2 q ci
|
||||
C.dup(q + 3); // q -cr2 q ci
|
||||
C.dup(a + 4); // ar q -cr2 q ci
|
||||
C.dup(a + 5); // br ar q -cr2 q ci
|
||||
C.mulmod(); // cr1 -cr2 q ci
|
||||
C.addmod(); // cr ci
|
||||
}
|
||||
|
||||
function add1(a, q) {
|
||||
C.dup(a+1); // im
|
||||
C.dup(1 + q); // q
|
||||
C.dup(2 + a); // re q im
|
||||
C.push(1); // 1 re q im
|
||||
C.dup(a + 1); // im
|
||||
C.dup(1 + q); // q
|
||||
C.dup(2 + a); // re q im
|
||||
C.push(1); // 1 re q im
|
||||
C.addmod();
|
||||
}
|
||||
|
||||
@@ -187,220 +184,212 @@ function createCode(P, w) {
|
||||
C.dup(a);
|
||||
C.dup(b);
|
||||
C.eq();
|
||||
C.dup(a+1);
|
||||
C.dup(a+1);
|
||||
C.dup(a + 1);
|
||||
C.dup(a + 1);
|
||||
C.and();
|
||||
}
|
||||
|
||||
function rm(a) {
|
||||
if (a>0) C.swap(a);
|
||||
if (a > 0) C.swap(a);
|
||||
C.pop();
|
||||
if (a>0) C.swap(a);
|
||||
if (a > 0) C.swap(a);
|
||||
C.pop();
|
||||
}
|
||||
|
||||
function double() {
|
||||
C.label("double"); // xR, xI, yR, yI, zR zI, q
|
||||
C.label("double"); // xR, xI, yR, yI, zR zI, q
|
||||
|
||||
C.dup(4);
|
||||
C.iszero();
|
||||
C.dup(6);
|
||||
C.iszero();
|
||||
C.and();
|
||||
C.jumpi("enddouble"); // X Y Z q
|
||||
|
||||
C.jumpi("enddouble"); // X Y Z q
|
||||
|
||||
// Z3 = 2*Y*Z // Remove Z
|
||||
mul(2, 4, 6); // yz X Y Z q
|
||||
rm(6); // X Y yz q
|
||||
mul(2, 4, 6); // yz X Y Z q
|
||||
rm(6); // X Y yz q
|
||||
|
||||
add(4, 4, 6); // 2yz X Y yz q
|
||||
rm(6); // X Y Z3 q
|
||||
add(4, 4, 6); // 2yz X Y yz q
|
||||
rm(6); // X Y Z3 q
|
||||
|
||||
// A = X^2
|
||||
square(0,6); // A X Y Z3 q
|
||||
square(0, 6); // A X Y Z3 q
|
||||
|
||||
// B = Y^2 // Remove Y
|
||||
square(4,8); // B A X Y Z3 q
|
||||
rm(6); // A X B Z3 q
|
||||
square(4, 8); // B A X Y Z3 q
|
||||
rm(6); // A X B Z3 q
|
||||
|
||||
// C = B^2
|
||||
square(4,8); // C A X B Z3 q
|
||||
square(4, 8); // C A X B Z3 q
|
||||
|
||||
// D = (X+B)^2-A-C // Remove X, Remove B
|
||||
add(4,6, 10); // X+B C A X B Z3 q
|
||||
rm(6); // C A X+B B Z3 q
|
||||
rm(6); // A X+B C Z3 q
|
||||
square(2,8); // (X+B)^2 A X+B C Z3 q
|
||||
rm(4); // A (X+B)^2 C Z3 q
|
||||
sub(2, 0, 8); // (X+B)^2-A A (X+B)^2 C Z3 q
|
||||
rm(4); // A (X+B)^2-A C Z3 q
|
||||
sub(2, 4, 8); // (X+B)^2-A-C A (X+B)^2-A C Z3 q
|
||||
rm(4); // A D C Z3 q
|
||||
add(4, 6, 10); // X+B C A X B Z3 q
|
||||
rm(6); // C A X+B B Z3 q
|
||||
rm(6); // A X+B C Z3 q
|
||||
square(2, 8); // (X+B)^2 A X+B C Z3 q
|
||||
rm(4); // A (X+B)^2 C Z3 q
|
||||
sub(2, 0, 8); // (X+B)^2-A A (X+B)^2 C Z3 q
|
||||
rm(4); // A (X+B)^2-A C Z3 q
|
||||
sub(2, 4, 8); // (X+B)^2-A-C A (X+B)^2-A C Z3 q
|
||||
rm(4); // A D C Z3 q
|
||||
|
||||
// D = D+D
|
||||
add(2,2, 8); // D+D A D C Z3 q
|
||||
rm(4); // A D C Z3 q
|
||||
add(2, 2, 8); // D+D A D C Z3 q
|
||||
rm(4); // A D C Z3 q
|
||||
|
||||
// E=A+A+A
|
||||
add(0, 0, 8); // 2A A D C Z3 q
|
||||
add(0, 2, 10); // 3A 2A A D C Z3 q
|
||||
rm(4); // 2A 3A D C Z3 q
|
||||
rm(0); // E D C Z3 q
|
||||
add(0, 0, 8); // 2A A D C Z3 q
|
||||
add(0, 2, 10); // 3A 2A A D C Z3 q
|
||||
rm(4); // 2A 3A D C Z3 q
|
||||
rm(0); // E D C Z3 q
|
||||
|
||||
// F=E^2
|
||||
square(0, 8); // F E D C Z3 q
|
||||
square(0, 8); // F E D C Z3 q
|
||||
|
||||
// X3= F - 2*D // Remove F
|
||||
add(4, 4, 10); // 2D F E D C Z3 q
|
||||
sub(2, 0, 12); // F-2D 2D F E D C Z3 q
|
||||
rm(4); // 2D X3 E D C Z3 q
|
||||
rm(0); // X3 E D C Z3 q
|
||||
add(4, 4, 10); // 2D F E D C Z3 q
|
||||
sub(2, 0, 12); // F-2D 2D F E D C Z3 q
|
||||
rm(4); // 2D X3 E D C Z3 q
|
||||
rm(0); // X3 E D C Z3 q
|
||||
|
||||
// Y3 = E * (D - X3) - 8 * C // Remove D C E
|
||||
|
||||
sub(4, 0, 10); // D-X3 X3 E D C Z3 q
|
||||
rm(6); // X3 E D-X3 C Z3 q
|
||||
mul(2, 4, 10); // E*(D-X3) X3 E D-X3 C Z3 q
|
||||
rm(6); // X3 E E*(D-X3) C Z3 q
|
||||
rm(2); // X3 E*(D-X3) C Z3 q
|
||||
add(4, 4, 8); // 2C X3 E*(D-X3) C Z3 q
|
||||
rm(6); // X3 E*(D-X3) 2C Z3 q
|
||||
add(4, 4, 8); // 4C X3 E*(D-X3) 2C Z3 q
|
||||
rm(6); // X3 E*(D-X3) 4C Z3 q
|
||||
add(4, 4, 8); // 8C X3 E*(D-X3) 4C Z3 q
|
||||
rm(6); // X3 E*(D-X3) 8C Z3 q
|
||||
sub(2, 4, 8); // E*(D-X3)-8C X3 E*(D-X3) 8C Z3 q
|
||||
rm(6); // X3 E*(D-X3) Y3 Z3 q
|
||||
rm(2); // X3 Y3 Z3 q
|
||||
sub(4, 0, 10); // D-X3 X3 E D C Z3 q
|
||||
rm(6); // X3 E D-X3 C Z3 q
|
||||
mul(2, 4, 10); // E*(D-X3) X3 E D-X3 C Z3 q
|
||||
rm(6); // X3 E E*(D-X3) C Z3 q
|
||||
rm(2); // X3 E*(D-X3) C Z3 q
|
||||
add(4, 4, 8); // 2C X3 E*(D-X3) C Z3 q
|
||||
rm(6); // X3 E*(D-X3) 2C Z3 q
|
||||
add(4, 4, 8); // 4C X3 E*(D-X3) 2C Z3 q
|
||||
rm(6); // X3 E*(D-X3) 4C Z3 q
|
||||
add(4, 4, 8); // 8C X3 E*(D-X3) 4C Z3 q
|
||||
rm(6); // X3 E*(D-X3) 8C Z3 q
|
||||
sub(2, 4, 8); // E*(D-X3)-8C X3 E*(D-X3) 8C Z3 q
|
||||
rm(6); // X3 E*(D-X3) Y3 Z3 q
|
||||
rm(2); // X3 Y3 Z3 q
|
||||
|
||||
C.label("enddouble");
|
||||
C.returnCall();
|
||||
}
|
||||
|
||||
function addPoint() { // p, xR, xI, yR, yI, zR zI, q
|
||||
function addPoint() {
|
||||
// p, xR, xI, yR, yI, zR zI, q
|
||||
|
||||
|
||||
C.dup(0); // p p X2 Y2 Z2 q
|
||||
C.dup(0); // p p X2 Y2 Z2 q
|
||||
|
||||
C.push(savedP);
|
||||
C.mstore();
|
||||
|
||||
C.iszero(); // X2 Y2 Z2 q
|
||||
C.iszero(); // X2 Y2 Z2 q
|
||||
C.jumpi("endpadd");
|
||||
|
||||
|
||||
C.dup(4);
|
||||
C.iszero();
|
||||
C.dup(6);
|
||||
C.iszero();
|
||||
C.and();
|
||||
C.jumpi("returnP"); // X2 Y2 Z2 q
|
||||
|
||||
|
||||
C.jumpi("returnP"); // X2 Y2 Z2 q
|
||||
|
||||
// lastZ3 = (Z2+1)^2 - Z2^2
|
||||
add1(4, 6); // Z2+1 X2 Y2 Z2 q
|
||||
square(0, 8); // (Z2+1)^2 Z2+1 X2 Y2 Z2 q
|
||||
rm(2); // (Z2+1)^2 X2 Y2 Z2 q
|
||||
square(6, 8); // Z2^2 (Z2+1)^2 X2 Y2 Z2 q
|
||||
add1(4, 6); // Z2+1 X2 Y2 Z2 q
|
||||
square(0, 8); // (Z2+1)^2 Z2+1 X2 Y2 Z2 q
|
||||
rm(2); // (Z2+1)^2 X2 Y2 Z2 q
|
||||
square(6, 8); // Z2^2 (Z2+1)^2 X2 Y2 Z2 q
|
||||
|
||||
sub(2, 0, 10); // (Z2+1)^2-Z2^2 Z2^2 (Z2+1)^2 X2 Y2 Z2 q
|
||||
|
||||
sub(2, 0, 10); // (Z2+1)^2-Z2^2 Z2^2 (Z2+1)^2 X2 Y2 Z2 q
|
||||
|
||||
saveZ3(); // Z2^2 (Z2+1)^2 X2 Y2 Z2 q
|
||||
rm(2); // Z2^2 X2 Y2 Z2 q
|
||||
saveZ3(); // Z2^2 (Z2+1)^2 X2 Y2 Z2 q
|
||||
rm(2); // Z2^2 X2 Y2 Z2 q
|
||||
|
||||
// U2 = X2
|
||||
// S2 = Y2 // Z2^2 U2 S2 Z2 q
|
||||
|
||||
|
||||
// U1 = X1 * Z2^2
|
||||
loadX(); // X1 Z2^2 U2 S2 Z2 q
|
||||
mul(0, 2, 10); // X1*Z2^2 X1 Z2^2 U2 S2 Z2 q
|
||||
rm(2); // X1*Z2^2 Z2^2 U2 S2 Z2 q
|
||||
loadX(); // X1 Z2^2 U2 S2 Z2 q
|
||||
mul(0, 2, 10); // X1*Z2^2 X1 Z2^2 U2 S2 Z2 q
|
||||
rm(2); // X1*Z2^2 Z2^2 U2 S2 Z2 q
|
||||
|
||||
|
||||
mul(2, 8, 10); // Z2^3 U1 Z2^2 U2 S2 Z2 q
|
||||
rm(4); // U1 Z2^3 U2 S2 Z2 q
|
||||
rm(8); // Z2^3 U2 S2 U1 q
|
||||
mul(2, 8, 10); // Z2^3 U1 Z2^2 U2 S2 Z2 q
|
||||
rm(4); // U1 Z2^3 U2 S2 Z2 q
|
||||
rm(8); // Z2^3 U2 S2 U1 q
|
||||
|
||||
// S1 = Y1 * Z1^3
|
||||
loadY(); // Y1 Z2^3 U2 S2 U1 q
|
||||
mul(0, 2, 10); // S1 Y1 Z2^3 U2 S2 U1 q
|
||||
rm(4); // Y1 S1 U2 S2 U1 q
|
||||
rm(0); // S1 U2 S2 U1 q
|
||||
loadY(); // Y1 Z2^3 U2 S2 U1 q
|
||||
mul(0, 2, 10); // S1 Y1 Z2^3 U2 S2 U1 q
|
||||
rm(4); // Y1 S1 U2 S2 U1 q
|
||||
rm(0); // S1 U2 S2 U1 q
|
||||
|
||||
cmp(0, 4); // c1 S1 U2 S2 U1 q
|
||||
cmp(3, 7); // c2 c1 S1 U2 S2 U1 q
|
||||
C.and(); // c2&c1 S1 U2 S2 U1 q
|
||||
cmp(0, 4); // c1 S1 U2 S2 U1 q
|
||||
cmp(3, 7); // c2 c1 S1 U2 S2 U1 q
|
||||
C.and(); // c2&c1 S1 U2 S2 U1 q
|
||||
C.jumpi("double1"); // S1 U2 S2 U1 q
|
||||
|
||||
|
||||
// Returns the double
|
||||
|
||||
// H = U2-U1 // Remove U2
|
||||
C.sub(4, 8, 10); // H S1 U2 S2 U1 q
|
||||
rm(4); // S1 H S2 U1 q
|
||||
C.sub(4, 8, 10); // H S1 U2 S2 U1 q
|
||||
rm(4); // S1 H S2 U1 q
|
||||
|
||||
// // r = 2 * (S2-S1) // Remove S2
|
||||
C.sub(4, 4, 8); // S1-S2 S1 H S2 U1 q
|
||||
rm(6); // S1 H S1-S2 U1 q
|
||||
C.add(4, 4, 8); // 2*(S1-S2) S1 H S1-S2 U1 q
|
||||
rm(6); // S1 H r U1 q
|
||||
C.sub(4, 4, 8); // S1-S2 S1 H S2 U1 q
|
||||
rm(6); // S1 H S1-S2 U1 q
|
||||
C.add(4, 4, 8); // 2*(S1-S2) S1 H S1-S2 U1 q
|
||||
rm(6); // S1 H r U1 q
|
||||
|
||||
// I = (2 * H)^2
|
||||
C.add(2, 2, 8); // 2*H S1 H r U1 q
|
||||
C.square(0, 10); // (2*H)^2 2*H S1 H r U1 q
|
||||
rm(2); // I S1 H r U1 q
|
||||
C.add(2, 2, 8); // 2*H S1 H r U1 q
|
||||
C.square(0, 10); // (2*H)^2 2*H S1 H r U1 q
|
||||
rm(2); // I S1 H r U1 q
|
||||
|
||||
// V = U1 * I
|
||||
mul(8, 0, 10); // V I S1 H r U1 q
|
||||
rm(10); // I S1 H r V q
|
||||
mul(8, 0, 10); // V I S1 H r U1 q
|
||||
rm(10); // I S1 H r V q
|
||||
|
||||
// J = H * I // Remove I
|
||||
mul(4, 0, 10); // J I S1 H r V q
|
||||
rm(2); // J S1 H r V q
|
||||
mul(4, 0, 10); // J I S1 H r V q
|
||||
rm(2); // J S1 H r V q
|
||||
|
||||
// X3 = r^2 - J - 2 * V
|
||||
|
||||
// S1J2 = (S1*J)*2 // Remove S1
|
||||
mul(2, 0, 10); // S1*J J S1 H r V q
|
||||
rm(4); // J S1*J H r V q
|
||||
add(2,2, 10); // (S1*J)*2 J S1*J H r V q
|
||||
rm(4); // J S1J2 H r V q
|
||||
mul(2, 0, 10); // S1*J J S1 H r V q
|
||||
rm(4); // J S1*J H r V q
|
||||
add(2, 2, 10); // (S1*J)*2 J S1*J H r V q
|
||||
rm(4); // J S1J2 H r V q
|
||||
|
||||
// X3 = r^2 - J - 2 * V
|
||||
square(6, 10); // r^2 J S1J2 H r V q
|
||||
sub(0, 2, 12); // r^2-J r^2 J S1J2 H r V q
|
||||
rm(2); // r^2-J J S1J2 H r V q
|
||||
rm(2); // r^2-J S1J2 H r V q
|
||||
add(8, 8, 10); // 2*V r^2-J S1J2 H r V q
|
||||
sub(2, 0, 12); // r^2-J-2*V 2*V r^2-J S1J2 H r V q
|
||||
rm(4); // 2*V X3 S1J2 H r V q
|
||||
rm(0); // X3 S1J2 H r V q
|
||||
square(6, 10); // r^2 J S1J2 H r V q
|
||||
sub(0, 2, 12); // r^2-J r^2 J S1J2 H r V q
|
||||
rm(2); // r^2-J J S1J2 H r V q
|
||||
rm(2); // r^2-J S1J2 H r V q
|
||||
add(8, 8, 10); // 2*V r^2-J S1J2 H r V q
|
||||
sub(2, 0, 12); // r^2-J-2*V 2*V r^2-J S1J2 H r V q
|
||||
rm(4); // 2*V X3 S1J2 H r V q
|
||||
rm(0); // X3 S1J2 H r V q
|
||||
|
||||
// Y3 = r * (V-X3)-S1J2
|
||||
|
||||
sub(8, 0, 10); // V-X3 X3 S1J2 H r V q
|
||||
rm(10); // X3 S1J2 H r V-X3 q
|
||||
mul(6, 8, 10); // r*(V-X3) X3 S1J2 H r V-X3 q
|
||||
rm(8); // X3 S1J2 H r*(V-X3) V-X3 q
|
||||
rm(8); // S1J2 H r*(V-X3) X3 q
|
||||
sub(4, 0, 8); // Y3 S1J2 H r*(V-X3) X3 q
|
||||
rm(6); // S1J2 H Y3 X3 q
|
||||
rm(0); // H Y3 X3 q
|
||||
sub(8, 0, 10); // V-X3 X3 S1J2 H r V q
|
||||
rm(10); // X3 S1J2 H r V-X3 q
|
||||
mul(6, 8, 10); // r*(V-X3) X3 S1J2 H r V-X3 q
|
||||
rm(8); // X3 S1J2 H r*(V-X3) V-X3 q
|
||||
rm(8); // S1J2 H r*(V-X3) X3 q
|
||||
sub(4, 0, 8); // Y3 S1J2 H r*(V-X3) X3 q
|
||||
rm(6); // S1J2 H Y3 X3 q
|
||||
rm(0); // H Y3 X3 q
|
||||
|
||||
// Z3 = lastZ * H
|
||||
loadZ3(); // lastZ3 H Y3 X3 q
|
||||
mul(0, 2, 8); // Z3 lastZ3 H Y3 X3 q
|
||||
rm(4); // lastZ3 Z3 Y3 X3 q
|
||||
rm(0); // Z3 Y3 X3 q
|
||||
loadZ3(); // lastZ3 H Y3 X3 q
|
||||
mul(0, 2, 8); // Z3 lastZ3 H Y3 X3 q
|
||||
rm(4); // lastZ3 Z3 Y3 X3 q
|
||||
rm(0); // Z3 Y3 X3 q
|
||||
|
||||
C.swap(1);
|
||||
C.swap(5);
|
||||
C.swap(1);
|
||||
C.swap(4); // X3 Y3 Z3 q
|
||||
C.swap(4); // X3 Y3 Z3 q
|
||||
|
||||
// returns the point in memory
|
||||
C.label("returnP"); // X Y Z q
|
||||
@@ -429,37 +418,37 @@ function createCode(P, w) {
|
||||
|
||||
function loadX() {
|
||||
C.push(savedP);
|
||||
C.mload(); // p
|
||||
C.mload(); // p
|
||||
C.push(32);
|
||||
C.mul(); // P*32
|
||||
C.push(VAR_POINTS+32);
|
||||
C.add(); // P*32+32
|
||||
C.dup(); // P*32+32 P*32+32
|
||||
C.mload(); // im P*32+32
|
||||
C.swap(1); // P*32+32 im
|
||||
C.push(0x20); // 32 P*32+32 im
|
||||
C.sub(); // P*32 im
|
||||
C.mload(); // re im
|
||||
C.mul(); // P*32
|
||||
C.push(VAR_POINTS + 32);
|
||||
C.add(); // P*32+32
|
||||
C.dup(); // P*32+32 P*32+32
|
||||
C.mload(); // im P*32+32
|
||||
C.swap(1); // P*32+32 im
|
||||
C.push(0x20); // 32 P*32+32 im
|
||||
C.sub(); // P*32 im
|
||||
C.mload(); // re im
|
||||
}
|
||||
|
||||
function loadY() {
|
||||
C.push(savedP);
|
||||
C.mload(); // p
|
||||
C.mload(); // p
|
||||
C.push(32);
|
||||
C.mul(); // P*32
|
||||
C.push(VAR_POINTS+32*3);
|
||||
C.add(); // P*32+32
|
||||
C.dup(); // P*32+32 P*32+32
|
||||
C.mload(); // im P*32+32
|
||||
C.swap(1); // P*32+32 im
|
||||
C.push(0x20); // 32 P*32+32 im
|
||||
C.sub(); // P*32 im
|
||||
C.mload(); // re im
|
||||
C.mul(); // P*32
|
||||
C.push(VAR_POINTS + 32 * 3);
|
||||
C.add(); // P*32+32
|
||||
C.dup(); // P*32+32 P*32+32
|
||||
C.mload(); // im P*32+32
|
||||
C.swap(1); // P*32+32 im
|
||||
C.push(0x20); // 32 P*32+32 im
|
||||
C.sub(); // P*32 im
|
||||
C.mload(); // re im
|
||||
}
|
||||
|
||||
function loadZ3() {
|
||||
C.push(savedZ3+32);
|
||||
C.mload(); // p
|
||||
C.push(savedZ3 + 32);
|
||||
C.mload(); // p
|
||||
C.push(savedZ3);
|
||||
C.mload();
|
||||
}
|
||||
@@ -467,18 +456,19 @@ function createCode(P, w) {
|
||||
function saveZ3() {
|
||||
C.push(savedZ3);
|
||||
C.mstore();
|
||||
C.push(savedZ3+32);
|
||||
C.push(savedZ3 + 32);
|
||||
C.mstore();
|
||||
}
|
||||
}
|
||||
|
||||
function affine() { // X Y Z q
|
||||
function affine() {
|
||||
// X Y Z q
|
||||
// If Z2=0 return 0
|
||||
C.label("affine");
|
||||
C.dup(4);
|
||||
C.dup(5 + 1);
|
||||
C.or();
|
||||
C.jumpi("notZero"); // X Y Z q
|
||||
C.jumpi("notZero"); // X Y Z q
|
||||
rm(0);
|
||||
rm(0);
|
||||
C.push(0);
|
||||
@@ -487,96 +477,95 @@ function createCode(P, w) {
|
||||
C.jmp("endAffine");
|
||||
C.label("notZero");
|
||||
|
||||
inverse2(4,6); // Z_inv X Y Z q
|
||||
square(2, 8); // Z2_inv Z_inv X Y Z q
|
||||
mul(0, 2, 10); // Z3_inv Z2_inv Z_inv X Y Z q
|
||||
rm(4); // Z2_inv Z3_inv X Y Z q
|
||||
inverse2(4, 6); // Z_inv X Y Z q
|
||||
square(2, 8); // Z2_inv Z_inv X Y Z q
|
||||
mul(0, 2, 10); // Z3_inv Z2_inv Z_inv X Y Z q
|
||||
rm(4); // Z2_inv Z3_inv X Y Z q
|
||||
C.push(1);
|
||||
C.push(0); // 1 Z2_inv Z3_inv X Y Z q
|
||||
rm(10); // Z2_inv Z3_inv X Y 1 q
|
||||
mul(2, 6, 10); // YI Z2_inv Z3_inv X Y 1 q
|
||||
rm(8); // Z2_inv Z3_inv X YI 1 q
|
||||
mul(0, 4, 10); // XI Z2_inv Z3_inv X YI 1 q
|
||||
rm(6); // Z2_inv Z3_inv XI YI 1 q
|
||||
rm(0); // Z3_inv XI YI 1 q
|
||||
rm(0); // XI YI 1 q
|
||||
C.push(0); // 1 Z2_inv Z3_inv X Y Z q
|
||||
rm(10); // Z2_inv Z3_inv X Y 1 q
|
||||
mul(2, 6, 10); // YI Z2_inv Z3_inv X Y 1 q
|
||||
rm(8); // Z2_inv Z3_inv X YI 1 q
|
||||
mul(0, 4, 10); // XI Z2_inv Z3_inv X YI 1 q
|
||||
rm(6); // Z2_inv Z3_inv XI YI 1 q
|
||||
rm(0); // Z3_inv XI YI 1 q
|
||||
rm(0); // XI YI 1 q
|
||||
C.label("endAffine");
|
||||
C.returnCall();
|
||||
}
|
||||
|
||||
function inverse2(a, q) {
|
||||
C.dup(q); // q
|
||||
C.dup(q + 1); // q q
|
||||
C.push(2); // 2 q q
|
||||
C.sub(); // q-2 q
|
||||
C.dup(q + 2); // q q-2 q
|
||||
C.dup(q + 3); // q q q-2 q
|
||||
C.dup(a + 4); // ar q q q-2 q
|
||||
C.dup(a + 5); // ar ar q q q-2 q
|
||||
C.mulmod(); // t0 q q-2 q
|
||||
C.dup(q); // q
|
||||
C.dup(q + 1); // q q
|
||||
C.push(2); // 2 q q
|
||||
C.sub(); // q-2 q
|
||||
C.dup(q + 2); // q q-2 q
|
||||
C.dup(q + 3); // q q q-2 q
|
||||
C.dup(a + 4); // ar q q q-2 q
|
||||
C.dup(a + 5); // ar ar q q q-2 q
|
||||
C.mulmod(); // t0 q q-2 q
|
||||
|
||||
C.dup(q + 4); // q t0 q q-2 q
|
||||
C.dup(a+1 + 5); // ai q t0 q q-2 q
|
||||
C.dup(a+1 + 6); // ai ai q t0 q q-2 q
|
||||
C.mulmod(); // t1 t0 q q-2 q
|
||||
C.dup(q + 4); // q t0 q q-2 q
|
||||
C.dup(a + 1 + 5); // ai q t0 q q-2 q
|
||||
C.dup(a + 1 + 6); // ai ai q t0 q q-2 q
|
||||
C.mulmod(); // t1 t0 q q-2 q
|
||||
|
||||
C.addmod(); // t2 q-2 q
|
||||
C.expmod(); // t3
|
||||
C.addmod(); // t2 q-2 q
|
||||
C.expmod(); // t3
|
||||
|
||||
C.dup(q + 1); // q t3
|
||||
C.dup(q + 2); // q q t3
|
||||
C.dup(q + 3); // q q q t3
|
||||
C.dup(1); // t3 q q q t3
|
||||
C.sub(); // -t3 q q t3
|
||||
C.dup(a+1 + 3); // ai -t3 q q t3
|
||||
C.mulmod(); // ii q t3
|
||||
C.swap(2); // t3 q ii
|
||||
C.dup(a + 3); // ar t3 q ii
|
||||
C.mulmod(); // ir ii
|
||||
C.dup(q + 1); // q t3
|
||||
C.dup(q + 2); // q q t3
|
||||
C.dup(q + 3); // q q q t3
|
||||
C.dup(1); // t3 q q q t3
|
||||
C.sub(); // -t3 q q t3
|
||||
C.dup(a + 1 + 3); // ai -t3 q q t3
|
||||
C.mulmod(); // ii q t3
|
||||
C.swap(2); // t3 q ii
|
||||
C.dup(a + 3); // ar t3 q ii
|
||||
C.mulmod(); // ir ii
|
||||
}
|
||||
|
||||
function storeVals() {
|
||||
C.push(VAR_POINTS); // p
|
||||
for (let i=0; i<NPOINTS; i++) {
|
||||
C.push(VAR_POINTS); // p
|
||||
for (let i = 0; i < NPOINTS; i++) {
|
||||
const MP = G2.affine(G2.mulScalar(P, i));
|
||||
for (let j=0; j<2; j++) {
|
||||
for (let k=0; k<2; k++) {
|
||||
C.push(toHex256(MP[j][k])); // MP[0][0] p
|
||||
C.dup(1); // p MP[0][0] p
|
||||
C.mstore(); // p
|
||||
C.push(32); // 32 p
|
||||
C.add(); // p+32
|
||||
for (let j = 0; j < 2; j++) {
|
||||
for (let k = 0; k < 2; k++) {
|
||||
C.push(toHex256(MP[j][k])); // MP[0][0] p
|
||||
C.dup(1); // p MP[0][0] p
|
||||
C.mstore(); // p
|
||||
C.push(32); // 32 p
|
||||
C.add(); // p+32
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports.abi = [
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
constant: true,
|
||||
inputs: [
|
||||
{
|
||||
"name": "escalar",
|
||||
"type": "uint256"
|
||||
}
|
||||
name: "escalar",
|
||||
type: "uint256",
|
||||
},
|
||||
],
|
||||
"name": "mulexp",
|
||||
"outputs": [
|
||||
name: "mulexp",
|
||||
outputs: [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
name: "",
|
||||
type: "uint256",
|
||||
},
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
name: "",
|
||||
type: "uint256",
|
||||
},
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "pure",
|
||||
"type": "function"
|
||||
}
|
||||
payable: false,
|
||||
stateMutability: "pure",
|
||||
type: "function",
|
||||
},
|
||||
];
|
||||
|
||||
module.exports.createCode = createCode;
|
||||
|
||||
@@ -14,22 +14,21 @@ const { C, M } = unstringifyBigInts(require("./poseidon_constants.json"));
|
||||
// Generated by https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/calc_round_numbers.py
|
||||
// And rounded up to nearest integer that divides by t
|
||||
const N_ROUNDS_F = 8;
|
||||
const N_ROUNDS_P = [56, 57, 56, 60, 60, 63, 64, 63];
|
||||
const N_ROUNDS_P = 35;
|
||||
|
||||
const pow5 = a => F.mul(a, F.square(F.square(a, a)));
|
||||
|
||||
function poseidon(inputs) {
|
||||
assert(inputs.length > 0);
|
||||
assert(inputs.length < N_ROUNDS_P.length - 1);
|
||||
assert(inputs.length < 5);
|
||||
|
||||
const t = inputs.length + 1;
|
||||
const nRoundsF = N_ROUNDS_F;
|
||||
const nRoundsP = N_ROUNDS_P[t - 2];
|
||||
const nRoundsP = N_ROUNDS_P;
|
||||
|
||||
let state = [...inputs.map(a => F.e(a)), F.zero];
|
||||
for (let r = 0; r < nRoundsF + nRoundsP; r++) {
|
||||
state = state.map((a, i) => F.add(a, C[t - 2][r * t + i]));
|
||||
|
||||
state = state.map((a, i) => F.add(a, BigInt(C[t - 2][r * t + i])));
|
||||
if (r < nRoundsF / 2 || r >= nRoundsF / 2 + nRoundsP) {
|
||||
state = state.map(a => pow5(a));
|
||||
} else {
|
||||
@@ -39,7 +38,7 @@ function poseidon(inputs) {
|
||||
// no matrix multiplication in the last round
|
||||
if (r < nRoundsF + nRoundsP - 1) {
|
||||
state = state.map((_, i) =>
|
||||
state.reduce((acc, a, j) => F.add(acc, F.mul(M[t - 2][j][i], a)), F.zero)
|
||||
state.reduce((acc, a, j) => F.add(acc, F.mul(BigInt(M[t - 2][j][i]), a)), F.zero)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,13 +4,17 @@
|
||||
|
||||
const Contract = require("./evmasm");
|
||||
const { unstringifyBigInts } = require("ffjavascript").utils;
|
||||
const Web3Utils = require("web3-utils");
|
||||
|
||||
const { C:K, M } = unstringifyBigInts(require("./poseidon_constants.json"));
|
||||
|
||||
const N_ROUNDS_F = 8;
|
||||
const N_ROUNDS_P = [56, 57, 56, 60, 60, 63, 64, 63];
|
||||
const N_ROUNDS_P = 35;
|
||||
|
||||
function toHex256(a) {
|
||||
if (typeof a === "string" && a.startsWith("0x")) {
|
||||
return a;
|
||||
}
|
||||
let S = a.toString(16);
|
||||
while (S.length < 64) S="0"+S;
|
||||
return "0x" + S;
|
||||
@@ -18,10 +22,10 @@ function toHex256(a) {
|
||||
|
||||
function createCode(nInputs) {
|
||||
|
||||
if (( nInputs<1) || (nInputs>8)) throw new Error("Invalid number of inputs. Must be 1<=nInputs<=8");
|
||||
if (( nInputs<1) || (nInputs>4)) throw new Error("Invalid number of inputs. Must be 1<=nInputs<=8");
|
||||
const t = nInputs + 1;
|
||||
const nRoundsF = N_ROUNDS_F;
|
||||
const nRoundsP = N_ROUNDS_P[t - 2];
|
||||
const nRoundsP = N_ROUNDS_P;
|
||||
|
||||
const C = new Contract();
|
||||
|
||||
@@ -99,8 +103,13 @@ function createCode(nInputs) {
|
||||
C.push(0);
|
||||
C.calldataload();
|
||||
C.div();
|
||||
C.push("0xc4420fb4"); // poseidon(uint256[])
|
||||
C.dup(0);
|
||||
C.push(Web3Utils.keccak256(`poseidon(uint256[${nInputs}])`).slice(0, 10)); // poseidon(uint256[n])
|
||||
C.eq();
|
||||
C.swap(1);
|
||||
C.push(Web3Utils.keccak256(`poseidon(bytes32[${nInputs}])`).slice(0, 10)); // poseidon(bytes32[n])
|
||||
C.eq();
|
||||
C.or();
|
||||
C.jmpi("start");
|
||||
C.invalid();
|
||||
|
||||
@@ -112,11 +121,10 @@ function createCode(nInputs) {
|
||||
|
||||
// Load t values from the call data.
|
||||
// The function has a single array param param
|
||||
// [Selector (4)] [Pointer (32)][Length (32)] [data1 (32)] ....
|
||||
// We ignore the pointer and the length and just load t values to the state
|
||||
// (Stack positions 0-{t-1}) If the array is shorter, we just set zeros.
|
||||
// [Selector (4)] [item1 (32)] [item2 (32)] ....
|
||||
// Stack positions 0-nInputs.
|
||||
for (let i=0; i<t; i++) {
|
||||
C.push(0x44+(0x20*(t-1-i)));
|
||||
C.push(0x04+(0x20*(nInputs-i)));
|
||||
C.calldataload();
|
||||
}
|
||||
|
||||
@@ -155,28 +163,54 @@ function createCode(nInputs) {
|
||||
return C.createTxData();
|
||||
}
|
||||
|
||||
module.exports.abi = [
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "input",
|
||||
"type": "uint256[]"
|
||||
}
|
||||
],
|
||||
"name": "poseidon",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "pure",
|
||||
"type": "function"
|
||||
}
|
||||
];
|
||||
function generateABI(nInputs) {
|
||||
return [
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": `bytes32[${nInputs}]`,
|
||||
"name": "input",
|
||||
"type": `bytes32[${nInputs}]`
|
||||
}
|
||||
],
|
||||
"name": "poseidon",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "pure",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": `uint256[${nInputs}]`,
|
||||
"name": "input",
|
||||
"type": `uint256[${nInputs}]`
|
||||
}
|
||||
],
|
||||
"name": "poseidon",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"payable": false,
|
||||
"stateMutability": "pure",
|
||||
"type": "function"
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
module.exports.generateABI = generateABI;
|
||||
module.exports.createCode = createCode;
|
||||
|
||||
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
|
||||
const snarkjs = require("snarkjs");
|
||||
const snarkjs = require("@tornado/snarkjs");
|
||||
|
||||
const bigInt = snarkjs.bigInt;
|
||||
|
||||
module.exports = function hexBits(cir, witness, sig, nBits) {
|
||||
let v = bigInt(0);
|
||||
for (let i=nBits-1; i>=0; i--) {
|
||||
for (let i = nBits - 1; i >= 0; i--) {
|
||||
v = v.shiftLeft(1);
|
||||
const name = sig+"["+i+"]";
|
||||
const name = sig + "[" + i + "]";
|
||||
const idx = cir.getSignalIdx(name);
|
||||
const vbit = bigInt(witness[idx].toString());
|
||||
if (vbit.equals(bigInt(1))) {
|
||||
@@ -15,7 +14,7 @@ module.exports = function hexBits(cir, witness, sig, nBits) {
|
||||
} else if (vbit.equals(bigInt(0))) {
|
||||
v;
|
||||
} else {
|
||||
console.log("Not Binary: "+name);
|
||||
console.log("Not Binary: " + name);
|
||||
}
|
||||
}
|
||||
return v.toString(16);
|
||||
|
||||
@@ -21,15 +21,16 @@ describe("Poseidon Smart contract test", function () {
|
||||
});
|
||||
|
||||
it("Should deploy the contract", async () => {
|
||||
const C = new web3.eth.Contract(poseidonGenContract.abi);
|
||||
const C6 = new web3.eth.Contract(poseidonGenContract.generateABI(5));
|
||||
const C3 = new web3.eth.Contract(poseidonGenContract.generateABI(2));
|
||||
|
||||
poseidon6 = await C.deploy({
|
||||
poseidon6 = await C6.deploy({
|
||||
data: poseidonGenContract.createCode(5)
|
||||
}).send({
|
||||
gas: 5000000,
|
||||
from: accounts[0]
|
||||
});
|
||||
poseidon3 = await C.deploy({
|
||||
poseidon3 = await C3.deploy({
|
||||
data: poseidonGenContract.createCode(2)
|
||||
}).send({
|
||||
gas: 5000000,
|
||||
@@ -37,7 +38,7 @@ describe("Poseidon Smart contract test", function () {
|
||||
});
|
||||
});
|
||||
|
||||
it("Shold calculate the poseidon correctly t=6", async () => {
|
||||
it("Should calculate the poseidon correctly t=6", async () => {
|
||||
|
||||
const res = await poseidon6.methods.poseidon([1,2, 0, 0, 0]).call();
|
||||
|
||||
@@ -48,7 +49,7 @@ describe("Poseidon Smart contract test", function () {
|
||||
|
||||
assert.equal(res.toString(), res2.toString());
|
||||
});
|
||||
it("Shold calculate the poseidon correctly t=3", async () => {
|
||||
it("Should calculate the poseidon correctly t=3", async () => {
|
||||
|
||||
const res = await poseidon3.methods.poseidon([1,2]).call();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user