[qa] Add tests for uncompressed pubkeys in segwit
This commit is contained in:
parent
9f0397aff7
commit
b811124202
1 changed files with 117 additions and 8 deletions
|
@ -166,6 +166,17 @@ class UTXO(object):
|
|||
self.n = n
|
||||
self.nValue = nValue
|
||||
|
||||
# Helper for getting the script associated with a P2PKH
|
||||
def GetP2PKHScript(pubkeyhash):
|
||||
return CScript([CScriptOp(OP_DUP), CScriptOp(OP_HASH160), pubkeyhash, CScriptOp(OP_EQUALVERIFY), CScriptOp(OP_CHECKSIG)])
|
||||
|
||||
# Add signature for a P2PK witness program.
|
||||
def sign_P2PK_witness_input(script, txTo, inIdx, hashtype, value, key):
|
||||
tx_hash = SegwitVersion1SignatureHash(script, txTo, inIdx, hashtype, value)
|
||||
signature = key.sign(tx_hash) + chr(hashtype).encode('latin-1')
|
||||
txTo.wit.vtxinwit[inIdx].scriptWitness.stack = [signature, script]
|
||||
txTo.rehash()
|
||||
|
||||
|
||||
class SegWitTest(BitcoinTestFramework):
|
||||
|
||||
|
@ -1323,13 +1334,6 @@ class SegWitTest(BitcoinTestFramework):
|
|||
sync_blocks(self.nodes)
|
||||
self.utxo.pop(0)
|
||||
|
||||
# Add signature for a P2PK witness program.
|
||||
def sign_P2PK_witness_input(script, txTo, inIdx, hashtype, value, key):
|
||||
tx_hash = SegwitVersion1SignatureHash(script, txTo, inIdx, hashtype, value)
|
||||
signature = key.sign(tx_hash) + chr(hashtype).encode('latin-1')
|
||||
txTo.wit.vtxinwit[inIdx].scriptWitness.stack = [signature, script]
|
||||
txTo.rehash()
|
||||
|
||||
# Test each hashtype
|
||||
prev_utxo = UTXO(tx.sha256, 0, tx.vout[0].nValue)
|
||||
for sigflag in [ 0, SIGHASH_ANYONECANPAY ]:
|
||||
|
@ -1443,7 +1447,7 @@ class SegWitTest(BitcoinTestFramework):
|
|||
tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b""))
|
||||
tx2.vout.append(CTxOut(tx.vout[0].nValue, CScript([OP_TRUE])))
|
||||
|
||||
script = CScript([CScriptOp(OP_DUP), CScriptOp(OP_HASH160), pubkeyhash, CScriptOp(OP_EQUALVERIFY), CScriptOp(OP_CHECKSIG)])
|
||||
script = GetP2PKHScript(pubkeyhash)
|
||||
sig_hash = SegwitVersion1SignatureHash(script, tx2, 0, SIGHASH_ALL, tx.vout[0].nValue)
|
||||
signature = key.sign(sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL
|
||||
|
||||
|
@ -1706,6 +1710,110 @@ class SegWitTest(BitcoinTestFramework):
|
|||
assert(block_version & (1 << VB_WITNESS_BIT) != 0)
|
||||
self.nodes[0].setmocktime(0) # undo mocktime
|
||||
|
||||
# Uncompressed pubkeys are no longer supported in default relay policy,
|
||||
# but (for now) are still valid in blocks.
|
||||
def test_uncompressed_pubkey(self):
|
||||
print("\tTesting uncompressed pubkeys")
|
||||
# Segwit transactions using uncompressed pubkeys are not accepted
|
||||
# under default policy, but should still pass consensus.
|
||||
key = CECKey()
|
||||
key.set_secretbytes(b"9")
|
||||
key.set_compressed(False)
|
||||
pubkey = CPubKey(key.get_pubkey())
|
||||
assert_equal(len(pubkey), 65) # This should be an uncompressed pubkey
|
||||
|
||||
assert(len(self.utxo) > 0)
|
||||
utxo = self.utxo.pop(0)
|
||||
|
||||
# Test 1: P2WPKH
|
||||
# First create a P2WPKH output that uses an uncompressed pubkey
|
||||
pubkeyhash = hash160(pubkey)
|
||||
scriptPKH = CScript([OP_0, pubkeyhash])
|
||||
tx = CTransaction()
|
||||
tx.vin.append(CTxIn(COutPoint(utxo.sha256, utxo.n), b""))
|
||||
tx.vout.append(CTxOut(utxo.nValue-1000, scriptPKH))
|
||||
tx.rehash()
|
||||
|
||||
# Confirm it in a block.
|
||||
block = self.build_next_block()
|
||||
self.update_witness_block_with_transactions(block, [tx])
|
||||
self.test_node.test_witness_block(block, accepted=True)
|
||||
|
||||
# Now try to spend it. Send it to a P2WSH output, which we'll
|
||||
# use in the next test.
|
||||
witness_program = CScript([pubkey, CScriptOp(OP_CHECKSIG)])
|
||||
witness_hash = sha256(witness_program)
|
||||
scriptWSH = CScript([OP_0, witness_hash])
|
||||
|
||||
tx2 = CTransaction()
|
||||
tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b""))
|
||||
tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, scriptWSH))
|
||||
script = GetP2PKHScript(pubkeyhash)
|
||||
sig_hash = SegwitVersion1SignatureHash(script, tx2, 0, SIGHASH_ALL, tx.vout[0].nValue)
|
||||
signature = key.sign(sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL
|
||||
tx2.wit.vtxinwit.append(CTxInWitness())
|
||||
tx2.wit.vtxinwit[0].scriptWitness.stack = [ signature, pubkey ]
|
||||
tx2.rehash()
|
||||
|
||||
# Should fail policy test.
|
||||
self.test_node.test_transaction_acceptance(tx2, True, False, b'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)')
|
||||
# But passes consensus.
|
||||
block = self.build_next_block()
|
||||
self.update_witness_block_with_transactions(block, [tx2])
|
||||
self.test_node.test_witness_block(block, accepted=True)
|
||||
|
||||
# Test 2: P2WSH
|
||||
# Try to spend the P2WSH output created in last test.
|
||||
# Send it to a P2SH(P2WSH) output, which we'll use in the next test.
|
||||
p2sh_witness_hash = hash160(scriptWSH)
|
||||
scriptP2SH = CScript([OP_HASH160, p2sh_witness_hash, OP_EQUAL])
|
||||
scriptSig = CScript([scriptWSH])
|
||||
|
||||
tx3 = CTransaction()
|
||||
tx3.vin.append(CTxIn(COutPoint(tx2.sha256, 0), b""))
|
||||
tx3.vout.append(CTxOut(tx2.vout[0].nValue-1000, scriptP2SH))
|
||||
tx3.wit.vtxinwit.append(CTxInWitness())
|
||||
sign_P2PK_witness_input(witness_program, tx3, 0, SIGHASH_ALL, tx2.vout[0].nValue, key)
|
||||
|
||||
# Should fail policy test.
|
||||
self.test_node.test_transaction_acceptance(tx3, True, False, b'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)')
|
||||
# But passes consensus.
|
||||
block = self.build_next_block()
|
||||
self.update_witness_block_with_transactions(block, [tx3])
|
||||
self.test_node.test_witness_block(block, accepted=True)
|
||||
|
||||
# Test 3: P2SH(P2WSH)
|
||||
# Try to spend the P2SH output created in the last test.
|
||||
# Send it to a P2PKH output, which we'll use in the next test.
|
||||
scriptPubKey = GetP2PKHScript(pubkeyhash)
|
||||
tx4 = CTransaction()
|
||||
tx4.vin.append(CTxIn(COutPoint(tx3.sha256, 0), scriptSig))
|
||||
tx4.vout.append(CTxOut(tx3.vout[0].nValue-1000, scriptPubKey))
|
||||
tx4.wit.vtxinwit.append(CTxInWitness())
|
||||
sign_P2PK_witness_input(witness_program, tx4, 0, SIGHASH_ALL, tx3.vout[0].nValue, key)
|
||||
|
||||
# Should fail policy test.
|
||||
self.test_node.test_transaction_acceptance(tx4, True, False, b'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)')
|
||||
block = self.build_next_block()
|
||||
self.update_witness_block_with_transactions(block, [tx4])
|
||||
self.test_node.test_witness_block(block, accepted=True)
|
||||
|
||||
# Test 4: Uncompressed pubkeys should still be valid in non-segwit
|
||||
# transactions.
|
||||
tx5 = CTransaction()
|
||||
tx5.vin.append(CTxIn(COutPoint(tx4.sha256, 0), b""))
|
||||
tx5.vout.append(CTxOut(tx4.vout[0].nValue-1000, CScript([OP_TRUE])))
|
||||
(sig_hash, err) = SignatureHash(scriptPubKey, tx5, 0, SIGHASH_ALL)
|
||||
signature = key.sign(sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL
|
||||
tx5.vin[0].scriptSig = CScript([signature, pubkey])
|
||||
tx5.rehash()
|
||||
# Should pass policy and consensus.
|
||||
self.test_node.test_transaction_acceptance(tx5, True, True)
|
||||
block = self.build_next_block()
|
||||
self.update_witness_block_with_transactions(block, [tx5])
|
||||
self.test_node.test_witness_block(block, accepted=True)
|
||||
self.utxo.append(UTXO(tx5.sha256, 0, tx5.vout[0].nValue))
|
||||
|
||||
def test_non_standard_witness(self):
|
||||
print("\tTesting detection of non-standard P2WSH witness")
|
||||
pad = chr(1).encode('latin-1')
|
||||
|
@ -1887,6 +1995,7 @@ class SegWitTest(BitcoinTestFramework):
|
|||
self.test_standardness_v0(segwit_activated=True)
|
||||
self.test_segwit_versions()
|
||||
self.test_premature_coinbase_witness_spend()
|
||||
self.test_uncompressed_pubkey()
|
||||
self.test_signature_version_1()
|
||||
self.test_non_standard_witness()
|
||||
sync_blocks(self.nodes)
|
||||
|
|
Loading…
Reference in a new issue