Skip to content

Commit b811124

Browse files
sdaftuarjl2012
authored andcommitted
[qa] Add tests for uncompressed pubkeys in segwit
1 parent 9f0397a commit b811124

File tree

1 file changed

+117
-8
lines changed

1 file changed

+117
-8
lines changed

qa/rpc-tests/p2p-segwit.py

Lines changed: 117 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,17 @@ def __init__(self, sha256, n, nValue):
166166
self.n = n
167167
self.nValue = nValue
168168

169+
# Helper for getting the script associated with a P2PKH
170+
def GetP2PKHScript(pubkeyhash):
171+
return CScript([CScriptOp(OP_DUP), CScriptOp(OP_HASH160), pubkeyhash, CScriptOp(OP_EQUALVERIFY), CScriptOp(OP_CHECKSIG)])
172+
173+
# Add signature for a P2PK witness program.
174+
def sign_P2PK_witness_input(script, txTo, inIdx, hashtype, value, key):
175+
tx_hash = SegwitVersion1SignatureHash(script, txTo, inIdx, hashtype, value)
176+
signature = key.sign(tx_hash) + chr(hashtype).encode('latin-1')
177+
txTo.wit.vtxinwit[inIdx].scriptWitness.stack = [signature, script]
178+
txTo.rehash()
179+
169180

170181
class SegWitTest(BitcoinTestFramework):
171182

@@ -1323,13 +1334,6 @@ def test_signature_version_1(self):
13231334
sync_blocks(self.nodes)
13241335
self.utxo.pop(0)
13251336

1326-
# Add signature for a P2PK witness program.
1327-
def sign_P2PK_witness_input(script, txTo, inIdx, hashtype, value, key):
1328-
tx_hash = SegwitVersion1SignatureHash(script, txTo, inIdx, hashtype, value)
1329-
signature = key.sign(tx_hash) + chr(hashtype).encode('latin-1')
1330-
txTo.wit.vtxinwit[inIdx].scriptWitness.stack = [signature, script]
1331-
txTo.rehash()
1332-
13331337
# Test each hashtype
13341338
prev_utxo = UTXO(tx.sha256, 0, tx.vout[0].nValue)
13351339
for sigflag in [ 0, SIGHASH_ANYONECANPAY ]:
@@ -1443,7 +1447,7 @@ def sign_P2PK_witness_input(script, txTo, inIdx, hashtype, value, key):
14431447
tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b""))
14441448
tx2.vout.append(CTxOut(tx.vout[0].nValue, CScript([OP_TRUE])))
14451449

