Speedrun de ZK: Noir, Circom, Zokrates en 15 mins
Published: 2024-02-09 20:36:30

---
title: Speedrun de ZK: Noir, Circom, Zokrates en 15 mins
published: true
description: 
tags: 
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/usaqj25gsc8sgmy2dw0v.png
# Use a ratio of 100:42 for best results.
# published_at: 2024-01-31 23:37 +0000
---

Hoy tenemos las herramientas para construir votos privados, transacciones anónimas, videojuegos ZK y más de una manera segura y verificable on-chain. Si ya conoces solidity y cómo crear dApps, el siguiente paso es aprender un DSL ZK, es decir un lenguaje de programación enfocado únicamente en construir circuitos ZK. En este artículo nos enfocamos en ejemplos para principiantes para aprender 3 DSLs: Zokrates, Noir y Circom. Para cada uno seguiremos los siguientes pasos:

1. Instalación del DSL
2. Crear una prueba
3. Verificar una prueba

Para crear una prueba crearemos primero un circuito ZK, le pasaremos parámetros como input y él generará una prueba de la computación realizada. Esta prueba se la pasaremos a un smart contract donde podrás agregar tu lógica personalizada. Es importante mencionar que los circuitos son capaces de recibir parámetros privados, y de ahí nace la posibilidad de trabajar con datos privados en un blockchain.

Aemás, al final les dejo una lista de artículos y contenido que me ha servido a mí para aprender sobre ZK.

## Zokrates

![ZK Zokrates Logo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p4ojuztmizan48h7cuqq.png)

### Instalación

```bash
curl -LSfs get.zokrat.es | sh
export PATH=$PATH:/home/YOURUSERNAME/.zokrates/bin
```

### Genera una prueba

Crea un circuito de Zokrates.

`root.zok`
```js
def main(private field a, field b) {
    assert(a * a == b);
    return;
}
```

Ahora compilalo y crea una prueba.

```bash
zokrates compile -i root.zok
zokrates setup
zokrates compute-witness -a 3 9
zokrates generate-proof
```

La prueba está ubicada en `proof.json`.

### Verifica una prueba

Genera un verificador de solidity.

```bash
zokrates export-verifier
```

Esto va a generar un contrato verificador en `verifier.sol`. Deplóyalo y pasa el address en el constructor del siguiente contrato donde puedes agregar lógica personalizada.

```javascript
// SPDX-License-Identifier: MIT

pragma solidity >=0.7.0 <0.9.0;

library Pairing {
    struct G1Point {
        uint X;
        uint Y;
    }
    struct G2Point {
        uint[2] X;
        uint[2] Y;
    }
}

struct Proof {
    Pairing.G1Point a;
    Pairing.G2Point b;
    Pairing.G1Point c;
}

interface IZokratesVerifier {
    function verifyTx(Proof memory proof, uint[1] memory input) external view returns (bool r);
}

contract ZokratesCustomLogic {
    IZokratesVerifier zokratesVerifier;
    uint public publicInput;

    constructor(address zokratesVeriferAddress) {
        zokratesVerifier = IZokratesVerifier(zokratesVeriferAddress);
    }

    function sendProof(Proof memory proof, uint[1] memory input) public {
        // ZK verification
        zokratesVerifier.verifyTx(proof, input);

        // Your custom logic
        publicInput = input[0];
    }
}
```

De esta manera puedes demostrar on-chain que tienes el conocimiento de `a`, tal que `a*a=b` sin revelar `a` que es un parámetros privado. Esta misma arquitectura puede aplicar en proyectos más avanzados donde puedes anonimizar, por ejemplo, al usuario que ejecutó una transacción o a el monto de una transacción.

## Noir

![ZK Noir Logo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oauub5ihspf289xhk4na.jpg)

### Instalación

#### En Linux

```bash
mkdir -p $HOME/.nargo/bin && \
curl -o $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.22.0/nargo-x86_64-unknown-linux-gnu.tar.gz && \
tar -xvf $HOME/.nargo/bin/nargo-x86_64-unknown-linux-gnu.tar.gz -C $HOME/.nargo/bin/ && \
echo -e '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.bashrc && \
source ~/.bashrc
```

#### En MacOs Apple Silicon

```bash
mkdir -p $HOME/.nargo/bin && \
curl -o $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.22.0/nargo-aarch64-apple-darwin.tar.gz && \
tar -xvf $HOME/.nargo/bin/nargo-aarch64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \
echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \
source ~/.zshrc
```

#### En MacOs Intel

```bash
mkdir -p $HOME/.nargo/bin && \
curl -o $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -L https://github.com/noir-lang/noir/releases/download/v0.22.0/nargo-x86_64-apple-darwin.tar.gz && \
tar -xvf $HOME/.nargo/bin/nargo-x86_64-apple-darwin.tar.gz -C $HOME/.nargo/bin/ && \
echo '\nexport PATH=$PATH:$HOME/.nargo/bin' >> ~/.zshrc && \
source ~/.zshrc
```

### Genera una prueba

Genera un nuevo proyecto de noir y prepáralo para recibir parámetros para el proveing.

```bash
nargo new hello_world
cd hello_world
nargo check
```

Ahora pon los inputs en `Prover.toml` y genera la prueba.

`Prover.toml`

```toml
x = "1"
y = "2"
```

```bash
nargo prove
```

La prueba ahora está ubicada en `proofs/hello_world.proof`.

### Verifica la prueba

