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

設計と実行フロー

検証パイプラインの設計原則、全体構造、実行フローを解説します。

設計原則

本システムの検証パイプラインは、以下の 3 つの原則に基づいて設計されています。

原則 1: 必要な検証が未実行なら Verified を表示しない

required チェックが not_run(未実行)、pending(依存待ち)、running(実行中)のいずれかにある場合、システムは「Verified」を表示しません。証拠の不在や未解決状態を成功として扱わないという姿勢です。

原則 2: 失敗した検証は即座にブロックする

いずれかの必須チェックが失敗すれば、「Verified」表示は即座にブロックされます。代表的な失敗条件:

  • excludedSlots > 0(除外されたスロットが存在する)
  • 整合性証明の失敗
  • 公開監査アーティファクトとの不一致
  • 第三者 STH 合意の不成立(設定時)

原則 3: チェック評価はサーバー中心、集約はサーバーとクライアントの双方で実施

  • 22 個の検証チェックは主にサーバー側(GET /api/verify)で評価されます。
  • Cast-as-Intended のみクライアントがローカルで上書き評価します(サーバーは not_run を返却)。
  • Recorded-as-Cast は cast-time 証跡voteReceiptuserVote.proof)を前提とします。store から再構成できない場合でも /api/verify200 を返し、関連チェックを not_run にして全体判定を missing_evidence 側へ fail-closed に倒します。
  • STARK 検証は専用サービス(POST /api/verification/run)で実行され、GET /api/verify がその結果を読み取ります。
  • verificationSteps[].status は required チェック群を基準に導出されますが、現行実装では journaluserVote.proof.treeSize が不在の場合に verificationSteps[].statusnot_run に上書きするガード条件もあります。
  • deriveVerificationSummary はサーバー側の /api/verify とクライアント側の /verify の両方で使われます。サーバーは verificationStatus を fail-closed(安全側に倒す方向)に補正し、unsupported な verifier status でも verificationSteps / verificationChecks を含む 200 応答を返します。クライアントは summary に加えて STARK timeout や transport failure も最終失敗表示に反映します。UI 側の補助分岐については ゲーティングロジック を参照してください。

検証パイプラインの全体構造

1. 段階の依存関係

  1. Stage 1 — Cast-as-Intended
  2. Stage 2 — Recorded-as-Cast
  3. Stage 3 — Counted-as-Recorded
  4. Stage 4 — STARK Verification
  5. 結果表示

2. 実行責務(どこで評価・検証されるか)

flowchart TD
  subgraph SERVER["サーバー側"]
    VFY["GET /api/verify<br/>Stage 2-4 の 22 チェックを組み立て<br/>cast-time 証跡不在時は fail-closed<br/>(Cast は not_run)"]
    RUN["POST /api/verification/run<br/>bundle 参照と expected Image ID で<br/>Stage 4 を検証"]
  end

  subgraph CLIENT["クライアント(UI)"]
    UI["Cast のローカル再評価<br/>STARK 解決後に step 表示を開始<br/>summary と明示的 proof failure を反映"]
  end

  VFY --> UI
  RUN --> UI

検証の実行フロー

検証導線では通常 /result から /verify へ進みます。

  1. /result は継続用のクライアント状態(verificationRequestedAt と正準な finalization snapshot)を保存し、必要なら POST /api/verification/run を先行起動します
  2. /verify はその継続状態がある場合に検証シーケンスを続行します。STARK が未開始ならシーケンス内で起動できます
  3. 継続状態がなく STARK が not_run のまま直接 /verify へアクセスした場合は、自動続行せずブロックします
  4. /verify の UI シーケンスは、step を順に見せる前に STARK が terminal status に到達するまでポーリングします。timeout や transport failure は STARK failure として扱われます
sequenceDiagram
  participant U as ブラウザ
  participant R as /result
  participant V as /verify
  participant A as API サーバー
  participant VS as 検証サービス

  U->>R: 「検証へ進む」をクリック
  R->>A: POST /api/verification/run(必要時)
  A->>VS: bundle 参照 + expected Image ID
  VS->>VS: Receipt::verify(imageId)
  VS-->>A: 検証レポート保存
  R-->>V: /verify へ遷移

  loop STARK 完了までポーリング
    V->>A: GET /api/verify
    A-->>V: 検証ペイロード<br/>(ステップ, チェック, 証明材料)
  end

  Note over V: 継続には verificationRequestedAt と finalization snapshot が必要<br/>not_run の direct access はブロック<br/>step 表示は STARK 解決後に開始

4 段階の概要

段階名称証明する内容検証の実行場所
Stage 1Cast-as-Intended投票者の意図通りにコミットメントが生成されたクライアント(/verify 画面でローカル再計算)
Stage 2Recorded-as-Castコミットメントが追記専用掲示板に正しく記録されたサーバー(GET /api/verify
Stage 3Counted-as-Recorded記録された全投票が正しく集計に含まれたサーバー(GET /api/verify
Stage 4STARK VerificationzkVM の実行が正しく行われたことの暗号学的証明サーバー(POST /api/verification/run

クライアントは Cast-as-Intended のローカル再計算、STARK 解決後の step 表示、最終表示の整形を担当します。サーバー側の fail-closed 補正と cast-time 証跡不在時の動作は上記「原則 3」を参照してください。

各ステージの verificationSteps[].status は、そのステージで required 扱いになるチェック群から導出されます。たとえば Recorded-as-Cast では、STH ソースが設定されている場合に限り recorded_sth_third_party も必須条件に昇格します。ただし、一部のステージにはデータ不在時のガード条件があります(上記「原則 3」参照)。特に Recorded-as-Cast は userVote.proof.treeSize がなければ not_run になり、Counted-as-Recorded は journal がなければ failed でない限り not_run に補正されます。

各段階の詳細は 4 段階検証モデル を参照してください。

検証チェック数

パイプライン全体で 22 個の検証チェックが定義されており、各チェックには一意の ID が割り当てられています。チェック ID の単一ソースは src/lib/verification/verification-checks.ts です。

段階チェック数
Cast-as-Intended4
Recorded-as-Cast6
Counted-as-Recorded10
STARK Verification2
合計22

Counted-as-Recorded の required チェックには counted_election_manifest_consistentcounted_close_statement_consistent も含まれます。これにより、公開された election-manifest.json / close-statement.json と検証対象データの整合も stage success の条件に含まれます。

チェックの詳細は チェック一覧 を参照してください。