Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Getting 'Scalar size does not match' error when proving a simple circuit with addition or subtraction #471

Closed
Maki325 opened this issue Mar 4, 2024 · 1 comment

Comments

@Maki325
Copy link

Maki325 commented Mar 4, 2024

The error can be reproduced by copying the example Multiplier2 template from Circom docs, and replacing the multiplication sign with a plus.

Full code:
./example.circom

pragma circom 2.0.0;

template Multiplier2() {
  signal input a;
  signal input b;
  signal output c;
  c <== a+b;
}

component main = Multiplier2();

./input.json

{
  "a": "100",
  "b": "10"
}

I then run these commands:

circom example.circom --r1cs --wasm --sym

node example_js/generate_witness.js example_js/example.wasm input.json witness.wtns

mkdir powers_of_tau
mkdir zkey
mkdir proof

# Start a new "Powers Of Tau" ceremony
snarkjs powersoftau new bn128 12 powers_of_tau/pot12_0000.ptau -v

# Contribute to the ceremony - Requires random input
openssl rand -base64 32 | snarkjs powersoftau contribute powers_of_tau/pot12_0000.ptau powers_of_tau/pot12_0001.ptau --name="First contribution" -v

# Phase 2
snarkjs powersoftau prepare phase2 powers_of_tau/pot12_0001.ptau powers_of_tau/pot12_final.ptau -v

# Generate .zkey (contain the proving and verification keys together with all phase 2 contributions)
snarkjs groth16 setup example.r1cs powers_of_tau/pot12_final.ptau zkey/example_0000.zkey

# Contribute to the phase 2 of the ceremony - Requires random input
openssl rand -base64 32 | snarkjs zkey contribute zkey/example_0000.zkey zkey/example_0001.zkey --name="1st Contributor Name" -v

# Export the verification key
snarkjs zkey export verificationkey zkey/example_0001.zkey proof/verification_key.json

# Gen proof
snarkjs groth16 prove zkey/example_0001.zkey witness.wtns proof/proof.json proof/public.json

The last command will fail with this error:

[ERROR] snarkJS: Error: Scalar size does not match
    at _multiExp (~/.nvm/versions/node/v18.19.1/lib/node_modules/snarkjs/node_modules/ffjavascript/build/main.cjs:4972:19)
    at WasmCurve.multiExpAffine (~/.nvm/versions/node/v18.19.1/lib/node_modules/snarkjs/node_modules/ffjavascript/build/main.cjs:5009:22)
    at groth16Prove$1 (~/.nvm/versions/node/v18.19.1/lib/node_modules/snarkjs/build/cli.cjs:5768:33)
    at async Object.groth16Prove [as action] (~/.nvm/versions/node/v18.19.1/lib/node_modules/snarkjs/build/cli.cjs:12975:36)
    at async clProcessor (~/.nvm/versions/node/v18.19.1/lib/node_modules/snarkjs/build/cli.cjs:481:27)

And from looking around the code, it's when the _mutiExp function is called for multiexp C. For some reason, in this case the byte lengths for buffBases and buffScalars are both 0. The length of buffBases is used to calculate the nPoints variable, which is 0 because the length is 0, which in turn makes the variable sScalar equal to NaN, because it's trying to divide the length of buffScalars with the sScalar which is 0.

The code in question:

const nPoints = Math.floor(buffBases.byteLength / sGIn);
const sScalar = Math.floor(buffScalars.byteLength / nPoints);
if( sScalar * nPoints != buffScalars.byteLength) {
    throw new Error("Scalar size does not match");
}

I don't know what these calculations mean exactly, so I can't create a fix. But maybe it can just be defaulted to 0 if it's trying to divide with 0, because in that case the scalar size would match.

This is how I would do it:

const nPoints = Math.floor(buffBases.byteLength / sGIn) ?? 0;
const sScalar = Math.floor(buffScalars.byteLength / nPoints) ?? 0;
if( sScalar * nPoints != buffScalars.byteLength) {
    throw new Error("Scalar size does not match");
}

I would use the Nullish coalescing operator, so that if the output of the flooring is NaN or 0 or undefined, it would be converted into a 0, thus still giving, what I think is the correct output.

@Arvolear
Copy link
Contributor

In snarkjs language this error means that "there are no constraints found in that circuit".

Given the example:

pragma circom 2.0.0;

template Multiplier2() {
  signal input a;
  signal input b;
  signal output c;
  
  c <== a + b;
}

component main = Multiplier2();

And the quote from circom documentation:

All constraints must be quadratic of the form A*B + C = 0, where A, B and C are linear combinations of signals.

The following expression c <== a + b; isn't a constraint, so snarkjs can't generate a proof.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants