WEB3DEV

Cover image for Como Construir Seu Primeiro zkApp no Protocolo Mina com o SnarkyJS
Panegali
Panegali

Posted on

Como Construir Seu Primeiro zkApp no Protocolo Mina com o SnarkyJS

Aproveite o poder das provas de conhecimento zero (ZKPs) para criar zkApps para privacidade e escalabilidade no Protocolo Mina.


Provas de conhecimento zero (ZKPs) já estão revolucionando o mundo das blockchains. Seja agrupando milhares de transações juntas ou fornecendo computação verificável a custos de gás drasticamente reduzidos, essas maravilhas matemáticas estão se mostrando um impulso que conduzirá a tecnologia blockchain para sua próxima era.

Naturalmente, os desenvolvedores estão muito animados com a perspectiva de aprender a usar novas ferramentas alimentadas por ZKPs e construir suas próprias aplicações de conhecimento zero ou zkApps.

Mina é uma blockchain de Camada 1 construída do zero usando ZKPs. Os desenvolvedores podem usar a criptografia de ponta que alimenta o Mina para construir zkApps com o SnarkyJS, uma biblioteca TypeScript.

Neste artigo, você construirá sua primeira zkApp com o SnarkyJS. Você aprenderá o básico de como as ZKPs funcionam, como configurar seu ambiente de desenvolvimento e como escrever seus próprios zkApps.

O que são Provas de Conhecimento Zero?

Uma ZKP permite provar que uma determinada afirmação é verdadeira sem revelar informações adicionais. Se isso parece confuso, vamos analisar um exemplo do mundo real: o popular jogo de busca "Where's Waldo" (Onde está Waldo).

Exemplo: Where's Waldo

O objetivo do jogo é encontrar o personagem Waldo, mas como você pode mostrar que descobriu Waldo sem revelar sua localização? Se você apontar para Waldo na imagem, qualquer pessoa verá exatamente onde encontrá-lo!

Existe uma maneira diferente, no entanto:

  1. Pegue um pedaço enorme de papelão. Ele precisa ser muito maior do que a imagem do jogo "Where's Waldo".
  2. Recorte um buraco em forma de Waldo no papelão.
  3. Coloque o papelão sobre a imagem do jogo e alinhe o buraco em forma de Waldo exatamente com o Waldo na imagem.
  4. Mostre a imagem do jogo "Where's Waldo" com o papel colocado sobre ela.

Agora você pode provar que sabe onde está Waldo. Todos podem ver Waldo através do buraco. Se o seu papelão for grande o suficiente, ninguém poderá ver onde você o colocou na imagem do jogo sem olhar atrás do papelão. Você provou seu conhecimento sobre a localização de Waldo e nenhuma informação adicional foi revelada, ou em termos de programação: sua função de prova apenas retornou um booleano, sem coordenadas 2D.

Um dos arquitetos do Mina, Brandon Kase, explica isso com mais detalhes no vídeo acima.

Usando ZKPs em Sua Aplicação

Agora que você sabe o que é uma prova de conhecimento zero... e daí? Bem, acontece que as ZKPs são extremamente poderosas e podem ser usadas para muitos casos de uso, incluindo escalabilidade e privacidade, ambos aspectos importantes a serem considerados ao desenvolver em blockchain. Vamos comparar as ZKPs com alguns outros princípios criptográficos primeiro:

Image description

https://docs.minaprotocol.com/zkapps

Funções de Hash Unidirecionais

Uma função de hash unidirecional permite a verificação da integridade dos dados.

Ao gerar uma saída de comprimento fixo quando fornecidos alguns dados como entrada, você pode verificar se alguns dados são equivalentes a outros; se forem, a função de hash dará a mesma saída.

Assinaturas de Chave Pública

As assinaturas de chave pública são primitivas mais avançadas do que os hashes porque permitem verificar a autenticidade, além da integridade dos dados.

Elas funcionam com pares de chaves pública e privada. Uma chave privada, ou secreta, é conhecida apenas por seu criador e vem com uma chave pública que pode ser publicamente disponível para todos. O criador pode usar a chave privada para assinar uma mensagem, e qualquer pessoa pode usar a chave pública correspondente para verificar se a assinatura pertence à chave privada. Como apenas o criador da chave conhece a chave privada, ninguém mais pode criar uma assinatura válida.

Por exemplo, um desenvolvedor pode assinar binários de software com sua chave privada, e os usuários podem verificar a assinatura usando a chave pública correspondente, garantindo que têm um software autêntico.

