Skip to content

[shared] PoSW 検証が 1 反復ごとに await crypto.subtle.digest しており実測 28 倍遅い (spec §6.1 の時間記述も乖離) #267

Description

@shinyaoguri

2026-08 レビューの残件トリアージ (#243) で #241 (PoSW のコスト構造を再評価) の材料を集めた際、検証時間の大部分が反復数ではなく実装のオーバーヘッドだと判明したので、#241 の設計判断とは独立に起票する。

実測

Darwin 25.6.0 / Node v25.9.0 で、同じ 10,000 反復を 2 通りで計測:

経路 実測 1000 events 換算
現行の検証実装 (verifyPoSW) 113.8 ms / event ≈ 114 秒
同じ 10,000 反復を同期ハッシュで 4.07 ms / event ≈ 4.1 秒

約 28 倍の差。

原因

packages/shared/src/verification.ts:670 付近:

for (let i = 1; i < posw.iterations; i++) hash = await computeHash(hash);

computeHashpackages/shared/src/utils/hashUtils.ts:40 付近の await crypto.subtle.digest1 反復ごとに WebCrypto の非同期 API と Promise を経由している。10,000 回 × イベント数だけ Promise が積まれる。

  • verify web と verify-cli はどちらもこの同一経路を使う
  • 検証側に並列化は無い (worker_threads / Worker の使用は記録側の PoswManager.ts:41 のみ)

なぜ #241 と分けるか

#241 は「PoSW の反復数を下げるか / PoSW 自体を見直すか」という設計判断で、選択肢 (B) の「反復数を 1/10」は全 proof のフォーマット互換設計を要する。poswIterations は proof 本体だけでなく署名 cp payload (signedCheckpoints.ts:115 で焼き :445 で検証) と session start token payload (sessionStartToken.ts:105 / :165) にも入っており、変えると署名済みの過去 envelope / token まで一斉に fail する。

一方実装の高速化は互換性コストがゼロで、POSW_ITERATIONS を 10,000 のまま据え置いても 1/28 が得られる。#241 の判断を待つ理由が無い。

あわせて直したい: spec の時間記述

docs/system-spec.md:419 の「full = 1000 events で ~10〜60 秒」は実測 (~114 秒) より 2〜10 倍楽観的。採点者の待ち時間の見積もりに直結するので、高速化と同じ PR で実測値に合わせたい (#231 の spec 陳腐化リストにこの項目は入っていない)。

対応案

hashUtils.ts に同期ハッシュのパスを足し、verifyPoSW の反復ループだけそちらへ差し替える (2 ファイル ~40 行 + テスト)。Node と ブラウザで実装が分かれるので、環境判定の置き場を決める必要がある。

未確認

  • 実測は 1 マシン (Darwin / Node v25.9.0) のみ。ブラウザ (verify web の Worker) 上での実測はしていないので、web 側で同じ比率が出るかは要確認
  • 記録時のコスト (spec §4.4 の「約 5〜30ms / event」) は Web Worker 側 (PoswManager.ts) の別問題。native 実測 4ms とは概ね整合しており、本 Issue の対象外

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions