You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Thanks to @Chengxuan for the help during our discussion this afternoon.
After the discussion, I found that the main reason for the verification failure of the ZKProof generated concurrently for transfers on the contract side is related to the calculateWTNSBin() function.
This function is provided by the witness_calculator.js file, which is generated after compiling the circom file. It reads the witness data from the globally unique WebAssembly instance’s SharedRWMemory functions,which are not promise safe.
async_doCalculateWitness(input,sanityCheck){//input is assumed to be a map from signals to arrays of bigintsthis.instance.exports.init(this.sanityCheck||sanityCheck ? 1 : 0);constkeys=Object.keys(input);varinput_counter=0;keys.forEach((k)=>{consth=fnvHash(k);consthMSB=parseInt(h.slice(0,8),16);consthLSB=parseInt(h.slice(8,16),16);constfArr=flatArray(input[k]);letsignalSize=this.instance.exports.getInputSignalSize(hMSB,hLSB);if(signalSize<0){thrownewError(`Signal ${k} not found\n`);}if(fArr.length<signalSize){thrownewError(`Not enough values for input signal ${k}\n`);}if(fArr.length>signalSize){thrownewError(`Too many values for input signal ${k}\n`);}for(leti=0;i<fArr.length;i++){constarrFr=toArray32(normalize(fArr[i],this.prime),this.n32);for(letj=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}`)thrownewError(err);}}});if(input_counter<this.instance.exports.getInputSize()){thrownewError(`Not all inputs have been set. Only ${input_counter} out of ${this.instance.exports.getInputSize()}`);}}
When using promises for concurrent ZKProof generations, this may lead to multiple different requests returning the same witness value, resulting in identical (and incorrect) contents in the generated public.json and proof.json.
I noticed that @Chengxuan has already submitted a PR #79 to address this issue 👍.
And from the perspective of better checking and protection, is it necessary to validate whether the input values of the circuit correspond to the data in the public signals, after the prove() function call is completed and the public signal is generated?
For example, we could check whether nullifiers[0] is equal to publicSignal[n], and so on.
This may allow us to discover this issue with the ZKProof before it is sent for verification on the contract side.”
The text was updated successfully, but these errors were encountered:
Thank you for your response and detailed explanation.
In our testing, we discovered a solution that might solve the issue of “Wrong witness data generated during concurrent requests using promises".
Whether this solution is suitable for all scenarios needs to be confirmed after a review by the Iden3 team. Therefore, I tried to submit a pull request here: iden3/circom#299.
In the meantime, we will also try using the solution you provided to address the issue.
Thanks to @Chengxuan for the help during our discussion this afternoon.
After the discussion, I found that the main reason for the verification failure of the ZKProof generated concurrently for transfers on the contract side is related to the
calculateWTNSBin()
function.This function is provided by the
witness_calculator.js
file, which is generated after compiling the circom file. It reads the witness data from the globally unique WebAssembly instance’s SharedRWMemory functions,which are not promise safe.When using promises for concurrent ZKProof generations, this may lead to multiple different requests returning the same witness value, resulting in identical (and incorrect) contents in the generated public.json and proof.json.
I noticed that @Chengxuan has already submitted a PR #79 to address this issue 👍.
And from the perspective of better checking and protection, is it necessary to validate whether the input values of the circuit correspond to the data in the public signals, after the prove() function call is completed and the public signal is generated?
For example, we could check whether nullifiers[0] is equal to publicSignal[n], and so on.
This may allow us to discover this issue with the ZKProof before it is sent for verification on the contract side.”
The text was updated successfully, but these errors were encountered: