txをシリアライズする際に、redeem_script=None としてp2pkh か p2shかを分ける
def sig_hash(self, input_index, redeem_script=None):
s = int_to_little_endian(self.version, 4)
s += encode_varint(len(self.tx_ins))
for i, tx_in in enumerate(self.tx_ins):
if i == input_index:
if redeem_script:
script_sig = redeem_script
else:
script_sig = tx_in.script_pubkey(self.testnet)
else:
script_sig = None
s += TxIn(
prev_tx = tx_in.prev_tx,
prev_index = tx_in.prev_index,
script_sig = tx_in.script_pubkey(self.testnet),
sequence = tx_in.sequence,
).serialize()
s += encode_varint(len(self.tx_outs))
for tx_out in self.tx_outs:
s += tx_out.serialize()
s += int_to_little_endian(self.locktime, 4)
s += int_to_little_endian(SIGHASH_ALL, 4)
h256 = hash256(s)
return int.from_bytes(h256, 'big')
def verify_input(self, input_index):
tx_in = self.tx_ins[input_index]
script_pubkey = tx_in.script_pubkey(testnet=self.testnet)
if script_pubkey.is_p2sh_script_pubkey():
cmd = tx_in.script_sig.cmds[-1]
raw_redeem = encode_varint(len(cmd)) + cmd
redeem_script = Script.parse(BytesIO(raw_redeem))
else:
redeem_script = None
z = self.sig_hash(input_index, redeem_script)
combined = tx_in.script_sig + script_pubkey
return combined.evaluate(z)
def is_p2pkh_script_pubkey(self):
return len(self.cmds) == 5 and self.cmds[0] == 0x76 \
and self.cmds[1] == 0xa9 \
and type(self.cmds[2]) == bytes and len(self.cmds[2]) == 20 \
and self.cmds[3] == 0x88 and self.cmds[4] == 0xac
def is_p2sh_script_pubkey(self):
return len(self.cmds) == 3 and self.cmds[0] == 0xa9 \
and type(self.cmds[1]) == bytes and len(self.cmds[1]) == 20 \
adn self.cmds[2] == 0x87