ゼロ知識証明により、プライベートで安全なトランザクションが可能になります。 zkSNARK と zkSTARK を使用すると、証明者は実際のデータを明らかにすることなく、検証者に何らかの情報の所有を証明できます。
これには、匿名性と機密性が確保される可能性が非常に高くなります。しかし、zkSTARK と zkSNARK は複雑です。 Risc0 により、アクセスしやすくなります。非常に基本的な実装を見てみましょう。
このチュートリアルでは以下について説明します。
Risc0のインストール
Rust を使用して最初のゼロ知識証明プログラムを作成する
前提条件:
ショートカットをコピー&ペーストする
必要なインストール:
Rust の基本的なコーディング知識
コードエディタ (可能であれば VSCODE)
最後には、Risc0 でのゼロ知識証明の実践的な経験が得られるでしょう。高度な数学や暗号学の知識は必要ありません。
実際のソリューションの構築を開始するために不可欠なコーディングに焦点を当てます。この実践的な紹介は、強力なプライバシー技術をあらゆる開発者が理解できるようにすることを目的としています。
(MacOS の場合) Rust と Cargo をインストールするには、ターミナルで以下のコマンドを実行できます。
curl [https://sh.rustup.rs](https://sh.rustup.rs/) -sSf | sh
Risc0 をインストールするには、Rust のインストール後に以下のコマンドを実行し、ターミナルを再起動します。
cargo install cargo-risczero
brew install openssl
brew install pkgconf
risc0
ツールチェーンをインストールする必要があります。Cargo cargo risczero install
必要なのはそれだけです。それでは、コードエディターに進みましょう。
インストールが完了したので、次の abra kadabra 🪄 の手順を読んで実行できます。
コード エディターを開き、エディターのターミナルでプロジェクトを作成する場所に移動します。
ターミナルで次のコマンドを使用して、プロジェクトの新しいインスタンスを作成します: cargo risczero new multiply
。
multiply という名前のフォルダーが作成されているはずです。それにCDを入れます。 cd multiply
フォルダー構造は非常にシンプルです。
ホストフォルダーとメソッドフォルダーがあります。
ホスト フォルダーには、ゲスト プログラムと呼ばれるホスト プログラムが含まれています。必要に応じて検証する機能もあります。
メソッド フォルダーには、zkvm アプリケーションの実証済みの部分を含むゲスト プログラムが含まれています。ホストから入力パラメータを受信し、ロジックに基づいて結果を生成し、ジャーナルにコミットして、受信としてホストに送信します。
残りのファイルについては、必要に応じて移動中に説明します。
まずはゲストプログラムから。
ファイルの名前をmain.rs —> multiply.rs
に変更しましょう。
src
フォルダー内にbin
という名前のフォルダーを作成し、そこにmutiply.rs
を移動します。フォルダー構造は次のようになります。
Cargo.toml
を開き、更新内容をname = "method_name” —> name = "multiply”
に変更します。
以下のコードをCargo.toml
に追加します。
[[bin]] name = "multiply" path = "src/bin/multiply.rs"
最終的なCargo.toml
は次のようになります。
次に、 multiply.rs
を開きます。ここではmain関数を編集していきます。これはzkvmで実行される関数です。
以下のコードでは、ホスト プログラムから入力を取得しています。次に、入力が 1 という自明な要素ではないことを確認します。次に、積を計算し、最後にそれをプログラムのホストにコミットします。
// 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);
上記の変更後、 multiply.rs
は次のようになります。
methods
フォルダーのCargo.toml
にもう 1 つ最後の変更があります。
name = "multiply-methods”
を開いて値を更新します。
最終的なCargo.toml
は以下のようになります。
ここでの私たちの仕事は終わりました。
さて、ホストプログラムに行きましょう。
ホストフォルダーは現在次のようになっているはずです。
main.rs
prover.rs
とverify.rs
という 2 つのファイルに分割したいと考えています。
src
の下に新しいフォルダーを作成し、 bin
という名前を付けます。
main.rs
を削除します。ファイルを作成し、 verify.rs
およびprove.rs
という名前を付けます。
フォルダー構造は次のようになっているはずです。
prove.rs
開いてコーディングを始めましょう。
以下のコードを追加します。これらは必要となるインポートです。
use multiply_methods::MULTIPLY_ELF; // It is a binary file of multiply_method use risc0_zkvm::{ default_prover, serde::{from_slice, to_vec}, ExecutorEnv, };
main関数に変更を加えてみましょう。
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 !!"), }; }
最終的なprove.rs
は次のようになります。
verify.rs
を開いてコードを追加しましょう。
ここでは、ゲスト プログラムのイメージ ID といくつかの基本的なインポートをインポートします。
use multiply_methods::MULTIPLY_ID; use risc0_zkvm::Receipt;
main関数に変更を加えてみましょう。
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 !!"), }; }
最終的なverify.rs
は次のようになります。
これらが最終的な変更であることをお約束します。これでほぼ完了です。
host
フォルダーのCargo.toml
を開き、依存関係で以下の変更を加えます。
multiply-methods = { path = "../methods" }
Cargo.toml は次のようになります。
いよいよコードが機能するかどうかを確認します。
プロジェクトのルート ディレクトリでコンソールを起動し、 console cargo run --release --bin prove
このコマンドは、検証者向けに証明と領収書を生成します。
初めて実行する場合は非常に時間がかかります。したがって、完了するまで心配する必要はありません。
これが完了したら、必要に応じて、生成した領収書を確認できます。そのためには、次のコマンドを実行しますcargo run --release --bin verify
初めて実行する場合は非常に時間がかかります。したがって、完了するまで心配する必要はありません。