Crashラウンド中、オンチェーンでは何が起きていますか?
すべてのCrashラウンドは、3つのオンチェーントランザクションで次の順に構成されます。- コミット:ベット受付開始前に、バックエンドがランダムな32バイトの秘密の値を生成し、そのSHA-256ハッシュをオンチェーンで公開します(
start_new_round命令)。これがコミットメントです。この瞬間から、そのラウンドを精算できるのはまったく同じ秘密の値だけになります。コミットメントはトランザクションのCrashRoundPreparedイベントで公開されます。 - ベット:プレイヤーがベットします。秘密の値は隠されたままで、コミットメントによってすり替えができないことが保証されます。
- ラウンド開始/エントロピーの取得:ラウンドが始まると(
start_game命令)、プログラムはSolanaのSlotHashessysvarから最新のスロットハッシュを読み取り、ラウンドに保存します。アプリではこの値をラウンドのブロックハッシュと呼んでいます。この時点でクラッシュポイントは完全に確定します(保存されたスロットハッシュとコミットされた秘密の値だけで決まる関数です)。ただし、秘密の値を知らない人はまだそれを計算できません。この値はCrashGameStartedイベントで公開されます。 - ラウンドの進行:倍率が上昇し、プレイヤーがキャッシュアウトします。
- 公開:バックエンドが秘密の値を提出します(
crash命令)。プログラムはsha256(secret)がコミットメントと等しいことをオンチェーンで検証し(一致しなければトランザクションは失敗します)、クラッシュポイントを自ら計算してラウンドを確定させます。CrashRoundFinalizedイベントで秘密の値、スロットハッシュ、最終的なクラッシュポイントが公開されます。
クラッシュポイントの正確な計算式は?
クラッシュポイントは正確に次のように導出されます(これはオンチェーンプログラムが実行する演算そのものです。整数演算なので、丸めによる予期せぬずれはありません)。- 連結の順序は先にblockhash、次にsecretです。
XはSHA-256出力の先頭4バイトからビッグエンディアンで読み取ります。- 除算はすべて切り捨て(整数)除算です。
max(10000, …)という下限により、倍率が1.00xを下回ることはありません。またXの上限によって、分母が極端に小さくなることを防いでいます。
計算例
X = 0xABCD1234(2,882,343,476)、現在の1.5%のエッジ(edge_bps = 150)の場合:
分布の形
この式は一様分布のXを、典型的なクラッシュ曲線に対応させます。ラウンドが少なくとも倍率mに到達する確率は、おおよそ次のとおりです。
保証されること、されないこと
プログラムによって強制されること:- コミットメントがオンチェーンに記録された後は、運営者がラウンドの秘密の値を変更することはできません。ハッシュが一致しない秘密の値では、公開トランザクションが失敗します。
- ラウンドが開始されると(スロットハッシュが保存されると)、クラッシュポイントは確定します。早くキャッシュアウトしても、遅くキャッシュアウトしても、大勢がキャッシュアウトしても何も変わりません。結果は倍率が上昇し始める前に決まっています。
- クラッシュポイントはバックエンドが報告するのではなく、プログラムが計算します。誤った値をオンチェーンに書き込むことはできません。
- 検証に必要なすべての情報(コミットメント、スロットハッシュ、秘密の値、最終的なクラッシュポイント)は、オンチェーンイベントで永続的に公開されます。
- 開始のタイミング。 運営者はラウンド開始前に秘密の値を知っており、そのバックエンドがラウンド開始トランザクションをいつ送信するかを決めます。直近のスロットハッシュは公開されているため、原理的には候補となるスロットについて倍率を事前に計算し、開始のタイミングを調整して、取得されるスロットハッシュに影響を与えることが可能です。この方式はそれを防ぐものではありませんが、観測可能にします。ラウンド開始のタイミングは公開されており、体系的な偏りがあれば、公開されたクラッシュポイントの統計に表れます。これは誰でも一括で再計算できます。
- キャンセル。 ラウンド開始後、運営者はプレイヤーより先に結果を知るため、不利なラウンドを公開せずにキャンセルすることが可能です。ただし2つの厳格な制限があります。キャンセルするとすべての賭け金が全額返金され(プログラムに没収の手段はありません)、すべてのキャンセルは公開イベントを発行します。キャンセルの頻度こそがオンチェーン上の手がかりです。キャンセルは、秘密の値が失われた場合(たとえばコミットと公開の間にバックエンドがクラッシュした場合)の復旧手段として存在しており、実際にはほぼ使われない想定です。