仮想通貨ブロックチェイン技術
勉強会
近畿大学 山崎重一郎
Bitcoin福岡勉強会
2015年7月11日
送金時のトランザクション
未使用のoutput(UTXO)の残金を集める
in 0	
out 0
0.05 btc	
out 1
0.049 btc	
out 0
0.1 btc	
out 0
0.1 btc	
 UTXO
A
A
B
公開鍵B
ハッシュ	
公開鍵A
ハッシュ	
公開鍵A
ハッシュ	
公開鍵A
ハッシュ	
UTXO
送金時のトランザクション
使用するUTXOに対応するinputに電子署名
• 電子署名が入っていないトランザクションの
ハッシュ値を使って電子署名
in 0	
out 0
0.05 btc	
out 1
0.049 btc	
out 0
0.1 btc	
in 0	
out 0
0.1 btc	
in 0	
電子署名	
公開鍵 A	
A
A
B公開鍵B
ハッシュ	
公開鍵A
ハッシュ	
秘密鍵	
out 0
0.1 btc	
out 0
0.1 btc	
公開鍵A
ハッシュ	
公開鍵A
ハッシュ
送金時のトランザクション
署名、公開鍵をセットしたトランザクションを
P2Pネットワーク全体に放送する
in 0	
out 0
0.05 btc	
out 1
0.049 btc	
out 0
0.1 btc	
in 0	
out 0
0.1 btc	
in 0	
電子署名	
公開鍵 A	
A
B公開鍵B
ハッシュ	
公開鍵A
ハッシュ	
out 0
0.1 btc	
out 0
0.1 btc	
公開鍵A
ハッシュ	
公開鍵A
ハッシュ
トランザクションの検証
直前のoutput とinputの結合を検証
in 0	
out 0
0.05 btc	
out 1
0.049 btc	
電子署名	
公開鍵 A	
A
A
B公開鍵B
ハッシュ	
公開鍵A
ハッシュ	
out 0
0.1 btc	
スクリプト
公開鍵A
ハッシュ
トランザクションの検証
検証に成功すればブロックチェインに登録
in 0	
out 0
0.05 btc	
out 1
0.049 btc	
電子署名	
公開鍵 A	
A
A
B公開鍵B
ハッシュ	
公開鍵A
ハッシュ	
out 0
0.1 btc	
スクリプト
公開鍵A
ハッシュ	
ブロックブロックブロック
登録
bitcoinのスクリプト処理
目的 送金された金額の使い方を規定
• トランザクションのアウトプットに記載
• 受領者が次に使うときに評価される
0.5
BTC	
この公開 のハッシュに
対応する秘密 を
持っている人だけ
使用可能なお金
秘密 公開
受領者
bitcoinのスクリプト言語
Forth言語に似たスタック型言語
逆ポーランド記法=日本語記法 (1と2をたして3をかける)
•  定数:スタックにプッシュする
•  OP_DUP :スタックのトップ要素をコピーする
•  OP_HASH160 :スタックのトップ要素のダブルハッシュ値を求める
•  OP_EQUALVERIFY :スタックのトップ2要素を取り出して、双方
が等しいことを確認する
•  OP_CHECKSIG:スタックのトップ2要素を取り出して、1つめの公
開鍵と使って2つ目の電子署名を検証する
•  OP_RETURN:トランザクションinvalidとしてマークする
P2PKH (公開鍵ハッシュが条件)
このお金はこの公開鍵の所有者だけが次に使用できる
scriptPubKey:
OP_DUP OP_HASH160 <公開 Hash値> OP_EQUALVERIFY OP_CHECKSIG
scriptSig:
<電子署名> <公開 >
直前のoutput
送金input
証明すること
(1)この公開 は、公開 Hash値に対応していること
(2)電子署名によって公開 とペアになっている秘密 を持っていること
Stack 	
  Script	
  説明	
 
 	
 
<電子署名> <公開 > OP_DUP
OP_HASH160 <公開 ハッシュ>
OP_EQUALVERIFY
OP_CHECKSIG	
 
スタックは空	
 
OP_DUP OP_HASH160 <公開
ハッシュ> OP_EQUALVERIFY
OP_CHECKSIG 	
 
最初の2つの定数をスタックにプッシュする	
 
OP_HASH160 <公開 ハッシュ>
OP_EQUALVERIFY
OP_CHECKSIG 	
 
スタックの先頭要素をコピーする	
 
<公開 ハッシュ>
OP_EQUALVERIFY
OP_CHECKSIG
	
 
スタックの先頭をsha256,RIPEMD160で
ダブルハッシュする	
 
OP_EQUALVERIFY
OP_CHECKSIG
	
 
scriptPubKeyの公開 Hash値をスタック
にプッシュする	
 
OP_CHECKSIG
	
 
スタックの先頭2要素を取り出して等しいこと
をチェック	
 
	
 
スタックの先頭2要素を取り出し、公開 から
電子署名の検証を行う
#bitcoind	 へのアクセス

require	 'bitcoin'

require	 'net/http'

require	 'uri'

require	 'json'

require	 'ffi'

USER=ユーザ

PW=パスワード

HOST="localhost"

PORT=8332

#ネットワーク

Bitcoin.network	 =	 :bitcoin

#bitcoindへのHTTPアクセスするメソッド

