ブロックチェーンエンジニア Lv. 1 —スマートコントラクトをデバッグするぞ—


はじめに

この記事は普通のエンジニアでスマートコントラクト初心者の私が、Ethereumを使ったスマートコントラクトを勉強していく様を綴っていきます。今回はLv.1ということで、一から開発環境を立ち上げてスマートコントラクトのデバッグをはじめるところまで進めたいと思います。

参考資料

Smartcontractの開発を効率化するBrowser-solidityの使い方

開発環境を整える

Ethereumのスマートコントラクトの開発言語もいろいろありますが、ここでは一番メジャーなSolidityという言語を使うことにします。

Solidityの開発環境として一番メジャーなものがbrowser-solidityです。Webアプリとして動作します。

これをgitで落としてきます。

git clone https://github.com/ethereum/browser-solidity.git

この中のindex.htmlを開くとWebアプリとしてスマートコントラクトのIDEが立ち上がります。

こんな感じの画面です。真ん中の画面がエディタになっていて、ポチポチとプログラムを書いていきます。実行するには右側でRunというタブを選んで実行したいコントラクトに対してパラメータをセットしてCreateを押すと、自分のマシンの中で仮想的にスマートコントラクトがデプロイされます。

スマートコントラクト?デバッグ?何でそんなことするの?

スマートコントラクトと聞くと、なんだか凄く賢いマシンが勝手に世の中をよくしていってくれそうなそんなイメージを抱かれるかもしれません。しかし、そんなものはただの幻想です。スマートコントラクトはブロックチェーン上で動く単なるプログラムに過ぎません。そのプログラムは人がコーディングします。人がコーディングして組むプログラムである以上はバグが潜む可能性があります。よって、本番環境にデプロイする前にきちんとデバッグやテストを行って品質を担保する必要があるわけです。以降で、その一例を見ていくことにします。

おれも仮想通貨作ってやったぞぉ Lv.1

ブロックチェーンエンジニアLv.1のkackyは仮想通貨を作りたくなったのでちょっとsolidityをかじって、仮想通貨(ERC20準拠)を作って見ました。

pragma solidity ^0.4.15;

contract MyToken { 
    /* Public variables of the token */
    string public name;
    string public symbol;
    uint8 public decimals;

    /* This creates an array with all balances */
    mapping (address => uint256) public balanceOf;

    /* This generates a public event on the blockchain that will notify clients */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /* Initializes contract with initial supply tokens to the creator of the contract */
    function MyToken(uint256 _supply, string _name, string _symbol, uint8 _decimals) {
        /* if supply not given then generate 1 million of the smallest unit of the token */
        if (_supply == 0) _supply = 1000000;

        /* Unless you add other functions these variables will never change */
        balanceOf[msg.sender] = _supply;
        name = _name;     
        symbol = _symbol;

        /* If you want a divisible token then add the amount of decimals the base unit has  */
        decimals = _decimals;
    }

    /* Send coins */
    function transfer(address _to, uint256 _value) {
        /* if the sender doenst have enough balance then stop */
        assert (balanceOf[msg.sender] >= _value);
        assert (balanceOf[_to] + _value >= balanceOf[_to]);

        /* Add and subtract new balances */
        balanceOf[_to] += _value;
        /* あ、送信元の残高減らすの忘れたてへぺろ */

        /* Notifiy anyone listening that this transfer took place */
        Transfer(msg.sender, _to, _value);
    }
}

一見すると、ちゃんと実装された仮想通貨のプログラムをコピペしてきたように見えますが、このプログラムには残念ながらバグがあります。
この仮想通貨にちゃんとした名前をつけるのは憚られるので、名前を「HEBO Coin」としましょう。このスマートコントラクトをデプロイしてみます。

やったーHEBO Coin 100000ゲットです。
このCoinを誰かに送りましょう。100ヘボ送信ポチ。

やったー。送れたぜ。あれ、でもどこか違和感が・・・

あれ、コインが増えてる!?無から有が生まれてしまいました。無限通貨ヘボコイン 爆 誕  です。こんなクソコイン誰も使いませんね。皆さんお察しかと思いますが、コインの送信処理のなかで

        /* Add and subtract new balances */
        balanceOf[_to] += _value;
        /* あ、送信元の残高減らすの忘れたてへぺろ */

送信先の残高を増やす処理の後で送信元の残高を同じだけ減らす処理を書くのを忘れていました。こういうバグありますよね。てへぺろ。こんなことやってたらプログラマー失格です。早く直さないと。

しかしこの後、勇者kackyはスマートコントラクトの恐ろしさを知ることになります。

スマートコントラクトの恐ろしさ

あばば、スマートコントラクトでバグを出してしまいました。
こんなとき、普通のアプリ開発なら、

リーダー 「何やってんだ、kacky、早くバグを直しなさい!」

kacky 「すみません、直しました(´・ω・`)」

リーダー 「早速、アップデートだ。ビルドしてAppleに申請しなくちゃ」

となるわけですが、スマートコントラクトでは残念ながら一度デプロイしてしまったコントラクトを改変することはできません。これは覚えておくべき非常に大切なことです。ブロックチェーンは改変不可のデータベースであるからこそ信頼されています。これはスマートコントラクトも例外ではありません。たとえ、そのプログラムにバグがあろうとも・・・、な、なんだってー。

つまり今回作られたHEBO Coinは黒歴史として永久に残り続けることになります。合掌。

・・・これは嫌ですね。まあ、今回はテスト用のネットワークに追加しただけなのでこのネットワークそのものを消し去ってしまえば綺麗さっぱりなくせます。しかし、Ethereumのメインネットに乗せてしまった場合、そんなこともできません。メインネットに乗せるスマートコントラクトは入念に検証を行い、不具合が起こらないことを確認しなければなりません。

とは言え、大規模なプログラムを全部検証済でデプロイするというのも非現実的というものです。そんなこと言ってたら一生サービスリリースできないかもしれません。何かしらの方法でバージョンアップを実現する必要があると思います。しかし今はエンジニアLv.1ですからまだその時ではありません。おいおい勉強しながら実現していきましょう。

ということで、まずはちゃんとデバッグできるようになりましょう。

デバッグの基本ブレークポイント

デバッグの基本はやはりブレークポイントです。ブレークポイントを貼るにはエディター上の左端をクリックすると赤くなります。これで完了です。大抵のIDEと変わりませんね。

デバッグを実行するには下のウインドウに出ているいろんな実行履歴の中から該当するトランザクションの「Debug」というボタンを押します。今回は送金をデバッグするので、transferと書かれた一番下のものをクリックします。すると、まず、関数の先頭で止まった状態になります。

デバッグは右側のタブのDebuggerを使って行います。大抵のIDEと同じようなボタンが用意されています。ブレークポイントまで進めるには▶| みたいなボタンを押します。その下には他の言語のデバッガと同じようにローカル変数やグローバル変数と言ったものがつらつらと見られるようになっており、これを追いかけながら、ステップ実行をするなどしてプログラムの内部状態を確認してデバッグしていきます。

おわりに

今回はEthereumスマートコントラクトの開発環境を立ち上げて、デバッグを実践しました。また、スマートコントラクトにおけるデバッグの重要性を確認しました。次回からはちょっとずつ実践的なプログラムを組んで行けたらよいかなと考えています。