Serverlessしかなかったので、ブラウザに働いてもらいました

PoWでランキングを守ってみた話

Serverless LT

自己紹介

田中博悠 / tanahiro2010

  • 三田学園高等学校 1年生
  • TypeScript / Ruby
  • Web / CLI
  • 個人開発
  • OSSに少し貢献
  • 小説も書く

皆さん

自分の謎のこだわりと

環境制限のせいで

暴走したこと、ありますか?

僕はあります

ランキングを作りたかっただけなんです

作ったもの

「なんでも問題集」

匿名で問題を投げるサイト

技術 採用
Frontend Next.js
Database Neon(PostgreSQL)
Hosting Vercel

全部サーバーレス

機能は素朴

誰でも匿名で

問題を作って投げる場所

  • 問題の作成
  • 公開
  • 解く
  • ランキング

力を入れたのは、解く場所とランキング

つまり今回の本題。

問題

解かれた数ランキングを作りたい

ぶっちゃけ、素直に増やすと死ぬ

POST /solve 解いた扱い
→
while(true) fetch連打
→
ランキング終了 数字が壊れる

APIだけだと弱い

どうする?

  • ログイン?
  • CAPTCHA?
  • Turnstile?
  • Rate Limit?

どれも重い

サーバーレスの縛り

  • 重い処理は無理
  • CPU時間が怖い
  • DB直撃も怖い
  • 課金も怖い
  • でもログインは嫌

現実はもっと泥

  • 起動待ちに怯える
  • 権限設定で詰む
  • ログ追跡がつらい
  • 課金グラフを見る
  • 夜中に眉間が寄る

結論

ブラウザに働かせる

PoW(Proof of Work)で殴る

以前Discord Botで

PoWを書いた記憶が蘇った。

Proof of Workとは?

pow

全体の流れ

Browser お題を取る
→
PoW計算 nonce探し
→
Verify 結果を投げる
→
Server検証 一瞬で見る
→
ランキング更新 通れば加算

Challenge取得

GET /api/works/:id/challenges

返すもの

  • prefix
  • token(JWT)

端末で難易度を変える

  • PC
  • スマホ

検証

POST /api/works/:id/challenges/:challengeId
送信 nonce / token
→
サーバーで検証 条件だけ見る
→
ランキング更新 成功だけ反映

完璧?

もちろん穴はある

  • UA偽装
  • Bot突破
  • 端末判定は雑
  • 本気の攻撃は無理

でも、今回の狙いは

大量送信のコストを上げる

ここだけ。

実は……

PoWを書きたかった

これが理由の半分くらい。

個人開発だからこそ

「面白そう」

で突っ込めるのが最高。

サーバーレスだから

「できない」

ではなく

どう実現する?

ご清聴ありがとうございました

GitHub・質問などぜひ