取引所「OKX」の監査 (Proof of Reserves; PoR) を自分でやってみた

サムネイル引用元:Proof of Reserves(OKX)

こんにちは!弐号です。

取引所の監査が自分でできる!Proof of Reserves (PoR) とは?」という記事で PoR の仕組みの解説をしましたが、この記事では実際に OKX の提供しているデータを用いて監査をやる方法を解説します。

なお、PoR については上記の記事で詳しく解説しておりますので、「PoR って何?」という方はまずはそちらの記事をお読みください。

監査といえば、監査法人と呼ばれる大企業にやってもらうイメージがあると思いますが、クリプトの世界では「Don’t trust, verify.」ですので、交換所も自分で監査するというのがナウでヤングです(死語)。

基本情報

OKX の監査に必要な情報や、やり方については

OKX Proof of Reserves | Why Proof of Reserves matters | OKX

に書かれていますので、適宜こちらのページを参照してください。

公式で Go 言語製の監査ツールがオープンソースで公開されていますので、基本的にはこのツールを使って確認していきます。

OKX Proof-of-Reserves (GitHub)

このツールには3つの実行ファイルがついてきます。

それぞれ

  • CheckBalance – 取引所の保有する現物コインの枚数を計算するツール
  • VerifyAddress – 取引所がアドレスを保有していることを電子署名データのチェックにより確認するツール
  • MerkleValidator – 全ユーザの残高情報に対して、各ユーザの Merkle プルーフのデータが正しいかを確認するツール

となっています。

監査ツールのダウンロード

ビルド済みバイナリの利用

GitHub にビルド済みバイナリが公開されていますので、こちらをダウンロードします。

https://github.com/okx/proof-of-reserves/releases

利用している OS や CPU に合致したバイナリをダウンロードして解凍してください。

ソースコードからビルドする(※上級者向け)

上級者向けとなりますが、ソースコードから自分でビルドすることもできます。

「ビルド済みバイナリは不正に改造されている可能性が……」という慎重派の方はこちらのやり方をとりましょう。

$ go mod tidy
$ git clone https://github.com/okx/proof-of-reserves.git
$ cd proof-of-reserves
$ make all

これでバイナリのビルドができます。

少しコンパイルに時間がかかりますが、すぐに終わります。

ビルドが終了すると /build にバイナリが出来上がりますのでこちらを利用してください。

なお、ビルド済みバイナリに付属している rpc.json/example/rpc.json にありますので、以下ではこのファイルに置き換えて読み進めてください。

各監査ツールの使い方

CheckBalance

まずは OKX の保有するアドレスの残高が正しいかをチェックしましょう。

そのためには保有アドレスの一覧が書かれた CSV ファイルをダウンロードする必要があります。

https://www.okx.com/proof-of-reserves/download

上記のリンクから、最新の CSV データをダウンロードしてください。

ダウンロードができたら

$ ./CheckBalance --rpc_json_filename ./rpc.json --por_csv_filename (ダウンロードしたCSVファイルへのパス)

と入力し実行します。

そして

INFO[0000] loading por csv data…
INFO[0002] por data, coin: BTC, snapshot height: 772462, address count: 100897, total balance: 123914.4805
INFO[0002] por data, coin: ETH-ARBITRUM, snapshot height: 53798175, address count: 4, total balance: 5713.5605
INFO[0002] por data, coin: ETH-OPTIMISM, snapshot height: 68812558, address count: 5, total balance: 17082.1507
INFO[0002] por data, coin: USDT-TRC20, snapshot height: 47802842, address count: 230, total balance: 354171162.9565
INFO[0002] por data, coin: USDT-POLY, snapshot height: 38213946, address count: 2, total balance: 7316690.5590
INFO[0002] por data, coin: USDT-AVAXC, snapshot height: 25081295, address count: 1, total balance: 9355036.8069
INFO[0002] por data, coin: ETH, snapshot height: 16430560, address count: 101, total balance: 1210919.1170
INFO[0002] por data, coin: USDT-ERC20, snapshot height: 16430560, address count: 30, total balance: 2597894478.2513
INFO[0002] por data, coin: USDT-ARBITRUM, snapshot height: 53798175, address count: 1, total balance: 9529885.8421
INFO[0002] por data, coin: USDT-OPTIMISM, snapshot height: 68812558, address count: 1, total balance: 1599046.9121
INFO[0002] por data: BTC total balance 123914.4805, ETH(ALL) total balance 1233714.8282, USDT(ALL) total balance 2979866301.3279

といった内容が表示されます。

