@ -1,35 +0,0 @@ |
|||||
#!/usr/bin/env node
|
|
||||
|
|
||||
const fs = require("fs"); |
|
||||
const {stringifyBigInts, unstringifyBigInts} = require("snarkjs"); |
|
||||
const WitnessCalculatorBuilder = require("./witness_calculator.js"); |
|
||||
|
|
||||
// const wasmName = "smtverifier10.wasm"
|
|
||||
// const inputName = "smtverifier10-input.json"
|
|
||||
|
|
||||
const wasmName = "nconstraints.wasm" |
|
||||
const inputName = "nconstraints-input.json" |
|
||||
|
|
||||
async function run () { |
|
||||
const wasm = await fs.promises.readFile(wasmName); |
|
||||
const input = unstringifyBigInts(JSON.parse(await fs.promises.readFile(inputName, "utf8"))); |
|
||||
|
|
||||
console.log("input:", input); |
|
||||
let options; |
|
||||
const wc = await WitnessCalculatorBuilder(wasm, options); |
|
||||
|
|
||||
const w = await wc.calculateWitness(input); |
|
||||
|
|
||||
console.log("witness:\n", JSON.stringify(stringifyBigInts(w))); |
|
||||
|
|
||||
// const wb = await wc.calculateBinWitness(input);
|
|
||||
|
|
||||
// console.log("witnessBin:", Buffer.from(wb).toString('hex'));
|
|
||||
|
|
||||
// await fs.promises.writeFile(witnessName, JSON.stringify(stringifyBigInts(w), null, 1));
|
|
||||
|
|
||||
} |
|
||||
|
|
||||
run().then(() => { |
|
||||
process.exit(); |
|
||||
}); |
|
@ -0,0 +1,20 @@ |
|||||
|
const wc = require("./witness_calculator.js"); |
||||
|
const { readFileSync, writeFile } = require("fs"); |
||||
|
|
||||
|
if (process.argv.length != 5) { |
||||
|
console.log("Usage: node generate_witness.js <file.wasm> <input.json> <output.wtns>"); |
||||
|
} else { |
||||
|
const input = JSON.parse(readFileSync(process.argv[3], "utf8")); |
||||
|
|
||||
|
const buffer = readFileSync(process.argv[2]); |
||||
|
wc(buffer).then(async witnessCalculator => { |
||||
|
// const w= await witnessCalculator.calculateWitness(input,0);
|
||||
|
// for (let i=0; i< w.length; i++){
|
||||
|
// console.log(w[i]);
|
||||
|
// }
|
||||
|
const buff= await witnessCalculator.calculateWTNSBin(input,0); |
||||
|
writeFile(process.argv[4], buff, function(err) { |
||||
|
if (err) throw err; |
||||
|
}); |
||||
|
}); |
||||
|
} |
@ -0,0 +1,337 @@ |
|||||
|
module.exports = async function builder(code, options) { |
||||
|
|
||||
|
options = options || {}; |
||||
|
|
||||
|
let wasmModule; |
||||
|
try { |
||||
|
wasmModule = await WebAssembly.compile(code); |
||||
|
} catch (err) { |
||||
|
console.log(err); |
||||
|
console.log("\nTry to run circom --c in order to generate c++ code instead\n"); |
||||
|
throw new Error(err); |
||||
|
} |
||||
|
|
||||
|
let wc; |
||||
|
|
||||
|
let errStr = ""; |
||||
|
let msgStr = ""; |
||||
|
|
||||
|
const instance = await WebAssembly.instantiate(wasmModule, { |
||||
|
runtime: { |
||||
|
exceptionHandler : function(code) { |
||||
|
let err; |
||||
|
if (code == 1) { |
||||
|
err = "Signal not found.\n"; |
||||
|
} else if (code == 2) { |
||||
|
err = "Too many signals set.\n"; |
||||
|
} else if (code == 3) { |
||||
|
err = "Signal already set.\n"; |
||||
|
} else if (code == 4) { |
||||
|
err = "Assert Failed.\n"; |
||||
|
} else if (code == 5) { |
||||
|
err = "Not enough memory.\n"; |
||||
|
} else if (code == 6) { |
||||
|
err = "Input signal array access exceeds the size.\n"; |
||||
|
} else { |
||||
|
err = "Unknown error.\n"; |
||||
|
} |
||||
|
throw new Error(err + errStr); |
||||
|
}, |
||||
|
printErrorMessage : function() { |
||||
|
errStr += getMessage() + "\n"; |
||||
|
// console.error(getMessage());
|
||||
|
}, |
||||
|
writeBufferMessage : function() { |
||||
|
const msg = getMessage(); |
||||
|
// Any calls to `log()` will always end with a `\n`, so that's when we print and reset
|
||||
|
if (msg === "\n") { |
||||
|
console.log(msgStr); |
||||
|
msgStr = ""; |
||||
|
} else { |
||||
|
// If we've buffered other content, put a space in between the items
|
||||
|
if (msgStr !== "") { |
||||
|
msgStr += " " |
||||
|
} |
||||
|
// Then append the message to the message we are creating
|
||||
|
msgStr += msg; |
||||
|
} |
||||
|
}, |
||||
|
showSharedRWMemory : function() { |
||||
|
printSharedRWMemory (); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
const sanityCheck = |
||||
|
options |
||||
|
// options &&
|
||||
|
// (
|
||||
|
// options.sanityCheck ||
|
||||
|
// options.logGetSignal ||
|
||||
|
// options.logSetSignal ||
|
||||
|
// options.logStartComponent ||
|
||||
|
// options.logFinishComponent
|
||||
|
// );
|
||||
|
|
||||
|
|
||||
|
wc = new WitnessCalculator(instance, sanityCheck); |
||||
|
return wc; |
||||
|
|
||||
|
function getMessage() { |
||||
|
var message = ""; |
||||
|
var c = instance.exports.getMessageChar(); |
||||
|
while ( c != 0 ) { |
||||
|
message += String.fromCharCode(c); |
||||
|
c = instance.exports.getMessageChar(); |
||||
|
} |
||||
|
return message; |
||||
|
} |
||||
|
|
||||
|
function printSharedRWMemory () { |
||||
|
const shared_rw_memory_size = instance.exports.getFieldNumLen32(); |
||||
|
const arr = new Uint32Array(shared_rw_memory_size); |
||||
|
for (let j=0; j<shared_rw_memory_size; j++) { |
||||
|
arr[shared_rw_memory_size-1-j] = instance.exports.readSharedRWMemory(j); |
||||
|
} |
||||
|
|
||||
|
// If we've buffered other content, put a space in between the items
|
||||
|
if (msgStr !== "") { |
||||
|
msgStr += " " |
||||
|
} |
||||
|
// Then append the value to the message we are creating
|
||||
|
msgStr += (fromArray32(arr).toString()); |
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
class WitnessCalculator { |
||||
|
constructor(instance, sanityCheck) { |
||||
|
this.instance = instance; |
||||
|
|
||||
|
this.version = this.instance.exports.getVersion(); |
||||
|
this.n32 = this.instance.exports.getFieldNumLen32(); |
||||
|
|
||||
|
this.instance.exports.getRawPrime(); |
||||
|
const arr = new Uint32Array(this.n32); |
||||
|
for (let i=0; i<this.n32; i++) { |
||||
|
arr[this.n32-1-i] = this.instance.exports.readSharedRWMemory(i); |
||||
|
} |
||||
|
this.prime = fromArray32(arr); |
||||
|
|
||||
|
this.witnessSize = this.instance.exports.getWitnessSize(); |
||||
|
|
||||
|
this.sanityCheck = sanityCheck; |
||||
|
} |
||||
|
|
||||
|
circom_version() { |
||||
|
return this.instance.exports.getVersion(); |
||||
|
} |
||||
|
|
||||
|
async _doCalculateWitness(input, sanityCheck) { |
||||
|
//input is assumed to be a map from signals to arrays of bigints
|
||||
|
this.instance.exports.init((this.sanityCheck || sanityCheck) ? 1 : 0); |
||||
|
const keys = Object.keys(input); |
||||
|
var input_counter = 0; |
||||
|
keys.forEach( (k) => { |
||||
|
const h = fnvHash(k); |
||||
|
const hMSB = parseInt(h.slice(0,8), 16); |
||||
|
const hLSB = parseInt(h.slice(8,16), 16); |
||||
|
const fArr = flatArray(input[k]); |
||||
|
let signalSize = this.instance.exports.getInputSignalSize(hMSB, hLSB); |
||||
|
if (signalSize < 0){ |
||||
|
throw new Error(`Signal ${k} not found\n`); |
||||
|
} |
||||
|
if (fArr.length < signalSize) { |
||||
|
throw new Error(`Not enough values for input signal ${k}\n`); |
||||
|
} |
||||
|
if (fArr.length > signalSize) { |
||||
|
throw new Error(`Too many values for input signal ${k}\n`); |
||||
|
} |
||||
|
for (let i=0; i<fArr.length; i++) { |
||||
|
const arrFr = toArray32(normalize(fArr[i],this.prime),this.n32) |
||||
|
for (let j=0; j<this.n32; j++) { |
||||
|
this.instance.exports.writeSharedRWMemory(j,arrFr[this.n32-1-j]); |
||||
|
} |
||||
|
try { |
||||
|
this.instance.exports.setInputSignal(hMSB, hLSB,i); |
||||
|
input_counter++; |
||||
|
} catch (err) { |
||||
|
// console.log(`After adding signal ${i} of ${k}`)
|
||||
|
throw new Error(err); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
}); |
||||
|
if (input_counter < this.instance.exports.getInputSize()) { |
||||
|
throw new Error(`Not all inputs have been set. Only ${input_counter} out of ${this.instance.exports.getInputSize()}`); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async calculateWitness(input, sanityCheck) { |
||||
|
|
||||
|
const w = []; |
||||
|
|
||||
|
await this._doCalculateWitness(input, sanityCheck); |
||||
|
|
||||
|
for (let i=0; i<this.witnessSize; i++) { |
||||
|
this.instance.exports.getWitness(i); |
||||
|
const arr = new Uint32Array(this.n32); |
||||
|
for (let j=0; j<this.n32; j++) { |
||||
|
arr[this.n32-1-j] = this.instance.exports.readSharedRWMemory(j); |
||||
|
} |
||||
|
w.push(fromArray32(arr)); |
||||
|
} |
||||
|
|
||||
|
return w; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
async calculateBinWitness(input, sanityCheck) { |
||||
|
|
||||
|
const buff32 = new Uint32Array(this.witnessSize*this.n32); |
||||
|
const buff = new Uint8Array( buff32.buffer); |
||||
|
await this._doCalculateWitness(input, sanityCheck); |
||||
|
|
||||
|
for (let i=0; i<this.witnessSize; i++) { |
||||
|
this.instance.exports.getWitness(i); |
||||
|
const pos = i*this.n32; |
||||
|
for (let j=0; j<this.n32; j++) { |
||||
|
buff32[pos+j] = this.instance.exports.readSharedRWMemory(j); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return buff; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
async calculateWTNSBin(input, sanityCheck) { |
||||
|
|
||||
|
const buff32 = new Uint32Array(this.witnessSize*this.n32+this.n32+11); |
||||
|
const buff = new Uint8Array( buff32.buffer); |
||||
|
await this._doCalculateWitness(input, sanityCheck); |
||||
|
|
||||
|
//"wtns"
|
||||
|
buff[0] = "w".charCodeAt(0) |
||||
|
buff[1] = "t".charCodeAt(0) |
||||
|
buff[2] = "n".charCodeAt(0) |
||||
|
buff[3] = "s".charCodeAt(0) |
||||
|
|
||||
|
//version 2
|
||||
|
buff32[1] = 2; |
||||
|
|
||||
|
//number of sections: 2
|
||||
|
buff32[2] = 2; |
||||
|
|
||||
|
//id section 1
|
||||
|
buff32[3] = 1; |
||||
|
|
||||
|
const n8 = this.n32*4; |
||||
|
//id section 1 length in 64bytes
|
||||
|
const idSection1length = 8 + n8; |
||||
|
const idSection1lengthHex = idSection1length.toString(16); |
||||
|
buff32[4] = parseInt(idSection1lengthHex.slice(0,8), 16); |
||||
|
buff32[5] = parseInt(idSection1lengthHex.slice(8,16), 16); |
||||
|
|
||||
|
//this.n32
|
||||
|
buff32[6] = n8; |
||||
|
|
||||
|
//prime number
|
||||
|
this.instance.exports.getRawPrime(); |
||||
|
|
||||
|
var pos = 7; |
||||
|
for (let j=0; j<this.n32; j++) { |
||||
|
buff32[pos+j] = this.instance.exports.readSharedRWMemory(j); |
||||
|
} |
||||
|
pos += this.n32; |
||||
|
|
||||
|
// witness size
|
||||
|
buff32[pos] = this.witnessSize; |
||||
|
pos++; |
||||
|
|
||||
|
//id section 2
|
||||
|
buff32[pos] = 2; |
||||
|
pos++; |
||||
|
|
||||
|
// section 2 length
|
||||
|
const idSection2length = n8*this.witnessSize; |
||||
|
const idSection2lengthHex = idSection2length.toString(16); |
||||
|
buff32[pos] = parseInt(idSection2lengthHex.slice(0,8), 16); |
||||
|
buff32[pos+1] = parseInt(idSection2lengthHex.slice(8,16), 16); |
||||
|
|
||||
|
pos += 2; |
||||
|
for (let i=0; i<this.witnessSize; i++) { |
||||
|
this.instance.exports.getWitness(i); |
||||
|
for (let j=0; j<this.n32; j++) { |
||||
|
buff32[pos+j] = this.instance.exports.readSharedRWMemory(j); |
||||
|
} |
||||
|
pos += this.n32; |
||||
|
} |
||||
|
|
||||
|
return buff; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
function toArray32(rem,size) { |
||||
|
const res = []; //new Uint32Array(size); //has no unshift
|
||||
|
const radix = BigInt(0x100000000); |
||||
|
while (rem) { |
||||
|
res.unshift( Number(rem % radix)); |
||||
|
rem = rem / radix; |
||||
|
} |
||||
|
if (size) { |
||||
|
var i = size - res.length; |
||||
|
while (i>0) { |
||||
|
res.unshift(0); |
||||
|
i--; |
||||
|
} |
||||
|
} |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
function fromArray32(arr) { //returns a BigInt
|
||||
|
var res = BigInt(0); |
||||
|
const radix = BigInt(0x100000000); |
||||
|
for (let i = 0; i<arr.length; i++) { |
||||
|
res = res*radix + BigInt(arr[i]); |
||||
|
} |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
function flatArray(a) { |
||||
|
var res = []; |
||||
|
fillArray(res, a); |
||||
|
return res; |
||||
|
|
||||
|
function fillArray(res, a) { |
||||
|
if (Array.isArray(a)) { |
||||
|
for (let i=0; i<a.length; i++) { |
||||
|
fillArray(res, a[i]); |
||||
|
} |
||||
|
} else { |
||||
|
res.push(a); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function normalize(n, prime) { |
||||
|
let res = BigInt(n) % prime |
||||
|
if (res < 0) res += prime |
||||
|
return res |
||||
|
} |
||||
|
|
||||
|
function fnvHash(str) { |
||||
|
const uint64_max = BigInt(2) ** BigInt(64); |
||||
|
let hash = BigInt("0xCBF29CE484222325"); |
||||
|
for (var i = 0; i < str.length; i++) { |
||||
|
hash ^= BigInt(str[i].charCodeAt()); |
||||
|
hash *= BigInt(0x100000001B3); |
||||
|
hash %= uint64_max; |
||||
|
} |
||||
|
let shash = hash.toString(16); |
||||
|
let n = 16 - shash.length; |
||||
|
shash = '0'.repeat(n).concat(shash); |
||||
|
return shash; |
||||
|
} |
@ -1 +0,0 @@ |
|||||
{ "a": 3, "b": 11 } |
|
@ -1,3 +0,0 @@ |
|||||
1,2,0,main.a |
|
||||
2,3,0,main.b |
|
||||
3,1,0,main.c |
|
@ -0,0 +1,20 @@ |
|||||
|
const wc = require("./witness_calculator.js"); |
||||
|
const { readFileSync, writeFile } = require("fs"); |
||||
|
|
||||
|
if (process.argv.length != 5) { |
||||
|
console.log("Usage: node generate_witness.js <file.wasm> <input.json> <output.wtns>"); |
||||
|
} else { |
||||
|
const input = JSON.parse(readFileSync(process.argv[3], "utf8")); |
||||
|
|
||||
|
const buffer = readFileSync(process.argv[2]); |
||||
|
wc(buffer).then(async witnessCalculator => { |
||||
|
// const w= await witnessCalculator.calculateWitness(input,0);
|
||||
|
// for (let i=0; i< w.length; i++){
|
||||
|
// console.log(w[i]);
|
||||
|
// }
|
||||
|
const buff= await witnessCalculator.calculateWTNSBin(input,0); |
||||
|
writeFile(process.argv[4], buff, function(err) { |
||||
|
if (err) throw err; |
||||
|
}); |
||||
|
}); |
||||
|
} |
@ -0,0 +1,337 @@ |
|||||
|
module.exports = async function builder(code, options) { |
||||
|
|
||||
|
options = options || {}; |
||||
|
|
||||
|
let wasmModule; |
||||
|
try { |
||||
|
wasmModule = await WebAssembly.compile(code); |
||||
|
} catch (err) { |
||||
|
console.log(err); |
||||
|
console.log("\nTry to run circom --c in order to generate c++ code instead\n"); |
||||
|
throw new Error(err); |
||||
|
} |
||||
|
|
||||
|
let wc; |
||||
|
|
||||
|
let errStr = ""; |
||||
|
let msgStr = ""; |
||||
|
|
||||
|
const instance = await WebAssembly.instantiate(wasmModule, { |
||||
|
runtime: { |
||||
|
exceptionHandler : function(code) { |
||||
|
let err; |
||||
|
if (code == 1) { |
||||
|
err = "Signal not found.\n"; |
||||
|
} else if (code == 2) { |
||||
|
err = "Too many signals set.\n"; |
||||
|
} else if (code == 3) { |
||||
|
err = "Signal already set.\n"; |
||||
|
} else if (code == 4) { |
||||
|
err = "Assert Failed.\n"; |
||||
|
} else if (code == 5) { |
||||
|
err = "Not enough memory.\n"; |
||||
|
} else if (code == 6) { |
||||
|
err = "Input signal array access exceeds the size.\n"; |
||||
|
} else { |
||||
|
err = "Unknown error.\n"; |
||||
|
} |
||||
|
throw new Error(err + errStr); |
||||
|
}, |
||||
|
printErrorMessage : function() { |
||||
|
errStr += getMessage() + "\n"; |
||||
|
// console.error(getMessage());
|
||||
|
}, |
||||
|
writeBufferMessage : function() { |
||||
|
const msg = getMessage(); |
||||
|
// Any calls to `log()` will always end with a `\n`, so that's when we print and reset
|
||||
|
if (msg === "\n") { |
||||
|
console.log(msgStr); |
||||
|
msgStr = ""; |
||||
|
} else { |
||||
|
// If we've buffered other content, put a space in between the items
|
||||
|
if (msgStr !== "") { |
||||
|
msgStr += " " |
||||
|
} |
||||
|
// Then append the message to the message we are creating
|
||||
|
msgStr += msg; |
||||
|
} |
||||
|
}, |
||||
|
showSharedRWMemory : function() { |
||||
|
printSharedRWMemory (); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
const sanityCheck = |
||||
|
options |
||||
|
// options &&
|
||||
|
// (
|
||||
|
// options.sanityCheck ||
|
||||
|
// options.logGetSignal ||
|
||||
|
// options.logSetSignal ||
|
||||
|
// options.logStartComponent ||
|
||||
|
// options.logFinishComponent
|
||||
|
// );
|
||||
|
|
||||
|
|
||||
|
wc = new WitnessCalculator(instance, sanityCheck); |
||||
|
return wc; |
||||
|
|
||||
|
function getMessage() { |
||||
|
var message = ""; |
||||
|
var c = instance.exports.getMessageChar(); |
||||
|
while ( c != 0 ) { |
||||
|
message += String.fromCharCode(c); |
||||
|
c = instance.exports.getMessageChar(); |
||||
|
} |
||||
|
return message; |
||||
|
} |
||||
|
|
||||
|
function printSharedRWMemory () { |
||||
|
const shared_rw_memory_size = instance.exports.getFieldNumLen32(); |
||||
|
const arr = new Uint32Array(shared_rw_memory_size); |
||||
|
for (let j=0; j<shared_rw_memory_size; j++) { |
||||
|
arr[shared_rw_memory_size-1-j] = instance.exports.readSharedRWMemory(j); |
||||
|
} |
||||
|
|
||||
|
// If we've buffered other content, put a space in between the items
|
||||
|
if (msgStr !== "") { |
||||
|
msgStr += " " |
||||
|
} |
||||
|
// Then append the value to the message we are creating
|
||||
|
msgStr += (fromArray32(arr).toString()); |
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
class WitnessCalculator { |
||||
|
constructor(instance, sanityCheck) { |
||||
|
this.instance = instance; |
||||
|
|
||||
|
this.version = this.instance.exports.getVersion(); |
||||
|
this.n32 = this.instance.exports.getFieldNumLen32(); |
||||
|
|
||||
|
this.instance.exports.getRawPrime(); |
||||
|
const arr = new Uint32Array(this.n32); |
||||
|
for (let i=0; i<this.n32; i++) { |
||||
|
arr[this.n32-1-i] = this.instance.exports.readSharedRWMemory(i); |
||||
|
} |
||||
|
this.prime = fromArray32(arr); |
||||
|
|
||||
|
this.witnessSize = this.instance.exports.getWitnessSize(); |
||||
|
|
||||
|
this.sanityCheck = sanityCheck; |
||||
|
} |
||||
|
|
||||
|
circom_version() { |
||||
|
return this.instance.exports.getVersion(); |
||||
|
} |
||||
|
|
||||
|
async _doCalculateWitness(input, sanityCheck) { |
||||
|
//input is assumed to be a map from signals to arrays of bigints
|
||||
|
this.instance.exports.init((this.sanityCheck || sanityCheck) ? 1 : 0); |
||||
|
const keys = Object.keys(input); |
||||
|
var input_counter = 0; |
||||
|
keys.forEach( (k) => { |
||||
|
const h = fnvHash(k); |
||||
|
const hMSB = parseInt(h.slice(0,8), 16); |
||||
|
const hLSB = parseInt(h.slice(8,16), 16); |
||||
|
const fArr = flatArray(input[k]); |
||||
|
let signalSize = this.instance.exports.getInputSignalSize(hMSB, hLSB); |
||||
|
if (signalSize < 0){ |
||||
|
throw new Error(`Signal ${k} not found\n`); |
||||
|
} |
||||
|
if (fArr.length < signalSize) { |
||||
|
throw new Error(`Not enough values for input signal ${k}\n`); |
||||
|
} |
||||
|
if (fArr.length > signalSize) { |
||||
|
throw new Error(`Too many values for input signal ${k}\n`); |
||||
|
} |
||||
|
for (let i=0; i<fArr.length; i++) { |
||||
|
const arrFr = toArray32(normalize(fArr[i],this.prime),this.n32) |
||||
|
for (let j=0; j<this.n32; j++) { |
||||
|
this.instance.exports.writeSharedRWMemory(j,arrFr[this.n32-1-j]); |
||||
|
} |
||||
|
try { |
||||
|
this.instance.exports.setInputSignal(hMSB, hLSB,i); |
||||
|
input_counter++; |
||||
|
} catch (err) { |
||||
|
// console.log(`After adding signal ${i} of ${k}`)
|
||||
|
throw new Error(err); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
}); |
||||
|
if (input_counter < this.instance.exports.getInputSize()) { |
||||
|
throw new Error(`Not all inputs have been set. Only ${input_counter} out of ${this.instance.exports.getInputSize()}`); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async calculateWitness(input, sanityCheck) { |
||||
|
|
||||
|
const w = []; |
||||
|
|
||||
|
await this._doCalculateWitness(input, sanityCheck); |
||||
|
|
||||
|
for (let i=0; i<this.witnessSize; i++) { |
||||
|
this.instance.exports.getWitness(i); |
||||
|
const arr = new Uint32Array(this.n32); |
||||
|
for (let j=0; j<this.n32; j++) { |
||||
|
arr[this.n32-1-j] = this.instance.exports.readSharedRWMemory(j); |
||||
|
} |
||||
|
w.push(fromArray32(arr)); |
||||
|
} |
||||
|
|
||||
|
return w; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
async calculateBinWitness(input, sanityCheck) { |
||||
|
|
||||
|
const buff32 = new Uint32Array(this.witnessSize*this.n32); |
||||
|
const buff = new Uint8Array( buff32.buffer); |
||||
|
await this._doCalculateWitness(input, sanityCheck); |
||||
|
|
||||
|
for (let i=0; i<this.witnessSize; i++) { |
||||
|
this.instance.exports.getWitness(i); |
||||
|
const pos = i*this.n32; |
||||
|
for (let j=0; j<this.n32; j++) { |
||||
|
buff32[pos+j] = this.instance.exports.readSharedRWMemory(j); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return buff; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
async calculateWTNSBin(input, sanityCheck) { |
||||
|
|
||||
|
const buff32 = new Uint32Array(this.witnessSize*this.n32+this.n32+11); |
||||
|
const buff = new Uint8Array( buff32.buffer); |
||||
|
await this._doCalculateWitness(input, sanityCheck); |
||||
|
|
||||
|
//"wtns"
|
||||
|
buff[0] = "w".charCodeAt(0) |
||||
|
buff[1] = "t".charCodeAt(0) |
||||
|
buff[2] = "n".charCodeAt(0) |
||||
|
buff[3] = "s".charCodeAt(0) |
||||
|
|
||||
|
//version 2
|
||||
|
buff32[1] = 2; |
||||
|
|
||||
|
//number of sections: 2
|
||||
|
buff32[2] = 2; |
||||
|
|
||||
|
//id section 1
|
||||
|
buff32[3] = 1; |
||||
|
|
||||
|
const n8 = this.n32*4; |
||||
|
//id section 1 length in 64bytes
|
||||
|
const idSection1length = 8 + n8; |
||||
|
const idSection1lengthHex = idSection1length.toString(16); |
||||
|
buff32[4] = parseInt(idSection1lengthHex.slice(0,8), 16); |
||||
|
buff32[5] = parseInt(idSection1lengthHex.slice(8,16), 16); |
||||
|
|
||||
|
//this.n32
|
||||
|
buff32[6] = n8; |
||||
|
|
||||
|
//prime number
|
||||
|
this.instance.exports.getRawPrime(); |
||||
|
|
||||
|
var pos = 7; |
||||
|
for (let j=0; j<this.n32; j++) { |
||||
|
buff32[pos+j] = this.instance.exports.readSharedRWMemory(j); |
||||
|
} |
||||
|
pos += this.n32; |
||||
|
|
||||
|
// witness size
|
||||
|
buff32[pos] = this.witnessSize; |
||||
|
pos++; |
||||
|
|
||||
|
//id section 2
|
||||
|
buff32[pos] = 2; |
||||
|
pos++; |
||||
|
|
||||
|
// section 2 length
|
||||
|
const idSection2length = n8*this.witnessSize; |
||||
|
const idSection2lengthHex = idSection2length.toString(16); |
||||
|
buff32[pos] = parseInt(idSection2lengthHex.slice(0,8), 16); |
||||
|
buff32[pos+1] = parseInt(idSection2lengthHex.slice(8,16), 16); |
||||
|
|
||||
|
pos += 2; |
||||
|
for (let i=0; i<this.witnessSize; i++) { |
||||
|
this.instance.exports.getWitness(i); |
||||
|
for (let j=0; j<this.n32; j++) { |
||||
|
buff32[pos+j] = this.instance.exports.readSharedRWMemory(j); |
||||
|
} |
||||
|
pos += this.n32; |
||||
|
} |
||||
|
|
||||
|
return buff; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
function toArray32(rem,size) { |
||||
|
const res = []; //new Uint32Array(size); //has no unshift
|
||||
|
const radix = BigInt(0x100000000); |
||||
|
while (rem) { |
||||
|
res.unshift( Number(rem % radix)); |
||||
|
rem = rem / radix; |
||||
|
} |
||||
|
if (size) { |
||||
|
var i = size - res.length; |
||||
|
while (i>0) { |
||||
|
res.unshift(0); |
||||
|
i--; |
||||
|
} |
||||
|
} |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
function fromArray32(arr) { //returns a BigInt
|
||||
|
var res = BigInt(0); |
||||
|
const radix = BigInt(0x100000000); |
||||
|
for (let i = 0; i<arr.length; i++) { |
||||
|
res = res*radix + BigInt(arr[i]); |
||||
|
} |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
function flatArray(a) { |
||||
|
var res = []; |
||||
|
fillArray(res, a); |
||||
|
return res; |
||||
|
|
||||
|
function fillArray(res, a) { |
||||
|
if (Array.isArray(a)) { |
||||
|
for (let i=0; i<a.length; i++) { |
||||
|
fillArray(res, a[i]); |
||||
|
} |
||||
|
} else { |
||||
|
res.push(a); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function normalize(n, prime) { |
||||
|
let res = BigInt(n) % prime |
||||
|
if (res < 0) res += prime |
||||
|
return res |
||||
|
} |
||||
|
|
||||
|
function fnvHash(str) { |
||||
|
const uint64_max = BigInt(2) ** BigInt(64); |
||||
|
let hash = BigInt("0xCBF29CE484222325"); |
||||
|
for (var i = 0; i < str.length; i++) { |
||||
|
hash ^= BigInt(str[i].charCodeAt()); |
||||
|
hash *= BigInt(0x100000001B3); |
||||
|
hash %= uint64_max; |
||||
|
} |
||||
|
let shash = hash.toString(16); |
||||
|
let n = 16 - shash.length; |
||||
|
shash = '0'.repeat(n).concat(shash); |
||||
|
return shash; |
||||
|
} |
@ -1,14 +0,0 @@ |
|||||
template A(n) { |
|
||||
signal input in; |
|
||||
signal output out; |
|
||||
|
|
||||
signal intermediate[n]; |
|
||||
|
|
||||
intermediate[0] <== in; |
|
||||
for (var i=1; i<n; i++) { |
|
||||
intermediate[i] <== intermediate[i-1] * intermediate[i-1] + i; |
|
||||
} |
|
||||
out <== intermediate[n-1]; |
|
||||
} |
|
||||
|
|
||||
component main = A({{N}}); |
|
@ -1,28 +0,0 @@ |
|||||
{ |
|
||||
"pi_a": [ |
|
||||
"6235746210673106891683313862449025023627555115162992763714613342703079170148", |
|
||||
"12399711040178466467332477784020211067450597599035925008336813728555144120335", |
|
||||
"1" |
|
||||
], |
|
||||
"pi_b": [ |
|
||||
[ |
|
||||
"3878778368997395576585378205610237973645840367459368364069435490380759882761", |
|
||||
"6372446288114997398874714591076628465205914797783709795970421045876437438845" |
|
||||
], |
|
||||
[ |
|
||||
"1848758415443668505660007055104065117685874818267116126442518003813688485119", |
|
||||
"13151381207181352787620244234186261096498266850828100859417113864178798435289" |
|
||||
], |
|
||||
[ |
|
||||
"1", |
|
||||
"0" |
|
||||
] |
|
||||
], |
|
||||
"pi_c": [ |
|
||||
"20702909955866523755177574141774962608204777398014771961964213040023134853917", |
|
||||
"11380617408700662148925472638480792573061992967930438232337416544412668869948", |
|
||||
"1" |
|
||||
], |
|
||||
"protocol": "groth16", |
|
||||
"curve": "bn128" |
|
||||
} |
|
@ -1,3 +0,0 @@ |
|||||
[ |
|
||||
"20227169454906525228014700210166866282343639252280745415680311389428188660505" |
|
||||
] |
|