diff --git a/build/websnark.js b/build/websnark.js index f65aab0..96798cb 100644 --- a/build/websnark.js +++ b/build/websnark.js @@ -1,11 +1,11 @@ (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i { }; }); },{"./src/groth16":17,"./src/utils":18}],3:[function(require,module,exports){ -(function (global){ +(function (global){(function (){ 'use strict'; var objectAssign = require('object-assign'); @@ -570,7 +570,7 @@ var objectKeys = Object.keys || function (obj) { return keys; }; -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"object-assign":11,"util/":6}],4:[function(require,module,exports){ if (typeof Object.create === 'function') { // implementation from standard node.js 'util' module @@ -604,7 +604,7 @@ module.exports = function isBuffer(arg) { && typeof arg.readUInt8 === 'function'; } },{}],6:[function(require,module,exports){ -(function (process,global){ +(function (process,global){(function (){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -1192,7 +1192,7 @@ function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } -}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +}).call(this)}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"./support/isBuffer":5,"_process":12,"inherits":4}],7:[function(require,module,exports){ 'use strict' @@ -1261,7 +1261,8 @@ function toByteArray (b64) { ? validLen - 4 : validLen - for (var i = 0; i < len; i += 4) { + var i + for (i = 0; i < len; i += 4) { tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | @@ -1320,9 +1321,7 @@ function fromByteArray (uint8) { // go through the array every three bytes, we'll deal with trailing stuff later for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { - parts.push(encodeChunk( - uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength) - )) + parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength))) } // pad the end with zeros, but make sure to not forget the extra bytes @@ -2032,6 +2031,10 @@ var bigInt = (function (undefined) { if (mod.isZero()) throw new Error("Cannot take modPow with modulus 0"); var r = Integer[1], base = this.mod(mod); + if (exp.isNegative()) { + exp = exp.multiply(Integer[-1]); + base = base.modInv(mod); + } while (exp.isPositive()) { if (base.isZero()) return Integer[0]; if (exp.isOdd()) r = r.multiply(base).mod(mod); @@ -2275,13 +2278,13 @@ var bigInt = (function (undefined) { }; NativeBigInt.prototype.isPrime = SmallInteger.prototype.isPrime = BigInteger.prototype.isPrime; - BigInteger.prototype.isProbablePrime = function (iterations) { + BigInteger.prototype.isProbablePrime = function (iterations, rng) { var isPrime = isBasicPrime(this); if (isPrime !== undefined) return isPrime; var n = this.abs(); var t = iterations === undefined ? 5 : iterations; for (var a = [], i = 0; i < t; i++) { - a.push(bigInt.randBetween(2, n.minus(2))); + a.push(bigInt.randBetween(2, n.minus(2), rng)); } return millerRabinTest(n, a); }; @@ -2513,19 +2516,20 @@ var bigInt = (function (undefined) { b = parseValue(b).abs(); return a.divide(gcd(a, b)).multiply(b); } - function randBetween(a, b) { + function randBetween(a, b, rng) { a = parseValue(a); b = parseValue(b); + var usedRNG = rng || Math.random; var low = min(a, b), high = max(a, b); var range = high.subtract(low).add(1); - if (range.isSmall) return low.add(Math.floor(Math.random() * range)); + if (range.isSmall) return low.add(Math.floor(usedRNG() * range)); var digits = toBase(range, BASE).value; var result = [], restricted = true; for (var i = 0; i < digits.length; i++) { - var top = restricted ? digits[i] : BASE; - var digit = truncate(Math.random() * top); + var top = restricted ? digits[i] + (i + 1 < digits.length ? digits[i + 1] / BASE : 0) : BASE; + var digit = truncate(usedRNG() * top); result.push(digit); - if (digit < top) restricted = false; + if (digit < digits[i]) restricted = false; } return low.add(Integer.fromArray(result, BASE, false)); } @@ -2791,13 +2795,13 @@ if (typeof module !== "undefined" && module.hasOwnProperty("exports")) { //amd check if (typeof define === "function" && define.amd) { - define("big-integer", [], function () { + define( function () { return bigInt; }); } },{}],9:[function(require,module,exports){ -(function (Buffer){ +(function (Buffer){(function (){ /*! * The buffer module from node.js, for the browser. * @@ -4576,8 +4580,9 @@ function numberIsNaN (obj) { return obj !== obj // eslint-disable-line no-self-compare } -}).call(this,require("buffer").Buffer) +}).call(this)}).call(this,require("buffer").Buffer) },{"base64-js":7,"buffer":9,"ieee754":10}],10:[function(require,module,exports){ +/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh */ exports.read = function (buffer, offset, isLE, mLen, nBytes) { var e, m var eLen = (nBytes * 8) - mLen - 1 @@ -4942,7 +4947,7 @@ process.chdir = function (dir) { process.umask = function() { return 0; }; },{}],13:[function(require,module,exports){ -(function (Buffer){ +(function (Buffer){(function (){ /* Copyright 2018 0kims association. @@ -5122,6 +5127,14 @@ if (typeof(BigInt) != "undefined") { return this % c; }; + wBigInt.prototype.pow = function(c) { + return this ** c; + }; + + wBigInt.prototype.abs = function() { + return (this > wBigInt.zero) ? this : -this; + }; + wBigInt.prototype.modPow = function(e, m) { let acc = wBigInt.one; let exp = this; @@ -5163,6 +5176,11 @@ if (typeof(BigInt) != "undefined") { return this != b; }; + wBigInt.prototype.toJSNumber = function() { + return Number(this); + }; + + } else { var oldProto = bigInt.prototype; @@ -5423,10 +5441,37 @@ wBigInt.prototype.leInt2Buff = function (len) { }; +wBigInt.beBuff2int = function(buff) { + let res = wBigInt.zero; + for (let i=0; i=0)) { + let c = Number(r.and(wBigInt("255"))); + buff[o] = c; + o--; + r = r.shr(8); + } + if (r.greater(wBigInt.zero)) throw new Error("Number does not feed in buffer"); + return buff; +}; + +wBigInt.prototype.beInt2Buff = function (len) { + return wBigInt.beInt2Buff(this,len); +}; + module.exports = wBigInt; -}).call(this,require("buffer").Buffer) +}).call(this)}).call(this,require("buffer").Buffer) },{"big-integer":8,"buffer":9}],14:[function(require,module,exports){ /* Copyright 2018 0kims association. @@ -5451,9 +5496,10 @@ const bigInt = require("./bigint"); module.exports = calculateWitness; -function calculateWitness(circuit, inputSignals, log) { - log = log || (() => {}); - const ctx = new RTCtx(circuit, log); +function calculateWitness(circuit, inputSignals, options) { + options = options || {}; + if (!options.logFunction) options.logFunction = console.log; + const ctx = new RTCtx(circuit, options); function iterateSelector(values, sels, cb) { if (!Array.isArray(values)) { @@ -5492,15 +5538,15 @@ function calculateWitness(circuit, inputSignals, log) { if (typeof(ctx.witness[i]) == "undefined") { throw new Error("Signal not assigned: " + circuit.signalNames(i)); } - log(circuit.signalNames(i) + " --> " + ctx.witness[i].toString()); + if (options.logOutput) options.logFunction(circuit.signalNames(i) + " --> " + ctx.witness[i].toString()); } return ctx.witness.slice(0, circuit.nVars); // return ctx.witness; } class RTCtx { - constructor(circuit, log) { - this.log = log || function() {}; + constructor(circuit, options) { + this.options = options; this.scopes = []; this.circuit = circuit; this.witness = new Array(circuit.nSignals); @@ -5534,8 +5580,7 @@ class RTCtx { } triggerComponent(c) { - this.log("Component Treiggered: " + this.circuit.components[c].name); -// console.log("Start Component Treiggered: " + this.circuit.components[c].name); + if (this.options.logTrigger) this.options.logFunction("Component Treiggered: " + this.circuit.components[c].name); // Set notInitSignals to -1 to not initialize again this.notInitSignals[c] --; @@ -5556,7 +5601,8 @@ class RTCtx { this.circuit.templates[template](this); this.scopes = oldScope; this.currentComponent = oldComponent; -// console.log("End Component Treiggered: " + this.circuit.components[c].name); + + if (this.options.logTrigger) this.options.logFunction("End Component Treiggered: " + this.circuit.components[c].name); } callFunction(functionName, params) { @@ -5579,7 +5625,7 @@ class RTCtx { } setSignalFullName(fullName, value) { - this.log("set " + fullName + " <-- " + value.toString()); + if (this.options.logSet) this.options.logFunction("set " + fullName + " <-- " + value.toString()); const sId = this.circuit.getSignalIdx(fullName); let firstInit =false; if (typeof(this.witness[sId]) == "undefined") { @@ -5648,15 +5694,15 @@ class RTCtx { if (typeof(this.witness[sId]) == "undefined") { throw new Error("Signal not initialized: "+fullName); } - this.log("get --->" + fullName + " = " + this.witness[sId].toString() ); + if (this.options.logGet) this.options.logFunction("get --->" + fullName + " = " + this.witness[sId].toString() ); return this.witness[sId]; } - assert(a,b) { + assert(a,b,errStr) { const ba = bigInt(a); const bb = bigInt(b); if (!ba.equals(bb)) { - throw new Error("Constraint doesn't match: " + ba.toString() + " != " + bb.toString()); + throw new Error("Constraint doesn't match "+ this.currentComponent+": "+ errStr + " -> "+ ba.toString() + " != " + bb.toString()); } } } @@ -5880,7 +5926,7 @@ module.exports.stringifyBigInts = stringifyBigInts; module.exports.unstringifyBigInts = unstringifyBigInts; function stringifyBigInts(o) { - if ((typeof(o) == "bigint") || (o instanceof bigInt)) { + if ((typeof(o) == "bigint") || o.isZero !== undefined) { return o.toString(10); } else if (Array.isArray(o)) { return o.map(stringifyBigInts); @@ -5912,7 +5958,7 @@ function unstringifyBigInts(o) { } },{"./bigint.js":13}],17:[function(require,module,exports){ -(function (process){ +(function (process){(function (){ /* Copyright 2019 0KIMS association. @@ -5937,9 +5983,15 @@ const bigInt = require("big-integer"); const groth16_wasm = require("../build/groth16_wasm.js"); const assert = require("assert"); -const inBrowser = (typeof window !== "undefined"); +const inBrowser = (typeof window !== "undefined") || process && process.env && process.env.FOR_BROWSER === "true"; + + let NodeWorker; let NodeCrypto; + +// eslint-disable-next-line no-console +console.log(`Running in browser ${inBrowser}`); + if (!inBrowser) { NodeWorker = require("worker_threads").Worker; NodeCrypto = require("crypto"); @@ -5984,7 +6036,7 @@ function thread(self) { const res = i32[0]; i32[0] += length; while (i32[0] > memory.buffer.byteLength) { - memory.grow(100); + memory.grow(100); } i32 = new Uint32Array(memory.buffer); return res; @@ -6084,8 +6136,11 @@ function thread(self) { }; } -async function build() { - +// We use the Object.assign approach for the backwards compatibility +// @params Number wasmInitialMemory +async function build(params) { + const defaultParams = { wasmInitialMemory: 5000 }; + Object.assign(defaultParams, params); const groth16 = new Groth16(); groth16.q = bigInt("21888242871839275222246405745257275088696311157297823662689037894645226208583"); @@ -6094,7 +6149,7 @@ async function build() { groth16.n32 = groth16.n64*2; groth16.n8 = groth16.n64*8; - groth16.memory = new WebAssembly.Memory({initial:5000}); + groth16.memory = new WebAssembly.Memory({initial:defaultParams.wasmInitialMemory}); groth16.i32 = new Uint32Array(groth16.memory.buffer); const wasmModule = await WebAssembly.compile(groth16_wasm.code); @@ -6162,7 +6217,7 @@ async function build() { const copyCode = groth16_wasm.code.buffer.slice(0); initPromises.push(groth16.postAction(i, { command: "INIT", - init: 5000, + init: defaultParams.wasmInitialMemory, code: copyCode }, [copyCode])); @@ -6407,7 +6462,7 @@ class Groth16 { const pH = this.calcH(signals.slice(0), polsA, polsB, nSignals, domainSize).then( (h) => { -/* Debug code to print the result of h + /* Debug code to print the result of h for (let i=0; i " + a.toString()); @@ -6462,9 +6517,9 @@ class Groth16 { this.putBin(ps, bs); } -/// Uncoment it to debug and check it works -// this.instance.exports.f1m_zero(pr); -// this.instance.exports.f1m_zero(ps); + /// Uncoment it to debug and check it works + // this.instance.exports.f1m_zero(pr); + // this.instance.exports.f1m_zero(ps); // pi_a = pi_a + Alfa1 + r*Delta1 this.instance.exports.g1_add(pAlfa1, pi_a, pi_a); @@ -6522,7 +6577,7 @@ class Groth16 { module.exports = build; -}).call(this,require('_process')) +}).call(this)}).call(this,require('_process')) },{"../build/groth16_wasm.js":1,"_process":12,"assert":3,"big-integer":8,"crypto":undefined,"worker_threads":undefined}],18:[function(require,module,exports){ /* Copyright 2019 0KIMS association. @@ -6547,6 +6602,8 @@ const bigInt = require("big-integer"); const Circuit = require("tornado-snarkjs/src/circuit"); const bigInt2 = require("tornado-snarkjs/src/bigint"); const hexifyBigInts = require("../tools/stringifybigint").hexifyBigInts; +const unhexifyBigInts = require("../tools/stringifybigint").unhexifyBigInts; +const stringifyBigInts = require("../tools/stringifybigint").stringifyBigInts; const unstringifyBigInts = require("../tools/stringifybigint").unstringifyBigInts; const stringifyBigInts2 = require("tornado-snarkjs/src/stringifybigint").stringifyBigInts; const unstringifyBigInts2 = require("tornado-snarkjs/src/stringifybigint").unstringifyBigInts; @@ -6589,21 +6646,31 @@ function convertWitness(witness) { return buff; } +function toHex32(number) { + let str = number.toString(16); + while (str.length < 64) str = "0" + str; + return str; +} + function toSolidityInput(proof) { + const flatProof = unstringifyBigInts([ + proof.pi_a[0], proof.pi_a[1], + proof.pi_b[0][1], proof.pi_b[0][0], + proof.pi_b[1][1], proof.pi_b[1][0], + proof.pi_c[0], proof.pi_c[1], + ]); const result = { - pi_a: [proof.pi_a[0], proof.pi_a[1]], - pi_b: [[proof.pi_b[0][1], proof.pi_b[0][0]], [proof.pi_b[1][1], proof.pi_b[1][0]]], - pi_c: [proof.pi_c[0], proof.pi_c[1]], + proof: "0x" + flatProof.map(x => toHex32(x)).join("") }; if (proof.publicSignals) { - result.publicSignals = proof.publicSignals; + result.publicSignals = hexifyBigInts(unstringifyBigInts(proof.publicSignals)); } - return hexifyBigInts(unstringifyBigInts(result)); + return result; } function genWitness(input, circuitJson) { const circuit = new Circuit(unstringifyBigInts2(circuitJson)); - const witness = circuit.calculateWitness(input); + const witness = circuit.calculateWitness(unstringifyBigInts2(input)); const publicSignals = witness.slice(1, circuit.nPubInputs + circuit.nOutputs + 1); return {witness, publicSignals}; } @@ -6617,7 +6684,7 @@ async function genWitnessAndProve(groth16, input, circuitJson, provingKey) { } module.exports = {bigInt2BytesLE, bigInt2U32LE, toSolidityInput, genWitnessAndProve}; -},{"../tools/stringifybigint":19,"big-integer":8,"snarkjs/src/bigint":13,"snarkjs/src/circuit":15,"snarkjs/src/stringifybigint":16}],19:[function(require,module,exports){ +},{"../tools/stringifybigint":19,"big-integer":8,"tornado-snarkjs/src/bigint":13,"tornado-snarkjs/src/circuit":15,"tornado-snarkjs/src/stringifybigint":16}],19:[function(require,module,exports){ /* Copyright 2018 0kims association. @@ -6642,6 +6709,7 @@ const bigInt = require("big-integer"); module.exports.stringifyBigInts = stringifyBigInts; module.exports.unstringifyBigInts = unstringifyBigInts; module.exports.hexifyBigInts = hexifyBigInts; +module.exports.unhexifyBigInts = unhexifyBigInts; function stringifyBigInts(o) { if ((typeof(o) == "bigint") || (o instanceof bigInt)) { @@ -6694,4 +6762,20 @@ function hexifyBigInts(o) { } } +function unhexifyBigInts(o) { + if ((typeof(o) == "string") && (/^0x[0-9a-fA-F]+$/.test(o))) { + return bigInt(o); + } else if (Array.isArray(o)) { + return o.map(unhexifyBigInts); + } else if (typeof o == "object") { + const res = {}; + for (let k in o) { + res[k] = unhexifyBigInts(o[k]); + } + return res; + } else { + return o; + } +} + },{"big-integer":8}]},{},[2]); diff --git a/example/websnark.js b/example/websnark.js index f65aab0..96798cb 100644 --- a/example/websnark.js +++ b/example/websnark.js @@ -1,11 +1,11 @@ (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i { }; }); },{"./src/groth16":17,"./src/utils":18}],3:[function(require,module,exports){ -(function (global){ +(function (global){(function (){ 'use strict'; var objectAssign = require('object-assign'); @@ -570,7 +570,7 @@ var objectKeys = Object.keys || function (obj) { return keys; }; -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"object-assign":11,"util/":6}],4:[function(require,module,exports){ if (typeof Object.create === 'function') { // implementation from standard node.js 'util' module @@ -604,7 +604,7 @@ module.exports = function isBuffer(arg) { && typeof arg.readUInt8 === 'function'; } },{}],6:[function(require,module,exports){ -(function (process,global){ +(function (process,global){(function (){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -1192,7 +1192,7 @@ function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } -}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +}).call(this)}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"./support/isBuffer":5,"_process":12,"inherits":4}],7:[function(require,module,exports){ 'use strict' @@ -1261,7 +1261,8 @@ function toByteArray (b64) { ? validLen - 4 : validLen - for (var i = 0; i < len; i += 4) { + var i + for (i = 0; i < len; i += 4) { tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | @@ -1320,9 +1321,7 @@ function fromByteArray (uint8) { // go through the array every three bytes, we'll deal with trailing stuff later for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { - parts.push(encodeChunk( - uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength) - )) + parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength))) } // pad the end with zeros, but make sure to not forget the extra bytes @@ -2032,6 +2031,10 @@ var bigInt = (function (undefined) { if (mod.isZero()) throw new Error("Cannot take modPow with modulus 0"); var r = Integer[1], base = this.mod(mod); + if (exp.isNegative()) { + exp = exp.multiply(Integer[-1]); + base = base.modInv(mod); + } while (exp.isPositive()) { if (base.isZero()) return Integer[0]; if (exp.isOdd()) r = r.multiply(base).mod(mod); @@ -2275,13 +2278,13 @@ var bigInt = (function (undefined) { }; NativeBigInt.prototype.isPrime = SmallInteger.prototype.isPrime = BigInteger.prototype.isPrime; - BigInteger.prototype.isProbablePrime = function (iterations) { + BigInteger.prototype.isProbablePrime = function (iterations, rng) { var isPrime = isBasicPrime(this); if (isPrime !== undefined) return isPrime; var n = this.abs(); var t = iterations === undefined ? 5 : iterations; for (var a = [], i = 0; i < t; i++) { - a.push(bigInt.randBetween(2, n.minus(2))); + a.push(bigInt.randBetween(2, n.minus(2), rng)); } return millerRabinTest(n, a); }; @@ -2513,19 +2516,20 @@ var bigInt = (function (undefined) { b = parseValue(b).abs(); return a.divide(gcd(a, b)).multiply(b); } - function randBetween(a, b) { + function randBetween(a, b, rng) { a = parseValue(a); b = parseValue(b); + var usedRNG = rng || Math.random; var low = min(a, b), high = max(a, b); var range = high.subtract(low).add(1); - if (range.isSmall) return low.add(Math.floor(Math.random() * range)); + if (range.isSmall) return low.add(Math.floor(usedRNG() * range)); var digits = toBase(range, BASE).value; var result = [], restricted = true; for (var i = 0; i < digits.length; i++) { - var top = restricted ? digits[i] : BASE; - var digit = truncate(Math.random() * top); + var top = restricted ? digits[i] + (i + 1 < digits.length ? digits[i + 1] / BASE : 0) : BASE; + var digit = truncate(usedRNG() * top); result.push(digit); - if (digit < top) restricted = false; + if (digit < digits[i]) restricted = false; } return low.add(Integer.fromArray(result, BASE, false)); } @@ -2791,13 +2795,13 @@ if (typeof module !== "undefined" && module.hasOwnProperty("exports")) { //amd check if (typeof define === "function" && define.amd) { - define("big-integer", [], function () { + define( function () { return bigInt; }); } },{}],9:[function(require,module,exports){ -(function (Buffer){ +(function (Buffer){(function (){ /*! * The buffer module from node.js, for the browser. * @@ -4576,8 +4580,9 @@ function numberIsNaN (obj) { return obj !== obj // eslint-disable-line no-self-compare } -}).call(this,require("buffer").Buffer) +}).call(this)}).call(this,require("buffer").Buffer) },{"base64-js":7,"buffer":9,"ieee754":10}],10:[function(require,module,exports){ +/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh */ exports.read = function (buffer, offset, isLE, mLen, nBytes) { var e, m var eLen = (nBytes * 8) - mLen - 1 @@ -4942,7 +4947,7 @@ process.chdir = function (dir) { process.umask = function() { return 0; }; },{}],13:[function(require,module,exports){ -(function (Buffer){ +(function (Buffer){(function (){ /* Copyright 2018 0kims association. @@ -5122,6 +5127,14 @@ if (typeof(BigInt) != "undefined") { return this % c; }; + wBigInt.prototype.pow = function(c) { + return this ** c; + }; + + wBigInt.prototype.abs = function() { + return (this > wBigInt.zero) ? this : -this; + }; + wBigInt.prototype.modPow = function(e, m) { let acc = wBigInt.one; let exp = this; @@ -5163,6 +5176,11 @@ if (typeof(BigInt) != "undefined") { return this != b; }; + wBigInt.prototype.toJSNumber = function() { + return Number(this); + }; + + } else { var oldProto = bigInt.prototype; @@ -5423,10 +5441,37 @@ wBigInt.prototype.leInt2Buff = function (len) { }; +wBigInt.beBuff2int = function(buff) { + let res = wBigInt.zero; + for (let i=0; i=0)) { + let c = Number(r.and(wBigInt("255"))); + buff[o] = c; + o--; + r = r.shr(8); + } + if (r.greater(wBigInt.zero)) throw new Error("Number does not feed in buffer"); + return buff; +}; + +wBigInt.prototype.beInt2Buff = function (len) { + return wBigInt.beInt2Buff(this,len); +}; + module.exports = wBigInt; -}).call(this,require("buffer").Buffer) +}).call(this)}).call(this,require("buffer").Buffer) },{"big-integer":8,"buffer":9}],14:[function(require,module,exports){ /* Copyright 2018 0kims association. @@ -5451,9 +5496,10 @@ const bigInt = require("./bigint"); module.exports = calculateWitness; -function calculateWitness(circuit, inputSignals, log) { - log = log || (() => {}); - const ctx = new RTCtx(circuit, log); +function calculateWitness(circuit, inputSignals, options) { + options = options || {}; + if (!options.logFunction) options.logFunction = console.log; + const ctx = new RTCtx(circuit, options); function iterateSelector(values, sels, cb) { if (!Array.isArray(values)) { @@ -5492,15 +5538,15 @@ function calculateWitness(circuit, inputSignals, log) { if (typeof(ctx.witness[i]) == "undefined") { throw new Error("Signal not assigned: " + circuit.signalNames(i)); } - log(circuit.signalNames(i) + " --> " + ctx.witness[i].toString()); + if (options.logOutput) options.logFunction(circuit.signalNames(i) + " --> " + ctx.witness[i].toString()); } return ctx.witness.slice(0, circuit.nVars); // return ctx.witness; } class RTCtx { - constructor(circuit, log) { - this.log = log || function() {}; + constructor(circuit, options) { + this.options = options; this.scopes = []; this.circuit = circuit; this.witness = new Array(circuit.nSignals); @@ -5534,8 +5580,7 @@ class RTCtx { } triggerComponent(c) { - this.log("Component Treiggered: " + this.circuit.components[c].name); -// console.log("Start Component Treiggered: " + this.circuit.components[c].name); + if (this.options.logTrigger) this.options.logFunction("Component Treiggered: " + this.circuit.components[c].name); // Set notInitSignals to -1 to not initialize again this.notInitSignals[c] --; @@ -5556,7 +5601,8 @@ class RTCtx { this.circuit.templates[template](this); this.scopes = oldScope; this.currentComponent = oldComponent; -// console.log("End Component Treiggered: " + this.circuit.components[c].name); + + if (this.options.logTrigger) this.options.logFunction("End Component Treiggered: " + this.circuit.components[c].name); } callFunction(functionName, params) { @@ -5579,7 +5625,7 @@ class RTCtx { } setSignalFullName(fullName, value) { - this.log("set " + fullName + " <-- " + value.toString()); + if (this.options.logSet) this.options.logFunction("set " + fullName + " <-- " + value.toString()); const sId = this.circuit.getSignalIdx(fullName); let firstInit =false; if (typeof(this.witness[sId]) == "undefined") { @@ -5648,15 +5694,15 @@ class RTCtx { if (typeof(this.witness[sId]) == "undefined") { throw new Error("Signal not initialized: "+fullName); } - this.log("get --->" + fullName + " = " + this.witness[sId].toString() ); + if (this.options.logGet) this.options.logFunction("get --->" + fullName + " = " + this.witness[sId].toString() ); return this.witness[sId]; } - assert(a,b) { + assert(a,b,errStr) { const ba = bigInt(a); const bb = bigInt(b); if (!ba.equals(bb)) { - throw new Error("Constraint doesn't match: " + ba.toString() + " != " + bb.toString()); + throw new Error("Constraint doesn't match "+ this.currentComponent+": "+ errStr + " -> "+ ba.toString() + " != " + bb.toString()); } } } @@ -5880,7 +5926,7 @@ module.exports.stringifyBigInts = stringifyBigInts; module.exports.unstringifyBigInts = unstringifyBigInts; function stringifyBigInts(o) { - if ((typeof(o) == "bigint") || (o instanceof bigInt)) { + if ((typeof(o) == "bigint") || o.isZero !== undefined) { return o.toString(10); } else if (Array.isArray(o)) { return o.map(stringifyBigInts); @@ -5912,7 +5958,7 @@ function unstringifyBigInts(o) { } },{"./bigint.js":13}],17:[function(require,module,exports){ -(function (process){ +(function (process){(function (){ /* Copyright 2019 0KIMS association. @@ -5937,9 +5983,15 @@ const bigInt = require("big-integer"); const groth16_wasm = require("../build/groth16_wasm.js"); const assert = require("assert"); -const inBrowser = (typeof window !== "undefined"); +const inBrowser = (typeof window !== "undefined") || process && process.env && process.env.FOR_BROWSER === "true"; + + let NodeWorker; let NodeCrypto; + +// eslint-disable-next-line no-console +console.log(`Running in browser ${inBrowser}`); + if (!inBrowser) { NodeWorker = require("worker_threads").Worker; NodeCrypto = require("crypto"); @@ -5984,7 +6036,7 @@ function thread(self) { const res = i32[0]; i32[0] += length; while (i32[0] > memory.buffer.byteLength) { - memory.grow(100); + memory.grow(100); } i32 = new Uint32Array(memory.buffer); return res; @@ -6084,8 +6136,11 @@ function thread(self) { }; } -async function build() { - +// We use the Object.assign approach for the backwards compatibility +// @params Number wasmInitialMemory +async function build(params) { + const defaultParams = { wasmInitialMemory: 5000 }; + Object.assign(defaultParams, params); const groth16 = new Groth16(); groth16.q = bigInt("21888242871839275222246405745257275088696311157297823662689037894645226208583"); @@ -6094,7 +6149,7 @@ async function build() { groth16.n32 = groth16.n64*2; groth16.n8 = groth16.n64*8; - groth16.memory = new WebAssembly.Memory({initial:5000}); + groth16.memory = new WebAssembly.Memory({initial:defaultParams.wasmInitialMemory}); groth16.i32 = new Uint32Array(groth16.memory.buffer); const wasmModule = await WebAssembly.compile(groth16_wasm.code); @@ -6162,7 +6217,7 @@ async function build() { const copyCode = groth16_wasm.code.buffer.slice(0); initPromises.push(groth16.postAction(i, { command: "INIT", - init: 5000, + init: defaultParams.wasmInitialMemory, code: copyCode }, [copyCode])); @@ -6407,7 +6462,7 @@ class Groth16 { const pH = this.calcH(signals.slice(0), polsA, polsB, nSignals, domainSize).then( (h) => { -/* Debug code to print the result of h + /* Debug code to print the result of h for (let i=0; i " + a.toString()); @@ -6462,9 +6517,9 @@ class Groth16 { this.putBin(ps, bs); } -/// Uncoment it to debug and check it works -// this.instance.exports.f1m_zero(pr); -// this.instance.exports.f1m_zero(ps); + /// Uncoment it to debug and check it works + // this.instance.exports.f1m_zero(pr); + // this.instance.exports.f1m_zero(ps); // pi_a = pi_a + Alfa1 + r*Delta1 this.instance.exports.g1_add(pAlfa1, pi_a, pi_a); @@ -6522,7 +6577,7 @@ class Groth16 { module.exports = build; -}).call(this,require('_process')) +}).call(this)}).call(this,require('_process')) },{"../build/groth16_wasm.js":1,"_process":12,"assert":3,"big-integer":8,"crypto":undefined,"worker_threads":undefined}],18:[function(require,module,exports){ /* Copyright 2019 0KIMS association. @@ -6547,6 +6602,8 @@ const bigInt = require("big-integer"); const Circuit = require("tornado-snarkjs/src/circuit"); const bigInt2 = require("tornado-snarkjs/src/bigint"); const hexifyBigInts = require("../tools/stringifybigint").hexifyBigInts; +const unhexifyBigInts = require("../tools/stringifybigint").unhexifyBigInts; +const stringifyBigInts = require("../tools/stringifybigint").stringifyBigInts; const unstringifyBigInts = require("../tools/stringifybigint").unstringifyBigInts; const stringifyBigInts2 = require("tornado-snarkjs/src/stringifybigint").stringifyBigInts; const unstringifyBigInts2 = require("tornado-snarkjs/src/stringifybigint").unstringifyBigInts; @@ -6589,21 +6646,31 @@ function convertWitness(witness) { return buff; } +function toHex32(number) { + let str = number.toString(16); + while (str.length < 64) str = "0" + str; + return str; +} + function toSolidityInput(proof) { + const flatProof = unstringifyBigInts([ + proof.pi_a[0], proof.pi_a[1], + proof.pi_b[0][1], proof.pi_b[0][0], + proof.pi_b[1][1], proof.pi_b[1][0], + proof.pi_c[0], proof.pi_c[1], + ]); const result = { - pi_a: [proof.pi_a[0], proof.pi_a[1]], - pi_b: [[proof.pi_b[0][1], proof.pi_b[0][0]], [proof.pi_b[1][1], proof.pi_b[1][0]]], - pi_c: [proof.pi_c[0], proof.pi_c[1]], + proof: "0x" + flatProof.map(x => toHex32(x)).join("") }; if (proof.publicSignals) { - result.publicSignals = proof.publicSignals; + result.publicSignals = hexifyBigInts(unstringifyBigInts(proof.publicSignals)); } - return hexifyBigInts(unstringifyBigInts(result)); + return result; } function genWitness(input, circuitJson) { const circuit = new Circuit(unstringifyBigInts2(circuitJson)); - const witness = circuit.calculateWitness(input); + const witness = circuit.calculateWitness(unstringifyBigInts2(input)); const publicSignals = witness.slice(1, circuit.nPubInputs + circuit.nOutputs + 1); return {witness, publicSignals}; } @@ -6617,7 +6684,7 @@ async function genWitnessAndProve(groth16, input, circuitJson, provingKey) { } module.exports = {bigInt2BytesLE, bigInt2U32LE, toSolidityInput, genWitnessAndProve}; -},{"../tools/stringifybigint":19,"big-integer":8,"snarkjs/src/bigint":13,"snarkjs/src/circuit":15,"snarkjs/src/stringifybigint":16}],19:[function(require,module,exports){ +},{"../tools/stringifybigint":19,"big-integer":8,"tornado-snarkjs/src/bigint":13,"tornado-snarkjs/src/circuit":15,"tornado-snarkjs/src/stringifybigint":16}],19:[function(require,module,exports){ /* Copyright 2018 0kims association. @@ -6642,6 +6709,7 @@ const bigInt = require("big-integer"); module.exports.stringifyBigInts = stringifyBigInts; module.exports.unstringifyBigInts = unstringifyBigInts; module.exports.hexifyBigInts = hexifyBigInts; +module.exports.unhexifyBigInts = unhexifyBigInts; function stringifyBigInts(o) { if ((typeof(o) == "bigint") || (o instanceof bigInt)) { @@ -6694,4 +6762,20 @@ function hexifyBigInts(o) { } } +function unhexifyBigInts(o) { + if ((typeof(o) == "string") && (/^0x[0-9a-fA-F]+$/.test(o))) { + return bigInt(o); + } else if (Array.isArray(o)) { + return o.map(unhexifyBigInts); + } else if (typeof o == "object") { + const res = {}; + for (let k in o) { + res[k] = unhexifyBigInts(o[k]); + } + return res; + } else { + return o; + } +} + },{"big-integer":8}]},{},[2]); diff --git a/src/groth16.js b/src/groth16.js index ddd3989..f5af0ce 100644 --- a/src/groth16.js +++ b/src/groth16.js @@ -22,9 +22,15 @@ const bigInt = require("big-integer"); const groth16_wasm = require("../build/groth16_wasm.js"); const assert = require("assert"); -const inBrowser = (typeof window !== "undefined"); +const inBrowser = (typeof window !== "undefined") || process && process.env && process.env.FOR_BROWSER === "true"; + + let NodeWorker; let NodeCrypto; + +// eslint-disable-next-line no-console +console.log(`Running in browser ${inBrowser}`); + if (!inBrowser) { NodeWorker = require("worker_threads").Worker; NodeCrypto = require("crypto"); @@ -170,7 +176,7 @@ function thread(self) { } // We use the Object.assign approach for the backwards compatibility -// @params Number wasmInitialMemory +// @params Number wasmInitialMemory async function build(params) { const defaultParams = { wasmInitialMemory: 5000 }; Object.assign(defaultParams, params);