読者です 読者をやめる 読者になる 読者になる

Reality Keys(事実に関する認証局サービス)のrealitykeysdemo.pyを読む(2/3)

Reality Keys

f:id:yzono:20150205163652j:plain

はじめに

前回「契約のセットアップ(execute_setup)」についてソースコードを読みました。今回は「勝利の主張(execute_claim)」について調べてみます。

目次

  • 前回の振り返り
  • 勝利の主張(execute_claim)
  • エラーの原因調査

前回の振り返り

前回claimを実行した時の結果はこれです。Aliceが選択したNOが事実認証され、Aliceが勝利の主張(簡単に言えば、引き出しの権利行使かな)を行った時の結果です。

$ ./realitykeysdemo.py claim 1 043e90a622f851754b83c0d28bc0d4a4c619b13c70c174658a0b0dd7480a32631629734a00ba16434e6f64060ec6e3837b5d148134cd6522302b5243b34ad37543 040190c6e169d2aaadb45cae2964db48d48c16b42a9cf963aceda3644068a73f3d23a33a4efd87f2e73e9482bb7425a8500a2ca19124f1c2930df2aa5e726ff119 -f 0 -d 1Fcyh3T6zsQtwBpwpTADf6M24GY5CC4vbx --seed [Aliceのseed]

claim時に必要なパラメータは以下です。

reality_key_id = 1 yes_winner_public_key = 043e90a622f851754b83c0d28bc0d4a4c619b13c70c174658a0b0dd7480a32631629734a00ba16434e6f64060ec6e3837b5d148134cd6522302b5243b34ad37543(BobのPublic key) no_winner_public_key = 040190c6e169d2aaadb45cae2964db48d48c16b42a9cf963aceda3644068a73f3d23a33a4efd87f2e73e9482bb7425a8500a2ca19124f1c2930df2aa5e726ff119(AliceのPublic key) fee = 0(トランザクションfee) destination_address = 1Fcyh3T6zsQtwBpwpTADf6M24GY5CC4vbx(送信先アドレス)

def execute_claim(settings, reality_key_id, yes_winner_public_key, no_winner_public_key, fee=0, destination_address=None):

前回実行した時は以下結果が出てだけで、送信先にビットコインが送られていませんでした。今回はその原因も含めて確認します。

Found 2000 in the P2SH address

勝利の主張(execute_claim)

execute_claimの処理を順に見ていきます。

(1)秘密鍵取得

private_key = user_private_key(False, seed)

(2)送信先ビットコインアドレス作成

送信先を指定しない場合(-dオプションをつけない場合)は、秘密鍵からビットコインアドレスを生成して、そこに対して送信されます。つまり、P2SHアドレスを作成した時のAliceのアドレスに送金されます。Bobの分も含めてAliceに送り返さます。claimの場合はseedオプションは無くても分かりやすいです。

if destination_address is None:
    destination_address = pubtoaddr(privtopub(private_key), magic_byte(settings))

(3)イベントのPublick Keyと勝者のPrivate keyを取得

Reality Keys APIを実行して各公開鍵と勝利した秘密鍵を取得します。

req = urllib2.Request(REALITY_KEYS_API % (reality_key_id))
response = urllib2.urlopen(req)
fact_json = simplejson.load(response)
yes_reality_key = fact_json['yes_pubkey']   
no_reality_key = fact_json['no_pubkey']

winner = fact_json['winner']
winner_privkey = fact_json['winner_privkey']

(4)マルチシグのredeemスクリプト作成

setupと同様にマルチシグのredeemスクリプトを作成します。

multisig_script = mk_multisig_script_if_else([[yes_winner_public_key, yes_reality_key], [no_winner_public_key, no_reality_key]])

(5)P2SHアドレス作成

setupと同様にP2SHアドレスを作成します。

p2sh_address = p2sh_scriptaddr(multisig_script)

(6)P2SHアドレスのspendできるトランザクションの配列を取得

P2SHアドレスのspendableなトランザクションinputの配列を取得します。 spendableなinputが0の場合はエラーを返します。

