Skip to content

Commit

Permalink
Merge bitcoin#15893: Add test for superfluous witness record in deser…
Browse files Browse the repository at this point in the history
…ialization

cc556e4 Add test for superfluous witness record in deserialization (Gregory Sanders)
25b0786 Fix missing input template by making minimal tx (Gregory Sanders)

Pull request description:

  Adds coverage for changed behavior in bitcoin#14039

ACKs for commit cc556e:
  MarcoFalke:
    utACK cc556e4

Tree-SHA512: 3404c8f75e87503983fac5ae27d877309eb3b902f2ec993762911c71610ca449bef0ed98bd17e029414828025b2713e1bd012e63b2a06497e34f1056acaa6321
  • Loading branch information
MarcoFalke committed Apr 26, 2019
2 parents c65c77c + cc556e4 commit 653b2b4
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 15 deletions.
6 changes: 5 additions & 1 deletion test/functional/data/invalid_txs.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,13 @@ class InputMissing(BadTxTemplate):
reject_reason = "bad-txns-vin-empty"
expect_disconnect = False

# We use a blank transaction here to make sure
# it is interpreted as a non-witness transaction.
# Otherwise the transaction will fail the
# "surpufluous witness" check during deserialization
# rather than the input count check.
def get_tx(self):
tx = CTransaction()
tx.vout.append(CTxOut(0, sc.CScript([sc.OP_TRUE] * 100)))
tx.calc_sha256()
return tx

Expand Down
14 changes: 0 additions & 14 deletions test/functional/feature_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,20 +146,6 @@ def run_test(self):
badtx = template.get_tx()
if TxTemplate != invalid_txs.InputMissing:
self.sign_tx(badtx, attempt_spend_tx)
else:
# Segwit is active in regtest at this point, so to deserialize a
# transaction without any inputs correctly, we set the outputs
# to an empty list. This is a hack, as the serialization of an
# empty list of outputs is deserialized as flags==0 and thus
# deserialization of the outputs is skipped.
# A policy check requires "loose" txs to be of a minimum size,
# so vtx is not set to be empty in the TxTemplate class and we
# only apply the workaround where txs are not "loose", i.e. in
# blocks.
#
# The workaround has the purpose that both sides calculate
# the same tx hash in the merkle tree
badtx.vout = []
badtx.rehash()
badblock = self.update_block(blockname, [badtx])
self.send_blocks(
Expand Down
29 changes: 29 additions & 0 deletions test/functional/p2p_segwit.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
ser_vector,
sha256,
uint256_from_str,
FromHex,
)
from test_framework.mininode import (
P2PInterface,
Expand Down Expand Up @@ -77,6 +78,7 @@
disconnect_nodes,
get_bip9_status,
hex_str_to_bytes,
assert_raises_rpc_error,
)

# The versionbit bit used to signal activation of SegWit
Expand Down Expand Up @@ -269,6 +271,7 @@ def run_test(self):
self.test_non_standard_witness()
self.test_upgrade_after_activation()
self.test_witness_sigops()
self.test_superfluous_witness()

# Individual tests

Expand Down Expand Up @@ -2034,5 +2037,31 @@ def test_witness_sigops(self):

# TODO: test p2sh sigop counting

def test_superfluous_witness(self):
# Serialization of tx that puts witness flag to 1 always
def serialize_with_bogus_witness(tx):
flags = 1
r = b""
r += struct.pack("<i", tx.nVersion)
if flags:
dummy = []
r += ser_vector(dummy)
r += struct.pack("<B", flags)
r += ser_vector(tx.vin)
r += ser_vector(tx.vout)
if flags & 1:
if (len(tx.wit.vtxinwit) != len(tx.vin)):
# vtxinwit must have the same length as vin
tx.wit.vtxinwit = tx.wit.vtxinwit[:len(tx.vin)]
for i in range(len(tx.wit.vtxinwit), len(tx.vin)):
tx.wit.vtxinwit.append(CTxInWitness())
r += tx.wit.serialize()
r += struct.pack("<I", tx.nLockTime)
return r

raw = self.nodes[0].createrawtransaction([{"txid":"00"*32, "vout":0}], {self.nodes[0].getnewaddress():1})
tx = FromHex(CTransaction(), raw)
assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].decoderawtransaction, serialize_with_bogus_witness(tx).hex())

if __name__ == '__main__':
SegWitTest().main()

0 comments on commit 653b2b4

Please sign in to comment.