|
Outputにはlocking scriptに
OP_DUP OP_HASH160 <Cafe Public Key Hash> OP_EQUAL OP_CHECKING
と書いてあって
Inputにはunlocking scriptに
<Cafe Signature> <Cafe Public Key>
と書いてあってこれらを組み合わせて
<Cafe Signature> <Cafe Public Key> OP_DUP OP_HASH160 <Cafe Public Key Hash> OP_EQUAL OP_CHECKING
この検証scriptがTRUEになったら有効な秘密鍵をもっていることになるらしいです。
なんのことやらさっぱり? なので、具体的なデータをみてみます。
トランザクションID=07e8989e7bc46f87485b975f153a3887e76c3e63f0a0d88af70186bbf1ce8306
のInputの0番目が解錠条件を満たしているのかbitcoin-rubyは使わずにRubyの標準添付ライブラリ は使ってよいというしばりで検証してみます。
このトランザクションIDは本物のbitcoinで使われているトランザクションです。
BLOCKCHAIN
chainFlyer
このトランザクションIDは適当に選びました。
前提
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'json' | |
require 'digest' | |
require 'bitcoin' | |
TRANSACTION_ID = '07e8989e7bc46f87485b975f153a3887e76c3e63f0a0d88af70186bbf1ce8306' | |
Vin = Struct.new(:txid, :index, :unlocking_script) | |
Vout = Struct.new(:locking_script) | |
def decode_transaction(tx_id) | |
JSON.parse(`bitcoin-cli getrawtransaction #{tx_id} 1`) | |
end | |
def decodescript(hex) | |
JSON.parse(`bitcoin-cli decodescript #{hex}`)['asm'] | |
end | |
def get_vin_n(transaction, n = 0) | |
json = transaction['vin'][n] | |
unlocking_script = decodescript(json['scriptSig']['hex']) | |
Vin.new(json['txid'], json['vout'], unlocking_script) | |
end | |
def get_vout_n(transaction, index) | |
json = transaction['vout'][index] | |
locking_script = decodescript(json['scriptPubKey']['hex']) | |
Vout.new(locking_script) | |
end | |
def hash160(input) | |
digest = Digest::SHA256.digest(["#{input}"].pack('H*')) | |
Digest::RMD160.hexdigest(digest) | |
end | |
def check_sig(public_key, signature) | |
# https://en.bitcoin.it/wiki/OP_CHECKSIG | |
# 理解およばず・・・・・・ | |
# https://github.com/lian/bitcoin-ruby 様のお力をお借りいたしました🙇 | |
Bitcoin::Script.from_string(signature, "#{public_key} OP_CHECKSIG").run | |
end | |
transaction = decode_transaction(TRANSACTION_ID) | |
vin = get_vin_n(transaction) | |
vout = get_vout_n(decode_transaction(vin.txid), vin.index) | |
script = "#{vin.unlocking_script} #{vout.locking_script}" | |
puts script | |
# => | |
# 304502210095787cb1ba8ebc48911c891924d62b8ff421accd40c2fba6070395fd772398f5022020f3df39b498b16eb61023f3947cb4386a75d68ed3628786c700f73e8743e54501 03d0dedbb2ca7e2c1aecd9d88dc36d1a101db20d70594ecfc1e34e0811541c44cb OP_DUP OP_HASH160 e667088e73ebfc2c6c3a5bc90ed29c3473f167a2 OP_EQUALVERIFY OP_CHECKSIG | |
script_ary = script.split(' ') | |
# 逆ポーランド記法を解く | |
stack = [] | |
script_ary.each do |s| | |
case s | |
when /^OP_DUP$/ | |
stack.push(stack.last) | |
when /^OP_HASH160$/ | |
stack.push(hash160(stack.pop)) | |
when /^OP_EQUALVERIFY$/ | |
if stack[-1] == stack[-2] | |
stack.pop | |
stack.pop | |
end | |
when /^OP_CHECKSIG$/ | |
stack.push(check_sig(stack.pop, stack.pop)) | |
else | |
stack.push(s) | |
end | |
p stack | |
end | |
puts stack.first | |
# => true |
OP_CHECKSIGをまだ理解できず、bitcoin-ruby 様の力をお借りしました。
理解して書き直したいとおもっています。
0 件のコメント:
コメントを投稿