Skip to content

Commit b9f34e8

Browse files
committed
Improve readability of segwit.py
1 parent 21833f9 commit b9f34e8

File tree

2 files changed

+45
-43
lines changed

2 files changed

+45
-43
lines changed

qa/rpc-tests/bumpfee.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ def test_segwit_bumpfee_succeeds(rbf_node, dest_address):
102102
segwit_out = rbf_node.validateaddress(rbf_node.getnewaddress())
103103
rbf_node.addwitnessaddress(segwit_out["address"])
104104
segwitid = send_to_witness(
105-
version=0,
105+
use_p2wsh=False,
106106
node=rbf_node,
107107
utxo=segwit_in,
108108
pubkey=segwit_out["pubkey"],

qa/rpc-tests/segwit.py

Lines changed: 44 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,59 +6,61 @@
66

77
from test_framework.test_framework import BitcoinTestFramework
88
from test_framework.util import *
9-
from test_framework.mininode import sha256, ripemd160, CTransaction, CTxIn, COutPoint, CTxOut
9+
from test_framework.mininode import sha256, ripemd160, CTransaction, CTxIn, COutPoint, CTxOut, COIN
1010
from test_framework.address import script_to_p2sh, key_to_p2pkh
11-
from test_framework.script import CScript, OP_HASH160, OP_CHECKSIG, OP_0, hash160, OP_EQUAL, OP_DUP, OP_EQUALVERIFY, OP_1, OP_2, OP_CHECKMULTISIG
11+
from test_framework.script import CScript, OP_HASH160, OP_CHECKSIG, OP_0, hash160, OP_EQUAL, OP_DUP, OP_EQUALVERIFY, OP_1, OP_2, OP_CHECKMULTISIG, hash160
1212
from io import BytesIO
13-
from test_framework.mininode import FromHex
13+
from test_framework.mininode import FromHex, ToHex
1414

1515
NODE_0 = 0
1616
NODE_1 = 1
1717
NODE_2 = 2
1818
WIT_V0 = 0
1919
WIT_V1 = 1
2020

21-
def witness_script(version, pubkey):
22-
if (version == 0):
23-
pubkeyhash = bytes_to_hex_str(ripemd160(sha256(hex_str_to_bytes(pubkey))))
24-
pkscript = "0014" + pubkeyhash
25-
elif (version == 1):
26-
# 1-of-1 multisig
27-
scripthash = bytes_to_hex_str(sha256(hex_str_to_bytes("5121" + pubkey + "51ae")))
28-
pkscript = "0020" + scripthash
21+
# Create a scriptPubKey corresponding to either a P2WPKH output for the
22+
# given pubkey, or a P2WSH output of a 1-of-1 multisig for the given
23+
# pubkey. Returns the hex encoding of the scriptPubKey.
24+
def witness_script(use_p2wsh, pubkey):
25+
if (use_p2wsh == False):
26+
# P2WPKH instead
27+
pubkeyhash = hash160(hex_str_to_bytes(pubkey))
28+
pkscript = CScript([OP_0, pubkeyhash])
2929
else:
30-
assert("Wrong version" == "0 or 1")
31-
return pkscript
32-
33-
def addlength(script):
34-
scriptlen = format(len(script)//2, 'x')
35-
assert(len(scriptlen) == 2)
36-
return scriptlen + script
37-
38-
def create_witnessprogram(version, node, utxo, pubkey, encode_p2sh, amount):
39-
pkscript = witness_script(version, pubkey)
30+
# 1-of-1 multisig
31+
witness_program = CScript([OP_1, hex_str_to_bytes(pubkey), OP_1, OP_CHECKMULTISIG])
32+
scripthash = sha256(witness_program)
33+
pkscript = CScript([OP_0, scripthash])
34+
return bytes_to_hex_str(pkscript)
35+
36+
# Return a transaction (in hex) that spends the given utxo to a segwit output,
37+
# optionally wrapping the segwit output using P2SH.
38+
def create_witnessprogram(use_p2wsh, utxo, pubkey, encode_p2sh, amount):
39+
pkscript = hex_str_to_bytes(witness_script(use_p2wsh, pubkey))
4040
if (encode_p2sh):
41-
p2sh_hash = bytes_to_hex_str(ripemd160(sha256(hex_str_to_bytes(pkscript))))
42-
pkscript = "a914"+p2sh_hash+"87"
43-
inputs = []
44-
outputs = {}
45-
inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"]} )
46-
DUMMY_P2SH = "2MySexEGVzZpRgNQ1JdjdP5bRETznm3roQ2" # P2SH of "OP_1 OP_DROP"
47-
outputs[DUMMY_P2SH] = amount
48-
tx_to_witness = node.createrawtransaction(inputs,outputs)
49-
#replace dummy output with our own
50-
tx_to_witness = tx_to_witness[0:110] + addlength(pkscript) + tx_to_witness[-8:]
51-
return tx_to_witness
52-
53-
def send_to_witness(version, node, utxo, pubkey, encode_p2sh, amount, sign=True, insert_redeem_script=""):
54-
tx_to_witness = create_witnessprogram(version, node, utxo, pubkey, encode_p2sh, amount)
41+
p2sh_hash = hash160(pkscript)
42+
pkscript = CScript([OP_HASH160, p2sh_hash, OP_EQUAL])
43+
tx = CTransaction()
44+
tx.vin.append(CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"]), b""))
45+
tx.vout.append(CTxOut(int(amount*COIN), pkscript))
46+
return ToHex(tx)
47+
48+
# Create a transaction spending a given utxo to a segwit output corresponding
49+
# to the given pubkey: use_p2wsh determines whether to use P2WPKH or P2WSH;
50+
# encode_p2sh determines whether to wrap in P2SH.
51+
# sign=True will have the given node sign the transaction.
52+
# insert_redeem_script will be added to the scriptSig, if given.
53+
def send_to_witness(use_p2wsh, node, utxo, pubkey, encode_p2sh, amount, sign=True, insert_redeem_script=""):
54+
tx_to_witness = create_witnessprogram(use_p2wsh, utxo, pubkey, encode_p2sh, amount)
5555
if (sign):
5656
signed = node.signrawtransaction(tx_to_witness)
5757
assert("errors" not in signed or len(["errors"]) == 0)
5858
return node.sendrawtransaction(signed["hex"])
5959
else:
6060
if (insert_redeem_script):
61-
tx_to_witness = tx_to_witness[0:82] + addlength(insert_redeem_script) + tx_to_witness[84:]
61+
tx = FromHex(CTransaction(), tx_to_witness)
62+
tx.vin[0].scriptSig += CScript([hex_str_to_bytes(insert_redeem_script)])
63+
tx_to_witness = ToHex(tx)
6264

6365
return node.sendrawtransaction(tx_to_witness)
6466

@@ -180,8 +182,8 @@ def run_test(self):
180182
self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], False)
181183
self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], False)
182184
# unsigned with redeem script
183-
self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], False, addlength(witness_script(0, self.pubkey[0])))
184-
self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], False, addlength(witness_script(1, self.pubkey[0])))
185+
self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], False, witness_script(False, self.pubkey[0]))
186+
self.fail_accept(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], False, witness_script(True, self.pubkey[0]))
185187
# signed
186188
self.fail_accept(self.nodes[0], wit_ids[NODE_0][WIT_V0][0], True)
187189
self.fail_accept(self.nodes[0], wit_ids[NODE_0][WIT_V1][0], True)
@@ -205,8 +207,8 @@ def run_test(self):
205207
self.fail_accept(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][1], False)
206208

