hugahuga秘密結社 仮想通貨支部

hugahugaがぼっとさまの力を借りて仮想通貨界を暗躍するその一部始終

The DAO の失態

本記事は、元記事を墨汁うまいさんが翻訳したものをさらに意訳したものです。
つまり漁夫の利 きたない さすが秘密結社きたない

元記事 : Why The DAO didn’t stand a chance – COINTIMES.TECH
墨汁うまいさんの翻訳記事 : http://bokujyuumai.hatenadiary.com/entry/2016/09/13/015558

がっつり意訳を入れてます。ご注意ください

コードパスについて

まず、乗算か除算を行うアプリケーションA(図1)を考える。

f:id:hugahuga_bit:20160913112744p:plain
図1

このアプリケーションのバグについて考えてみよう。
このためには、プログラムの全ての動作を考えていけばいい。

この記事を読んでいるあなたは、乗算と除算の二つの動作しかないと思うだろう。
だから、適当な数を入れてプログラムを実行し、乗算と除算が成功すれば、
このプログラムは完璧だと思うかもしれない。

しかし本当にそれで完璧だろうか?

今回のアプリケーションの場合、x=5,y=4なら完璧に動作する。
しかしy=0の時、このプログラムはエラーを起こす。
(算数や数学で0で割ってはいけないのと同様、プログラムの世界でも0で割ろうとするとエラーを起こす)

今回の例において、入力のx,yが8bitであるとすれば、(8bitで、-128から127までの256個の整数を表現できる)
256×256×2 = 131072パターンの入力があり、プログラムも131072パターンの動作がある。
それぞれのプログラムの動作パターンをコードパスと呼ぶ。

f:id:hugahuga_bit:20160913112827p:plain
図2

y=0で除算する時にエラーを起こすということは、エラーを起こすコードパスは256本あることになる。
(xの値は自由だから-128から127までの256通りあるよね)

アプリケーションのバグの可能性

動作をテストしたアプリケーションにバグが含まれる確率について考えてみよう。

これは、以下の式で表すことができる。

f:id:hugahuga_bit:20160913113048j:plain

P(F)はバグが含まれる確率
Uはテストしていないコードパスの数
Cは全てのコードパスの数
P(Fu)はテストしていないコードパスにおいて、バグが含まれる確率

P(Fu)はもちろん、プログラムの制作チームの力量が大きく影響する。


下の式は "e"の回数だけ、ランダム入力でプログラムを実行しうまく動作した場合に、
まだバグが残っている確率を表している。
(もちろん実際のプログラムではこんなに簡単ではないが、問題を簡単にするために簡単な式を使っている)

f:id:hugahuga_bit:20160913113104j:plain

P(Fe)はバグが残っている確率
e は実行回数

さて、上記の式をグラフにした場合以下のようになる。

f:id:hugahuga_bit:20160913113155j:plain
図3

黄色の線はP(Fu)=1の場合、つまり実行されていないコードパスを全く信用していない場合である。
青線、緑線はそれぞれ P(Fu)=0.5と0.1の時を示している。
(つまり実行されていないコードパスのバグが含まれる確率を50%と10%と仮定している)


仮に優秀なプログラマーによって、正しく動作するプログラムを書ける確率を90%としよう。
(つまりプログラムにバグがある確率が10%ある)
プログラムを全く実行していないとき、バグの存在する確率は10%である。
ここで興味深いことといえば、
このアプリケーションを80000回実行して正しく動いていたとしても、バグの存在する確率は5%もある。
300000回実行して正しく動いたとして、ようやくバグの存在する確率は1%になる。

1000人のユーザが1日に1回このプログラムを使うとすると、
バグの存在する確率が5%になるまでに80日かかるし、1%になるには300日もかかってしまう!!
(もちろんこれは、コードパス数がアプリケーションAと同じく131072本で、
プログラムにバグがある確率が10%だと仮定した場合であるが、、)


さて、話をアプリケーションAに戻そう
アプリケーションAは131072本のコードパスのうち256本がエラーになることを思い出して欲しい。
このアプリケーションを実行した時にバグが発生する確率は約0.2%だ

このアプリケーションを、ランダムな数値でテストした場合、
350回実行しても、50%の確率でy=0の除算エラーを見逃すし、
1500回実行しても、5%の確率で除算エラーを見逃してしまうのだ。

スマートコントラクトと the DAOについて

