iden3 / circom_old

Circuit compiler for zkSNARKs
GNU General Public License v3.0
471 stars 82 forks source link

INVALID verify after successful calculatewitness #32

Closed 3q-coder closed 5 years ago

3q-coder commented 5 years ago

There was strange behavior of snarkjs: calculatewitness command ran successful, but verify command returned INVALID. My circuit (github link):

include "../circomlib/circuits/pedersen.circom";
include "../circomlib/circuits/bitify.circom";

component main = Income(2)

template Income(n) {
    signal private input type[n]; // 1 - buy, 0 - sell
    signal private input value[n];
    signal private input salt[n];
    signal input hash[n];
    signal input price[n+1]; // last price is current price
    signal output income;

    component hasher[n];

    for (var i = 0; i<n; i++) {
        hasher[i] = tradeHasher();
        hasher[i].type <== type[i];
        hasher[i].value <== value[i];
        hasher[i].salt <== salt[i];
        hash[i] === hasher[i].hash;
    }

    var curUSD = 0;
    var curBTC = 0;

    for (var i = 0; i<n; i++) {
        if (type[i] == 1) {
            curUSD += -value[i]*price[i];
            curBTC += value[i];
        } else {
            curUSD += value[i]*price[i];
            curBTC += -value[i];
        }
    }

    income <== curUSD + curBTC*price[n];
}

template tradeHasher() {
  signal input type;
  signal input value;
  signal input salt;
  signal output hash;

  component hasher = Pedersen(256);
  var cur = 0;
  var i;

  component b_type = Num2Bits(8);
  b_type.in <== type;
  for (i = 0; i<8; i++) {
    hasher.in[cur] <== b_type.out[i];
    cur+=1;
  }

  component b_value = Num2Bits(136);
  b_value.in <== value;
  for (i = 0; i<136; i++) {
    hasher.in[cur] <== b_value.out[i];
    cur+=1;
  }

  component b_salt = Num2Bits(112);
  b_salt.in <== salt;
  for (i = 0; i<112; i++) {
    hasher.in[cur] <== b_salt.out[i];
    cur+=1;
  }

  hash <== hasher.out[0];

}
czarly commented 5 years ago

have you solved this?

I have the same problem. My circuit is very simple:

include "node_modules/circomlib/circuits/gates.circom";

template Battleship() {
    signal private input data[10][10];
    signal output valid;

    var numFields = 0;
    var sumFields = 0;

    for (var row=0; row<10; row++) {
    for(var col=0; col<10; col++) {
        if (data[row][col] > 0) {
        numFields++;
        sumFields += data[row][col];
        }
    }
    }

    var is20Fields = (numFields == 20);
    var isValidSum = (sumFields == 50);

    component and = AND();
    and.a <-- is20Fields;
    and.b <-- isValidSum;
    and.out === 1;
    valid <-- and.out;
}

component main = Battleship();

UPDATE:

I solved it by removing the IF statement like so:

for (var row=0; row<10; row++) {
    for(var col=0; col<10; col++) {
        numFields += (data[row][col] > 0);
        sumFields += data[row][col];
    }
}
3q-coder commented 5 years ago

I've rewritten my code next way. (use signals for sum instead of variables)

include "tradeHasher.circom";

template Income(n) {
    signal private input type[n]; // 1 - buy, 0 - sell
    signal private input value[n];
    signal private input salt[n];
    signal input hash[n];
    signal input price[n+1]; // last price is current price
    signal output income;

    component hasher[n];

    for (var i = 0; i<n; i++) {
        hasher[i] = tradeHasher();
        hasher[i].type <== type[i];
        hasher[i].value <== value[i];
        hasher[i].salt <== salt[i];
        hash[i] === hasher[i].hash;
    }

    signal curUSD[n+1];
    signal curBTC[n+1];
    curUSD[0] <-- 0;
    curBTC[0] <-- 0;

    for (var i = 0; i<n; i++) {
        if (type[i] == 1) { //buy
            curUSD[i+1] <-- curUSD[i] - value[i]*price[i];
            curBTC[i+1] <-- curBTC[i] + value[i];
        } else { //sell
            curUSD[i+1] <-- curUSD[i] + value[i]*price[i];
            curBTC[i+1] <-- curBTC[i] - value[i];
        }
    }

    income <== curUSD[n] + curBTC[n]*price[n];
}

component main = Income(2)