Provas de Conhecimento Zero

A criptografia de conhecimento zero é mais complexa do que as funções de hash e assinaturas. Ela nos permite gerar provas não apenas sobre dados, mas também sobre computação.

Como aprendemos anteriormente, as ZKPs permitem provar que você sabe algo sem revelar o que é. Uma ZKP também pode mostrar que você fez algum cálculo com alguns dados, sem revelar esses dados.

Isso pode ser útil em situações em que você não quer compartilhar informações; por exemplo, você poderia provar que sua idade é superior a algum número sem precisar mostrar seu documento de identidade e expor seu endereço, nome completo ou outras informações.

Então, como elas funcionam na prática?

Provas de Conhecimento Zero no Protocolo Mina

Mina é uma rede blockchain de camada 1 construída do zero usando provas de conhecimento zero (ZKPs). Os desenvolvedores podem utilizar a criptografia de ponta que alimenta o Mina para construir zkApps com SnarkyJS, uma biblioteca TypeScript.

Em um zkApp do Mina, existem três etapas:

  • Compilação:

Você, o desenvolvedor zkApp, constrói e implanta um zkApp. O processo de construção cria uma função probatória e uma chave de verificação. A chave de verificação é armazenada na rede Mina.

  • Prova:

Um usuário executa seu zkApp em seu navegador, juntamente com a função probatória. Esta função usa as entradas fornecidas pelo usuário para produzir uma prova. Tudo isso acontece no computador do usuário e não online. Esta prova é incluída (sem as entradas do usuário) em uma transação e enviada para a rede Mina.

  • Verificação:

Os nós na rede Mina então verificam a prova usando a chave de verificação zkApp armazenada na rede durante a etapa de compilação.

Se a prova for válida, os nós processarão a transação e a adicionarão à cadeia. Se a prova for inválida, os nós rejeitarão a transação.

Exemplo: Sudoku

Para ilustrar o conceito, considere um exemplo como o Sudoku. Você pode escrever um zkApp que permite aos usuários provar que resolveram um quebra-cabeça do Sudoku. O usuário envia o quebra-cabeça do Sudoku vazio (por exemplo, a entrada pública) e sua solução preenchida (por exemplo, a entrada privada). Se tiverem uma solução válida, o zkApp produz uma prova. Os nós na rede Mina podem verificar essa prova usando a entrada pública (quebra-cabeça não resolvido) e a chave de verificação.

A solução não é necessária para verificar a prova, apenas para criá-la. Dessa forma, o zkApp permite que qualquer usuário insira qualquer quebra-cabeça do Sudoku e prove que têm uma solução sem revelá-la à rede. Podemos aplicar esse método a milhares de aplicativos que se beneficiariam da privacidade e segurança!

Implementando seu Primeiro zkApp

Agora que você conhece o básico das ZKPs, está pronto para ver algum código.

Pré-requisitos

Existem algumas dependências que você precisará para começar este tutorial:

O primeiro passo para se tornar um desenvolvedor zkApp é instalar o zkapp-cli. Esta ferramenta de linha de comando facilitará a criação, configuração e implantação de projetos zkApp.

Instale com o NPM:

npm install -g zkapp-cli
Enter fullscreen mode Exit fullscreen mode

Confirme que sua instalação funciona com o seguinte comando:

zk -v
Enter fullscreen mode Exit fullscreen mode

Criando um Projeto zkApp

Agora que você instalou suas ferramentas, navegue até seu diretório de trabalho e crie um novo projeto usando o comando zk project. O exemplo nomeará o projeto de D_D-tutorial, mas você pode nomeá-lo como quiser.

zk project D_D-tutorial
Enter fullscreen mode Exit fullscreen mode

O comando zk project também pode criar uma interface do usuário (UI) para o seu projeto (mais sobre isso depois). Por enquanto, selecione none (nenhum):

? Create an accompanying UI project too? …
  next
  svelte
  nuxt
  empty
❯ none

Enter fullscreen mode Exit fullscreen mode

Após o comando ser concluído, você deverá ter um novo diretório chamado D_D-tutorial, que contém o esqueleto do seu projeto, incluindo ferramentas como Prettier (formatação de código), ESLint (análise estática de código) e Jest (estrutura de teste JavaScript).

Você pode dar uma olhada no conteúdo.

cd D_D-tutorial 
ls
Enter fullscreen mode Exit fullscreen mode

A saída deve parecer com isso:

LICENSE
README.md
babel.config.cjs
build
config.json
jest-resolver.cjs
jest.config.js
keys
node_modules
package-lock.json
package.json
src
tsconfig.json
Enter fullscreen mode Exit fullscreen mode

Durante este tutorial, você executará comandos neste diretório e trabalhará com os arquivos de código no diretório ./src. Quando você construir ou implantar seu zkApp, o zkapp-cli transpilará o código TypeScript nesses arquivos para JavaScript no diretório ./build.

Nota: "Transpilar" é um termo específico para transformar código fonte escrito em uma linguagem em outra.

Configurando, Construindo e Implantando

Agora você está na etapa de Compilação conforme explicado acima, mas antes de compilar e implantar, você precisa configurar algumas opções usando o comando zk config:

zk config
Enter fullscreen mode Exit fullscreen mode

Será solicitado que você especifique um name (nome, pode ser qualquer coisa), um URL para implantar e uma taxa (em tokens tMINA) a ser usada ao enviar sua transação de implantação.

O URL é o URL da API GraphQL do Mina que receberá sua transação de implantação e a transmitirá para a rede Mina. Observe que este URL é importante porque determina em qual rede você irá implantar (ou seja, QANet, Rede de Testes, Rede Principal, etc).

Aqui estão valores de exemplo razoáveis:

  • Nome: berkeley
  • URL: https://proxy.berkeley.minaexplorer.com/graphql
  • Taxa: 0.1

Agora você será apresentado com o seguinte prompt:

? Choose an account to pay transaction fees: …
❯ Recover fee payer account from an existing base58 private key
  Create a new fee payer key pair
  NOTE: the private key will be stored in plain text on this computer.
Enter fullscreen mode Exit fullscreen mode

Esta seção permite que você reutilize pares de chaves preexistentes para implantar novos zkApps, economizando a necessidade de acessar repetidamente a torneira (faucet). Como você está implantando pela primeira vez, selecione Create a new fee payer key pair (Criar um novo par de chaves pagador de taxas). Use dev como o nome para a nova conta.

Você deverá ver a seguinte saída:

  ┌──────────────────────────────────┐
  │  Deploy aliases in config.json   │
  ├────────┬────────┬────────────────┤
  │ Name   │ Url    │ Smart Contract │
  ├────────┴────────┴────────────────┤
  │ None found                       │
  └──────────────────────────────────┘

Enter values to create a deploy alias:
✔ Create a name (can be anything): · berkeley
✔ Set the Mina GraphQL API URL to deploy to: · https://proxy.berkeley.minaexplorer.com/graphql
✔ Set transaction fee to use when deploying (in MINA): · 0.1
✔ Choose an account to pay transaction fees: · Create a new fee payer key pair
  NOTE: the private key will be stored in plain text on this computer.
inside create if
✔ Create an alias for this account · dev
✔ Create fee payer key pair at /Users/[username]/.cache/zkapp-cli/keys/dev.json
✔ Create zkApp key pair at keys/berkeley.json
✔ Add deploy alias to config.json

Success!

Next steps:
  - If this is a testnet, request tMINA at:
    https://faucet.minaprotocol.com/?address=[YOUR ADDRESS]&?explorer=minaexplorer
  - To deploy, run: `zk deploy berkeley`

Enter fullscreen mode Exit fullscreen mode

Nota: Estou usando o MacOS. Seus caminhos podem parecer diferentes.

Você criou um par de chaves! Uhuu \o/

Agora você precisa de tokens de rede de teste para implementar zkApps e enviar transações. Felizmente, o zkapp-cli já imprimiu um link conveniente no terminal para levá-lo à torneira. Você pode solicitar tokens para sua nova conta clicando no grande botão "Request" (Solicitar).

Nota: Você pode precisar esperar alguns minutos para que sua transação de financiamento seja incluída em um bloco... parece ser um momento perfeito para um intervalo para chá

/* INTERVALO PARA CHÁ */
Enter fullscreen mode Exit fullscreen mode

Que bebida refrescante!

Agora, você deverá conseguir implementar a partir da sua conta de desenvolvedor:

zk deploy berkeley
Enter fullscreen mode Exit fullscreen mode

O comando lhe dirá para usar o contrato inteligente Adde pedirá que você confirme os detalhes da implantação. Selecione yes.

Você deverá ver a seguinte saída:

> zk deploy berkeley
✔ Build project
✔ Generate build.json
✔ Choose smart contract
  The 'Add' smart contract will be used
  for this deploy alias as specified in config.json.