(ここから意訳度が上がります)

我々がアプリケーションを公開する前に、とても重要なことは、テストをしっかりとすることだ。

コードパスの本数は、アプリケーションAの例でも見たとおり、
使用される変数 (今回の場合 x , y , (乗算or除算))の数による。
また、同じコードでも、非同期実行(並列で動作させたりすること)の場合も
異なるコードパスとして扱うべきだ。

実際には、全てのコードパスをテストすることは不可能です。
しかし、変数に入力する数値と組み合わせ選びを慎重に行うことにより
バグの可能性は限りなく0に近づけられる。


(例えばアプリケーションAの場合 x , yについて、
それぞれ1度もでてこない数がないようにテストをすれば 512回のテストで0除算は必ず見つかる)
(このように、テストをうまく設定することで、
ランダムな数値でテストする場合より圧倒的にバグの可能性を潰すことができる)
(実際にバグの確率0は無理だけどね! 無理だけどね! いや本当に無理なんだけどね!)


コントラクトのプログラムが完成しても、コントラクトが安全であると思う前に、
さらに言うと実際に稼働させて実際の値をアプリケーションに流しこむ前に、
十分な時間をとってテストすることが必要です。
テストの時間は、コントラクトの複雑さに依存しているべきです。


the DAOは基本的に、ダム(資金プール)からの放流に関するコントラクトでした。
the DAOはまだ成長途中でした。
とても短い開発期間に大量に資金を集めすぎてしまいました。
事故は起こるべくして起こったのです。

そこからはあっという間の出来事でした。

デウスエクスマキナによって、
この失敗の痕跡を消し去りました。
そして次はうまくやるさと簡単に言いやがります。

                                    • -

デウスエクスマキナ
演劇手法 : 劇の内容が錯綜してもつれた糸のように解決困難な局面に陥った時、
絶対的な力を持つ存在(神)が現れ、混乱した状況に一石を投じて解決に導き、
物語を収束させるという手法を指した
直訳としては、機械仕掛けから出てくる神 機械仕掛けの神 (wikipediaより)
(つまり絶対神vitalikによって、騒動を無理やり収束させたことを指している)
(しかも直訳が機械仕掛け(ethereumプラットホーム)から出て来る神(vitalik)とか)
(これが言いたかっただけだろ)

                                    • -

(ここにパズドラのデウスエクスマキナとvitalikのクソコラを貼りたいので誰か作って)

これは、ブロックチェーンの技術の本質を破壊したことに他なりません。
我々はehtereumが稼働して真っ先にそれを思い知らされたのです。

ユーザにたいしてどのように開発すれば安全でスマートなコントラクトが開発できるかの指標を
コントラクトが備えられれば、こういった大きな事故が起こることは減るでしょう。

もしそれができるというのならば、その知性を証明してみせろ。


=======

この記事を翻訳意訳するにあたり墨汁うまいさんの記事を大変参考にいたしました。
墨汁うまいさんの翻訳記事 : http://bokujyuumai.hatenadiary.com/entry/2016/09/13/015558

こちらの寄付アドレスへの寄付は墨汁うまいさんへ送られます。
Address: 1LsGWycRiMxdfkUpQGT9AUsbe4Kcp4xYiT

ぼっとくん入門 第一回 環境を整えて、ハローAPI

だいぶ遅れましたね 絶賛夏休み大忙しのhugahugaです

そんな合間にも我がぼっとさまは着々と取引してくれています

さて、今回からC#によるぼっとくん入門を始めていきます

適当にアンケートとったら

質問です
はてなぶろぐでお伝えしたc#ぼっとですが
OSはどうしましょう?

うん、

ギリギリwindowsでの解説が許されそうなので、windowsでいきます

一応、プログラミングをしたことがない 〜 大学の講義でちょっとやったなぁ

くらいでもなんとかなることを目標にいきます

まず、プログラミングをするための環境を整えましょう

初心者からプロまで使える VisualStudioCommunityさんを入れます

Free IDE and Developer Tools | Visual Studio Community

ここからダウンロードしてきて

あとは流れに身を任せればいいです

途中、(おそらく)ユーザー登録とかもあると思うので、

適当に個人情報を投げつけましょう

VisualStudioCommunityを起動して、求められるままに受け答えして

さて、これでc#プログラミングを始める環境が整いました。


