iden3 / snarkjs

zkSNARK implementation in JavaScript & WASM
GNU General Public License v3.0
1.77k stars 421 forks source link

How to fix `wtns calculate` error? #217

Closed 3for closed 2 years ago

3for commented 2 years ago

Hi, I'm following our README guide from step 0 to step 15, and run in snarkjs_example folder:

$ node ../build/cli.cjs wtns calculate  circuit_js/circuit.wasm input.json  witness.wtns
[ERROR] snarkJS: LinkError: WebAssembly.instantiate(): Import #1 module="runtime" function="printErrorMessage" error: function import requires a callable
    at Object.builder [as WitnessCalculatorBuilder] (/Users/lanyu/zyd/snarkjs/node_modules/circom_runtime/build/main.cjs:100:40)
    at async wtnsCalculate$1 (/Users/lanyu/zyd/snarkjs/build/cli.cjs:5856:16)
    at async Object.wtnsCalculate [as action] (/Users/lanyu/zyd/snarkjs/build/cli.cjs:8267:5)
    at async clProcessor (/Users/lanyu/zyd/snarkjs/build/cli.cjs:456:27)

and my env:

$ node -v
v18.7.0
$ circom --version
circom compiler 2.0.7
phated commented 2 years ago

circom 2.0.7 changed the wasm imports. If you are on the bleeding-edge of circom, you need to be using witness calculator that they write to your file system.

It takes us (the snarkjs team) a while to sync the changes to circom_runtime to support the newest circom version

3for commented 2 years ago

Thanks for reply @phated . I've fixed by adding dummy implementation of printErrorMessage and writeBufferMessage func in the runtime module:

const instance = await WebAssembly.instantiate(wasmModule, {
    env: {
        "memory": memory
    },
    runtime: {
        exceptionHandler: function(code) {
            let errStr;
            if (code == 1) {
                errStr = "Signal not found. ";
            } else if (code == 2) {
                errStr = "Too many signals set. ";
            } else if (code == 3) {
                errStr = "Signal already set. ";
            } else if (code == 4) {
                errStr = "Assert Failed. ";
            } else if (code == 5) {
                errStr = "Not enough memory. ";
            } else if (code == 6) {
                errStr = "Input signal array access exceeds the size";
            } else {
                errStr = "Unknown error.";
            }
            console.log("ERROR: ", code, errStr);
            throw new Error(errStr);
        },
        showSharedRWMemory: function() {
            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);
            }
            console.log(ffjavascript.Scalar.fromArray(arr, 0x100000000));
        },
        error: function(code, pstr, a,b,c,d) {
            let errStr;
            if (code == 7) {
                errStr=p2str(pstr) + " " + wc.getFr(b).toString() + " != " + wc.getFr(c).toString() + " " +p2str(d);
            } else if (code == 9) {
                errStr=p2str(pstr) + " " + wc.getFr(b).toString() + " " +p2str(c);
            } else if ((code == 5)&&(options.sym)) {
                errStr=p2str(pstr)+ " " + options.sym.labelIdx2Name[c];
            } else {
                errStr=p2str(pstr)+ " " + a + " " + b + " " + c + " " + d;
            }
            console.log("ERROR: ", code, errStr);
            throw new Error(errStr);
        },
        printErrorMessage: function(a) {
            console.log(wc.getFr(a).toString());
        },
        writeBufferMessage: function(a) {
            console.log(wc.getFr(a).toString());
        },
        log: function(a) {
            console.log(wc.getFr(a).toString());
        },
        logGetSignal: function(signal, pVal) {
            if (options.logGetSignal) {
                options.logGetSignal(signal, wc.getFr(pVal) );
            }
        },
        logSetSignal: function(signal, pVal) {
            if (options.logSetSignal) {
                options.logSetSignal(signal, wc.getFr(pVal) );
            }
        },
        logStartComponent: function(cIdx) {
            if (options.logStartComponent) {
                options.logStartComponent(cIdx);
            }
        },
        logFinishComponent: function(cIdx) {
            if (options.logFinishComponent) {
                options.logFinishComponent(cIdx);
            }
        }
    }
});
phated commented 2 years ago

Those are incorrect and will make your code not work correctly. Don't stub them like that. Don't use snarkjs with Circom 2.0.7 until we properly fix it.

3for commented 2 years ago

Okay, thanks @phated

flyingnobita commented 2 years ago

I got this problem and using circom v2.0.6 indeed fixes it.

Right now the circom doc suggest to git clone and thus we always use the latest circom version. Is there anywhere in the snarkjs docs (or future plans) that suggest the circom version that is fully compatible with snarkjs?

phated commented 2 years ago

The snarkjs maintainers are not the developers of circom anymore and the circom developers don't follow semver. It is a large effort to try to follow behind them to make it work when they break things.

phated commented 2 years ago

This was fixed in circom_runtime 0.1.19 - circom doesn't follow semantic versioning, and as I said it that PR:

This relies on my patch at https://github.com/iden3/circom/pull/105 which added getMinorVersion and getPatchVersion to the WASM exports.

Technically, someone could have a cloned version of circom between the log change and my patch, but we can't really solve that (we will just tell them to pull the latest changes).

Hopefully a new release of snarkjs will be out soon.

remi-gai commented 2 years ago

I'm currently facing the same issue with circom compiler 2.0.8. How can I downgrade or download the 2.0.6 version?

phated commented 2 years ago

Snarkjs 0.4.26 contains the fix

zlemon819 commented 1 year ago

Snarkjs 0.4.26 contains the fix

hi, Is Snarkjs 0.5.0 compatible with Circom compiler 2.1.2 now ? i run "npm run test" in the ed25519/circom directory and come across the same issues as follows: LinkError: WebAssembly.instantiate(): Import #1 module="runtime" function="printErrorMessage" error: function import requires a callable