暗号通貨の採掘ソフトをwasmに移植してみた

WebAssembly(wasm)というのは前から気になっていましたが、特に作りたいものが なかったため、あまり使い方を調べておりませんでした。

暗号通貨界隈ではcoinhiveというサービスでMoneroという暗号通貨の採掘ソフトを Webサービスだけで実現しているという話題があり、これを他の暗号通貨であるBitZeny に適用できないか調べてみることにしました。

coinhiveとPoWについて

coinhiveはソースが公開されているのかと思っていたのですが、どうやら一部の コードしか公開されていないらしく、特にPoW(Proof of Work)を処理している部分が よく分かりませんでした。

PoWというのはざっくり言うと、ブロックチェーンの末尾ブロックにあるバイナリ列 のハッシュ値と最新のトランザクションと適当な数値(nonce)をかけ合わせたバイナリ 列のハッシュ値を計算して、そのハッシュ値があるしきい値よりも小さいものを見つ ける処理です。ハッシュ値を計算するにはCPU, GPU, FPGA/ASIC, メモリなどの資源が 必要となります。

一番有名なbitcoinは公開当初はCPUでこの計算を行い、報酬をもらえていましたが、 GPUに移植されるとCPUでは勝ち目がなくなり、最終的にはASICで専用ハードが設計 されてGPUでも勝ち目がなくなりました。

MoneroやBitZenyというGPUでは効率よく採掘できないようなハッシュアルゴリズムが 使用されており、現在でもCPUでの採掘が有利となっております。 このため、wasmへ移植してもある程度は採掘ができるはずで、実際coinhiveではそれ を実現しているようです。

簡単な関数を試してみる

まずはwasmを使えるようになる必要があるので、Ubuntuでapt installしたEmscripten というのを試してみました。しかし、どうもこのソフトは開発がどんどん進んでいる ようで、Ubuntu 16.04 LTSのパッケージでは古すぎてWeb上にあるチュートリアルと 合わない感じでした。

このため、最新のEmscripten SDK(emsdk)というソフトをインストールし、それを使う とチュートリアルも簡単に動かすことができました。

C言語で書かれた簡単な関数を用意し、それをwasm化してJavaScriptから呼ぶことにも 成功し、これで準備が整いました。

複雑な関数の場合

次はCPU採掘ソフト(cpuminer)のyescryptハッシュ計算部分を単体で動かすために C言語の関数部分を取り出してみました。この関数は複雑で依存関係もいろいろと あるため、Emscriptenにすべてを任せてHTMLを生成する方法で動かしてみました。

適当バイナリ列のハッシュ計算を行うmain関数を用意し、それをemccでコンパイル し、生成されたHTMLを実行するとちゃんと計算結果を表示することができました。

ただし、このままでは自動生成されるHTMLだと使いにくいので、HTML内のJavaScript コードから必要部分だけを取り出す必要がありました。 またmain関数を呼ばずに任意の関数を直接呼べるようにしたり手を入れました。

ブロックハッシュの計算も必要

ここまでは割とすんなり動いたのですが、ここからが結構大変でした。 まずブロックハッシュはPoWとは違うハッシュ関数であるsha256dを使用しており、 これもコンパイルに含める必要がありました。

また、採掘プールからもらった情報とnonceからブロックを構築する必要もあり、 エンディアンを1個所でも間違うと当然ちゃんとしたハッシュ値にならず、結構 苦労しました。

=採掘プールとのプロトコルをWebSocket化 採掘プールは生のTCPで1行にJSONを入れて通信するのですが、これだとWebブラウザ からはアクセスできません。そこでGo言語でこれをWebSocket化するプロキシサーバ を作成しました。

リバースプロキシにはCaddyを使い、ほぼ全自動でLet's EncryptによるHTTPS対応を 行いました。WebSocketと静的コンテンツが同じポート番号で振り分けられるので、 非常に便利です。

まとめ

以上で暗号通貨の採掘ソフトをwasmに移植して、ブラウザで採掘ができるようにな りました。仕組み上どうしてもプロキシが必要となりますが、このプロキシはシン プルなので低リソースで動かすことができますし、分散させることも可能でしょう。

ソースコード

GitHub - ohac/cpuminer: [Updating] A multi-threaded CPU miner for BitZeny

GitHub - ohac/wasmminer: Browser mining on any pool. Currently support BitZeny.

デモページ

https://ohac.github.io/wasmminer/

速度は予想通りあまり出ませんでした。これはwasm化することにより低速化もあり ますが、特にSIMDが有効活用できないことに起因していると思います。今後wasmが SIMD対応すればそれを使うように改造することで改善するとは思います。

電気代に対して利益が出るようなものではありませんが、暗号通貨の採掘を体験し てみたいといった用途や広告の代替などには使えるかもしれません。