Genera un verificador en Solidity.

```bash
nargo codegen-verifier
```

El contrato verificador ahora está ubicado en `contract/hello_world/plonk_vk.sol`. Deplóyalo y envía su address como parámetro del siguiente contrato con lógica personalizada.

```javascript
// SPDX-License-Identifier: MIT

pragma solidity >=0.7.0 <0.9.0;

interface INoirVerifier {
    function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool);
}

contract NoirCustomLogic {
    INoirVerifier noirVerifier;
    uint public publicInput;

    constructor(address noirVeriferAddress) {
        noirVerifier = INoirVerifier(noirVeriferAddress);
    }

    function sendProof(bytes calldata _proof, bytes32[] calldata _publicInputs) public {
        // ZK verification
        noirVerifier.verify(_proof, _publicInputs);

        // Your custom logic
        publicInput = uint(_publicInputs[0]);
    }
}
```

De esta manera puedes demostrar on-chain que tienes el conocimiento de `a`, tal que `a!=b`, esto sin revelar `a` que es un parámetros privado. Esta misma arquitectura puede aplicar en proyectos más avanzados donde puedes anonimizar, por ejemplo, al usuario que ejecutó una transacción o a el monto de una transacción.

## Circom

![ZK Circom Logo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iy4t0s8j89ii29beracz.png)

### Instalación

```bash
curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh
git clone https://github.com/iden3/circom.git
cd circom
cargo build --release
cargo install --path circom
npm install -g snarkjs
```

### Genera una prueba

Crea el archivo de circuito y el de inputs de proving.

`multiplier2.circom`

```js
pragma circom 2.0.0;

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

 component main = Multiplier2();
```

`input.json`

```json
{"a": "3", "b": "11"}
```

Ahora genera una prueba.

```bash
circom multiplier2.circom --r1cs --wasm --sym --c
node multiplier2_js/generate_witness.js multiplier2_js/multiplier2.wasm input.json witness.wtns
snarkjs powersoftau new bn128 12 pot12_0000.ptau -v
snarkjs powersoftau contribute pot12_0000.ptau pot12_0001.ptau --name="First contribution" -v
snarkjs powersoftau prepare phase2 pot12_0001.ptau pot12_final.ptau -v
snarkjs groth16 setup multiplier2.r1cs pot12_final.ptau multiplier2_0000.zkey
snarkjs zkey contribute multiplier2_0000.zkey multiplier2_0001.zkey --name="1st Contributor Name" -v
snarkjs zkey export verificationkey multiplier2_0001.zkey verification_key.json
snarkjs groth16 prove multiplier2_0001.zkey witness.wtns proof.json public.json
snarkjs groth16 verify verification_key.json public.json proof.json
snarkjs generatecall
```

La prueba será impresa en la terminal en el formato que espera Remix.

### Verifica la prueba

Genera el verificador de Solidity.

```bash
snarkjs zkey export solidityverifier multiplier2_0001.zkey verifier.sol
```

Esto generará el contrato verificador en `verifier.sol`. Deplóyalo y pasa su address como parámetro de constructor del contrato con lógica personalizada a continuación.

```javascript
// SPDX-License-Identifier: MIT

pragma solidity >=0.7.0 <0.9.0;

interface ICircomVerifier {
    function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[1] calldata _pubSignals) external view returns (bool);
}

contract CircomCustomLogic {
    ICircomVerifier circomVerifier;
    uint public publicInput;

    constructor(address circomVeriferAddress) {
        circomVerifier = ICircomVerifier(circomVeriferAddress);
    }

    function sendProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[1] calldata _pubSignals) public {
        // ZK verification
        circomVerifier.verifyProof(_pA, _pB, _pC, _pubSignals);

        // Your custom logic
        publicInput = _pubSignals[0];
    }
}
```

De esta manera puedes demostrar on-chain que tienes el conocimiento de `a` y `b`, tal que `a*b=c`, esto sin revelar `a` y `b` que son parámetros privados. Esta misma arquitectura puede aplicar en proyectos más avanzados donde puedes anonimizar, por ejemplo, al usuario que ejecutó una transacción o a el monto de una transacción.

Para más información visita la documentación oficial de [Zokrates](https://zokrates.github.io/gettingstarted.html), [Noir](https://noir-lang.org/docs/), y [Circom](https://docs.circom.io/getting-started/installation/).

También te dejo un par de tutoriales que yo he hecho o información que me ha servido a mí para aprender a desarrollar sobre esta tecnología:

* [Playlist de ZK-ES](https://www.youtube.com/watch?v=dSlhXtvgbI8&list=PL5LoUunXvIgI2LSiD1xH6MNIHOvMn4SHN), workshops por Filosofía Código y Layer2 en Español
* [Ejemplos de Noir](https://noir-by-example.org/)
* [Awesome Noir](https://github.com/noir-lang/awesome-noir), artículos varios para aprender Noir
* [Introducción a Plonk](https://www.youtube.com/watch?v=Uldlq35Se3k), vistazo a las matemáticas detrás de Plonk
* [ZK MOOC](https://www.youtube.com/watch?v=bGEXYpt3sj0), estudio sobre el origen y fundamentos matemáticos sobre ZK

**¡Gracias por leer este artículo!**

Sígueme en dev.to y en [Youtube](https://www.youtube.com/channel/UCNRB4tgwp09z4391JRjEsRA) para todo lo relacionado al desarrollo en Blockchain en Español.