Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

計算するプログラムを指定する

「正しく実行された」という証明だけでは、どのプログラムを実行したのかが決まりません。攻撃者が任意の得票数を返すゲストを用意すれば、そのゲストについて有効な証明を作れてしまいます。検証者は、証明を受け取る前に、受け入れる集計プログラムを決めておく必要があります。

その識別に使うのが Image ID です。RISC Zero はゲストの ELF バイナリから 256 ビットの識別子を導出します。検証者は別途用意した期待値を Receipt::verify(expected_image_id) に渡し、指定したゲストの実行結果かを確認します。レシートに書かれた ID をそのまま期待値として採用するだけでは、プログラムの選択を差出人に任せたことになります。

RISC Zero の Image ID

flowchart TB
  S[レビューした集計プログラム] --> B[固定した環境でビルド]
  B --> E[ゲスト ELF]
  E --> I[Image ID を導出]
  I --> X[検証者が期待値として選択]
  R[受け取ったレシート] --> V[レシートを検証]
  X --> V

Image ID はゲストの実行イメージから決定的に導出されます。ELF ファイル全体を単純に SHA-256 した値でも、プローバーのコンテナイメージの digest でもありません。

ゲストのソース、依存ライブラリ、Rust コンパイラ、RISC Zero SDK、ビルド環境が変わり、生成されるゲストが変われば Image ID も変わり得ます。同じソース名や同じ methodVersion であることだけでは、同じバイナリの証拠になりません。

Image ID の導出

ホストはビルド時にゲスト ELF とその Image ID を埋め込みます。証明を生成せず、そのホストが使う値を確認するには、リポジトリルートで次を実行します。

./zkvm/target/release/host --print-image-id --json

出力には imageId と methodVersion が入ります。このコマンドは埋め込まれた値を表示するので、どのソースとビルド環境から作ったホストかを別途確認します。変更後の ID を確定するときは、新しいビルド出力先を使い、以前のゲスト成果物を再利用していないことを確かめます。

variant とアーキテクチャ

公開マッピングは、ビルド環境別に二つの値を管理します。

variant値の由来
default採用された ARM64 のプローバーリリース
x86_64独立に確認したローカル x86_64 のビルド

ARM64 と x86_64 はホスト側のビルド環境です。どちらもゲストの命令セットは RV32IM です。検証者のマシンの CPU に合わせて値を選ぶのではなく、受け取ったレシートを生成したゲストに対応する値を選びます。

各 variant は confirmed または unconfirmed の状態を持ちます。前者には imageId と由来の provenance があり、後者には requiredEvidence: "accepted-prover-release" があるだけで、期待 Image ID としては使えません。

Image ID マッピング

public/imageId-mapping.json は、公開検証者がバージョンとビルド由来を確認するための台帳です。現在の current は 14 です。変更後のゲストについて、default は採用済み ARM64 プローバーリリースの証拠を待つ unconfirmed、x86_64 は新しい出力先で行ったローカル production ビルドに基づく confirmed です。deprecated は空です。

フィールド意味
mappingTypeimage-id-mapping
current現在の method version のキー
mappings.*.methodVersionジャーナル契約のバージョン
mappings.*.variants二つのビルド由来と確認状態
description / featuresプログラムの説明
deprecated / metadata過去バージョンとファイルの管理情報

マッピングは公開リポジトリで履歴を確認できます。ただし、正しい期待値として使うには、そのソースとビルド由来を信頼する判断が必要です。攻撃者が用意したマッピングとレシートを一緒に検証しても、その判断を省略したことには変わりありません。

Image ID の解決

アプリは検査済みジャーナルの methodVersion を使って期待値を解決します。現在の検証フローが受け入れるのは、現行のジャーナル契約です。

条件採用する期待値
EXPECTED_IMAGE_ID が設定されているその明示値。mapping と variant による解決を使わない
明示値なし、variant の指定あり現行 mapping の指定 variant
明示値も variant もなし現行 mapping の default

EXPECTED_IMAGE_ID_VARIANT は default または x86_64 に限定します。実行環境の自動判定は行いません。未知のバージョン、不正または読み込めないマッピング、未確認の variant はエラーになり、別の値で検証を続けません。

明示した EXPECTED_IMAGE_ID は、対象 methodVersion のゲストに対応させる必要があります。AWS のデプロイでは、選択したプローバーリリースの Image ID と method version を使い、公開マッピングとも照合します。公開マッピング自体が、コンテナを実行してよいという許可を与えるわけではありません。

ローカル検証での選択

verifier-service 単体は EXPECTED_IMAGE_ID を読みますが、EXPECTED_IMAGE_ID_VARIANT を直接は読みません。たとえばローカル x86_64 で生成したレシートの期待値は、次のスクリプトで導出します。

node verifier-service/scripts/read-image-id.mjs \
  public/imageId-mapping.json --variant x86_64

この出力を検証 CLI の --image-id または EXPECTED_IMAGE_ID に渡します。ARM64 の配布レシートには、そのリリースに対応するソースの確認済み default を使います。現在のソースでは default が未確認のため、ARM64 の期待値の解決と通常の App デプロイは停止します。

検証パイプラインでの役割

検証サービスはレシートラッパーの image_id を期待値と比較し、さらに暗号学的な Receipt::verify を行います。単に JSON の文字列が一致したことを証明検証の代わりにはしません。

アプリは stark_image_id_match と stark_receipt_verify の両方を必須とし、レポート・集計結果側の ID の整合も確認します。それらが成功しても、投票の記録、入力の完全性、表示の得票数に対する確認が残ります。

ゲスト更新とコンテナ更新

ゲストが変わる更新では、新しい Image ID を確定し、マッピング、検証側の期待値、生成するレシートをそろえます。片側だけの更新では、新旧の不一致として検証できなくなります。

一方、ゲストが変わらないコンテナの起動処理の更新なら、コンテナ digest が変わっても Image ID は変わらないことがあります。AWS はこの二つを別々に検査します。コンテナの出所と実行許可はイメージ署名、ゲストの実行結果は Image ID に対するレシート検証で確認します。