Vamos a dar una revisada rápida de lo que necesitamos para construir una zkdapp en la layer 2 de Scroll usando NOIR para crear nuestro circuito de cero conocimiento implementando un pequeño ejemplo de como hacerlo paso a paso. No te preocupes si no tienes un conocimiento profundo del tema, el objetivo de hoy es que te lleves una probadita de esta tecnología, si terminas enganchado como me pasó a mí, estate atento que en posteriores post iremos profundizando más sobre este tema.


Índice


Construir dapps es genial, pero ¿sabías que construir zkdapps es más emocionante? Si!!, entonces estás listo para sentir un poco de entusiasmo mientras construyes circuitos, únete y continúa leyendo para juntos explorar algunas complejidades sobre la construcción de dapps habilitadas para ZK. Al final del artículo habremos creado un zkdapp simple para verificar si adivinaste o no el año en que la comunidad se unió a YouTube. .

Si alguno de los términos te suena algo extraño, no te preocupes, estás en buenas manos, analicémoslo poco a poco.

Aplicaciones descentralizadas (Dapps): son programas informáticos creados para ejecutarse en una cadena de bloques, generalmente escritos en lenguajes como Solidity para cadenas EVM, Rust para polkadot, solana, etc.

Zkdapps: también son aplicaciones descentralizadas que se ejecutan en blockchain, pero tienen más funcionalidades adicionales al aprovechar primitivas de conocimiento cero.

¿Qué es exactamente la prueba de conocimiento cero?

La prueba de conocimiento cero (ZKP) permite a una parte (probador) afirmar que conoce un secreto que satisface algunas restricciones sin revelar nada más que el reclamo a la otra entidad (verificador). Por ejemplo, puedo afirmar que adiviné el año en el que Solow se unió a la plataforma de YouTube sin revelar el año que mencionó para esta adivinanza. En esencia, se puede decir que ZK permite la comunicación entre sistemas sin revelar más de lo necesario.

Hay 3 componentes involucrados en este sistema:

  • Prover: Una parte que afirma conocer al testigo (los datos secretos).
  • Verificador: La parte que verifica la afirmación del probador de conocer al testigo.
  • Testigo: el valor secreto que solo conoce el probador, que no debe compartirse con el verificador durante todas sus interacciones.

Una prueba de conocimiento cero válida debe cumplir las siguientes condiciones:

  • Integridad: Si la prueba es válida, debe ser aceptada por el verificador.
  • Solidez: Si la prueba no es válida, debe ser rechazada por el verificador.
  • Conocimiento cero: el verificador no obtiene ninguna información sobre el testigo más que la afirmación de que el probador lo sabe.

Los ZKP se pueden usar para resolver los desafíos de privacidad y escalabilidad en blockchain, se pueden aplicar de tal manera que se genere prueba para cada bloque de transacción y en lugar de que los operadores en la red verifiquen cada transacción, verifican la prueba generada y esto puede realizar operaciones más rápido.

Introducción a Scroll

Scroll es un Zk-Rollup de capa 2 creado para abordar los problemas de escalabilidad asociados con Ethereum al poder procesar más transacciones a un ritmo muy rápido sin sacrificar la descentralización o la seguridad; tiene compatibilidad de código de bytes con la máquina virtual Ethereum (EVM), lo que significa que su flujo de trabajo existente basado en cadenas EVM también se puede aplicar a Scroll. También utiliza ETH como moneda nativa que se utilizará para pagar la ejecución de sus transacciones.

Configuración

Implementaremos en la red de pruebas Scroll Sepolia para este tutorial si aún no lo has configurado, sigue estos detalles para agregar la red a tu billetera.

  1. Abre este link: https://sepolia.scroll.io/bridge
  2. Conecta tu wallet a la red Scroll Sepolia, fíjate que los datos deben ser los de acá abajo.
  3. Faucet: Después de agregar la red, se deben tener fondos, estos los puedes obtener fondos faucet desde aquí

Presentación del Lenguaje Noir

