iden3 / circom_old

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

Passing arrays into function #28

Closed kenchangh closed 5 years ago

kenchangh commented 5 years ago

First off, very cool library!

I found that you cannot pass arrays into functions. For example, in the code below, siblings and fnc parameters are arrays.

function processSMT(nlevels, nsiblings, oldRoot,
  siblings, oldKey, oldValue,
  isOld0, newKey, newValue, fnc) {
  component smt = SMTProcessor(nlevels);

  smt.oldRoot <== oldRoot;
  smt.fnc[0] <== fnc[0];
  smt.fnc[1] <== fnc[1];

  smt.oldKey <== oldKey;
  smt.oldValue <== oldValue;
  smt.isOld0 <== isOld0;
  smt.newKey <== newKey;
  smt.newValue <== newValue;

  for (var j=0; j<nsiblings; j++) {
    smt.siblings[j] <== siblings[j];
  }

  return smt.newRoot;
}

The error code I'm getting is:

Error: Invalid signal identifier: main.siblings[0]
    at Circuit.getSignalIdx (/Users/hao/Desktop/Anconia/node_modules/snarkjs/src/circuit.js:131:15)
    at RTCtx.getSignalFullName (/Users/hao/Desktop/Anconia/node_modules/snarkjs/src/calculateWitness.js:217:34)
    at RTCtx.getSignal (/Users/hao/Desktop/Anconia/node_modules/snarkjs/src/calculateWitness.js:203:21)
    at Object.__f [as MultiSMT] (eval at Circuit (/Users/hao/Desktop/Anconia/node_modules/snarkjs/src/circuit.js:46:33), <anonymous>:4:170)
    at RTCtx.triggerComponent (/Users/hao/Desktop/Anconia/node_modules/snarkjs/src/calculateWitness.js:126:41)
    at callComponents.map (/Users/hao/Desktop/Anconia/node_modules/snarkjs/src/calculateWitness.js:166:51)
    at Array.map (<anonymous>)
    at RTCtx.setSignalFullName (/Users/hao/Desktop/Anconia/node_modules/snarkjs/src/calculateWitness.js:165:24)
    at RTCtx.setSignal (/Users/hao/Desktop/Anconia/node_modules/snarkjs/src/calculateWitness.js:103:14)
    at /Users/hao/Desktop/Anconia/node_modules/snarkjs/src/calculateWitness.js:49:17

I have grepped for main.siblings[0] in the circuit.json file but it doesn't exist. So the selector does not exist at all.

I'm happy to work on fixing this, would need your help to point me to how I would add arrays as part of the selectors.

kenchangh commented 5 years ago

I made this work with a workaround

Instead of passing siblings into the function, what I did is to refer the main.siblings[i][j] directly. This is because you can only access the numbers, but not the full array. The main component gives you access to the siblings signal.

function processSMT(transitionIndex, nlevels, nsiblings, oldRoot,
  siblings, oldKey, oldValue,
  isOld0, newKey, newValue) {
  component smt = SMTProcessor(nlevels);

  smt.oldRoot <== oldRoot;
  smt.fnc[0] <== main.fnc[transitionIndex][0];
  smt.fnc[1] <== main.fnc[transitionIndex][1];

  smt.oldKey <== oldKey;
  smt.oldValue <== oldValue;
  smt.isOld0 <== isOld0;
  smt.newKey <== newKey;
  smt.newValue <== main.newValue[transitionIndex];

  for (var j=0; j<nsiblings; j++) {
    smt.siblings[j] <== main.siblings[transitionIndex][j];
  }

  return smt.newRoot;
}
a2468834 commented 2 years ago

Sorry for asking question in a closed issue. Recently, I'm writing some circom circuit and also need to pass some array into a function.

If I wrote this piece of function code

function arrayAvg(in_array, length) {
    var sum = 0;

    for(var index = 0; index < length; index++) {
        sum += in_array[index];
    }

    return sum / length;
}

Then, how can I pass the array into that function within template main()? Maybe in this way(?)

template mainFunc() {
    signal private input in_array[11];
    signal output out;

    var result = arrayAvg(in_array, 11);
}
component main = mainFunc();