207209
self.log.info("Verify unsigned p2sh witness txs with a redeem script in versionbits-settings blocks are valid before the fork")
208-
self.success_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][1], False, addlength(witness_script(0, self.pubkey[2]))) #block 430
209-
self.success_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][1], False, addlength(witness_script(1, self.pubkey[2]))) #block 431
210+
self.success_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][1], False, witness_script(False, self.pubkey[2])) #block 430
211+
self.success_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][1], False, witness_script(True, self.pubkey[2])) #block 431
210212

211213
self.log.info("Verify previous witness txs skipped for mining can now be mined")
212214
assert_equal(len(self.nodes[2].getrawmempool()), 4)
@@ -230,8 +232,8 @@ def run_test(self):
230232
self.log.info("Verify witness txs without witness data are invalid after the fork")
231233
self.fail_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][2], False)
232234
self.fail_mine(self.nodes[2], wit_ids[NODE_2][WIT_V1][2], False)
233-
self.fail_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][2], False, addlength(witness_script(0, self.pubkey[2])))
234-
self.fail_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][2], False, addlength(witness_script(1, self.pubkey[2])))
235+
self.fail_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][2], False, witness_script(False, self.pubkey[2]))
236+
self.fail_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][2], False, witness_script(True, self.pubkey[2]))
235237

236238
self.log.info("Verify default node can now use witness txs")
237239
self.success_mine(self.nodes[0], wit_ids[NODE_0][WIT_V0][0], True) #block 432

0 commit comments

Comments
 (0)