Rust検証技術、低レベルなシステムコードに適用
(github.com/verus-lang)- VerusはRustで書かれたコードの正しさを検証するツールで、開発者がコードが果たすべきことを仕様として記述すると、実行可能なRustコードがあらゆる実行でその仕様を満たすかを静的に確認する
- ランタイム検査を追加せず、強力なソルバーを使ってコードが正しいことを証明する方式で、現在はRustの一部のみをサポートしている
- 一部のケースでは、標準のRust型システムを超えて、raw pointerを操作するコードの正しさまで静的に検査できる
- プロジェクトは活発に開発中であり、機能が壊れていたり不足していたりする場合があり、ドキュメントもまだ完全ではないため、利用者はZulipで助けを求める準備が必要
- ブラウザ向けのVerus Playground、インストール案内、チュートリアルとリファレンス、標準ライブラリAPIドキュメント、並行コード検証ガイド、サンプルとテストが学習・実験の導線として提供されている
Verusが検証するもの
- VerusはRustコードの正しさを検証するツール
- 開発者はコードが実行すべき動作を仕様として記述する
- Verusは、実行可能なRustコードが可能なすべての実行でその仕様を常に満たすかを静的に検査する
- ランタイム検査を追加する代わりに、ソルバーを使ってコードが正しいことを証明する
- 現在の対応範囲はRustのサブセットで、対応範囲を広げる作業が進められている
- 一部のケースでは、標準のRust型システムを超えて、たとえばraw pointerを操作するコードの正しさを静的に確認できる
開発状況と利用時の注意点
- Verusは活発に開発中のプロジェクト
- 機能が壊れていたり不足していたりする場合がある
- ドキュメントはまだ完全ではない
- Verusを試すには、Zulipで助けを求める準備が必要
- Verusコミュニティは複数の研究論文を発表しており、産業界と学術界のさまざまなプロジェクトがVerusを利用している
- 関連一覧はpublications and projectsページで確認できる
始め方と開発ツール
- ブラウザでVerusを試すには、Verus Playgroundを利用できる
- より本格的な開発には、インストール案内に従う必要がある
- 学習は Tutorial and referenceから始められる
- Verusコード向けの自動フォーマッタverusfmtもサポートしている
ドキュメントと学習資料
- 作成途中のドキュメントリソースには次が含まれる
- Tutorial and reference: Verusのチュートリアルとリファレンス
- API documentation for Verus's standard library: Verus標準ライブラリのAPIドキュメント
- Guide for verifying concurrent code: 並行コード検証ガイド
- Verusへの貢献
- crates.ioでVerus関連クレートを公開するためのベストプラクティス
- Verus License
- Verus Logos
サンプルとコミュニティ参加
- Verusの利用例は、ドキュメント以外にも複数の出発点を提供している
- Publications and projects: Verusを利用する出版物とプロジェクト
- Videos, slides, and exercises: 1日版Verusチュートリアルの動画、スライド、演習問題
- Standalone examples: 小さく具体的なタスクでVerusを使う独立したサンプル
- Small and medium-sized examples: さまざまなVerus機能を示すサンプル
- Unit tests: Verusの構文と機能の例を含むテスト
- イシュー報告と議論はGitHubまたはZulipで行える
- 機能要望とオープンな対話にはGitHub discussionsを使い、既存機能の再現可能なバグはGitHub issuesに置くという運用を採っている
- コードで貢献したい場合は、Verusへの貢献の案内を参照できる
1件のコメント
Hacker News の意見
Verus で形式検証済みの Kubernetes コントローラーを書いてみた
基本的には「いつかコントローラーがクラスタを要求された目標状態へ調整する」といった ライブネス性質を証明できる
ただし目標状態が素早く変わる場合、非同期性、失敗などを考えると、「正しさ」を仕様化すること自体にも微妙な点が多い
コード: [https://github.com/vmware-research/verifiable-controllers/](https://github.com/vmware-research/verifiable-controllers/)、関連論文は OSDI 2024 に掲載予定
Verus へ進む小さな足がかりとして、Rust の debug_assert を事前条件と事後条件に付けてみることができる
Rust コンパイラはデフォルトでプロダクションビルドではこれを取り除く
Verus チュートリアルの検証例では
requiresとensuresで入力範囲と結果条件を書き、ランタイム検査版ではdebug_assert(-16 <= x1)、debug_assert(x8 == 8 * x1)のように同じ条件を実行中に確認する形になるCreusot のような他の Rust 向け証明/検証/契約式設計ツールは属性ベースの構文を使っており、一般により軽量で Rust らしく感じられる
将来の Verus リリースでこうした方式も可能になるとよい
ドキュメント化ツールとして優れていて、型システムとテストを非常によく補完する
"contracts"クレートも試せる: https://docs.rs/contracts/latest/contracts/ほとんどの関数に 事前条件と事後条件を付け、JVM にはプロダクションビルドでそれらを簡単に取り除けるフラグがある
実際のコンピューターサイエンス経験が多くない立場として気になるのだが、README の「コードの正しさを検証する」における 検証と、他の場所で言う「証明」は何が違うのか?
コンピューターサイエンス/数学の背景が強くない実務プログラマーが、コードについて「証明」を学ぶのに良い資料も知りたい
さらに ゼロ知識証明がなぜそれほど重要で関連性が高いのかもよく分からない。たとえば x.com/ZorpZK のような話を聞いたが、なぜすごいのか理解できない
ただし Verus と Software Foundations で使う Coq はアプローチが異なる
Verus は SMT ソルバーという自動制約解決システムで性質を自動証明しようとし、Coq ははるかに多くの部分を手作業で証明する必要があり、自動化は限定的
どちらにも長所と短所があり、自動化はうまくいくときは良いが、うまくいかないときはもどかしい
ゼロ知識証明は少し別分野と見るのが妥当で、形式検証/証明の仕事をしている多くの人もゼロ知識証明には手を出していない。暗号学のプリミティブとして考えるほうがよい
ゼロ知識証明はオーバーヘッドが大きく、いわゆる「キラーアプリ」が不足しているため、実用的な用途や重要性、関連性はまだ大きくないが、概念としては興味深い
学習資料は自分もあればよいと思う。Dafny の文書はかなり良いが、形式的ソフトウェア検証はコンピューターサイエンス/数学の博士でない普通のプログラマーが使いやすい段階には、まだ達していないように思う
例だけ見ると比較的簡単そうに見えるが、すぐに「証明できない」にぶつかり、その理由への答えは作者だけが知っていそうな深い実装詳細に入りがち
たとえばパスワードをサーバーに送らずにパスワードを知っていることを検証できるため、悪意あるサーバーや中間者攻撃者がパスワードを盗み見るのが難しくなる
身元確認にもより良い選択肢を与えられる。政府発行の身分証を持っていることを証明しつつ、文書そのものをサーバーに渡さなくてよいので、「最大2年/3年/6か月保管」した末に結局流出する事態を減らせる
コードに関する証明は、まだ実務プログラマーが行うものではない
Hoare 論理が良い出発点で、入門のコンピューターサイエンス授業でも時々教えられる
Coq は学習曲線が急で、OCaml や似た言語に慣れていないと特に難しい。Why3 のほうが初心者にやさしいかもしれない: https://www.why3.org
証明と検証は同じ意味の場合もあるが、証明はより対話的な印象で、検証はモデル検査や注釈付きプログラムの SMT 解決のように自動化できる印象がある
似たプロジェクトを知らなかった人向けに言うと、Dafny は Rust にコンパイルできる「検証を意識したプログラミング言語」: https://github.com/dafny-lang/dafny
数日前に Dafny 初心者向けの入門記事を書いた: https://www.linkedin.com/pulse/getting-started-dafny-your-fi...
本当に素晴らしく見える。既存のコードベースに証明を追加する方法についてのガイドや例があると、人々の役に立ちそうだ。
例えば、テキストボックスが1つだけある最小限のGUIアプリが、HTTPリクエストでコンパイル時には分からず信頼できない配列を受け取り、バブルソートしてから表示するとしよう。
バブルソートにはオフバイワンエラーで最後の要素がそのまま残るような意図的なバグがあり、単体テストはたまたまそのバグを見逃す。テストが不完全かもしれないと心配することが、証明へ向かう主な動機になり得る。
そのうえで、単体テストを証明に置き換えながら、バグを発見して修正する過程を見せるとよさそうだ。
証明コードそのものを詳しく説明する必要はなく、証明された数学的コードと証明されていない入出力コードの境界、証明とビルドに使うコマンドライン、実際に触れるzipアーカイブのような現実的な細部に焦点を当てればよい。
実際のところ、標準入力から読み込み標準出力に書き出す程度でも十分そうだ。
主要な貢献者の1人が、Zürich RustミートアップでVerusについて素晴らしい発表をしていた: https://www.youtube.com/watch?v=ZZTk-zS4ZCY
この「ghost」コードがプログラム内にどれほどきれいに収まっているかが印象的で、Adaを少し思い出した。
RustにもC/C++、Common Lisp、Ada/SPARK2014のような標準がすでにあるのか気になる。
そうしたものがないなら、Ada/SPARK2014向けに開発された検証ツールと比べると、動く標的を相手にすることになる。
ベアメタルから高整合性の安全必須アプリケーションまで続くAda/SPARK2014の遺産も無視しにくい。
これのことを言っている?
これとKaniの間にどんな関係があるのか気になる。互いに違う動き方をするのだろうか?
https://github.com/model-checking/kani
Verus、Dafny、F*、そして私のVCCのような自動SMTベースの検証器は、ほぼすべての関数とループに注釈を付ける必要があるが、プログラムの正しさについてより広い保証を提供する。
CoqやLeanのような対話型証明器ベースのツールは、通常ユーザーによる誘導がより多く必要だが、より複雑な性質まで保証できる。
VerusはSPARKとどう比較されるのか気になる。
同じ一般的な分類の検証器なのだろうか? Ada用の検証器ではなくRust用の検証器である点以外に、Verusはどう違うのか?
Verusに詳しい人が、VerusとLean4の性能と表現力の違いを説明してくれるとありがたい。
VerusはSMTベースの検証ツールで、Leanは対話型証明器であると同時にSMTベースのツールでもある、と理解している。
ただし形式検証分野への理解は限られているので、ソフトウェア形式手法に詳しい人の見解を聞きたい。
例えばCoqの「Software Foundations」の本のように、Cコードに関する命題を立てて証明することはできるが、Leanでそれをしている人はほとんどいないようで、ツールも不足している。
Lean4でプログラムを書き、そのプログラムについて証明することもでき、一部の人がごく少しずつ取り組んでいる。
純粋数学を形式化し、それについて論文を出すことが、現在Lean4とCoqの主な使われ方だ。
Lean/Coqが実際に記述して証明できるものの種類はより一般的だが、現実世界のプログラムにはそこまでの一般性は必ずしも必要ないかもしれない。