エンジニアの皆さん
ビットコインの価格が爆上がりし、何を思っているでしょうか?
- 儲けるチャンスを逃した!
- 今から買うのもちょっとこわいなあ。というかバブルでしょ。
- アルトコイン買うか..!?(アルトコインで浸透している?みたいなのであえてアルトコインと書きましたが、発音はオルトの方が近い)
- ウォールストリートってすげぇ。
- そういえばウルフ・オブ・ウォールストリートって面白かったし、レオナルド・デカプリオかっこいいな。
- そろそろビットコインとかブロックチェーンどうなってるか知りたいな。
思うことは人それぞれだと思いますが、中でも、この記事は「そろそろビットコインとかブロックチェーンってどうなってるか知りたいな」と思った方の参考になればと思い書きました。というか、昨日ビットコインの原論文 "Bitcoin: A Peer-to-Peer Electronic Cash System"を読みましが、あんまり理解できていないので、つくりながら理解していこうと思い、この記事を執筆しています。しかも思いのほか終わらなかったので2回に分けます汗
目的
- ビットコイン・ブロックチェーンの仕組みを理解する
- とりあえずつくってみる
- シミュレーション的なもので、Rubyで書きます。
Part 1の概要
- 取引(トランザクション)、ブロック、ブロックチェーンの大雑把な理解
ビットコイン・ブロックチェーンの大雑把な理解
ビットコイン
論文のAbstractを説明すると以下のようになります。
- ビットコインは今までの電子マネーと違い、中央サーバのいない純粋なP2Pネットワークで個人対個人間の直接支払いができる。
- 二重使用問題を第三者機関によるチェックではなく、プルーフ・オブ・ワークという仕組みにより解決する。
二重使用問題とは、例えば100コイン持っていたとして、AさんとBさんに100コイン送ることができてしまうというような問題です。100円玉などの物体のない電子マネーだからこそ起きてしまいます。
コインの送金
2章Transactionsの最初の文章は以下で始まります。
We define an electronic coin as a chain of digital signatures.
電子コインをデジタル署名のチェーンと定義すると。どういうことかというと、自分に送られたコインに、「これは自分のコインですよ。だからあなたに送る権利がありますよ」という署名をして、誰かに送る。それを送られた人も同様に誰かに送る。するとデジタル署名のチェーンになることが想像できるでしょうか。ということで、1人=1nodeと表して以下のように秘密鍵を作ります。
require 'openssl'
class Node
def initialize()
@rsa = OpenSSL::PKey::RSA.generate(2048)
end
end
この秘密鍵で自分に送られたコインに、これは自分のものですよという署名して送れます。さらに送り先は、その送り相手の公開鍵によって指定します。
これによって、自分に送られたコインが自分宛てであることと、送り主の署名により、確かなものであることが確認できます。
取引
Transaction(取引)についてもう少し取引について詳しく載っている、9章Combining and Splitting Valueを見てみると、複数のInput(コインが自分宛てに送られた取引)と複数のOutput(送り先)を指定しています。これによってAさんから2コイン、Bさんから3コイン、Cさんから1コインを合わせて、Dさんに6コイン送ることができるようです。一旦以下のようにしました。
class Transaction
def initialize(args)
@inputs = args[:inputs]
@outputs = args[:outputs]
end
private
class Input
end
class Output
def initialize(args)
@to = args[:to]
@coin_value = args[:coin_value]
end
end
end
ブロックチェーン
ブロックチェーンの話は3章Timestamp Serverで出てきます。
ブロックには複数のアイテム(取引)が含まれています。
3章の図を見ると、2章の図のようにチェーンが作られているのが見られるかと思います。
ブロックチェーンのチェーンは、あるブロックが、「前のブロックのハッシュ値」と「そのブロック自体のデータのハッシュ値」を持つことで作られます。
このブロックチェーンは基本的には全ノードが同じものを持っています。つまり、ブロックチェーンはこれまでの全ての取引履歴になります。
そして、誰かに送金しようと思ったら、取引データを全ノードに送信して、各ノードは受信した複数の取引をブロックにまとめることになります。
一旦ここで、ノード、ブロック、ブロックチェーンをプログラムにします。
require 'openssl'
class Node
def initialize()
@rsa = OpenSSL::PKey::RSA.generate(2048)
@blockchain = Blockchain.new
end
end
class Blockchain
end
class Block
def initialize(args)
@timestamp = args[:timestamp]
@transactions = args[:transactions]
@hash = args[:hash]
@previous_hash = args[:previous_hash]
end
end
最初のブロック
最初のブロック、取引はどうなるんだと疑問を持たれた方はいらっしゃるでしょうか。
ぐぐったところココに書いてありました。
50コインを0x5F1DF16B2B704C8A578D0B(ビットコインアドレス)宛に送っています。
このビットコインアドレスは公開鍵をさらにハッシュして符号化したものです。
最初のブロックは以下のようにして、作ることにしました。
class Blockchain
def initialize
@blockchain = [Block.create_genesis_block]
end
end
class Block
def self.create_genesis_block
Block.new(timestamp: Time.utc(2017,12,18), transactions: [Transaction.create_genesis_transaction])
end
def initialize(args)
@timestamp = args[:timestamp]
@transactions = args[:transactions]
@hash = args[:hash]
@previous_hash = args[:previous_hash]
end
end
class Transaction
def self.create_genesis_transaction
inputs = [Input.new(coinbase: "my blockchain")]
outputs = [Output.new(to: 0, coin_value: 1000)]
new(inputs: inputs, outputs: outputs)
end
def initialize(args)
@inputs = args[:inputs]
@outputs = args[:outputs]
@previous_hash = args[:previous_hash]
@hash = args[:hash]
@sign = args[:sign]
end
private
class Input
def initialize(args)
@coinbase = args[:coinbase]
end
end
class Output
def initialize(args)
@to = args[:to]
@coin_value = args[:coin_value]
end
end
end
Inputのcoinbaseというのは、ブロックチェーンに自由に残せる文字列です。
通常は自分宛てに送られたトランザクションを指定します。
ビットコインのcoinbaseには「The Times 03/Jan/2009 Chancellor on brink of second bailout for bank」というTimes紙の見出しが書かれてあるそうです。ロマンを感じます。
次回
Part1は一旦ここまでです。
作ったプログラムはgithubに公開していますが、
一気に書いたので、もう少しちゃんと書き直して整理予定です汗
次回は
- プルーフ・オブ・ワーク
- P2Pネットワーク部分(論文には書いてない)
を説明して行きます。
たぶんだいぶ量が多くなりそうな予感がします。