transactions = [spendable_input(p2sh_address, 0, 0, 0, settings.get('inputs', None))]

if len(transactions) == 0:
   out.append("There do not seem to be any payments made to this address.")
   return out

(7)送金金額取得

(6)の配列をループして送信する値を取得します。

val = 0
for outtrans in transactions:
    # eg [{'output': u'4cc806bb04f730c445c60b3e0f4f44b54769a1c196ca37d8d4002135e4abd171:1', 'value': 50000, 'address': u'1CQLd3bhw4EzaURHbKCwM5YZbUQfA4ReY6'}]
    val = val + outtrans['value']

if val == 0:
    raise Exception("Nothing to spend.")
    return out

val = val - fee
if verbose:
    out.append("Found %s in the P2SH address" % (str(val)))

(8)トランザクション作成

トランザクションを作成します。

outs = [{'value': val, 'address': destination_address}]
tx = mktx(transactions, outs)

(9)マルチシグのトランザクション作成

マルチシグのトランザクション作成を作成します。claimの処理ではここが一番大事なので詳細は別に調べます。

sig1 = multisign(tx,0,multisig_script,private_key)
sig2 = multisign(tx,0,multisig_script,winner_privkey)
if winner == 'Yes':
  if_flags = [1] # pybitcointools will serialize this as OP_1 OP_TRUE (81)
elif winner == 'No':
  if_flags = [None] # pybitcointools serializes this as OP_0 / OP_FALSE (0).
  
multi_tx = apply_multisignatures_with_if_flags(tx,0,multisig_script,if_flags,[sig1, sig2])

(10)ブロードキャスト

特殊なトランザクションのためeligius_pushtxを使用してブロードキャストします。そこでエラーの場合はblockchain.infoに対してブロードキャストします。

try:
  eligius_pushtx(multi_tx) # This should work even if the transaction 
except:
  try:
    pushtx(multi_tx) # Try blockchain.info, which will almost definitely fail unless we're using ECC voodoo

エラーの原因調査

(10)ブロードキャストのeligius_pushtx(multi_tx)が正しく動作していない可能性がありあます。

multi_txは生成されています。

01000000018ef7d75fc510e9ecf4272a152fa0fcf8c96bf98d1b9943e142db2c2dd032024200000000fd790100483045022100ad2ddb0cfe51e51a7628302b96c8070796de4887071d213257790ecf6bbbfae602202935347c9d375ab8737c24a06af00bf1f166a765162c4f2062b6024c146a62f00147304402202039f48dbaeee0be741c64e6b9870b791b49c8f966b4b1b4a9f86c16d4928cc802202ca2a7c50f0bd1f8a99aa6e96b6db0d4e526bb246f4836923f5d34e3b8df098601004ce45b39395d5241043e90a622f851754b83c0d28bc0d4a4c619b13c70c174658a0b0dd7480a32631629734a00ba16434e6f64060ec6e3837b5d148134cd6522302b5243b34ad375432103ea19d70a96a072a1881a6177ab47144168f19f9648675eb189e35e4bde4b16cd525b3137345d5b3130335d5241040190c6e169d2aaadb45cae2964db48d48c16b42a9cf963aceda3644068a73f3d23a33a4efd87f2e73e9482bb7425a8500a2ca19124f1c2930df2aa5e726ff11921036d4f24332e9c49861591558f074a112f9718e47383c394106325ac5b65b9cd30525b3137345d5b3130345dffffffff01e8030000000000001976a914a05fa4734f5d4b7b821b2f9379246eac2678787a88ac00000000

まとめ

まだP2SHアドレスに入れたビットコインを取り出すことに成功していません。eligius_pushtxが怪しいと思っています。次回はなんとか頑張ります..

参考

eligius

疑問点(今度エドに聞こう!)

Found 2000 in the P2SH address これは送金する金額のことだよね

eligius_pushtxって現在動いている?

blockchain.infoに対するブロードキャストではダメ?(実際ダメだった)

setupではblockchain.infoにブロードキャストできて、claimではできない理由はなんでしょうか?