Noir es un lenguaje de código abierto y de propósito general para escribir programas de conocimiento cero. Los programas Noir, cuando se compilan, son deliberadamente independientes del sistema, lo que los hace compatibles con cualquier sistema backend de prueba de su elección, como PLONK, Groth16, Marlin, etc.

Noir se creó para ayudarnos a los desarrolladores a comenzar a escribir circuitos fácilmente sin tener que conocer los aspectos internos de la criptografía.

Noir utiliza un método de compilación único que no produce circuitos o restricciones directamente, sino que genera un formato intermedio conocido como Representación Intermedia de Circuito Abstracto (ACIR). Es digno de mención aquí la flexibilidad que proporciona ACIR; después de crear un programa en ACIR, se puede transformar en restricciones adecuadas para cualquier backend criptográfico de su elección.

Este enfoque es similar a la estructura de las aplicaciones informáticas, que se dividen en un front-end y un back-end. Noir sirve como interfaz con una sintaxis inspirada en Rust, traduciendo programas al formato ACIR. Posteriormente, el back-end procesa ACIR para producir código de máquina adaptado a arquitecturas informáticas específicas. Este diseño nos permite poder escribir el programa en Noir y tener el programa de verificación basado en otra arquitectura. En nuestro tutorial escribiremos el circuito en Noir y el componente de verificación estará en un smart contract escrito en lenguaje Solidity que luego implementaremos en el Scroll Testnet.

Instalación

Abra una terminal en su máquina y escriba:


curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash
source ~/.bashrc

Cierra la terminal, abre otra y ejecuta:


noirup

Hecho. Eso es todo. Deberías tener la última versión funcionando. Puedes consultar con:


nargo –version

Al ejecutar el comando anterior debes visualizar en tu terminal algo similar a esto: 

Construye una ZKDAPP con Noir en Scroll

Nota: Dado que Noir es un DSL basado en Rust, aquí tienes acceso a algunas de las funcionalidades de Rust. Nargo es el equivalente de Cargo en Rust, que sirve como administrador de paquetes, y también puedes escribir las configuraciones de tu proyecto en Nargo.toml como lo harías en Cargo.toml para un programa en rust.

Extensión Vscode: para resaltar la sintaxis y tener una mejor experiencia codeando en NOIR puedes instalar la extensión para el lenguaje NOIR aquí

¡Es hora de construir!

Ahora que hemos instalado las herramientas necesarias, estamos listos para construir nuestro programa zk. Nuestro programa permitirá al usuario generar pruebas de adivina o no el año en el que la comunidad de Solow Cripto se unió a la plataforma de youtube sin revelar el año exacto al público.

Para inicializar nuestro proyecto, ejecute esto en su terminal


nargo new zkAgeProof

Esto generará la plantilla de un proyecto noir, abra la carpeta zkYearProof en su editor. Debería ver algo como esto:

Construye una ZKDAPP con Noir en Scroll

A continuación te explico lo que significan los archivos que se crearon:

Nargo.toml contiene los detalles y configuraciones de nuestro proyecto.

main.nr es el punto de entrada de su proyecto y contiene un proyecto ficticio generado para nosotros cuando inicializamos el proyecto. El código aquí acepta dos entradas; para que se cumpla el sistema de restricciones, las dos entradas no deben ser iguales. Las variables son privadas de forma predeterminada en Noir, por lo que para hacerlas visibles para otros debes agregar la palabra clave pub a la variable.

Para ejecutar el programa se usa este comando:


nargo check

¡Hora de evaluar!

Para evaluar si el sistema de restricciones tiene algún error, esto generará dos (2) archivos nuevos que son importantes para los próximos pasos, estos archivos son:

Prover.toml Aquí es donde agregaremos las variables de entrada necesarias según las restricciones; su archivo debería verse así en este momento.

Construye una ZKDAPP con Noir en Scroll

Verifier.toml Si observa que este archivo tiene solo una variable y, esto se debe a que es la única entrada marcada como pública en nuestras restricciones.

Construye una ZKDAPP con Noir en Scroll

