p2wpkhはBIP0173で定義されているBech32というアドレス形式を使用する
p2shでp2wpkhをラップする… Segwitスクリプトがp2shのRedeemScriptでネストされる
BIP0141以前
01000000 – version
01 – # of inputs
712e…2f – previous tx hash
00000000 – previous tx index
1715…96 – ScriptSig
feffffff – sequence
02 – # of outputs
3236…00 output amount
1976…ac ScriptPubKey
075a0700 – locktime
BIP0141以降
01000000 – version
00 – Segwit marker
01 – Segwit flag
01 – # of inputs
712e…2f – previous tx hash
00000000 – previous tx index
1716…96 – ScriptSig
feffffff – sequence
02 – # of outputs
3236…00 output amount
1976…ac ScriptPubKey
0248…61 – witness
075a0700 – locktime
p2wpkhとの違いは、ScriptSigが空ではないこと, RedeemScriptがある
@classmethod def parse(cls, s, testnet=False): s.read(4) if s.read(1) == b'\x00': parse_method = cls.parse_segwit else: parse_method = cls.parse_legacy s.seek(-5, 1) return parse_method(s, testnet=testnet) @classmethod def parse_legacy(cls, s, testnet=False): version = little_endian_to_int(s.read(4)) num_inputs = read_varint(s) inputs = [] for _ in range(num_inputs): inputs.append(TxIn.parse(s)) num_outputs = read_varint(s) outputs = [] for _ in range(num_outputs): outputs.append(TxOut.parse(s)) locktime = little_endian_to_int(s.read(4)) return cls(version, inputs, outputs, locktime, testnet=testnet, segwit=False) @classmethod def parse_segwit(cls, s, testnet=False): version = little_endian_to_int(s.read(4)) marker = s.read(2) if marker != b'\x00\x01': raise RuntimeError('Not a segwit transaction {}'.format(marker)) num_inputs = read_varint(s) inputs = [] for _ in range(num_inputs): inputs.append(TxIn.parse(s)) num_outputs = read_varint(s) outputs = [] for _ in range(num_outputs): outputs.append(TxOut.parse(s)) for tx_in in inputs: num_items = read_varint(s) items = [] for _ in range(num_items): item_len = read_varint(s) if item_len == 0: items.append(0) else: items.append(s.read(item_len)) tx_in.witness = items locktime = little_endian_to_int(s.read(4)) return cls(version, inputs, outputs, locktime, testnet=testnet, segwit=True) def serialize(self): if self.segwit: return self.serialize_segwit() else: return self.serialize_legacy() def serialize_legacy(self): result = int_to_little_endian(self.version, 4) result += encode_varint(len(self.tx_ins)) for tx_in in self.tx_ins: result += tx_in.serialize() result += encode_varint(len(self.tx_outs)) for tx_out in self.tx_outs: result += tx_out.serialize() result += int_to_little_endian(self.locktime, 4) return result def serialize_segwit(self): result = int_to_little_endian(self.version, 4) result += b'\x00\x01' result += encode_varint(len(self.tx_ins)) for tx_in in self.tx_ins: result += tx_in.serialize() result += encode_varint(len(self.tx_outs)) for tx_out in self.tx_outs: result += tx_out.serialize() for tx_in in self.tx_ins: result += int_to_little_endian(len(tx_in.witness), 1) for item in tx_in.witness: if type(item) == int: result += int_to_little_endian(item, 1) else: result += encode_varint(len(item)) + item result += int_to_little_endian(self.locktime, 4) return result // def sig_hash_bip143(self, input_index, redeem_script=None, witness_script=None): tx_in = self.tx_ins[input_index] s = int_to_little_endian(self.version, 4) s += self.hash_prevouts() + self.hash_sequence() s += tx_in.prev_tx[::-1] + int_to_little_endian(tx_in.prev_index, 4) if witness_script: script_code = witness_script.serialize() elif redeem_script: script_code = p2pkh_script(redeem_script.cmds[1]).serialize() else: script_code = p2pkh_script(tx_in.script_pubkey(self.testnet).cmds[1]).serialize() s += script_code s += int_to_little_endian(tx_in.value(), 8) s += int_to_little_endian(tx_in.sequence, 4) s += self.hash_outputs() s += int_to_little_endian(self.locktime, 4) s += int_to_little_endian(SIGHASH_ALL, 4) return int.from_bytes(hash256(s), 'big')