Skip to content

Commit 653b2b4

Browse files
author
MarcoFalke
committed
Merge #15893: Add test for superfluous witness record in deserialization
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/bitcoin#14039 ACKs for commit cc556e: MarcoFalke: utACK cc556e4 Tree-SHA512: 3404c8f75e87503983fac5ae27d877309eb3b902f2ec993762911c71610ca449bef0ed98bd17e029414828025b2713e1bd012e63b2a06497e34f1056acaa6321
2 parents c65c77c + cc556e4 commit 653b2b4

File tree

3 files changed

+34
-15
lines changed

3 files changed

+34
-15
lines changed

test/functional/data/invalid_txs.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,13 @@ class InputMissing(BadTxTemplate):
7171
reject_reason = "bad-txns-vin-empty"
7272
expect_disconnect = False
7373

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

test/functional/feature_block.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -146,20 +146,6 @@ def run_test(self):
146146
badtx = template.get_tx()
147147
if TxTemplate != invalid_txs.InputMissing:
148148
self.sign_tx(badtx, attempt_spend_tx)
149-
else:
150-
# Segwit is active in regtest at this point, so to deserialize a
151-
# transaction without any inputs correctly, we set the outputs
152-
# to an empty list. This is a hack, as the serialization of an
153-
# empty list of outputs is deserialized as flags==0 and thus
154-
# deserialization of the outputs is skipped.
155-
# A policy check requires "loose" txs to be of a minimum size,
156-
# so vtx is not set to be empty in the TxTemplate class and we
157-
# only apply the workaround where txs are not "loose", i.e. in
158-
# blocks.
159-
#
160-
# The workaround has the purpose that both sides calculate
161-
# the same tx hash in the merkle tree
162-
badtx.vout = []
163149
badtx.rehash()
164150
badblock = self.update_block(blockname, [badtx])
165151
self.send_blocks(

test/functional/p2p_segwit.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
ser_vector,
3737
sha256,
3838
uint256_from_str,
39+
FromHex,
3940
)
4041
from test_framework.mininode import (
4142
P2PInterface,
@@ -77,6 +78,7 @@
7778
disconnect_nodes,
7879
get_bip9_status,
7980
hex_str_to_bytes,
81+
assert_raises_rpc_error,
8082
)
8183

8284
# The versionbit bit used to signal activation of SegWit
@@ -269,6 +271,7 @@ def run_test(self):
269271
self.test_non_standard_witness()
270272
self.test_upgrade_after_activation()
271273
self.test_witness_sigops()
274+
self.test_superfluous_witness()
272275

273276
# Individual tests
274277

@@ -2034,5 +2037,31 @@ def test_witness_sigops(self):
20342037

20352038
# TODO: test p2sh sigop counting
20362039

2040+
def test_superfluous_witness(self):
2041+
# Serialization of tx that puts witness flag to 1 always
2042+
def serialize_with_bogus_witness(tx):
2043+
flags = 1
2044+
r = b""
2045+
r += struct.pack("<i", tx.nVersion)
2046+
if flags:
2047+
dummy = []
2048+
r += ser_vector(dummy)
2049+
r += struct.pack("<B", flags)
2050+
r += ser_vector(tx.vin)
2051+
r += ser_vector(tx.vout)
2052+
if flags & 1:
2053+
if (len(tx.wit.vtxinwit) != len(tx.vin)):
2054+
# vtxinwit must have the same length as vin
2055+
tx.wit.vtxinwit = tx.wit.vtxinwit[:len(tx.vin)]
2056+
for i in range(len(tx.wit.vtxinwit), len(tx.vin)):
2057+
tx.wit.vtxinwit.append(CTxInWitness())
2058+
r += tx.wit.serialize()
2059+
r += struct.pack("<I", tx.nLockTime)
2060+
return r
2061+
2062+
raw = self.nodes[0].createrawtransaction([{"txid":"00"*32, "vout":0}], {self.nodes[0].getnewaddress():1})
2063+
tx = FromHex(CTransaction(), raw)
2064+
assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].decoderawtransaction, serialize_with_bogus_witness(tx).hex())
2065+
20372066
if __name__ == '__main__':
20382067
SegWitTest().main()

0 commit comments

Comments
 (0)