✔ Generate verification key (takes 10-30 sec)
  Using the cached verification key
✔ Build transaction
✔ Confirm to send transaction

  ┌─────────────────┬─────────────────────────────────────────────────┐
  │ Deploy Alias    │ berkeley                                        │
  ├─────────────────┼─────────────────────────────────────────────────┤
  │ Fee-Payer Alias │ dev                                             │
  ├─────────────────┼─────────────────────────────────────────────────┤
  │ URL             │ https://proxy.berkeley.minaexplorer.com/graphql │
  ├─────────────────┼─────────────────────────────────────────────────┤
  │ Smart Contract  │ Add                                             │
  └─────────────────┴─────────────────────────────────────────────────┘

  Are you sure you want to send (yes/no)? · yes
✔ Send to network

Success! Deploy transaction sent.

Next step:
  Your smart contract will be live (or updated)
  as soon as the transaction is included in a block:
  https://berkeley.minaexplorer.com/transaction/[TRANSACTION HASH]

Enter fullscreen mode Exit fullscreen mode

E é isso! Você implementou seu primeiro zkApp na rede de testes Berkeley. Parabéns!

Entendendo o Código do zkApp

Agora, abra o arquivo ./src/Add.ts para ver o que seu primeiro zkApp faz.

import { Field, SmartContract, state, State, method } from 'snarkyjs';

/**
 * Exemplo Básico
 * Veja https://docs.minaprotocol.com/zkapps para mais informações.
 *
 * O contrato Add inicializa a variável de estado 'num' para ser um valor Field(1) por padrão quando implementado.
 * Quando o método 'update' é chamado, o contrato Add adiciona Field(2) ao seu estado de contrato 'num'.
 *
 * Este arquivo pode ser excluído com segurança e substituído pelo seu próprio contrato.
 */
export class Add extends SmartContract {
  @state(Field) num = State<Field>();

  init() {
    super.init();
    this.num.set(Field(1));
  }

  @method update() {
    const currentState = this.num.getAndAssertEquals();
    const newState = currentState.add(2);
    this.num.set(newState);
  }
}
Enter fullscreen mode Exit fullscreen mode

Como você pode ver, seu contrato inteligente zkApp é bastante simples. Você importa alguns módulos e nomeia seu zkApp como Add estendendo a classe SmartContract. Em seguida, você declara uma variável de estado chamada num usando o decorador @state. Ela é do tipo Field.

O tipoField representa a unidade básica de dados na programação do ZKP; todos os dados que você utiliza na criação de prova SnarkyJS devem ser do tipo Field ou compostos por vários tipos Field. Você pode aprender mais sobre os tipos Field na documentação do SnarkyJS.

Nota: Cada zkApp possui oito campos de 32 bytes de armazenamento on-chain arbitrário. Se o seu estado exceder esse limite, você deve expressá-lo usando árvores de Merkle ou outras estruturas de dados.

Em seguida, você chama a função init() para inicializar o zkApp. Você pode configurar coisas como permissões e valores iniciais nesta função. No nosso exemplo 'Add', você define a variável de estado num como 1.

Agora você chega ao método update, declarado usando o operador @method. Métodos são os componentes básicos dos zkApps. Métodos podem receber argumentos, realizar cálculos e alterar o estado on-chain (semelhante às funções Solidity). Uma prova é gerada quando alguém chama um método e o executa corretamente.

Agora dê uma olhada mais de perto em update:

  @method update() {
    const currentState = this.num.getAndAssertEquals();
    const newState = currentState.add(2);
    this.num.set(newState);
  }
}
Enter fullscreen mode Exit fullscreen mode

Este método não recebe argumentos. Quando é chamado, ele obtém o valor de num e chama o método getAndAssertEquals nele. Isso configura o valor de currentState como o valor on-chain de num e faz uma assertiva de que currentState e num são consequentemente iguais.

Isso pode parecer confuso ou desnecessário, mas ilustra um ponto importante ao usar o SnarkyJS:

Somente tipos e funções integradas do SnarkyJS definem e criam ZKPs.

Você pode usar código JavaScript convencional em seus métodos, mas ele não é incluído na sua prova. Consulte a documentação do Mina para obter mais informações.

Portanto, a primeira linha do método inclui na prova que o zkApp acessou a variável de estado on-chain num e, em seguida, definiu o valor constante currentState como num. Se alguma dessas etapas for ignorada ou feita incorretamente, a prova produzida não será válida durante a verificação.

