はじめに
ブロックチェーンについて社内でアンケートを取ったところ、「Bitcoinはなぜブロックチェーンという構造を取っているのか」、「そもそもブロックチェーンとはどういった構造なのか」、という疑問を持っている者が数人いました。
そこで、Bitcoinのような、パブリックで非中央集権な分散管理台帳を作ろうとしたとき、どんな問題が起こるか、その問題はどのように解決できるかを考えることで、どうしてブロックチェーンができたのかを見ていきましょう。
ここに書かれている方法は、必ずしもBitcoinと同じではありません。また、ここに書かれているもの以外にも方法はあるかもしれませんが、ブロックチェーンがどうしてできることになったかを知るヒントとして、読んでいただければ幸いです。
目的: パブリックで非中央集権な分散管理台帳を作る
例えば、銀行の預金は、台帳を銀行が管理しています。
このような台帳を、パブリックな仕組みで作ることが目的です。
ここでいう「台帳」について、特に厳密な定義はしませんが、みんなのお金を管理するのに必要な情報を記録するためのシステムだと考えてください。
銀行預金のシステムでは、私たちは、銀行が管理しているシステムを自分のコンピュータに取り込んだり、システムに直接アクセスしたりはできません。今から作ろうとしているシステムは、自分のコンピュータに取り込むことができ、システムに直接アクセスすることができます。
ここで「パブリックな」というのは、誰もが参加できること、参加者はもしかしたら自分自身の利益のために嘘をつくかもしれないし、いたずらをして台帳を壊そうとする人もいることを指します。また「非中央集権な」とは、管理者や特別な役割を持った参加者はいないことを指します。
自分の通帳を自分で管理する方法
まず思いつくのは、各参加者が、自分がどれだけお金を持っているかを自分自身で管理する方法です。
誰もが参加できて、自分のものは自分で管理する、とてもフェアな仕組みの出来上がりです。
けれど、これには重大な欠点があります。
自分の通帳を自分で管理すると、自分自身の残高を実際より多いように書き換える人が出てきます。
大変残念なのですが、パブリックなネットワークでは、嘘をつく人がいるため、自己申告制はうまく機能しません。
みんなでみんなの通帳を共有する方法
そしたら、みんなで、みんなの通帳を共有したらどうでしょう?
これも結局、自己申告と同じです。
Aさん「はい! 私の残高が100万円増えました」
Bさん「はい! 私も100万円増えました」
Cさん「私は5000兆円ふえました」
単純にみんなで共有しても、それだけで嘘つきを防ぐことはできません。
みんなでみんなの取引を共有する方式
そもそも、お金は何もないところから湧いてきません。
残高が増えるということは、別の誰かからもらったということです。
「AさんはBさんに100万円支払います」のような記録を「取引」と呼びます。
残高だけを管理するのではなく、こういった取引を記録すると、なぜか残高が増えているという事態は起こらなくなります。
これで解決ですね。パブリックな分散台帳の出来上がり。
……と思いきや、トラブルの予感です。
「取引: AさんはBさんに100万円支払います」
Aさん「え? 払うつもりないんだけど、なんで勝手に!?」
みんなでみんなの署名付き取引を共有する方法
残高の管理ではなく、取引の管理をすることで、お金は増えたり減ったりせず、誰かから誰かに受け渡されるようになりました。
けれど、これだと、不正に、他人からお金を受け取ったことにしてしまう人が出てきます。
これを解決するには「AさんがBさんにお金を支払いました」の取引は、支払う側であるAさんだけが作れるルールにする、という方法が有効そうです。
パブリックなネットの世界では、なりすまし等、発信者の偽装はいくらでもできてしまいそうです。
けれど、幸いにも、発信者の偽装を防ぐ方法は既に考案され、広く利用されています。「電子署名」です。
電子署名の詳細は本記事では述べませんが、取引に含まれている電子署名を検証することで、取引が支払う側によって作られたこと、その中身が改竄されていないことが分かります。
これで、お金の増減は取引によって行われることになったし、本人にしか取引は作れなくなったし、パブリックな分散管理台帳の完成です。
……とはいかないんですよねぇ。まだ不正できるんですよねぇ。
ほんと、どうすんだよ、これ
Aさん残高: 100万円
「取引: AさんはBさんに100万円支払います。署名: Aさん」
「取引: AさんはCさんに100万円支払います。署名: Aさん」
おや? 二重支払いです。
残念ながら、こういう場合も電子署名はできてしまいます。
Aさんが持っているお金は、何度でも、もう使ったはずのお金であっても、Aさんは署名をして取引を作ることができます。
これは大問題です。
使ったお金を何度も使うことができたら、お金は無限に増やせてしまいます。
けれど、待ってください。今、私たちが考えているシステムでは、みんながみんなの取引を共有しているのでした。
それだったら、新しい取引が作られたとき、そのお金が既に使われていないかチェックすることができます。
既に使ったお金をもう一度使おうとしていた場合には、その取引はできてはいけないので、無視するようにしたらいいですよね。
そうなんです。取引をみんなで共有することで、このような二重利用もチェックできるんです。
けれど、問題はそれだけでしょうか?
「新しい取引: AさんはBさんに100万円支払います。署名: Aさん」
Xさん「はーい、了解~!」
「新しい取引: AさんはCさんに100万円支払います。署名: Aさん」
Yさん「はーい、了解~!」
Xさん「この取引は無視~」
Yさん「え? Xさん、なんで無視したの?」
Xさん「だって、Aさん、もうBさんに払ったじゃん?」
Yさん「何それ? そんなの俺聞いてないよ?」
Xさん「うそー、あったじゃん。Cさんのをなかったことにして、Bさんに払ったようにしなよ」
Yさん「Cさん、その100万円を、もうDさんに払っちゃったんだけど。Xさんが俺のに合わせてくれない?」
「新しい取引: BさんはDさんに100万円支払います。署名: Bさん」
Xさん「あ、なんか来た。Bさんは100万円持ってるね。署名もある。チェック完了」
Yさん「え、ちょっと待って。今それをするとややこしい」
Xさん「取引完了! で、どうするって話だっけ?」
Yさん「……」
Zさん「さっきから横で聞いてたんだけど。そもそも、AさんはFさんに払ったはずだよね?」
大混乱です。分散台帳は崩壊しました。
合意アルゴリズムの必要性
署名付き取引を共有し、各々が、その取引が有効なものか、既に使われたお金を再度使おうとしていないかをチェックすれば、お金の二重利用は防ぐことができました。
けれど、その代償として、どの取引が有効であるかについて、参加者の間で食い違いが発生し、大混乱が起こってしまいました。
何か、うまいことやる方法はないでしょうか?
取引にタイムスタンプや連番をつけて、早い方を有効にする
タイムスタンプや連番は自己申告なので、偽装ができます。
全く同じタイムスタンプの取引が複数あったら、どっちが有効でしょう?
また、後になってから、より早いタイムスタンプの取引が見つかる可能性もあります。
先に自分のコンピュータに到着した取引を有効にする
分散管理台帳に参加しているコンピュータは世界中にあります。
世界中のコンピュータで、取引を同じ順番で受け取れるとは限りません。
また、「俺のところには、こっちが先に来た」と嘘をつく人がいるかもしれません。
取引の順番が入れ替わったとき、やはり混乱は起きてしまいます
多数決で決める
自由参加のネットワークにおいては、多数決で重要なことを決めるのは悪夢の始まりです。
1人の人間が、大量のコンピュータを使って、一人で何万、何十万もの参加者として参加することは容易にできてしまいます。
悪意ある人間が紛れ込めば、分散台帳はぐちゃぐちゃに荒らされてしまうでしょう。
誰かが取引を承認し、他のみんながその決定に従う
やっぱりこれ、誰かが取りまとめないと収拾がつかないですね。
けれど、管理者や特別な利用者がいないパブリックなネットワークで、一体どうやって、取りまとめる人を決めるのでしょうか?
また、他の利用者は、取りまとめた人に従う必要があるのでしょうか?
Proof of Workだ
実はこれ、かなりの難問です。
嘘をつく、ルールに従わないなど、意図的に台帳を書き換えたり壊したりしようとする人がいるかもしれない中、だいたいみんなで、だいたいひとつの意思決定をするというのは非常に難しいのです。
Bitcoinでは、Proof of Workという仕組みを使って、だいたいみんなで、だいたいひとつの意思決定をしています。
Proof of Workでは、管理者がいないネットワークであっても、取引をとりまとめる人を公平に決めることができます。
また、とりまとめる人に選ばれなかった人にとっても、とりまとめる人に従った方がメリットになります。
それは、大まかにはこんな方法です。
1 参加者は、いくつかの取引を「ブロック」という単位にまとめる
とりまとめのプロセスは大変なものなので、いくつかの取引をまとめて、みんなの合意をとってしまうことにしましょう。
「ブロック」と呼ばれる箱に、詰められる限りの取引を詰めます。
ただし、詰め込む取引に二重利用などの不正がないかは、詰め込む人が確認してください。
もし不正な取引が混ざっていたら、ブロックを作っても、他の参加者たちに無視されます。
2 まとめたブロックを、既にある別のブロックにつなぎ合わせる
プログラミング経験者向けに書くと、ただの線形リストです。
それぞれのブロックにはIDが振られていて、既にあるブロックのIDを、新しいブロックに書いておくことで、他の人がブロックを見たときに「この新しいブロックは、この古いブロックとつながっているんだな」と分かります。
3 ブロックのnonceという値を適当に設定する
何でもいいです。適当にセットします。
……え、これ、やる意味あるん? って感じですが、読んでいけば分かります。
4 ハッシュの計算をして、ブロックのIDを求める
「暗号学的ハッシュ関数」という小難しい名前の計算方法があります。
大雑把に言うとこれは、任意のデータを「ハッシュ」と呼ばれる決まった長さの数字列に変換する計算で、以下のような性質を持ちます。
- 計算対象のデータが少しでも異なると、計算結果のハッシュは全く違うものになる
- けれど、計算対象のデータが全く同じだと、誰が計算しても、計算結果のハッシュは全く同じになる
- 「こんなハッシュが欲しい」と思っても、それをうまく狙ってデータを作ることはできない
- どうしても狙いたいハッシュがある場合は、狙った値が出るまで、いろんなデータを計算する作業を繰り返すしかない
ブロックの中身のハッシュを求め、それをブロックのIDとします。
ここで、もしもあなたがズルをして、ブロックの中身のハッシュとは違う値をブロックのIDにしても、すぐにバレます。
他の参加者がブロックの中身のハッシュを求め、IDと一致しているか調べたら、あなたがズルをしたかどうかは一目瞭然です。
ズルをしたブロックは参加者から無視されます。
5 ブロックのIDがネットワークから指定された値より小さくなるまで、ハッシュの計算を繰り返す
ブロックのIDが、指定された値より大きい場合、そのブロックは送っても参加者から無視されます。
じゃあどうするの? そこでnonceの出番です。
4で書いたハッシュの計算方法の性質より、データが少しでも変わるとハッシュは全然違う値になるので、nonceを変えるとハッシュが変わります。
なので、3に戻って、指定された値より小さいブロックIDになるまで、新たなnonceでハッシュの計算を繰り返します。
6 ブロックのIDがネットワークから指定された値より小さかったら、そのブロックを他のみんなに送信する
ブロックの出来上がりです。出来たブロックをネットワークに送信します。
ここまで読んで分かる通り、ブロック作りは、何度も何度もハッシュの計算が必要な、大変な作業なのです。
このように、ブロックを別のブロックに鎖状につなげていく様子を、誰かが「ブロックチェーン」と名付けました。
鎖状につながっている構造自体は、別になんでもない、ただの「線形リスト」ですが、ブロックを作ってつなぐまでの過程に重要な意味があります。
それがどうしたって?
ブロックを作る手順を説明しましたが、なぜこんなことをするのか、いろいろ疑問が湧いてくるでしょう。
なんでブロックのIDが特定の値より小さいかを気にするの? どうでもよくない?
みんなが取引を承認できてしまうと、ネットワークが混乱する、というのが課題でした。
そこで、「IDが特定の値より小さいブロックのみが有効」で、「有効なブロックに入った取引のみが有効」というルールを付け加えます。
上述のハッシュ計算の特徴より、そのようなブロックを作るのは難しく、計算を何度も繰り返すことで得られます。
これにより、一気に大量にブロックができて混乱が起こることは避けられます。
それでも、複数のブロックができることはあるのでは?
はい、あります。
けれど、後で述べるように、どれかのブロックが生き残るような仕組みになっています。
「特定の値」って、どうやって決めるの?
例えばBitcoinでは、新たなブロックが見つかるタイミングがおよそ10分に1度となるように、決められた数式に従って、2016ブロックごとにブロックの見つけやすさの調整が行われています。
そもそも、こんな計算をやりたがる参加者いるの?
ブロックを作った人には報酬が与えられる仕組みになっています。
「お金は何もないところから湧いてこない」と上の方で書きましたが、Bitcoinでは、ブロック作りに関しては唯一の例外で、ブロックを作る際、あらかじめ決められた量のお金を自分の口座に入れることが許されています。
何もないところからお金が湧いてくるのは、金の採掘に似ているため、Bitcoinのブロック作りは「採掘」や「マイニング」と呼ばれることがよくあります。
また、Bitcoinでは、湧いてくるお金以外にも報酬があります。
取引を作る際、実は「手数料」を設定することができるのですが、「手数料」は、取引をブロックに入れた人がもらえることになっています。
これらの報酬があるため、Bitcoinのブロック作りをやりたい人は世界中にたくさんいます。
誰かがブロックを作っても、みんな、それを無視して採掘する可能性はないの?
ハッシュの計算は1回ごとに全然違う結果が出るので「もう少し計算したらブロック作れたのに!」ってことにはなりません。
(10個のサイコロを、全部ぞろ目が出るまで振る作業を考えてください。9個のぞろ目が出たら、すごく惜しいですが、惜しかったからといって、もうちょっとで10個のぞろ目が出るわけではありません)
なので、今、作ろうとしているブロックにこだわるメリットはあまりありません。
ところで、新たにブロックが出来た場合、そのブロックに付け加えるようなブロックを作った方が、長く連なった鎖を作れることになります。
次に述べるように、長い鎖を作った方が得なので、採掘者たちは、新しいブロックができたら、今探しているのをやめて、鎖を伸ばすようなブロックを作りはじめます。
なんで長く連なった鎖を作ったら得するの?
参加者たちは、複数のブロックがあった場合は、最も長く連なった鎖につながっているブロックを信用する、というルールで動いています。
ブロックをどの鎖につなげるかは、ブロックを作る人の自由です。けれど、長い鎖につながないと、作ったブロックは、他の参加者から無視されることになります。
ブロックが無視されたら、せっかくハッシュ計算をして報酬を得ても、その報酬を得たという事実は誰にも承認されず、無視されてしまいます。
なので、報酬が欲しいなら、一番長い鎖にブロックをつなぐのが得だと言えます。
そしたら、短い鎖は無視されるの? その鎖に入ってる取引はどうなるの?
はい。短い鎖に入っているブロックは無視されます。その中の取引は承認されません。
承認されていない取引は、おそらく、いずれ別のブロックに入れられるでしょう。
結局これ、いっぱい鎖ができたら、どれが正しいか収拾付かないんじゃ?
そうなのですが、採掘者にとっては長い鎖を作るのが一番得なので、みんな長い鎖を作ろうとして、そう長くない間に、1本の鎖に収束していくと期待できます。
中には、報酬に興味なくて、鎖をいっぱい作ってみんなを混乱させたい人もいるかもしれないですが、報酬が欲しくて頑張る採掘者がいっぱいいて、その人たちが一番長い鎖を育てていくので、そういういたずらをしても無駄な努力となるでしょう。
鎖が複数あったとき、どの鎖が正しいか決着がつくのは時間がかかるということ?
そうです。すぐには決着がつきません。
Bitcoinの場合は、後ろにブロックが6個つながったら確実に承認されたものとみなすことが多いようです。
けれど、もっと長い鎖が後から作られたら、そっちが正しくなるわけだよね?
そうなのですが、後から長い鎖を作るのは、ハッシュ計算がすごく大変です。
なので、事実上、そういうことはできない、とされています。
ハッシュ計算をいっぱいしたら長い鎖を作れるんだよね?
そうです。もし膨大なハッシュ計算を行えるなら、長い鎖を自分だけで作ることができます。
けれど、膨大なハッシュ計算を行うためには、高性能または大量のコンピュータを用意して、さらには動かすための電気代を払う必要があるので、お金がかかります。
そしてBitcoinのように、たくさんの採掘者がいるネットワークでは、そのための計算力は膨大なものとなり、現実的な予算では用意できません。
このように、ブロックを作るために、ハッシュ計算を行う、つまりコストをかけることを要求するのがProof of Workです。
Proof of Workのもとでは、自分だけで好きなブロックを作ろうとしたり、既にある鎖よりも長い鎖を作ろうとすると、膨大なハッシュ計算、すなわち膨大なコストが必要となります。
Proof of Work完全に理解した
長くなったので、話をまとめましょう。
採掘者
- 「採掘者」は、取引をブロックにまとめます。ブロックは「線形リスト」になっていて、一番長い鎖につなぎます。
- 採掘者は、条件を満たすハッシュ値が得られるまで、nonceを変えながらブロックのハッシュを計算します。このようなハッシュは、だいたい10分に1回くらいの割合で、誰かが見つけられるように調整されています。
- 条件を満たすハッシュ値が得られた採掘者は、そのハッシュ値をブロックのIDにして、ブロックをネットワークに流します。ブロックを作った採掘者は報酬が得られます。
- 採掘者は、1.に戻って新しいブロックにつながるブロックを作りはじめます。
これに従うか従わないかは自由ですが、従わない場合、ブロックを作っても参加者たちに無視されます。
参加者
採掘している人も、採掘していない人も、参加者は次のルールに従います。
- ネットワークに流れてくるブロックや、ブロックに含まれている取引に不正がないか確認します。
- 一番長い鎖を信用します。つまり、一番長い鎖を作っているブロック(最新のブロックだけではなく、「線形リスト」状につながっているブロックも合わせる)に含まれている取引が、承認された取引です。
これに従うか従わないかは自由ですが、従わない場合、その参加者だけ、みんなと同じ分散管理台帳を得られません。
合意が得られた
このように、「採掘者」に報酬を与えて、代表してブロックを作ってもらうことで、ネットワーク全体で、どの取引を承認されたものとみなすかの合意がなんとなく取れました。
末端の方のブロックは、もしかしたら別の鎖が長くなって無効になるかもしれないですが、ある程度伸びてきたら、現実的には、もう覆らないことがProof of Workで保証されています。
これで、パブリックで非中央集権な分散管理台帳が完成しました。
終わりに
ブロックチェーンについて理解を深めるために「パブリックで非中央集権な分散管理台帳を作る」という目的で、どう作っていけばいいのか試行錯誤を行いました。
いくらでも不正ができる仕組みを改善し、最後にProof of Workを取り入れることで、「パブリックで非中央集権な分散管理台帳」を作ることができました。
これで「ブロックチェーンってどういう構造?」「なんでBitcoinにはブロックチェーンが使われているの?」が理解できたのではないでしょうか。
ここに書いたものはBitcoinを参考にしていますが、Bitcoinとは異なる部分もあります。
また、Bitcoinの機能や仕組みはこれだけではないですし、Bitcoin以外にもブロックチェーンを実装したものはたくさんあります。
合意アルゴリズムにProof of Work以外を使っているブロックチェーンもありますし、ブロックもチェーンも使わない、パブリックで非中央集権な分散管理台帳も、実は提案されていたりします。
それらが「何をしているのか」、「どうなっているのか」だけではなく、どういった目的があって、そのためにどのような課題があって、どうやって課題を解決しているのか、といった観点で見ると、驚くほど理解が進みます。
興味を持たれた方は、調べてみると面白いですよ。