Ahora agregue 2 números diferentes de su elección a Prover.toml


nargo prove

Ejecuta el comando anterior en tu terminal para generar las pruebas para este sistema.

Ahora hemos generado con éxito la prueba para este sistema de restricciones utilizando los valores que enviamos en nuestro Prover.toml. Puede notar que Verifier.toml se actualizó con la entrada pública que ingresamos, por lo que cada vez que un verificador quiera verificar un reclamo deberá pasar la entrada pública y la prueba para saber si un reclamo es válido o no.

Para obtener información detallada de los circuitos, escribe esto en tu terminal


nargo info

¡Hora de ajustar!

Ahora debemos hacer algunos ajustes en el archivo main.nr para incluir nuestra lógica para la prueba del año.

use dep::std;


fn main(year: u32, guess_year: Field, yearHash: pub Field) {
    assert(year == guess_year as u32);

    // Check integrity of year hash
    let computed_hash = std::hash::pedersen_commitment([guess_year]);
    assert(computed_hash.x == yearHash);
}

#[test]
fn test_main() {
    let year_hash = std::hash::pedersen_commitment([2022]);
    std::println(year_hash);
    main(2022, 2022, year_hash.x);
}

Reemplace el contenido con el siguiente

Queremos que este programa se utilice para generar pruebas de que una determinada persona adivina el año en el que Solow Cripto se unió a la plataforma de youtube. Para generar la prueba, primero debemos hacer uso de la biblioteca estándar de NOIR para poder utilizar la funcionalidad que proporciona.

Se requiere que el probador pase tres (3) entradas: el año correcto que corresponde al año en el que se unió Solow a youtube, año que adivina y el hash del año correcto, ya que no queremos revelar el año correcto ni el año que adivina, los haremos privados, por si es necesario entrada pública, les exigimos que pasen el hash del año correcto y los circuitos evaluarán las entradas para ver que satisfacen las condiciones requeridas.

Nota: Si tu programa zk requiere hash, se recomienda utilizar funciones hash que tengan propiedades homomórficas como pedersen, poseidon, etc. para permitir la generación de hash conciso y computacionalmente eficiente para evitar un tiempo de prueba más largo en tu sistema.

Ahora, para probar la funcionalidad de nuestro sistema de restricciones, ejecuta esto en tu terminal.


nargo test –show-output

El resultado en la terminal que deberías tener es el siguiente. Toma nota de pedersen.x, será necesario para generar la prueba, ya que ese es el hash del año de entrada.

Para generar nuestra prueba, necesitamos hacer ajustes en el archivo Prover.toml para acomodar la entrada requerida. Usando lo que hay en nuestra prueba, tu Prover.toml debería ser así:

Puedes seguir adelante y generar la prueba usando el comando:


nargo prove

Contrato Verificador

Ahora que hemos generado pruebas para objetivo del tutorial, lo siguiente es obtener el contrato del verificador, para esto ejecute:


nargo codegen-verifier

Esto generará el código necesario para el smart contract en: ../contract/zkYearProof/plonk_vk.sol

El contrato se verá asi:

Ahora, utilizando REMIX y habilitando la optimización a 2000 dentro de las opciones avanzadas del compilador se debe de hacer el deploy con el proveedor inyectado conectado a Scroll Sepolia, implemente este contrato y copie la dirección, para que podamos usarlo en nuestro contrato lógico personalizado:


// 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 YearVerifier {
    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]);
    }
}

Para implementar este contrato, pasa a la dirección del primer contrato implementado anteriormente.

Ahora llama a la función sendproof y pasa la prueba de proofs/zkYearProof.proof anteponiendo el “0x” y la entrada pública de Verifier.toml

Resumen

Ahora hemos creado con éxito un programa zk para demostrar que puedes adivinar en qué año se unió Solow Cripto a la plataforma de youtube sin revelar el año con el cual estas queriendo adivinar en el lenguaje Noir, e implementamos la verificación y el contrato personalizado en scroll.

Puedes acceder al código aquí. 

Recursos