Bitcoinの細部

ここまで、Bitcoinの仕組みの本質的な部分について説明してきた。しかし、Bitcoinのウォレットを実装する上では、まだいくつかの本質的ではない概念が不足している。そのため、この章ではこれらについて解説する。

トランザクションの分割

Bitcoinのトランザクションは、複数のインプットとアウトプットを持てるようになっている。設計上は、Bitcoinの仕組みの図などで仮定していたように、1トランザクションを1コインとしても問題はない。しかし、これでは様々な面において不便である。複数のインプット・アウトプットを持つことで、コインをより細かい単位でやり取りでき、また、おつりを簡単に実装できるようになるなどの利点がある。

複数のインプット・アウトプットを使い、おつりを受け取ることを考える。例えば、自分が1コインを持っているとして、相手に0.5コインを渡し、自分は0.5コインのおつりが欲しいとする。このとき、アウトプットが相手のアドレスと自分のアドレスの二つとなっている、と表現すれば、シンプルに実装できることが分かると思う。

実際に多くのトランザクションは、1つ以上のインプットと、2つのアウトプットを持っている。インプットは、これまでに自分がコインを得た過去のトランザクションである。アウトプットは、コインを送る相手と、そのお釣りを受け取る自分の二つのアドレスである。このことは、Block Explorerを見ても分かる。

図: 複数のインプットとアウトプットを持つトランザクション

図: 複数のインプットとアウトプットを持つトランザクション

これらのインプット・アウトプットは「Bitcoinウォレットを実装する」の章では、それぞれtx_in, tx_outと呼ばれている。tx_inはコインを受け取ったトランザクションであるのに対して、tx_outはコインを送るアドレスであることに注意。

なお、実際のBitcoinで、コインはどこまで分割できるかというと、0.00000001 (=10^-8) BTCまでである。これをBitcoin発案者のSatoshi Nakamotoの名前にちなんで、1 satoshiなどと呼ぶことがある。

SPVとマークル・ツリー(ハッシュ木)

SPV(Simplified Payment Verification)クライアントを実現するためには、かかせなかった仕組みが「マークル・ツリー」(Merkle Tree)、あるいは日本語では「ハッシュ木」と呼ばれているものである。(論文(PDF)の8章)

ハッシュ木の理解は、二分木について知っていれば難しくないので、二分木について知らない方は自分で調べていただきたい。この節では「ノード」は二分木におけるノードのことを意味し、P2Pにおける個々のクライアントの意味ではない。

ハッシュ木とは、全てのノードがハッシュを持った二分木のことである。子を持つノードのハッシュは、子のハッシュを単純に繋げた物のハッシュである。葉は、Bitcoinの場合には、各トランザクションのハッシュを持つ。

図: ハッシュ木(Merkle Tree)

図: ハッシュ木(Merkle Tree) (論文(PDF)から引用)

このとき、根ノードをマークル・ルート(Merkle Root)と言う。Bitcoinでは、ブロックのヘッダーは、トランザクションのデータのうち、このマークル・ルートのハッシュのみを含む。ブロックのハッシュはブロックのヘッダーのみを範囲としている。このため、ナンスや仕事の証明と直接関わってくるのも、このマークル・ルートのハッシュだけであることに注意する。

このような木を作ることの利点は、少ないデータで、あるトランザクションがブロックに含まれていることを確認できる点である。あるトランザクションのハッシュがマークル・ツリーに含まれていることを確認するには、そのトランザクションのデータと、ブロックのヘッダーと、あとはわずかな木ノードのハッシュのみが必要である。このときの必要な木ノードの個数は、ブロックに含まれるトランザクションの総数Nについて、二分木の性質から、およそ log2(N) 個となる。

仮に、Bitcoinがマークルツリーを使わなかった場合を考える。ブロックヘッダーに含まれるハッシュが、マークル・ルートではなく、単純にトランザクションを全て繋げたデータのハッシュだったとする。このとき、ある1つのトランザクションが本当にブロックに含まれているのかどうか検証するには、他の全てのトランザクションのデータが必要となってしまう。

コインの量の上限とマイニングの難易度

Bitcoinにおいて、あるブロックをマイニングした時に得られるコインベースのコイン量は、そのブロックが一番最初のブロック(genesis blockと言う)から何番目かによって決め打ちされている。

具体的には以下のようなC++のコードに基づいている。(heightはブロックが何番目か)

(50 * 100000000) >> (height / 210000)

(単位はsatoshi)これをグラフにすると以下のようになる。

図: コインベース額の変化

図: コインベース額の変化

また、「Bitcoinのしくみ」の章でも述べたが、ブロックの採掘難易度(ブロックのSHA-256ハッシュの先頭に、0が何個以上並んたブロックを正当と認めるか)は、実際に一定数のブロックの採掘に要した時間を加味して決定される。 具体的には、2016ブロックごとに、1ブロックの採掘間隔がおよそ10分になるように調整されて決定される。

マイニングプール

マイニングプールは、大勢で協力してマイニングを行う仕組みである。

1ブロックを採掘する難易度は日に日に増してきている。このため、ASICによる専用の機材を用いても、一人だけでまぐれでブロックを掘り当てる可能性は極めて低いと言わざるをえない。

一方、1ブロックのマイニングで得られる報酬は比較的大きい。例えば、この記事の執筆当時(2014/3)では25BTC、これをUSDになおすと(執筆当時のレートで694.39 USD / BTC)17350ドル、日本円にして約177万円である。したがって、一人あたりのもらえる額が多少低くてもよいので、協力してブロックを採掘しようという発想に至るのは自然なことである。

マイニングプールでは、大勢がマイニングに協力して、条件をみたすナンスを探索する。そして、得られたコインベースを、貢献度に応じて各参加者に分配する。具体的には、マイニングプールのサーバーから、ナンス以外のブロックヘッダーが与えられ、これについて、条件を満たすナンスを探索することになる。

マイニングプールが、古典的なマイニングと異なるのは、プールによって、Bitcoinの本当のブロックチェーンよりもゆるい採掘難易度が、別途に設定されていることである。クライアントは、これを満たすナンスを発見する度にサーバーに報告する。これによって、参加者がハッシュを本当に探索していることをサーバー側に証明する。サーバー側はこのナンスの送信されてくるペースから、おおよその各クライアントの貢献度を割り出し、それに応じて個々人に報酬を支払う。

しかし、ナンスの送信されてくるペースから、単純に貢献度を計算するだけでは、完全に不正を防ぐことはできない。このため、より不正を困難にするために、いくつかの貢献度の計算方法が存在する。(加筆予定)

Bitcoinにどのような代表的なマイニングプールがあるかは、blockchain.infoで確認できる。実際のブロックの横に「中継所」として採掘したマイニングプールの名前が表示されるので、これを見てみるとよいだろう。また、各プールが、どの程度の比率を占めているかはビットコインハッシュレート分布 - Blockchain.infoから確認できる。

Bitcoinウォレットを実装する」につづく