> For the complete documentation index, see [llms.txt](https://calnix.gitbook.io/zk-notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://calnix.gitbook.io/zk-notes/0xparc-zk-learning-group/zk-learning-group-2-circom-workshop-2.md).

# \[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.

```solidity
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.

{% hint style="info" %}

* Snark-friendly hash functions: MIMC and poseidon
  {% endhint %}

### Paranthesis & params

```circom
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.