Por que você precisa do AssertEquals em currentState? Se você apenas incluir o requesito geto valor num on-chain, um usuário poderia definir a constante para algum outro valor com intenções maliciosas.

As duas linhas seguintes são muito mais simples. A segunda linha declara uma nova constante: o valor de currentState mais dois.

A terceira linha define o valor on-chain de num como sendo esse novo número.

Para resumir, o método incrementará um valor on-chain em dois cada vez que for chamado.

Interagindo com seu zkApp

Dê uma olhada no arquivo src/interact.ts incluído, que simulará a interação do usuário com seu novo zkApp implementado.

Nota: Quando você implementa um zkApp, você o constrói e produz uma chave de verificação. A chave de verificação é então enviada para a rede Mina. Quando os usuários desejam usar seu zkApp, eles também o constroem e o executam. Eles usam seu zkApp para criar uma prova, que é então enviada para a rede Mina. Os nós da rede então verificam a prova em relação à chave de verificação que você enviou no momento da implementação.

O script interact é executado localmente. Ele constrói e executa nosso zkApp e, cria uma transação que atualiza o estado on-chain. Você não vai examiná-lo em detalhes aqui, mas sinta-se à vontade para dar uma olhada no arquivo e nos comentários do código dentro dele. É importante observar que ele assina a transação com a chave privada da conta dev que você criou anteriormente. Em produção, os usuários assinariam a transação por meio de sua carteira.

Para executar o script interact, use o seguinte comando:

node build/src/interact.js berkeley
Enter fullscreen mode Exit fullscreen mode

Em seguida, você deverá ver o seguinte:

compile the contract...
build transaction and create proof...
send transaction...

Success! Update transaction sent.

Your smart contract state will be updated
as soon as the transaction is included in a block:
https://berkeley.minaexplorer.com/transaction/[TRANSACTION HASH]
Enter fullscreen mode Exit fullscreen mode

Parabéns! Você acabou de enviar sua primeira transação zkApp!

Pode levar alguns minutos para que a rede inclua a transação em um bloco, mas você pode verificar seu status usando o link no terminal.

Enquanto espera, reserve um momento para pensar sobre o que está acontecendo.

Seu zkApp executou o método update para incrementar a variável de estado on-chain num em 2, produzindo uma prova. Essa prova foi incluída em uma transação, juntamente com as atualizações de estado a serem aplicadas. Enviamos a transação para a rede Mina, que verifica a prova e aplica as atualizações de estado.

Você pode ver o estado do zkApp e as atualizações de estado quando a transação for incluída em um bloco. Primeiro, vá para o link impresso pelo script interact. Isso o levará aos detalhes da sua transação no explorador de blocos Mina Explorer. Encontre a seção Other Accounts Raw e clique em "Toggle raw data" (Alternar dados brutos).

Procure a opção state [8] e veja quais são os valores:

Perfeito - o primeiro elemento no array é a variável numque você inicializou como 1. Em seguida, olhe para a opção update (8). Lá você pode ver appState [8]:

Hurra!

Esta transação aplicou a atualização da conta para adicionar 2 ao estado, resultando em um valor num de 3.

Você também pode verificar o estado atualizado navegando até a página de visão geral da conta do seu zkApp, bem como informações como permissões e transações anteriores. Acesse clicando no endereço na linha Other Accounts Public Keys da página de transação.

Então, é isso. Agora você é um desenvolvedor de zkApp!

Resumo:

Neste artigo, você:

  • Aprendeu sobre ZKPs;
  • Instalou o zkapp-cli;
  • Configurou e construiu seu primeiro zkApp;
  • Implementou esse zkApp na rede de testes Berkeley;
  • Entendeu o contrato inteligente Add passo a passo;
  • Chamou o método update do zkApp para atualizar o estado do zkApp;
  • Verificou o estado do seu zkApp e transações no Mina Explorer.

Acho que você merece uma salva de palmas.

Próximos Passos

Gostou da sua introdução às Provas de Conhecimento Zero, Mina e SnarkyJS?

Se você quiser continuar sua jornada como desenvolvedor de zkApp, que tal tentar construir uma interface do usuário para zkApp com React neste tutorial?

Outros tutoriais estão disponíveis para ensinar conceitos como tokens personalizados, oráculos e recursão. Você pode encontrá-los todos na documentação do Mina.

Se precisar de ajuda, pode fazer suas perguntas também no Discord. Nos vemos lá!


Artigo escrito por Angus Maidment. Traduzido por Marcelo Panegali

Latest comments (0)