どうも、フィナンシェCTOの西出です。初投稿です。三度の飯よりカレーが好きです。
前回の @ku_suke さんの記事に引き続き、フィナンシェの開発したときの知見を共有します。今回はEthereum上での開発において、開発用チェーンを苦労しながら転々としたので、そのログをまとめます。
開発用チェーンとは何か
普通のEthereum(メインネット)をそのまま開発用に使うと、世界中のサービスが同居しているネットワークに負荷をかけることになり望ましくありません。また経済的な事情としても、GAS代(ETH)を無尽蔵に払い続けないといけないため、開発専用のネットワークを使うことが一般的です。
テストネットと呼ばれる公開ネットワークRopsten、自前ノードのみで構築されるプライベートチェーンを使う方法、またローカルのみで稼働させる揮発性のネットワークを使う方法(Ganache)などがあります。今回はこれら開発用のチェーンとそのサーバ構築について解説していきます。
最終的に固まった構成
現在の使い分けはこんなかんじ
環境 | 接続先ノード |
---|---|
ローカル | 開発者ごとに好きなものを利用(Ganacheが多い) |
Dev | Ropsten |
Production | Mainnet |
初期...Ropstenが動作しない問題
前回の記事で紹介したように、フィナンシェはBancorとダッチオークションというコントラクトを用意しているのですが、それ以外にも様々な機能をできるだけスマートコントラクトで実装しようと思っていました。
ある程度ライブラリを取り込み、さっそく使ってみようと一番有名なテストネットのRopstenに接続しようとしたところ、なんとGAS LIMITを超えてしまい動作しませんでした。コントラクトのバイトコードが巨大化していたため、デプロイすることができなかったのです。
Ropstenとは
Ethereumの主要なテストネットの一つ。JSON-RPCのサーバはinfura(https://infura.io/)を使うことが一般的です。
テストネットでもガスが不要なわけではなく、テストネット用ETHを入手する必要があります。自分がバリデーターとなってマイニングすることも可能ですが、faucet(蛇口)とよばれるところでお恵みをもらうことができます。Ropstenネットワークで作成した自分のウォレットアドレスを入力し、入金を待ちます。
代表的なFaucet
しかしながら、Ropstenは前述の理由から当初使えなかったため、自前でのネットワーク&ノード構築にチャレンジしました。
gethをEC2に構築
gethとはgoで書かれたEthereumの公式ノードパッケージです。gethをEC2にインストールし、GAS LIMITを高めに設定して稼働させることで、ひとまずは動かすことができるようになりました。
Go Ethereum - Official Go implementation of the Ethereum protocol
https://geth.ethereum.org/
速度が遅く開発に時間がかかる
gethの構築によって開発は無事スタートしたのですが、ほとんどデフォルト設定で使っていたため、ブロックの生成、トランザクションの承認に時間がかかり、しょっちゅうつまって頻繁に5分程度の承認待ち時間が発生していました。これはよくありません。
そのタイミングでちょうどご縁があり、プライベートネットワークをSaaSで提供(アルファ版)していたgethoを紹介してもらい使い始めました。
開発用チェーンSaaSのgetho.io
getho(ゲソ)はパラメータチューニング済みのプライベートチェーンノードが1クリックで起動するSaaSです。まだ絶賛開発中ということで、専用Slackチャンネルに入っていただき、要望を山盛りぶん投げさせていただきました。
gethoを導入してからは(いくつか機能追加のタイミングで再起動や不安定になることはあったものの)コントラクトのデプロイやトランザクションがスムーズに流れるようになって非常に開発がサクサク進むようになりました。
また、後半の方ではブロックチェーンエクスプローラのような開発画面も追加してパワーアップしました。gethoは最小構成は無料で使えるのでぜひ試してみてください。
getho
https://getho.io/
ローカルはGanacheも併用し始めた
gethoは快適ですがインターネット越しで使うので、ローカルでさらなる安定感が必要な人はGanacheを導入し始めました。Ganacheは開発用の便利ツールで、Truffleと呼ばれるコアをElectronベースのGUIでラップしたものです。
Ganacheは起動すると、100ETHが入金済みのウォレットアカウント10個を用意した状態で起動してくれるので、あとは少しGAS LIMITをいじるだけですぐに使い始めることができます。
GanacheをUbuntuで動作させているところ
このようにして、ローカルもdevサーバも比較的サクサクと開発を進められるようになりました。フィナンシェの開発自体もすすみ、ある程度の機能セットが固まったので、コントラクトを分割して整理することにしました。
コントラクトの整理とは
ウォレットから1回に呼び出せるコントラクト/ファンクションは1個だけなのですが、コントラクト内でさらに別のコントラクトを呼び出すことは可能です。そのため、1コントラクトに全部詰め込むのではなくある程度まとまった機能単位で分割することで、一般的な開発言語におけるライブラリのような使い方をすることができます。
メリット:
- 1コントラクトでは限界だったバイトコードサイズの上限を回避できる
- ソースコードの可読性・管理性の向上
- 分割したコントラクト単位での差し替え(マイグレーション)対応が可能になる
デメリット・リスク:
- 各コントラクト間の呼び出しはすべてpublicになるため、自前で呼び出しの権限管理などをきっちりやる必要がある
- コントラクトまたぎで呼び出すことによる多少の実行コスト(ガス代)の上昇
今回は特に、ユーザーデータの管理コントラクトとそれに対するオペレーション用のコントラクトに分割しました。これによりまずバイトコードが小さくなり、またデータを引き継いだままオペレーション部分の機能追加・改善が可能となりました。膨大なコントラクト内データを、次のコントラクトに「スマートコントラクト内で」「1トランザクションとして」引き継ぐことは非常に困難なので、少なくともデータ構造だけは最初にデプロイしたコントラクトを永続的に使うつもりで設計する必要があります。
再度Ropstenにチャレンジ
ある程度テストも動作したのですが、いよいよクローズドβテストの締め切りが近づいてきて、「あまりサクサク動いてしまうといざメインネットで稼働させた時に起こりうる課題を見落とすかも」ということで再びRopstenにチャレンジすることにしました。幸いこの間にRopstenもGAS LIMITが引き上げられ、我々のコードも整理できたため、問題なくデプロイすることができました。
また、このタイミングではsolidityに関する知見がたまっており、最適化オプションも活用しました。コンパイル時に適切な最適化オプションをかけることで、同じ効果を得られるバイトコードのままでもサイズを削減できる仕組みです。
まとめ
このように、開発フェーズや目的によってさまざまなチェーンを使い分けることにより、スムーズな開発ができるようになります。ほかには別のテストネットであるKOVANや、TECHFUNDとMicrosoftが組んでいるACCEL BaaS、あとはGincoさんも似たようなサービスを開発中のようです。
現在のユーザー規模では一旦現状の構成でうまくワークしています。が、今後ユーザー数が拡大していくにつれてまた課題が出てくると思われるため、引き続きEthereumの最新動向を見つつ最適な方法を模索していきたいと思います!
また、フィナンシェではエンジニアを募集しております。コンシューマー向けサービスとして既に提供を始めているブロックチェーンサービスってまだまだ少ないので、未踏の地に切りこんでいく人柱フロンティアスピリッツをお持ちの方は是非こちらからお声がけください!