[ZK Learning Group 2] Circom workshop #2

Background

  • Circuit verifies if the secret key generates 1 of 3 known public keys.

  • Secret key must be kept hidden. Public keys can be public inputs.

PubKeyGen computes the public key from the provided secret key. GroupSig compares the generated pkGen against the 3 public keys.

pragma circom  2.0.3;

template PubKeyGen(){
    // private key 
    signal input sk_in;
    
    //public key
    signal output pk_out;

    //computes pk_out from sk_in
}


template GroupSig (){
    // private key
    signal input sk;

    //public keys
    signal input pk1;
    signal input pk2;
    signal input pk3;

    // has one input signal, and one output signal
    component pkGen = PubKeyGen();
    pkGen.sk_in <== sk;

    signal pk;
    pk <== pkGen.pk_out;

    // if pk generated matches 1 of the public key, will be 0
    //(pk - pk1) * (pk - pk2) * (pk - pk3) === 0; <- this is not qudratic, so split it up
    interm <== (pk - pk1) * (pk - pk2)
    interm * (pk - pk3) === 0;
    
} 

component main { public [pk1, pk2 pk3] } = GroupSig();

/* INPUT = {
    "sk":,
    "pk1":,
    "pk2":,
    "pk3":
} */

We can replace PubKeyGen with a 1-way hash function that is snark-friendly (friendly in that its low gas).

The alternative is to use a signature scheme to generate the actual pub key - which is gas-intensive.

  • Snark-friendly hash functions: MIMC and poseidon

Paranthesis & params

template Num2Bits(nBits){
    signal input x;
    
    // array of length: nBits
    signal output b[nBits];
    
    // loop gets flatten at compile time 
    for (var i = 0; i < nBits; i++) {
        b[i] <-- x \ (2 ** i) % 2;
    }

}

Allows you to enter values that are params

  • params are for dynamic parts of the circuit

  • like counter of a for loop

  • must be specified by compile time. cos the compiled circuit cannot have such dynamic parts like loops.

Last updated

Was this helpful?