| @ -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" | |||
| ] | |||