f:id:hugahuga_bit:20160909095126j:plain

実際にAPIを叩くところまでやってみましょう。


まずプロジェクトを作ります

(一つのプロジェクトが一つのプログラム(アプリ)になります )

取引画面とかボタンとかグラフとか表とかそういうのはぼっとさんには不要なので

文字だけのプログラムであるコンソールアプリケーションを選びます

ファイル→新規作成→プロジェクト

f:id:hugahuga_bit:20160909095231j:plain

コンソールアプリケーションを選択します。

下のほうの名前は適当でいいです。自分がわかるようにしましょう。

f:id:hugahuga_bit:20160909095343j:plain

さて、プロジェクトが作られました。

f:id:hugahuga_bit:20160909095510j:plain

これが最もシンプルなプログラムになります。

CTRL + F5 を押すと実行できます。

実行してみましょう。

f:id:hugahuga_bit:20160909095705j:plain

特に何も起きることなくプログラムが終了しました。

さて、プログラムがどうなっているかというと

f:id:hugahuga_bit:20160909102326p:plain

という感じになっています

なんだか多い、、、どうしても最初は書くこといっぱいになりますね

さて、ここに、bitFlyerc#サンプルを足してみましょう

bitFlyer Playground

https://lightning.bitflyer.jp/docs/playground

より、getTicker ティッカーの取得のサンプルを持ってきました。


それが以下のコード

using System;

using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace bitFlyerAPItest
{
    class Program
    {
        static void Main(string[] args)
        {
            Task task = Sample.Main();
            task.Wait();
            return;
        }
    }
    class Sample
    {
        static readonly Uri endpointUri = new Uri("https://api.bitflyer.jp");

        public static async Task Main()
        {
            var method = "GET";
            var path = "/v1/ticker";
            var query = "";

            using (var client = new HttpClient())
            using (var request = new HttpRequestMessage(new HttpMethod(method), path + query))
            {
                client.BaseAddress = endpointUri;
                var message = await client.SendAsync(request);
                var response = await message.Content.ReadAsStringAsync();
                Console.WriteLine(response);
            }
        }
    }

}

bFのサンプルをあれやこれやしてこうなりました。
やったことは、

  • サンプル最初のusingを、一番最初に記述
  • Sampleクラスを自分のnamespace以下にコピー
  • static void Main(string[] args)から呼べるようにした

こんな感じです。

Sampleクラスの中にあるMainはメソッドと呼ばれ、
SampleクラスのMainを呼び出せばtickerが得られる。

        static void Main(string[] args)
        {
            Task task = Sample.Main();
            task.Wait();
            return;
        }

でSampleクラスのMainメソッドを呼び出しています。
bfのサンプルでは、SampleクラスのMainメソッドは
呼び出すとTaskを返してきます。
なので、受け取ったあと、Waitで終わるのを待ちます。

これは、WebAPIを叩いたときなど、時間がかかる動作をするときに、
こっちはこっちで処理しとくから、他のこと先に進めといてーという雰囲気のやつです。

この辺は気になったら調べてもらうとして、
ここでは、

bFのサンプルメソッドを呼ぶ
↓
Taskを受け取る
↓
TaskをWaitする

を一連の流れでおまじないにしておきます。


ここからこのプログラムを動かすために必要なことがもう一つあって、
パッケージの追加をします。
HTTPリクエストを送るためのnamespaceなどは、最初から使えるわけではなく、
パッケージの追加をする必要があります。

プロジェクト→NuGetパッケージの管理
f:id:hugahuga_bit:20160909183802j:plain

検索窓で適当に検索して
System.Net.Http
をインストールします。

f:id:hugahuga_bit:20160909184048j:plain

これで、

using System.Net.Http;
using System.Net.Http.Headers;

あたりが使えるようになります。

これでプログラムが動くようになったはずです。
さて、上のプログラムを実行してみると

f:id:hugahuga_bit:20160909180648p:plain

無事tiker情報が表示されました。

とりあえず今回はここまで。


さて、残りbotくんを作るための流れを考えると

  1. 他のメソッドを呼び出せるようにする
  2. データを変換して得られるようにする
  3. 注文データを送れるようにする
  4. 戦略を実装する
  5. 有り金全部溶かす

こんな流れになります。

後半になればなるほど、プログラムの知識は欲しいなぁという感じではあるので、
どこかで補足しないとねぇ