As provas de conhecimento zero permitem transações privadas e seguras. Com zkSNARKs e zkSTARKs, um provador pode provar a posse de algumas informações a um verificador sem revelar os dados reais.
Isso tem um enorme potencial para anonimato e confidencialidade. Mas zkSTARKs e zkSNARKs são complexos. Risc0 os torna mais acessíveis. Vamos ver sua implementação muito básica:
Este tutorial cobrirá:
Instalação do Risc0
Escrevendo seu primeiro programa à prova de conhecimento zero usando ferrugem
Pré-requisitos:
Copiar e colar atalhos
Instalações necessárias:
Algum conhecimento básico de codificação em ferrugem
Editor de código (VSCODE se possível)
Ao final, você terá experiência prática com provas de conhecimento zero no Risc0. Não é necessário conhecimento avançado em matemática ou criptografia.
Vamos nos concentrar nos fundamentos da codificação para começar a construir soluções do mundo real. Esta introdução prática tem como objetivo tornar a poderosa tecnologia de privacidade compreensível para qualquer desenvolvedor.
(Para MacOS) Para instalar ferrugem e carga, você pode executar o comando abaixo no terminal:
curl [https://sh.rustup.rs](https://sh.rustup.rs/) -sSf | sh
Para instalar o Risc0, execute o comando abaixo após a instalação do Rust e reinicie o terminal:
cargo install cargo-risczero
brew install openssl
brew install pkgconf
risc0
com: cargo risczero install
Isso é tudo que precisamos. Então, vamos para o editor de código.
Agora que concluímos a instalação, você pode ler e seguir estas etapas do abra kadabra 🪄:
Abra o editor de código e vá até o local onde deseja criar seu projeto no terminal do editor.
Crie uma nova instância do projeto usando o comando abaixo no terminal: cargo risczero new multiply
.
Você deverá ver uma pasta criada chamada multiplicar. CD nele. cd multiply
A estrutura de pastas é muito simples.
Temos uma pasta host e uma pasta de métodos.
A pasta host contém o programa host que chamamos de programa convidado. Ele também tem a capacidade de verificar, se desejar.
A pasta de métodos contém o programa convidado que contém a parte do aplicativo zkvm que foi testada. Ele recebe os parâmetros de entrada do host e, com base na lógica, gera resultados, confirma-os no diário e os envia ao host como recibo.
O restante dos arquivos será explicado em qualquer lugar conforme necessário.
Vamos começar com o programa convidado.
Vamos mudar o nome dos arquivos main.rs —> multiply.rs
.
Crie uma pasta chamada bin
na pasta src
e mova mutiply.rs
para ela. Sua estrutura de pastas deve ser semelhante a esta:
Abra Cargo.toml
e altere a atualização para name = "method_name” —> name = "multiply”
.
Adicione o código abaixo em Cargo.toml
.
[[bin]] name = "multiply" path = "src/bin/multiply.rs"
Portanto, seu Cargo.toml
final ficará assim:
Agora, multiply.rs
. Aqui iremos editar a função principal. Esta é a função que será executada no zkvm.
No código abaixo, estamos obtendo a entrada do programa host. Em seguida, garantimos que a entrada não seja um fator trivial, ou seja, 1. Em seguida, calculamos o produto e, finalmente, enviamos-o de volta ao host do programa.
// We will get the values for these variables from host program let a:u64 = env::read(); let b:u64 = env::read(); // To avoid trivial factors like multiplication by 1 if a == 1 || b == 1 { panic!("Trivial factors !!") // The panic! macro in Rust is used to intentionally crash a program when an unrecoverable error occurs } // Caculate the product of the two numbers let product = a.checked_mul(b).expect("Integer Overflow"); // Commit back the output to the host to save it as receipt env::commit(&product);
Após as alterações acima, seu multiply.rs
deverá ficar assim.
Há mais uma alteração final na pasta Cargo.toml
de methods
.
Abra e atualize o valor de name = "multiply-methods”
.
Seu Cargo.toml
final será semelhante ao abaixo.
Nosso trabalho aqui está concluído.
Agora, vamos para o programa host.
Sua pasta host deve estar assim agora.
Queremos dividir main.rs
em dois arquivos que são prover.rs
e verify.rs
.
Crie uma nova pasta em src
e nomeie-a como bin
.
Remova main.rs
. Crie arquivos e nomeie-os como verify.rs
& prove.rs
.
Sua estrutura de pastas deve ser semelhante a esta agora.
Abra prove.rs
e vamos começar a codificar:
Adicione o código abaixo. Estas são as importações que iremos exigir.
use multiply_methods::MULTIPLY_ELF; // It is a binary file of multiply_method use risc0_zkvm::{ default_prover, serde::{from_slice, to_vec}, ExecutorEnv, };
Vamos fazer alterações na função principal.
fn main() { // Declaring our secret input params let a: u64 = 17; let b: u64 = 23; // First, we construct an executor environment let env = ExecutorEnv::builder() .add_input(&to_vec(&a).unwrap()) // Passing the input params to environment so it can be used by gues proggram .add_input(&to_vec(&b).unwrap()) .build() .unwrap(); // Obtain the default prover. let prover = default_prover(); // Produce a receipt by proving the specified ELF binary. let receipt = prover.prove_elf(env, MULTIPLY_ELF).unwrap(); // Extract journal of receipt (ie output c, where c = a * b) let c: u64 = from_slice(&receipt.journal).unwrap(); // Print an assertion println!("Hello, world! I know the factors of {}, and I can prove it!", c); // Let's serialize the receipt so we can save it to an file for verifier program to verify. let serialized = bincode::serialize(&receipt).unwrap(); // Writing the serialized contect to receipt.bin file let _saved_file = match std::fs::write("./receipt.bin", serialized){ Ok(()) => println!("Receipt saved and serialized as receipt.bin"), Err(_) => println!("Something went wrong !!"), }; }
Suas prove.rs
finais devem ser assim.
Vamos abrir e adicionar código ao nosso verify.rs
.
Aqui, importaremos o ID da imagem do programa convidado e algumas importações básicas.
use multiply_methods::MULTIPLY_ID; use risc0_zkvm::Receipt;
Vamos fazer alterações na função principal.
fn main(){ // Let's impor the receipt that was generated by prove let receipt_path ="./receipt.bin".to_string(); let receipt_file = std::fs::read(receipt_path).unwrap(); // As we has serialized the receipt we need to desrialize it let receipt = bincode::deserialize::<Receipt>(&receipt_file).unwrap(); // Let's verify if the receipt that was generated was not created tampered with let _verification = match receipt.verify(MULTIPLY_ID){ Ok(()) => println!("Proof is Valid"), Err(_) => println!("Something went wrong !!"), }; }
Seu verify.rs
final deve ser parecido com isto.
Eu prometo que essas são as mudanças finais. Agora, estamos quase terminando.
Abra Cargo.toml
na pasta host
e faça as alterações abaixo nas dependências.
multiply-methods = { path = "../methods" }
Seu Cargo.toml ficará assim.
Finalmente chegou a hora de ver se nosso código funciona.
Abra seu console no diretório raiz do projeto e execute o comando abaixo no console cargo run --release --bin prove
Este comando irá gerar o comprovante e recibo para o verificador.
Ao executar pela primeira vez, levará muito tempo. Então não se preocupe, pegue um café até terminar.
Feito isso, se desejar, você pode verificar o recibo que gerou. Para isso, execute este comando cargo run --release --bin verify
Ao executar pela primeira vez, levará muito tempo. Então não se preocupe, pegue um café até terminar.