一番最後の行にコインの合計枚数が表示されますので、この値がこちらのページに「OKX wallet assets
」として記載されている内容と一致するかを確認します。

VerifyAddress

次にアドレスの保有者が OKX であることを確認しましょう。

これには先ほどダウンロードした CSV ファイルを再び利用します。

./VerifyAddress --por_csv_filename (ダウンロードしたCSVファイルへのパス)

と実行すると、CSV ファイルに書かれているアドレスとメッセージ、電子署名に対して検証が行われます。

Verify address signature start
Your input csv filename: ../okx_por_2023011810.csv
USDT(ALL) ‘s height is – and total balance is 2979866301.
ETH(ALL) ‘s height is – and total balance is 1233714.
BTC ‘s height is 772462 and total balance is 123914.
ETH ‘s height is 16430560 and total balance is 1210919.
ETH-ARBITRUM ‘s height is 53798175 and total balance is 5713.
ETH-OPTIMISM ‘s height is 68812558 and total balance is 17082.
USDT-ERC20 ‘s height is 16430560 and total balance is 2597894478.
USDT-TRC20 ‘s height is 47802842 and total balance is 354171162.
USDT-POLY ‘s height is 38213946 and total balance is 7316690.
USDT-AVAXC ‘s height is 25081295 and total balance is 9355036.
USDT-ARBITRUM ‘s height is 53798175 and total balance is 9529885.
USDT-OPTIMISM ‘s height is 68812558 and total balance is 1599046.
USDT-ARBITRUM 1 accoounts, 1 verified, 0 failed
ETH-ARBITRUM 4 accoounts, 4 verified, 0 failed
USDT-OPTIMISM 1 accoounts, 1 verified, 0 failed
BTC 100897 accoounts, 100897 verified, 0 failed
USDT-TRC20 230 accoounts, 230 verified, 0 failed
USDT-ERC20 30 accoounts, 30 verified, 0 failed
ETH 101 accoounts, 101 verified, 0 failed
ETH-OPTIMISM 5 accoounts, 5 verified, 0 failed
USDT-POLY 2 accoounts, 2 verified, 0 failed
USDT-AVAXC 1 accoounts, 1 verified, 0 failed
Total balance :BTC 123914,ETH(ALL) 1233714,USDT(ALL):2979866301
Verify address signature end, all address passed

といった出力が得られます。

この中の「failed」と書かれている部分が全部ゼロになっていることを確認してください。

検証に失敗したものがあると

Fail to verify address signature.The line 1 has invalid address.

といったメッセージが表示され、「failed」のカウントが増えます。

MerkleValidator

最後に自分の口座に紐付いた Merkle プルーフが正しいことを確認しましょう。

自分の Merkle プルーフのデータは OKX にログインしたうえで

https://www.okx.com/balance/audit

にアクセスすると確認することができます。

最新の監査報告の一番右にある「Details」というボタンを押すと詳細が見れます。

ここに書かれている日付の時点における残高が、記載されている値で正しいかどうかを確認してください。

もし、違う値が書かれていたら OKX が不正を行った証拠となります!

Twitter などで報告しましょう。

さらに「Copy data」というボタンを押すと Merkle プルーフのデータが JSON 形式の文字列としてクリップボードにコピーされますので、テキストエディタを開き拡張子を「.json」とした上で適当な場所に保存してください。

{
  "path": [
    {
      "auditId": "9876543210",
      "balances": {
        "BTC": "0",
        "ETH": "0",
        "USDT": "0"
      },
      "type": 1,
      "nonce": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
      "hash": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
      "height": 1
    },
      (途中省略)
    {
      "auditId": "9876543210",
      "balances": {
        "BTC": "117682.20167618",
        "ETH": "1178993.5439796",
        "USDT": "2955696824.59746834"
      },
      "type": 3,
      "hash": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
      "height": 24
    }
  ],
  "self": {
    "auditId": "9876543210",
    "balances": {
      "BTC": "0",
      "ETH": "0",
      "USDT": "0"
    },
    "type": 2,
    "nonce": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
    "hash": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
    "height": 1
  }
}

この JSON データの中身は上記のようなものになっています(プライバシー保護のため一部改変しています)。

「path」の部分に Merkle プルーフに使う各ノードの情報が、「self」の部分に自分のアカウントの残高が記載されていますので、後者が正しく記載されていることを確認しましょう。

ここにもし、違う値が書かれていたら OKX が不正を行った証拠となりますので、Twitter などで報告しましょう!

最後に

ここから先は、会員限定のコンテンツになります。残り全てを見るには、サロン入会案内ページから会員登録をよろしくおねがいします。

関連記事