def	 bitcoind(method,param)

	 	 begin

	 	 	 	 http	 =	 Net::HTTP.new(HOST,	 PORT)

	 	 	 	 request	 =	 Net::HTTP::Post.new('/')

	 	 	 	 request.basic_auth(USER,PW)

	 	 	 	 request.content_type	 =	 'application/json'

	 	 	 	 request.body	 =	 {method:	 method,	 params:	 param,	 id:	 'jsonrpc'}.to_json

	 	 	 	 JSON.parse(http.request(request).body)["result"]

	 	 rescue	 =>	 e

	 	 	 	 puts	 "bitcoind	 http	 access	 error	 :"+e.to_s

	 	 end

end

#生のトランザクションを得る

raw_transaction=->txid{bitcoind("getrawtransaction",[txid])}

#トランザクションオブジェクトを得る

transaction=->txid{Bitcoin::Protocol::Tx.new([raw_transaction[txid]].pack("H*"))}
#★テスト用トランザクションID

txid0="bcbd9f1720a7b4b0a8568e7db22040c020a1c4f408156c7d4f1d28ca15bb88d9"

#テスト用トランザクション

tx0=transaction[txid0]

tx0.to_hash

tx0.to_hash["in"][0]



#このインプット0に送金したトランザクションのアウトプットのインデックス1

txidp=tx0.to_hash["in"][0]["prev_out"]["hash"]
txp=transaction[txidp]

txp.to_hash

txp.to_hash["out"][1]



#インプットのスクリプト

scriptSig=Bitcoin::Script.new(tx0.in[0].script_sig)
scriptSig.to_string
#=>"304502210097dec104767588fef44eaec013dcffacd4668b1804e6b1e634f3857ac0762cac0220225aa2c3a
fff1f7bccc89cb54c7f420417836c4f36e770f7b2056f954b8ebbfa01
04887e78726151cc9159afbbba3aed9d929a75a5cc28fbc9efb3bf4535257cea707c7facf0f9b54e76435bf66a2
6823ab8e57ebd8dbb52f9572e138cd5f14b015a"


#直前のアウトプットのスクリプト

scriptPubKey=Bitcoin::Script.new(txp.out[1].pk_script)
scriptPubKey.to_string
#=> "OP_DUP OP_HASH160 80adbea585c59d50edd768d8b6fec324dbe0facf OP_EQUALVERIFY
OP_CHECKSIG"
#ttx0のインプットスクリプトの検証
tx0.verify_input_signature(0, txp)
カラードコイン
bitcoinのブロックチェインを利用
通貨ではなく、アセット(流動資産)の転々流通
• bitcoinとしては、600 satoshi
• アセットの発行者/責任主体が存在する
• 発行されたアセットの総量は保存される
0.000006
BTC	
10000
ラーメン
0.000006
BTC	
0.000006
BTC	
10000
ラーメン 0.000006
BTC	
1
ラーメン
0.000006
BTC	
9999
ラーメン
発行者
Open Asset Protocol
カラードコインの標準的な実装
Open Asset Address
•  カラーを認識できないワレットに送金しないようにする
例:akJ3bcrZmDB478sMn4SRmnoUPhWHrdwWqH4

Asset ID
• カラーを識別するID
例:Adj1tkK9zYC6WKsD5ib9Vyp127KQaJt7Dd

Asett Quantity
•  送金されるアセットの数(アセットは単位が存在する)符号なし整数
Open Asset Protocol
OP_RETURN を利用
• 意味:そのアウトプットをUTXOから外し、引数を返す
• 40バイトの引数を持てる(80バイトに仕様拡張)
• ブロックチェイン情報を登録する手段になる
ブロックチェインを非可逆的記録として利用する方法
Open Asset Address
ビットコインアドレスと1対1に対応
• カラーを認識するワレット用
• アセット情報を壊さないようにする
base58(名前空間+バージョン+[公開鍵のハッシュ値]+[チェックサム])
#オープンアセットアドレス生成

include	 Bitcoin::Util

open_asset_address=->bitcoin_addr{p='13'+'00'+(hash160_from_address(bitcoin_addr))

	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 encode_base58(p+checksum(p))}

bitcoin_addr="16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM"

open_asset_address[bitcoin_addr]

#=>	 "akB4NBW9UuCmHuepksob6yfZs6naHtRCPNy"
Asset ID
アセットを識別するID
• 秘密鍵を持っている主体のみが発行、追加発行できる?
• いろいろ謎がおおいので、実験で確かめる
• トランザクションの中にはID情報は存在しない
Marker output
アセットの発行、転送の情報を管理するアウトプット
• OP_RETURN で金額0のアウトプット
• マーカーアウトプットの前のアウトプットが発行
• マーカーアウトプットの後のアウトプットが転送
in 0	
 out 0
0.0000006 btc	
公開鍵
ハッシュ	
in 1	
in 2	
 out 2
0.0000006 btc	
公開鍵
ハッシュ	
out 1
0 btc	
OP_RET
URN	
 マーカーアウトプット
アセット発行
アセット転送
を解明するために、実際にアセットを発行、転送してみる
BA
C
B
D
C
E
F
F
A
E
100R
発行
10000B
発行
10000R
発行
10R
90R
A
B
A
B
5R
5R
1000R
9090R
1R
4R
500R
505R
505R
9090R
1000B
9000B
400B
600B
200B
200B
100B
100B
予想図
結果:予想図どおり

ブロックチェインとOpen asset protocol