1446-
script = CScript([CScriptOp(OP_DUP), CScriptOp(OP_HASH160), pubkeyhash, CScriptOp(OP_EQUALVERIFY), CScriptOp(OP_CHECKSIG)])
1450+
script = GetP2PKHScript(pubkeyhash)
14471451
sig_hash = SegwitVersion1SignatureHash(script, tx2, 0, SIGHASH_ALL, tx.vout[0].nValue)
14481452
signature = key.sign(sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL
14491453

@@ -1706,6 +1710,110 @@ def test_getblocktemplate_before_lockin(self):
17061710
assert(block_version & (1 << VB_WITNESS_BIT) != 0)
17071711
self.nodes[0].setmocktime(0) # undo mocktime
17081712

1713+
# Uncompressed pubkeys are no longer supported in default relay policy,
1714+
# but (for now) are still valid in blocks.
1715+
def test_uncompressed_pubkey(self):
1716+
print("\tTesting uncompressed pubkeys")
1717+
# Segwit transactions using uncompressed pubkeys are not accepted
1718+
# under default policy, but should still pass consensus.
1719+
key = CECKey()
1720+
key.set_secretbytes(b"9")
1721+
key.set_compressed(False)
1722+
pubkey = CPubKey(key.get_pubkey())
1723+
assert_equal(len(pubkey), 65) # This should be an uncompressed pubkey
1724+
1725+
assert(len(self.utxo) > 0)
1726+
utxo = self.utxo.pop(0)
1727+
1728+
# Test 1: P2WPKH
1729+
# First create a P2WPKH output that uses an uncompressed pubkey
1730+
pubkeyhash = hash160(pubkey)
1731+
scriptPKH = CScript([OP_0, pubkeyhash])
1732+
tx = CTransaction()
1733+
tx.vin.append(CTxIn(COutPoint(utxo.sha256, utxo.n), b""))
1734+
tx.vout.append(CTxOut(utxo.nValue-1000, scriptPKH))
1735+
tx.rehash()
1736+
1737+
# Confirm it in a block.
1738+
block = self.build_next_block()
1739+
self.update_witness_block_with_transactions(block, [tx])
1740+
self.test_node.test_witness_block(block, accepted=True)
1741+
1742+
# Now try to spend it. Send it to a P2WSH output, which we'll
1743+
# use in the next test.
1744+
witness_program = CScript([pubkey, CScriptOp(OP_CHECKSIG)])
1745+
witness_hash = sha256(witness_program)
1746+
scriptWSH = CScript([OP_0, witness_hash])
1747+
1748+
tx2 = CTransaction()
1749+
tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b""))
1750+
tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, scriptWSH))
1751+
script = GetP2PKHScript(pubkeyhash)
1752+
sig_hash = SegwitVersion1SignatureHash(script, tx2, 0, SIGHASH_ALL, tx.vout[0].nValue)
1753+
signature = key.sign(sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL
1754+
tx2.wit.vtxinwit.append(CTxInWitness())
1755+
tx2.wit.vtxinwit[0].scriptWitness.stack = [ signature, pubkey ]
1756+
tx2.rehash()
1757+
1758+
# Should fail policy test.
1759+
self.test_node.test_transaction_acceptance(tx2, True, False, b'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)')
1760+
# But passes consensus.
1761+
block = self.build_next_block()
1762+
self.update_witness_block_with_transactions(block, [tx2])
1763+
self.test_node.test_witness_block(block, accepted=True)
1764+
1765+
# Test 2: P2WSH
1766+
# Try to spend the P2WSH output created in last test.
1767+
# Send it to a P2SH(P2WSH) output, which we'll use in the next test.
1768+
p2sh_witness_hash = hash160(scriptWSH)
1769+
scriptP2SH = CScript([OP_HASH160, p2sh_witness_hash, OP_EQUAL])
1770+
scriptSig = CScript([scriptWSH])
1771+
1772+
tx3 = CTransaction()
1773+
tx3.vin.append(CTxIn(COutPoint(tx2.sha256, 0), b""))
1774+
tx3.vout.append(CTxOut(tx2.vout[0].nValue-1000, scriptP2SH))
1775+
tx3.wit.vtxinwit.append(CTxInWitness())
1776+
sign_P2PK_witness_input(witness_program, tx3, 0, SIGHASH_ALL, tx2.vout[0].nValue, key)
1777+
1778+
# Should fail policy test.
1779+
self.test_node.test_transaction_acceptance(tx3, True, False, b'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)')
1780+
# But passes consensus.
1781+
block = self.build_next_block()
1782+
self.update_witness_block_with_transactions(block, [tx3])
1783+
self.test_node.test_witness_block(block, accepted=True)
1784+
1785+
# Test 3: P2SH(P2WSH)
1786+
# Try to spend the P2SH output created in the last test.
1787+
# Send it to a P2PKH output, which we'll use in the next test.
1788+
scriptPubKey = GetP2PKHScript(pubkeyhash)
1789+
tx4 = CTransaction()
1790+
tx4.vin.append(CTxIn(COutPoint(tx3.sha256, 0), scriptSig))
1791+
tx4.vout.append(CTxOut(tx3.vout[0].nValue-1000, scriptPubKey))
1792+
tx4.wit.vtxinwit.append(CTxInWitness())
1793+
sign_P2PK_witness_input(witness_program, tx4, 0, SIGHASH_ALL, tx3.vout[0].nValue, key)
1794+
1795+
# Should fail policy test.
1796+
self.test_node.test_transaction_acceptance(tx4, True, False, b'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)')
1797+
block = self.build_next_block()
1798+
self.update_witness_block_with_transactions(block, [tx4])
1799+
self.test_node.test_witness_block(block, accepted=True)
1800+
1801+
# Test 4: Uncompressed pubkeys should still be valid in non-segwit
1802+
# transactions.
1803+
tx5 = CTransaction()
1804+
tx5.vin.append(CTxIn(COutPoint(tx4.sha256, 0), b""))
1805+
tx5.vout.append(CTxOut(tx4.vout[0].nValue-1000, CScript([OP_TRUE])))
1806+
(sig_hash, err) = SignatureHash(scriptPubKey, tx5, 0, SIGHASH_ALL)
1807+
signature = key.sign(sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL
1808+
tx5.vin[0].scriptSig = CScript([signature, pubkey])
1809+
tx5.rehash()
1810+
# Should pass policy and consensus.
1811+
self.test_node.test_transaction_acceptance(tx5, True, True)
1812+
block = self.build_next_block()
1813+
self.update_witness_block_with_transactions(block, [tx5])
1814+
self.test_node.test_witness_block(block, accepted=True)
1815+
self.utxo.append(UTXO(tx5.sha256, 0, tx5.vout[0].nValue))
1816+
17091817
def test_non_standard_witness(self):
17101818
print("\tTesting detection of non-standard P2WSH witness")
17111819
pad = chr(1).encode('latin-1')
@@ -1887,6 +1995,7 @@ def run_test(self):
18871995
self.test_standardness_v0(segwit_activated=True)
18881996
self.test_segwit_versions()
18891997
self.test_premature_coinbase_witness_spend()
1998+
self.test_uncompressed_pubkey()
18901999
self.test_signature_version_1()
18912000
self.test_non_standard_witness()
18922001
sync_blocks(self.nodes)

0 commit comments

Comments
 (0)