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

検出メカニズム

各改ざんシナリオに対して、検証パイプラインがどのチェックで失敗するかを整理します。本章は実 API の判定ロジックを基準にしており、STARK 検証が success になった後の挙動を前提とします。

mock API fixture(NEXT_PUBLIC_USE_MOCK_API=true)では異なるチェック結果を返すことがあります。現行 API は castSource=client のため、cast_* チェックはシナリオに関係なく not_run です。

Counted 系チェックの zkGate について

/api/verify の Counted 系チェックには、STARK 前に評価できる項目と、STARK 状態でゲートされる項目が混在します。

  • counted_input_sanity / counted_unique_indices / counted_unique_commitmentspublicInputSummary があれば STARK 未解決でも評価されます
  • counted_tally_consistent / counted_missing_indices_zero / counted_expected_vs_tree_size / counted_election_manifest_consistent / counted_close_statement_consistent / counted_my_vote_included / counted_input_commitment_match は zkGate の対象です
  • STARK 未解決(not_run/running)の間、zkGate 対象チェックは not_run または pending になります
  • verificationStatus=failed では、zkGate 対象チェックも failed になり得ます

検出の 2 つの原理

  • 原理1: 完全性違反 (excludedSlots > 0) → counted_missing_indices_zero が失敗(主に S1/S3/S5)
  • 原理2: 主張集計の不整合 (claimed ≠ verified) → counted_tally_consistent が失敗(主に S2/S4)

シナリオ別の主な失敗チェック(STARK 解決後)

シナリオ主に失敗するチェック説明
S0なし正常系
S1counted_missing_indices_zeroユーザー票除外により excludedSlots=1
S2counted_tally_consistentclaimed tally と verified tally が不一致
S3counted_missing_indices_zero現行実装では botId=1 のボット票除外により excludedSlots=1
S4counted_tally_consistentclaimed tally と verified tally が不一致
S5counted_missing_indices_zeroexcludedSlots>0 が必ず発生し、除外・再集計どちらでも完全性違反として検出される

補足:

  • S1 では、ビットマップ証明が利用可能な場合 counted_my_vote_included も失敗し得ます
  • S2/S4 では、counted_input_commitment_match は通常成功します(zkVM 入力を改変していないため)
  • S5 の再集計分岐では counted_tally_consistent も失敗します。choice だけ差し替えた票は commitment 不一致で zkVM が除外するため、verifiedTallyclaimedCounts が一致しなくなります

4 段階検証モデルとの対応(/api/verify 応答)

検証段階S0S1S2S3S4S5
Cast-as-Intendednot_runnot_runnot_runnot_runnot_runnot_run
Recorded-as-Cast
Counted-as-Recorded
STARK Verification

この表は「シナリオ適用による典型挙動」を示します。running や追加の not_run は運用状態や証拠不足により別途発生します。 なお、ここでの STARK Verification は段階別の表示ステータスです。全体の verificationStatus は fail-closed ルールにより failed になることがあります。


チェックID(主要項目)マトリクス(STARK 解決後)

チェック IDS0S1S2S3S4S5
cast_commitment_matchnot_runnot_runnot_runnot_runnot_runnot_run
counted_tally_consistent分岐依存
counted_missing_indices_zero
counted_my_vote_included❌ または not_run分岐依存
counted_input_commitment_match
  • S5 の counted_my_vote_included は、ランダム対象がユーザー票(除外または再集計)なら失敗し得ます。証拠不足時は not_run になります
  • S5 の counted_tally_consistent は、除外パスでは成功、再集計パスでは失敗します(commitment 不一致で zkVM が票を除外するため verifiedTally ≠ claimedCounts
  • いずれの分岐でも主な失敗は counted_missing_indices_zero です

S2/S4 で何が起きるか

S2/S4 は「入力改ざん」ではなく「主張集計改ざん」です。

flowchart TD
  A["tamperMode=claim (S2/S4)"]
  A --> V1["元の votes を zkVM 入力へ"]
  V1 --> V2["verifiedTally"]
  A --> C1["claimedCounts を改変"]
  C1 --> C2["API の tally.counts"]
  V2 --> X{"claimed と verified は一致?"}
  C2 --> X
  X -->|不一致| F["counted_tally_consistent = failed"]

このため counted_input_commitment_match の失敗は通常発生しません(zkVM 入力は元票)。


S5 の実装依存ポイント

S5 はランダムに除外または再集計を選びますが、実装上は常に tamperMode=input です。つまり claim tamper ではなく、改変後の votes が zkVM 入力に入ります。ジャーナル統計は sync / async どちらでも zkVM が返した値をそのまま使います(詳細はシナリオ一覧 > ジャーナル統計の扱いを参照)。

  • 除外分岐: missingSlots=1 となり、counted_missing_indices_zero が失敗
  • 再集計分岐: invalidPresentedSlots=1 となり、counted_missing_indices_zero が失敗
  • 再集計分岐では counted_tally_consistent も失敗します。claimedCounts は改変後の 64 票から算出されますが、zkVM は commitment 不一致の票を除外するため verifiedTally は 63 票ベースになります

ビットマップ証明の役割

counted_my_vote_included は、チェック定義上 required のユーザー包含チェックです。

  • S1(ユーザー票除外)では、証明が利用可能なら失敗して「自分の票が未集計」であることを直接示せる
  • 証拠不足で not_run になる場合でも、最終判定は Verified になりません:
    • 完全性違反が同時にある場合 → votes_excluded_unknown
    • 完全性違反が無く required evidence が欠ける場合 → missing_evidence

最終判定(Verified 表示)

最終表示は verification-summary のルールで決定されます。

flowchart TB
  A[検証チェック集合] --> B{必須チェック failed?}
  B -- yes --> F[failed 系ステータス]
  B -- no --> C{必須チェック not_run / running?}
  C -- yes --> W[in_progress / missing_evidence]
  C -- no --> D{任意チェックに劣化あり?}
  D -- yes --> L[verified_with_limitations]
  D -- no --> V[fully_verified]

代表的な失敗ステータス:

  • user_vote_excluded / votes_excluded / votes_excluded_unknown: 完全性違反(S1/S3/S5)
  • published_tally_mismatch: claimed と verified の不一致(S2/S4)
  • counted_integrity_failed: Counted 系必須チェック失敗の一般ケース