インプットがp2pkhのScriptPubKeyによってロックされたトランザクションの作成
1. ビットコインをどこに移動させるか
2. どのようなUTXOを使うことができるか
3. このトランザクションをどれくらい速くブロックチェーンに入れたいか
ビットコインではアドレス(公開鍵)はプライバシーやセキュリティの問題から再利用するべきではない。
### 手数料の算定
手数料はバイトサイズに基づき算定
300byteより600byteの方が高くなる
ブロックに空きがあるときは1bytesあたり1satoshi
### トランザクションの作成
アドレスを取得し、そこから20バイトのハッシュを取得する
数値を得たら、ビッグエンディアンバイトに変換
最初のバイトはネットワークプレフィックス、最後の4バイトはチェックサム、中間の20バイトが20バイトハッシュ(hash160)
def decode_base58(s): num = 0 for c in s: num *= 58 num += BASE58_ALPHABET.index(c) combined = num.to_bytes(25, byteorder='big') checksum = combined[-4:] if hash256(combined[:-4])[:4] != checksum: raise ValueError('bad address: {}{}'.format(checksum, hash256(combined[:-4])[:4])) return combined[1:-4]
この20バイトのハッシュをScriptPubKeyに変換する
script.py
def p2pkh_script(h160): return Script([0x76, 0xa9, h160, 0x88, 0xac])
0x76: OP_DUP
0xa9: OP_HASH160
h160 は20バイトのエレメント(引数)
0x88: OP_EQUALVERIFY
0xac: OP_CHECKSIG
### トランザクションの作成
from helper import decode_base58, SIGHASH_ALL from script import p2pkh_script, Script from tx import TxIn, TxOut, Tx prev_tx = bytes.fromhex('0d6fe5213c0b3291f208cba8bfb59b7476dffacc4e5cb66f6\ eb20a080843a299') prev_index = 13 tx_in = TxIn(prev_tx, prev_index) tx_outs = [] change_amount = int(0.33*100000000) change_h160 = decode_base58('mzx5YhAH9kNHtcN481u6WkjeHjYtVeKVh2') change_script = p2pkh_script(change_h160) change_output = TxOut(amount=change_amount, script_pubkey=change_script) target_amount = int(0.1*100000000) target_h160 = decode_base58('mnrVtF8DWjMu839VW3rBfgYaAfKk8983Xf') target_script = p2pkh_script(target_h160) target_output = TxOut(amount=target_amount, script_pubkey=target_script) tx_obj = Tx(1, [tx_in], [change_output, target_output], 0, True) print(tx_obj)
$ python3 test.py
tx: cd30a8da777d28ef0e61efe68a9f7c559c1d3e5bcd7b265c850ccb4068598d11
version: 1
tx_ins:
0d6fe5213c0b3291f208cba8bfb59b7476dffacc4e5cb66f6eb20a080843a299:13
tx_outs:
locktime: 33000000:OP_DUP OP_HASH160 d52ad7ca9b3d096a38e752c2018e6fbc40cdf26f OP_EQUALVERIFY OP_CHECKSIG
10000000:OP_DUP OP_HASH160 507b27411ccf7f16f10297de6cef3f291623eddf OP_EQUALVERIFY OP_CHECKSIG