qa: Read reject reasons from debug log, not p2p messages

This commit is contained in:
MarcoFalke 2018-08-24 15:26:42 -04:00
parent b012bbe358
commit fac3e22b18
No known key found for this signature in database
GPG key ID: CE2B75697E69A548
8 changed files with 138 additions and 191 deletions

View file

@ -169,7 +169,7 @@ class FullBlockTest(BitcoinTestFramework):
self.log.info("Reject a block where the miner creates too much coinbase reward") self.log.info("Reject a block where the miner creates too much coinbase reward")
self.move_tip(6) self.move_tip(6)
b9 = self.next_block(9, spend=out[4], additional_coinbase_value=1) b9 = self.next_block(9, spend=out[4], additional_coinbase_value=1)
self.sync_blocks([b9], success=False, reject_code=16, reject_reason=b'bad-cb-amount', reconnect=True) self.sync_blocks([b9], success=False, reject_reason='bad-cb-amount', reconnect=True)
# Create a fork that ends in a block with too much fee (the one that causes the reorg) # Create a fork that ends in a block with too much fee (the one that causes the reorg)
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3) # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
@ -181,7 +181,7 @@ class FullBlockTest(BitcoinTestFramework):
self.sync_blocks([b10], False) self.sync_blocks([b10], False)
b11 = self.next_block(11, spend=out[4], additional_coinbase_value=1) b11 = self.next_block(11, spend=out[4], additional_coinbase_value=1)
self.sync_blocks([b11], success=False, reject_code=16, reject_reason=b'bad-cb-amount', reconnect=True) self.sync_blocks([b11], success=False, reject_reason='bad-cb-amount', reconnect=True)
# Try again, but with a valid fork first # Try again, but with a valid fork first
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3) # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
@ -194,7 +194,7 @@ class FullBlockTest(BitcoinTestFramework):
b13 = self.next_block(13, spend=out[4]) b13 = self.next_block(13, spend=out[4])
self.save_spendable_output() self.save_spendable_output()
b14 = self.next_block(14, spend=out[5], additional_coinbase_value=1) b14 = self.next_block(14, spend=out[5], additional_coinbase_value=1)
self.sync_blocks([b12, b13, b14], success=False, reject_code=16, reject_reason=b'bad-cb-amount', reconnect=True) self.sync_blocks([b12, b13, b14], success=False, reject_reason='bad-cb-amount', reconnect=True)
# New tip should be b13. # New tip should be b13.
assert_equal(node.getbestblockhash(), b13.hash) assert_equal(node.getbestblockhash(), b13.hash)
@ -213,7 +213,7 @@ class FullBlockTest(BitcoinTestFramework):
self.log.info("Reject a block with too many checksigs") self.log.info("Reject a block with too many checksigs")
too_many_checksigs = CScript([OP_CHECKSIG] * (MAX_BLOCK_SIGOPS)) too_many_checksigs = CScript([OP_CHECKSIG] * (MAX_BLOCK_SIGOPS))
b16 = self.next_block(16, spend=out[6], script=too_many_checksigs) b16 = self.next_block(16, spend=out[6], script=too_many_checksigs)
self.sync_blocks([b16], success=False, reject_code=16, reject_reason=b'bad-blk-sigops', reconnect=True) self.sync_blocks([b16], success=False, reject_reason='bad-blk-sigops', reconnect=True)
# Attempt to spend a transaction created on a different fork # Attempt to spend a transaction created on a different fork
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3) # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
@ -222,7 +222,7 @@ class FullBlockTest(BitcoinTestFramework):
self.log.info("Reject a block with a spend from a re-org'ed out tx") self.log.info("Reject a block with a spend from a re-org'ed out tx")
self.move_tip(15) self.move_tip(15)
b17 = self.next_block(17, spend=txout_b3) b17 = self.next_block(17, spend=txout_b3)
self.sync_blocks([b17], success=False, reject_code=16, reject_reason=b'bad-txns-inputs-missingorspent', reconnect=True) self.sync_blocks([b17], success=False, reject_reason='bad-txns-inputs-missingorspent', reconnect=True)
# Attempt to spend a transaction created on a different fork (on a fork this time) # Attempt to spend a transaction created on a different fork (on a fork this time)
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3) # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
@ -235,7 +235,7 @@ class FullBlockTest(BitcoinTestFramework):
self.sync_blocks([b18], False) self.sync_blocks([b18], False)
b19 = self.next_block(19, spend=out[6]) b19 = self.next_block(19, spend=out[6])
self.sync_blocks([b19], success=False, reject_code=16, reject_reason=b'bad-txns-inputs-missingorspent', reconnect=True) self.sync_blocks([b19], success=False, reject_reason='bad-txns-inputs-missingorspent', reconnect=True)
# Attempt to spend a coinbase at depth too low # Attempt to spend a coinbase at depth too low
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3) # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
@ -244,7 +244,7 @@ class FullBlockTest(BitcoinTestFramework):
self.log.info("Reject a block spending an immature coinbase.") self.log.info("Reject a block spending an immature coinbase.")
self.move_tip(15) self.move_tip(15)
b20 = self.next_block(20, spend=out[7]) b20 = self.next_block(20, spend=out[7])
self.sync_blocks([b20], success=False, reject_code=16, reject_reason=b'bad-txns-premature-spend-of-coinbase') self.sync_blocks([b20], success=False, reject_reason='bad-txns-premature-spend-of-coinbase')
# Attempt to spend a coinbase at depth too low (on a fork this time) # Attempt to spend a coinbase at depth too low (on a fork this time)
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3) # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
@ -257,7 +257,7 @@ class FullBlockTest(BitcoinTestFramework):
self.sync_blocks([b21], False) self.sync_blocks([b21], False)
b22 = self.next_block(22, spend=out[5]) b22 = self.next_block(22, spend=out[5])
self.sync_blocks([b22], success=False, reject_code=16, reject_reason=b'bad-txns-premature-spend-of-coinbase') self.sync_blocks([b22], success=False, reject_reason='bad-txns-premature-spend-of-coinbase')
# Create a block on either side of MAX_BLOCK_BASE_SIZE and make sure its accepted/rejected # Create a block on either side of MAX_BLOCK_BASE_SIZE and make sure its accepted/rejected
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3) # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
@ -286,7 +286,7 @@ class FullBlockTest(BitcoinTestFramework):
tx.vout = [CTxOut(0, script_output)] tx.vout = [CTxOut(0, script_output)]
b24 = self.update_block(24, [tx]) b24 = self.update_block(24, [tx])
assert_equal(len(b24.serialize()), MAX_BLOCK_BASE_SIZE + 1) assert_equal(len(b24.serialize()), MAX_BLOCK_BASE_SIZE + 1)
self.sync_blocks([b24], success=False, reject_code=16, reject_reason=b'bad-blk-length', reconnect=True) self.sync_blocks([b24], success=False, reject_reason='bad-blk-length', reconnect=True)
b25 = self.next_block(25, spend=out[7]) b25 = self.next_block(25, spend=out[7])
self.sync_blocks([b25], False) self.sync_blocks([b25], False)
@ -304,7 +304,7 @@ class FullBlockTest(BitcoinTestFramework):
# update_block causes the merkle root to get updated, even with no new # update_block causes the merkle root to get updated, even with no new
# transactions, and updates the required state. # transactions, and updates the required state.
b26 = self.update_block(26, []) b26 = self.update_block(26, [])
self.sync_blocks([b26], success=False, reject_code=16, reject_reason=b'bad-cb-length', reconnect=True) self.sync_blocks([b26], success=False, reject_reason='bad-cb-length', reconnect=True)
# Extend the b26 chain to make sure bitcoind isn't accepting b26 # Extend the b26 chain to make sure bitcoind isn't accepting b26
b27 = self.next_block(27, spend=out[7]) b27 = self.next_block(27, spend=out[7])
@ -316,7 +316,7 @@ class FullBlockTest(BitcoinTestFramework):
b28.vtx[0].vin[0].scriptSig = b'\x00' * 101 b28.vtx[0].vin[0].scriptSig = b'\x00' * 101
b28.vtx[0].rehash() b28.vtx[0].rehash()
b28 = self.update_block(28, []) b28 = self.update_block(28, [])
self.sync_blocks([b28], success=False, reject_code=16, reject_reason=b'bad-cb-length', reconnect=True) self.sync_blocks([b28], success=False, reject_reason='bad-cb-length', reconnect=True)
# Extend the b28 chain to make sure bitcoind isn't accepting b28 # Extend the b28 chain to make sure bitcoind isn't accepting b28
b29 = self.next_block(29, spend=out[7]) b29 = self.next_block(29, spend=out[7])
@ -352,7 +352,7 @@ class FullBlockTest(BitcoinTestFramework):
too_many_multisigs = CScript([OP_CHECKMULTISIG] * (MAX_BLOCK_SIGOPS // 20)) too_many_multisigs = CScript([OP_CHECKMULTISIG] * (MAX_BLOCK_SIGOPS // 20))
b32 = self.next_block(32, spend=out[9], script=too_many_multisigs) b32 = self.next_block(32, spend=out[9], script=too_many_multisigs)
assert_equal(get_legacy_sigopcount_block(b32), MAX_BLOCK_SIGOPS + 1) assert_equal(get_legacy_sigopcount_block(b32), MAX_BLOCK_SIGOPS + 1)
self.sync_blocks([b32], success=False, reject_code=16, reject_reason=b'bad-blk-sigops', reconnect=True) self.sync_blocks([b32], success=False, reject_reason='bad-blk-sigops', reconnect=True)
# CHECKMULTISIGVERIFY # CHECKMULTISIGVERIFY
self.log.info("Accept a block with the max number of OP_CHECKMULTISIGVERIFY sigops") self.log.info("Accept a block with the max number of OP_CHECKMULTISIGVERIFY sigops")
@ -365,7 +365,7 @@ class FullBlockTest(BitcoinTestFramework):
self.log.info("Reject a block with too many OP_CHECKMULTISIGVERIFY sigops") self.log.info("Reject a block with too many OP_CHECKMULTISIGVERIFY sigops")
too_many_multisigs = CScript([OP_CHECKMULTISIGVERIFY] * (MAX_BLOCK_SIGOPS // 20)) too_many_multisigs = CScript([OP_CHECKMULTISIGVERIFY] * (MAX_BLOCK_SIGOPS // 20))
b34 = self.next_block(34, spend=out[10], script=too_many_multisigs) b34 = self.next_block(34, spend=out[10], script=too_many_multisigs)
self.sync_blocks([b34], success=False, reject_code=16, reject_reason=b'bad-blk-sigops', reconnect=True) self.sync_blocks([b34], success=False, reject_reason='bad-blk-sigops', reconnect=True)
# CHECKSIGVERIFY # CHECKSIGVERIFY
self.log.info("Accept a block with the max number of OP_CHECKSIGVERIFY sigops") self.log.info("Accept a block with the max number of OP_CHECKSIGVERIFY sigops")
@ -378,7 +378,7 @@ class FullBlockTest(BitcoinTestFramework):
self.log.info("Reject a block with too many OP_CHECKSIGVERIFY sigops") self.log.info("Reject a block with too many OP_CHECKSIGVERIFY sigops")
too_many_checksigs = CScript([OP_CHECKSIGVERIFY] * (MAX_BLOCK_SIGOPS)) too_many_checksigs = CScript([OP_CHECKSIGVERIFY] * (MAX_BLOCK_SIGOPS))
b36 = self.next_block(36, spend=out[11], script=too_many_checksigs) b36 = self.next_block(36, spend=out[11], script=too_many_checksigs)
self.sync_blocks([b36], success=False, reject_code=16, reject_reason=b'bad-blk-sigops', reconnect=True) self.sync_blocks([b36], success=False, reject_reason='bad-blk-sigops', reconnect=True)
# Check spending of a transaction in a block which failed to connect # Check spending of a transaction in a block which failed to connect
# #
@ -395,12 +395,12 @@ class FullBlockTest(BitcoinTestFramework):
txout_b37 = b37.vtx[1] txout_b37 = b37.vtx[1]
tx = self.create_and_sign_transaction(out[11], 0) tx = self.create_and_sign_transaction(out[11], 0)
b37 = self.update_block(37, [tx]) b37 = self.update_block(37, [tx])
self.sync_blocks([b37], success=False, reject_code=16, reject_reason=b'bad-txns-inputs-missingorspent', reconnect=True) self.sync_blocks([b37], success=False, reject_reason='bad-txns-inputs-missingorspent', reconnect=True)
# attempt to spend b37's first non-coinbase tx, at which point b37 was still considered valid # attempt to spend b37's first non-coinbase tx, at which point b37 was still considered valid
self.move_tip(35) self.move_tip(35)
b38 = self.next_block(38, spend=txout_b37) b38 = self.next_block(38, spend=txout_b37)
self.sync_blocks([b38], success=False, reject_code=16, reject_reason=b'bad-txns-inputs-missingorspent', reconnect=True) self.sync_blocks([b38], success=False, reject_reason='bad-txns-inputs-missingorspent', reconnect=True)
# Check P2SH SigOp counting # Check P2SH SigOp counting
# #
@ -492,7 +492,7 @@ class FullBlockTest(BitcoinTestFramework):
tx.rehash() tx.rehash()
new_txs.append(tx) new_txs.append(tx)
self.update_block(40, new_txs) self.update_block(40, new_txs)
self.sync_blocks([b40], success=False, reject_code=16, reject_reason=b'bad-blk-sigops', reconnect=True) self.sync_blocks([b40], success=False, reject_reason='bad-blk-sigops', reconnect=True)
# same as b40, but one less sigop # same as b40, but one less sigop
self.log.info("Accept a block with the max number of P2SH sigops") self.log.info("Accept a block with the max number of P2SH sigops")
@ -555,7 +555,7 @@ class FullBlockTest(BitcoinTestFramework):
self.block_heights[b45.sha256] = self.block_heights[self.tip.sha256] + 1 self.block_heights[b45.sha256] = self.block_heights[self.tip.sha256] + 1
self.tip = b45 self.tip = b45
self.blocks[45] = b45 self.blocks[45] = b45
self.sync_blocks([b45], success=False, reject_code=16, reject_reason=b'bad-cb-missing', reconnect=True) self.sync_blocks([b45], success=False, reject_reason='bad-cb-missing', reconnect=True)
self.log.info("Reject a block with no transactions") self.log.info("Reject a block with no transactions")
self.move_tip(44) self.move_tip(44)
@ -570,7 +570,7 @@ class FullBlockTest(BitcoinTestFramework):
self.tip = b46 self.tip = b46
assert 46 not in self.blocks assert 46 not in self.blocks
self.blocks[46] = b46 self.blocks[46] = b46
self.sync_blocks([b46], success=False, reject_code=16, reject_reason=b'bad-blk-length', reconnect=True) self.sync_blocks([b46], success=False, reject_reason='bad-blk-length', reconnect=True)
self.log.info("Reject a block with invalid work") self.log.info("Reject a block with invalid work")
self.move_tip(44) self.move_tip(44)
@ -593,7 +593,7 @@ class FullBlockTest(BitcoinTestFramework):
b49 = self.next_block(49) b49 = self.next_block(49)
b49.hashMerkleRoot += 1 b49.hashMerkleRoot += 1
b49.solve() b49.solve()
self.sync_blocks([b49], success=False, reject_code=16, reject_reason=b'bad-txnmrklroot', reconnect=True) self.sync_blocks([b49], success=False, reject_reason='bad-txnmrklroot', reconnect=True)
self.log.info("Reject a block with incorrect POW limit") self.log.info("Reject a block with incorrect POW limit")
self.move_tip(44) self.move_tip(44)
@ -607,7 +607,7 @@ class FullBlockTest(BitcoinTestFramework):
b51 = self.next_block(51) b51 = self.next_block(51)
cb2 = create_coinbase(51, self.coinbase_pubkey) cb2 = create_coinbase(51, self.coinbase_pubkey)
b51 = self.update_block(51, [cb2]) b51 = self.update_block(51, [cb2])
self.sync_blocks([b51], success=False, reject_code=16, reject_reason=b'bad-cb-multiple', reconnect=True) self.sync_blocks([b51], success=False, reject_reason='bad-cb-multiple', reconnect=True)
self.log.info("Reject a block with duplicate transactions") self.log.info("Reject a block with duplicate transactions")
# Note: txns have to be in the right position in the merkle tree to trigger this error # Note: txns have to be in the right position in the merkle tree to trigger this error
@ -615,7 +615,7 @@ class FullBlockTest(BitcoinTestFramework):
b52 = self.next_block(52, spend=out[15]) b52 = self.next_block(52, spend=out[15])
tx = self.create_tx(b52.vtx[1], 0, 1) tx = self.create_tx(b52.vtx[1], 0, 1)
b52 = self.update_block(52, [tx, tx]) b52 = self.update_block(52, [tx, tx])
self.sync_blocks([b52], success=False, reject_code=16, reject_reason=b'bad-txns-duplicate', reconnect=True) self.sync_blocks([b52], success=False, reject_reason='bad-txns-duplicate', reconnect=True)
# Test block timestamps # Test block timestamps
# -> b31 (8) -> b33 (9) -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15) # -> b31 (8) -> b33 (9) -> b35 (10) -> b39 (11) -> b42 (12) -> b43 (13) -> b53 (14) -> b55 (15)
@ -682,7 +682,7 @@ class FullBlockTest(BitcoinTestFramework):
assert_equal(len(b56.vtx), 3) assert_equal(len(b56.vtx), 3)
b56 = self.update_block(56, [tx1]) b56 = self.update_block(56, [tx1])
assert_equal(b56.hash, b57.hash) assert_equal(b56.hash, b57.hash)
self.sync_blocks([b56], success=False, reject_code=16, reject_reason=b'bad-txns-duplicate', reconnect=True) self.sync_blocks([b56], success=False, reject_reason='bad-txns-duplicate', reconnect=True)
# b57p2 - a good block with 6 tx'es, don't submit until end # b57p2 - a good block with 6 tx'es, don't submit until end
self.move_tip(55) self.move_tip(55)
@ -702,7 +702,7 @@ class FullBlockTest(BitcoinTestFramework):
assert_equal(b56p2.hash, b57p2.hash) assert_equal(b56p2.hash, b57p2.hash)
assert_equal(len(b56p2.vtx), 6) assert_equal(len(b56p2.vtx), 6)
b56p2 = self.update_block("b56p2", [tx3, tx4]) b56p2 = self.update_block("b56p2", [tx3, tx4])
self.sync_blocks([b56p2], success=False, reject_code=16, reject_reason=b'bad-txns-duplicate', reconnect=True) self.sync_blocks([b56p2], success=False, reject_reason='bad-txns-duplicate', reconnect=True)
self.move_tip("57p2") self.move_tip("57p2")
self.sync_blocks([b57p2], True) self.sync_blocks([b57p2], True)
@ -727,7 +727,7 @@ class FullBlockTest(BitcoinTestFramework):
tx.vout.append(CTxOut(0, b"")) tx.vout.append(CTxOut(0, b""))
tx.calc_sha256() tx.calc_sha256()
b58 = self.update_block(58, [tx]) b58 = self.update_block(58, [tx])
self.sync_blocks([b58], success=False, reject_code=16, reject_reason=b'bad-txns-inputs-missingorspent', reconnect=True) self.sync_blocks([b58], success=False, reject_reason='bad-txns-inputs-missingorspent', reconnect=True)
# tx with output value > input value # tx with output value > input value
self.log.info("Reject a block with a transaction with outputs > inputs") self.log.info("Reject a block with a transaction with outputs > inputs")
@ -735,7 +735,7 @@ class FullBlockTest(BitcoinTestFramework):
b59 = self.next_block(59) b59 = self.next_block(59)
tx = self.create_and_sign_transaction(out[17], 51 * COIN) tx = self.create_and_sign_transaction(out[17], 51 * COIN)
b59 = self.update_block(59, [tx]) b59 = self.update_block(59, [tx])
self.sync_blocks([b59], success=False, reject_code=16, reject_reason=b'bad-txns-in-belowout', reconnect=True) self.sync_blocks([b59], success=False, reject_reason='bad-txns-in-belowout', reconnect=True)
# reset to good chain # reset to good chain
self.move_tip(57) self.move_tip(57)
@ -759,7 +759,7 @@ class FullBlockTest(BitcoinTestFramework):
b61.vtx[0].rehash() b61.vtx[0].rehash()
b61 = self.update_block(61, []) b61 = self.update_block(61, [])
assert_equal(b60.vtx[0].serialize(), b61.vtx[0].serialize()) assert_equal(b60.vtx[0].serialize(), b61.vtx[0].serialize())
self.sync_blocks([b61], success=False, reject_code=16, reject_reason=b'bad-txns-BIP30', reconnect=True) self.sync_blocks([b61], success=False, reject_reason='bad-txns-BIP30', reconnect=True)
# Test tx.isFinal is properly rejected (not an exhaustive tx.isFinal test, that should be in data-driven transaction tests) # Test tx.isFinal is properly rejected (not an exhaustive tx.isFinal test, that should be in data-driven transaction tests)
# #
@ -776,7 +776,7 @@ class FullBlockTest(BitcoinTestFramework):
assert(tx.vin[0].nSequence < 0xffffffff) assert(tx.vin[0].nSequence < 0xffffffff)
tx.calc_sha256() tx.calc_sha256()
b62 = self.update_block(62, [tx]) b62 = self.update_block(62, [tx])
self.sync_blocks([b62], success=False, reject_code=16, reject_reason=b'bad-txns-nonfinal') self.sync_blocks([b62], success=False, reject_reason='bad-txns-nonfinal')
# Test a non-final coinbase is also rejected # Test a non-final coinbase is also rejected
# #
@ -790,7 +790,7 @@ class FullBlockTest(BitcoinTestFramework):
b63.vtx[0].vin[0].nSequence = 0xDEADBEEF b63.vtx[0].vin[0].nSequence = 0xDEADBEEF
b63.vtx[0].rehash() b63.vtx[0].rehash()
b63 = self.update_block(63, []) b63 = self.update_block(63, [])
self.sync_blocks([b63], success=False, reject_code=16, reject_reason=b'bad-txns-nonfinal') self.sync_blocks([b63], success=False, reject_reason='bad-txns-nonfinal')
# This checks that a block with a bloated VARINT between the block_header and the array of tx such that # This checks that a block with a bloated VARINT between the block_header and the array of tx such that
# the block is > MAX_BLOCK_BASE_SIZE with the bloated varint, but <= MAX_BLOCK_BASE_SIZE without the bloated varint, # the block is > MAX_BLOCK_BASE_SIZE with the bloated varint, but <= MAX_BLOCK_BASE_SIZE without the bloated varint,
@ -824,7 +824,7 @@ class FullBlockTest(BitcoinTestFramework):
tx.vin.append(CTxIn(COutPoint(b64a.vtx[1].sha256, 0))) tx.vin.append(CTxIn(COutPoint(b64a.vtx[1].sha256, 0)))
b64a = self.update_block("64a", [tx]) b64a = self.update_block("64a", [tx])
assert_equal(len(b64a.serialize()), MAX_BLOCK_BASE_SIZE + 8) assert_equal(len(b64a.serialize()), MAX_BLOCK_BASE_SIZE + 8)
self.sync_blocks([b64a], success=False, reject_code=1, reject_reason=b'error parsing message') self.sync_blocks([b64a], success=False, reject_reason='non-canonical ReadCompactSize(): iostream error')
# bitcoind doesn't disconnect us for sending a bloated block, but if we subsequently # bitcoind doesn't disconnect us for sending a bloated block, but if we subsequently
# resend the header message, it won't send us the getdata message again. Just # resend the header message, it won't send us the getdata message again. Just
@ -866,7 +866,7 @@ class FullBlockTest(BitcoinTestFramework):
tx1 = self.create_and_sign_transaction(out[20], out[20].vout[0].nValue) tx1 = self.create_and_sign_transaction(out[20], out[20].vout[0].nValue)
tx2 = self.create_and_sign_transaction(tx1, 1) tx2 = self.create_and_sign_transaction(tx1, 1)
b66 = self.update_block(66, [tx2, tx1]) b66 = self.update_block(66, [tx2, tx1])
self.sync_blocks([b66], success=False, reject_code=16, reject_reason=b'bad-txns-inputs-missingorspent', reconnect=True) self.sync_blocks([b66], success=False, reject_reason='bad-txns-inputs-missingorspent', reconnect=True)
# Attempt to double-spend a transaction created in a block # Attempt to double-spend a transaction created in a block
# #
@ -881,7 +881,7 @@ class FullBlockTest(BitcoinTestFramework):
tx2 = self.create_and_sign_transaction(tx1, 1) tx2 = self.create_and_sign_transaction(tx1, 1)
tx3 = self.create_and_sign_transaction(tx1, 2) tx3 = self.create_and_sign_transaction(tx1, 2)
b67 = self.update_block(67, [tx1, tx2, tx3]) b67 = self.update_block(67, [tx1, tx2, tx3])
self.sync_blocks([b67], success=False, reject_code=16, reject_reason=b'bad-txns-inputs-missingorspent', reconnect=True) self.sync_blocks([b67], success=False, reject_reason='bad-txns-inputs-missingorspent', reconnect=True)
# More tests of block subsidy # More tests of block subsidy
# #
@ -900,7 +900,7 @@ class FullBlockTest(BitcoinTestFramework):
b68 = self.next_block(68, additional_coinbase_value=10) b68 = self.next_block(68, additional_coinbase_value=10)
tx = self.create_and_sign_transaction(out[20], out[20].vout[0].nValue - 9) tx = self.create_and_sign_transaction(out[20], out[20].vout[0].nValue - 9)
b68 = self.update_block(68, [tx]) b68 = self.update_block(68, [tx])
self.sync_blocks([b68], success=False, reject_code=16, reject_reason=b'bad-cb-amount', reconnect=True) self.sync_blocks([b68], success=False, reject_reason='bad-cb-amount', reconnect=True)
self.log.info("Accept a block claiming the correct subsidy in the coinbase transaction") self.log.info("Accept a block claiming the correct subsidy in the coinbase transaction")
self.move_tip(65) self.move_tip(65)
@ -924,7 +924,7 @@ class FullBlockTest(BitcoinTestFramework):
tx.vin.append(CTxIn(COutPoint(bogus_tx.sha256, 0), b"", 0xffffffff)) tx.vin.append(CTxIn(COutPoint(bogus_tx.sha256, 0), b"", 0xffffffff))
tx.vout.append(CTxOut(1, b"")) tx.vout.append(CTxOut(1, b""))
b70 = self.update_block(70, [tx]) b70 = self.update_block(70, [tx])
self.sync_blocks([b70], success=False, reject_code=16, reject_reason=b'bad-txns-inputs-missingorspent', reconnect=True) self.sync_blocks([b70], success=False, reject_reason='bad-txns-inputs-missingorspent', reconnect=True)
# Test accepting an invalid block which has the same hash as a valid one (via merkle tree tricks) # Test accepting an invalid block which has the same hash as a valid one (via merkle tree tricks)
# #
@ -949,7 +949,7 @@ class FullBlockTest(BitcoinTestFramework):
assert_equal(b72.sha256, b71.sha256) assert_equal(b72.sha256, b71.sha256)
self.move_tip(71) self.move_tip(71)
self.sync_blocks([b71], success=False, reject_code=16, reject_reason=b'bad-txns-duplicate', reconnect=True) self.sync_blocks([b71], success=False, reject_reason='bad-txns-duplicate', reconnect=True)
self.move_tip(72) self.move_tip(72)
self.sync_blocks([b72], True) self.sync_blocks([b72], True)
@ -987,7 +987,7 @@ class FullBlockTest(BitcoinTestFramework):
tx = self.create_and_sign_transaction(out[22], 1, CScript(a)) tx = self.create_and_sign_transaction(out[22], 1, CScript(a))
b73 = self.update_block(73, [tx]) b73 = self.update_block(73, [tx])
assert_equal(get_legacy_sigopcount_block(b73), MAX_BLOCK_SIGOPS + 1) assert_equal(get_legacy_sigopcount_block(b73), MAX_BLOCK_SIGOPS + 1)
self.sync_blocks([b73], success=False, reject_code=16, reject_reason=b'bad-blk-sigops', reconnect=True) self.sync_blocks([b73], success=False, reject_reason='bad-blk-sigops', reconnect=True)
# b74/75 - if we push an invalid script element, all prevous sigops are counted, # b74/75 - if we push an invalid script element, all prevous sigops are counted,
# but sigops after the element are not counted. # but sigops after the element are not counted.
@ -1011,7 +1011,7 @@ class FullBlockTest(BitcoinTestFramework):
a[MAX_BLOCK_SIGOPS + 4] = 0xff a[MAX_BLOCK_SIGOPS + 4] = 0xff
tx = self.create_and_sign_transaction(out[22], 1, CScript(a)) tx = self.create_and_sign_transaction(out[22], 1, CScript(a))
b74 = self.update_block(74, [tx]) b74 = self.update_block(74, [tx])
self.sync_blocks([b74], success=False, reject_code=16, reject_reason=b'bad-blk-sigops', reconnect=True) self.sync_blocks([b74], success=False, reject_reason='bad-blk-sigops', reconnect=True)
self.move_tip(72) self.move_tip(72)
b75 = self.next_block(75) b75 = self.next_block(75)
@ -1160,7 +1160,7 @@ class FullBlockTest(BitcoinTestFramework):
b89a = self.next_block("89a", spend=out[32]) b89a = self.next_block("89a", spend=out[32])
tx = self.create_tx(tx1, 0, 0, CScript([OP_TRUE])) tx = self.create_tx(tx1, 0, 0, CScript([OP_TRUE]))
b89a = self.update_block("89a", [tx]) b89a = self.update_block("89a", [tx])
self.sync_blocks([b89a], success=False, reject_code=16, reject_reason=b'bad-txns-inputs-missingorspent', reconnect=True) self.sync_blocks([b89a], success=False, reject_reason='bad-txns-inputs-missingorspent', reconnect=True)
self.log.info("Test a re-org of one week's worth of blocks (1088 blocks)") self.log.info("Test a re-org of one week's worth of blocks (1088 blocks)")
@ -1309,11 +1309,11 @@ class FullBlockTest(BitcoinTestFramework):
self.nodes[0].disconnect_p2ps() self.nodes[0].disconnect_p2ps()
self.bootstrap_p2p() self.bootstrap_p2p()
def sync_blocks(self, blocks, success=True, reject_code=None, reject_reason=None, request_block=True, reconnect=False, timeout=60): def sync_blocks(self, blocks, success=True, reject_reason=None, request_block=True, reconnect=False, timeout=60):
"""Sends blocks to test node. Syncs and verifies that tip has advanced to most recent block. """Sends blocks to test node. Syncs and verifies that tip has advanced to most recent block.
Call with success = False if the tip shouldn't advance to the most recent block.""" Call with success = False if the tip shouldn't advance to the most recent block."""
self.nodes[0].p2p.send_blocks_and_test(blocks, self.nodes[0], success=success, reject_code=reject_code, reject_reason=reject_reason, request_block=request_block, timeout=timeout) self.nodes[0].p2p.send_blocks_and_test(blocks, self.nodes[0], success=success, reject_reason=reject_reason, request_block=request_block, timeout=timeout, expect_disconnect=reconnect)
if reconnect: if reconnect:
self.reconnect_p2p() self.reconnect_p2p()

View file

@ -10,10 +10,14 @@ Test that the CHECKLOCKTIMEVERIFY soft-fork activates at (regtest) block height
from test_framework.blocktools import create_coinbase, create_block, create_transaction from test_framework.blocktools import create_coinbase, create_block, create_transaction
from test_framework.messages import CTransaction, msg_block, ToHex from test_framework.messages import CTransaction, msg_block, ToHex
from test_framework.mininode import mininode_lock, P2PInterface from test_framework.mininode import P2PInterface
from test_framework.script import CScript, OP_1NEGATE, OP_CHECKLOCKTIMEVERIFY, OP_DROP, CScriptNum from test_framework.script import CScript, OP_1NEGATE, OP_CHECKLOCKTIMEVERIFY, OP_DROP, CScriptNum
from test_framework.test_framework import BitcoinTestFramework from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, bytes_to_hex_str, hex_str_to_bytes, wait_until from test_framework.util import (
assert_equal,
bytes_to_hex_str,
hex_str_to_bytes,
)
from io import BytesIO from io import BytesIO
@ -51,10 +55,11 @@ def cltv_validate(node, tx, height):
list(CScript(new_tx.vin[0].scriptSig))) list(CScript(new_tx.vin[0].scriptSig)))
return new_tx return new_tx
class BIP65Test(BitcoinTestFramework): class BIP65Test(BitcoinTestFramework):
def set_test_params(self): def set_test_params(self):
self.num_nodes = 1 self.num_nodes = 1
self.extra_args = [['-whitelist=127.0.0.1']] self.extra_args = [['-whitelist=127.0.0.1', '-par=1']] # Use only one script thread to get the exact reject reason for testing
self.setup_clean_chain = True self.setup_clean_chain = True
def run_test(self): def run_test(self):
@ -88,15 +93,11 @@ class BIP65Test(BitcoinTestFramework):
block = create_block(tip, create_coinbase(CLTV_HEIGHT), block_time) block = create_block(tip, create_coinbase(CLTV_HEIGHT), block_time)
block.nVersion = 3 block.nVersion = 3
block.solve() block.solve()
self.nodes[0].p2p.send_and_ping(msg_block(block))
assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip)
wait_until(lambda: "reject" in self.nodes[0].p2p.last_message.keys(), lock=mininode_lock) with self.nodes[0].assert_debug_log(expected_msgs=['{}, bad-version(0x00000003)'.format(block.hash)]):
with mininode_lock: self.nodes[0].p2p.send_and_ping(msg_block(block))
assert_equal(self.nodes[0].p2p.last_message["reject"].code, REJECT_OBSOLETE) assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip)
assert_equal(self.nodes[0].p2p.last_message["reject"].reason, b'bad-version(0x00000003)') self.nodes[0].p2p.sync_with_ping()
assert_equal(self.nodes[0].p2p.last_message["reject"].data, block.sha256)
del self.nodes[0].p2p.last_message["reject"]
self.log.info("Test that invalid-according-to-cltv transactions cannot appear in a block") self.log.info("Test that invalid-according-to-cltv transactions cannot appear in a block")
block.nVersion = 4 block.nVersion = 4
@ -118,18 +119,10 @@ class BIP65Test(BitcoinTestFramework):
block.hashMerkleRoot = block.calc_merkle_root() block.hashMerkleRoot = block.calc_merkle_root()
block.solve() block.solve()
self.nodes[0].p2p.send_and_ping(msg_block(block)) with self.nodes[0].assert_debug_log(expected_msgs=['CheckInputs on {} failed with non-mandatory-script-verify-flag (Negative locktime)'.format(block.vtx[-1].hash)]):
assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip) self.nodes[0].p2p.send_and_ping(msg_block(block))
assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip)
wait_until(lambda: "reject" in self.nodes[0].p2p.last_message.keys(), lock=mininode_lock) self.nodes[0].p2p.sync_with_ping()
with mininode_lock:
assert self.nodes[0].p2p.last_message["reject"].code in [REJECT_INVALID, REJECT_NONSTANDARD]
assert_equal(self.nodes[0].p2p.last_message["reject"].data, block.sha256)
if self.nodes[0].p2p.last_message["reject"].code == REJECT_INVALID:
# Generic rejection when a block is invalid
assert_equal(self.nodes[0].p2p.last_message["reject"].reason, b'block-validation-failed')
else:
assert b'Negative locktime' in self.nodes[0].p2p.last_message["reject"].reason
self.log.info("Test that a version 4 block with a valid-according-to-CLTV transaction is accepted") self.log.info("Test that a version 4 block with a valid-according-to-CLTV transaction is accepted")
spendtx = cltv_validate(self.nodes[0], spendtx, CLTV_HEIGHT - 1) spendtx = cltv_validate(self.nodes[0], spendtx, CLTV_HEIGHT - 1)

View file

@ -165,11 +165,11 @@ class BIP68_112_113Test(BitcoinTestFramework):
block.solve() block.solve()
return block return block
def sync_blocks(self, blocks, success=True, reject_code=None, reject_reason=None, request_block=True): def sync_blocks(self, blocks, success=True):
"""Sends blocks to test node. Syncs and verifies that tip has advanced to most recent block. """Sends blocks to test node. Syncs and verifies that tip has advanced to most recent block.
Call with success = False if the tip shouldn't advance to the most recent block.""" Call with success = False if the tip shouldn't advance to the most recent block."""
self.nodes[0].p2p.send_blocks_and_test(blocks, self.nodes[0], success=success, reject_code=reject_code, reject_reason=reject_reason, request_block=request_block) self.nodes[0].p2p.send_blocks_and_test(blocks, self.nodes[0], success=success)
def run_test(self): def run_test(self):
self.nodes[0].add_p2p_connection(P2PDataStore()) self.nodes[0].add_p2p_connection(P2PDataStore())

View file

@ -12,7 +12,11 @@ from test_framework.messages import msg_block
from test_framework.mininode import mininode_lock, P2PInterface from test_framework.mininode import mininode_lock, P2PInterface
from test_framework.script import CScript from test_framework.script import CScript
from test_framework.test_framework import BitcoinTestFramework from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, bytes_to_hex_str, wait_until from test_framework.util import (
assert_equal,
bytes_to_hex_str,
wait_until,
)
DERSIG_HEIGHT = 1251 DERSIG_HEIGHT = 1251
@ -42,7 +46,7 @@ def unDERify(tx):
class BIP66Test(BitcoinTestFramework): class BIP66Test(BitcoinTestFramework):
def set_test_params(self): def set_test_params(self):
self.num_nodes = 1 self.num_nodes = 1
self.extra_args = [['-whitelist=127.0.0.1']] self.extra_args = [['-whitelist=127.0.0.1', '-par=1', '-enablebip61']] # Use only one script thread to get the exact reject reason for testing
self.setup_clean_chain = True self.setup_clean_chain = True
def run_test(self): def run_test(self):
@ -78,15 +82,11 @@ class BIP66Test(BitcoinTestFramework):
block.nVersion = 2 block.nVersion = 2
block.rehash() block.rehash()
block.solve() block.solve()
self.nodes[0].p2p.send_and_ping(msg_block(block))
assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip)
wait_until(lambda: "reject" in self.nodes[0].p2p.last_message.keys(), lock=mininode_lock) with self.nodes[0].assert_debug_log(expected_msgs=['{}, bad-version(0x00000002)'.format(block.hash)]):
with mininode_lock: self.nodes[0].p2p.send_and_ping(msg_block(block))
assert_equal(self.nodes[0].p2p.last_message["reject"].code, REJECT_OBSOLETE) assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip)
assert_equal(self.nodes[0].p2p.last_message["reject"].reason, b'bad-version(0x00000002)') self.nodes[0].p2p.sync_with_ping()
assert_equal(self.nodes[0].p2p.last_message["reject"].data, block.sha256)
del self.nodes[0].p2p.last_message["reject"]
self.log.info("Test that transactions with non-DER signatures cannot appear in a block") self.log.info("Test that transactions with non-DER signatures cannot appear in a block")
block.nVersion = 3 block.nVersion = 3
@ -109,23 +109,16 @@ class BIP66Test(BitcoinTestFramework):
block.rehash() block.rehash()
block.solve() block.solve()
self.nodes[0].p2p.send_and_ping(msg_block(block)) with self.nodes[0].assert_debug_log(expected_msgs=['CheckInputs on {} failed with non-mandatory-script-verify-flag (Non-canonical DER signature)'.format(block.vtx[-1].hash)]):
assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip) self.nodes[0].p2p.send_and_ping(msg_block(block))
assert_equal(int(self.nodes[0].getbestblockhash(), 16), tip)
self.nodes[0].p2p.sync_with_ping()
wait_until(lambda: "reject" in self.nodes[0].p2p.last_message.keys(), lock=mininode_lock) wait_until(lambda: "reject" in self.nodes[0].p2p.last_message.keys(), lock=mininode_lock)
with mininode_lock: with mininode_lock:
# We can receive different reject messages depending on whether
# bitcoind is running with multiple script check threads. If script
# check threads are not in use, then transaction script validation
# happens sequentially, and bitcoind produces more specific reject
# reasons.
assert self.nodes[0].p2p.last_message["reject"].code in [REJECT_INVALID, REJECT_NONSTANDARD] assert self.nodes[0].p2p.last_message["reject"].code in [REJECT_INVALID, REJECT_NONSTANDARD]
assert_equal(self.nodes[0].p2p.last_message["reject"].data, block.sha256) assert_equal(self.nodes[0].p2p.last_message["reject"].data, block.sha256)
if self.nodes[0].p2p.last_message["reject"].code == REJECT_INVALID: assert b'Non-canonical DER signature' in self.nodes[0].p2p.last_message["reject"].reason
# Generic rejection when a block is invalid
assert_equal(self.nodes[0].p2p.last_message["reject"].reason, b'block-validation-failed')
else:
assert b'Non-canonical DER signature' in self.nodes[0].p2p.last_message["reject"].reason
self.log.info("Test that a version 3 block with a DERSIG-compliant transaction is accepted") self.log.info("Test that a version 3 block with a DERSIG-compliant transaction is accepted")
block.vtx[1] = create_transaction(self.nodes[0], self.coinbase_txids[1], self.nodeaddress, amount=1.0) block.vtx[1] = create_transaction(self.nodes[0], self.coinbase_txids[1], self.nodeaddress, amount=1.0)

View file

@ -79,7 +79,7 @@ class InvalidBlockRequestTest(BitcoinTestFramework):
assert_equal(orig_hash, block2.rehash()) assert_equal(orig_hash, block2.rehash())
assert(block2_orig.vtx != block2.vtx) assert(block2_orig.vtx != block2.vtx)
node.p2p.send_blocks_and_test([block2], node, success=False, request_block=False, reject_code=16, reject_reason=b'bad-txns-duplicate') node.p2p.send_blocks_and_test([block2], node, success=False, request_block=False, reject_reason='bad-txns-duplicate')
self.log.info("Test very broken block.") self.log.info("Test very broken block.")
@ -92,7 +92,7 @@ class InvalidBlockRequestTest(BitcoinTestFramework):
block3.rehash() block3.rehash()
block3.solve() block3.solve()
node.p2p.send_blocks_and_test([block3], node, success=False, request_block=False, reject_code=16, reject_reason=b'bad-cb-amount') node.p2p.send_blocks_and_test([block3], node, success=False, request_block=False, reject_reason='bad-cb-amount')
if __name__ == '__main__': if __name__ == '__main__':
InvalidBlockRequestTest().main() InvalidBlockRequestTest().main()

View file

@ -116,7 +116,8 @@ class InvalidTxRequestTest(BitcoinTestFramework):
assert_equal(2, len(node.getpeerinfo())) # p2ps[1] is still connected assert_equal(2, len(node.getpeerinfo())) # p2ps[1] is still connected
self.log.info('Send the withhold tx ... ') self.log.info('Send the withhold tx ... ')
node.p2p.send_txs_and_test([tx_withhold], node, success=True) with node.assert_debug_log(expected_msgs=["bad-txns-in-belowout"]):
node.p2p.send_txs_and_test([tx_withhold], node, success=True)
# Transactions that should end up in the mempool # Transactions that should end up in the mempool
expected_mempool = { expected_mempool = {
@ -134,18 +135,6 @@ class InvalidTxRequestTest(BitcoinTestFramework):
wait_until(lambda: 1 == len(node.getpeerinfo()), timeout=12) # p2ps[1] is no longer connected wait_until(lambda: 1 == len(node.getpeerinfo()), timeout=12) # p2ps[1] is no longer connected
assert_equal(expected_mempool, set(node.getrawmempool())) assert_equal(expected_mempool, set(node.getrawmempool()))
# restart node with sending BIP61 messages disabled, check that it disconnects without sending the reject message
self.log.info('Test a transaction that is rejected, with BIP61 disabled')
self.restart_node(0, ['-enablebip61=0', '-persistmempool=0'])
self.reconnect_p2p(num_connections=1)
with node.assert_debug_log(expected_msgs=[
"{} from peer=0 was not accepted: mandatory-script-verify-flag-failed (Invalid OP_IF construction) (code 16)".format(tx1.hash),
"disconnecting peer=0",
]):
node.p2p.send_txs_and_test([tx1], node, success=False, expect_disconnect=True)
# send_txs_and_test will have waited for disconnect, so we can safely check that no reject has been received
assert_equal(node.p2p.reject_code_received, None)
if __name__ == '__main__': if __name__ == '__main__':
InvalidTxRequestTest().main() InvalidTxRequestTest().main()

View file

@ -41,7 +41,6 @@ from test_framework.messages import (
from test_framework.mininode import ( from test_framework.mininode import (
P2PInterface, P2PInterface,
mininode_lock, mininode_lock,
wait_until,
) )
from test_framework.script import ( from test_framework.script import (
CScript, CScript,
@ -124,32 +123,23 @@ def test_transaction_acceptance(node, p2p, tx, with_witness, accepted, reason=No
- Submit the transaction over the p2p interface - Submit the transaction over the p2p interface
- use the getrawmempool rpc to check for acceptance.""" - use the getrawmempool rpc to check for acceptance."""
tx_message = msg_tx(tx) reason = [reason] if reason else []
if with_witness: with node.assert_debug_log(expected_msgs=reason):
tx_message = msg_witness_tx(tx) p2p.send_message(msg_witness_tx(tx) if with_witness else msg_tx(tx))
p2p.send_message(tx_message) p2p.sync_with_ping()
p2p.sync_with_ping() assert_equal(tx.hash in node.getrawmempool(), accepted)
assert_equal(tx.hash in node.getrawmempool(), accepted)
if (reason is not None and not accepted):
# Check the rejection reason as well.
with mininode_lock:
assert_equal(p2p.last_message["reject"].reason, reason)
def test_witness_block(node, p2p, block, accepted, with_witness=True, reason=None): def test_witness_block(node, p2p, block, accepted, with_witness=True, reason=None):
"""Send a block to the node and check that it's accepted """Send a block to the node and check that it's accepted
- Submit the block over the p2p interface - Submit the block over the p2p interface
- use the getbestblockhash rpc to check for acceptance.""" - use the getbestblockhash rpc to check for acceptance."""
if with_witness: reason = [reason] if reason else []
p2p.send_message(msg_witness_block(block)) with node.assert_debug_log(expected_msgs=reason):
else: p2p.send_message(msg_witness_block(block) if with_witness else msg_block(block))
p2p.send_message(msg_block(block)) p2p.sync_with_ping()
p2p.sync_with_ping() assert_equal(node.getbestblockhash() == block.hash, accepted)
assert_equal(node.getbestblockhash() == block.hash, accepted)
if (reason is not None and not accepted):
# Check the rejection reason as well.
with mininode_lock:
assert_equal(p2p.last_message["reject"].reason, reason)
class TestP2PConn(P2PInterface): class TestP2PConn(P2PInterface):
def __init__(self): def __init__(self):
@ -349,8 +339,7 @@ class SegWitTest(BitcoinTestFramework):
self.update_witness_block_with_transactions(block, [tx]) self.update_witness_block_with_transactions(block, [tx])
# Sending witness data before activation is not allowed (anti-spam # Sending witness data before activation is not allowed (anti-spam
# rule). # rule).
test_witness_block(self.nodes[0], self.test_node, block, accepted=False) test_witness_block(self.nodes[0], self.test_node, block, accepted=False, reason='unexpected-witness')
wait_until(lambda: 'reject' in self.test_node.last_message and self.test_node.last_message["reject"].reason == b"unexpected-witness")
# But it should not be permanently marked bad... # But it should not be permanently marked bad...
# Resend without witness information. # Resend without witness information.
@ -497,7 +486,7 @@ class SegWitTest(BitcoinTestFramework):
self.update_witness_block_with_transactions(block, [tx]) self.update_witness_block_with_transactions(block, [tx])
# Verify that segwit isn't activated. A block serialized with witness # Verify that segwit isn't activated. A block serialized with witness
# should be rejected prior to activation. # should be rejected prior to activation.
test_witness_block(self.nodes[0], self.test_node, block, accepted=False, with_witness=True, reason=b'unexpected-witness') test_witness_block(self.nodes[0], self.test_node, block, accepted=False, with_witness=True, reason='unexpected-witness')
# Now send the block without witness. It should be accepted # Now send the block without witness. It should be accepted
test_witness_block(self.nodes[0], self.test_node, block, accepted=True, with_witness=False) test_witness_block(self.nodes[0], self.test_node, block, accepted=True, with_witness=False)
@ -523,7 +512,7 @@ class SegWitTest(BitcoinTestFramework):
# When the block is serialized with a witness, the block will be rejected because witness # When the block is serialized with a witness, the block will be rejected because witness
# data isn't allowed in blocks that don't commit to witness data. # data isn't allowed in blocks that don't commit to witness data.
test_witness_block(self.nodes[0], self.test_node, block, accepted=False, with_witness=True, reason=b'unexpected-witness') test_witness_block(self.nodes[0], self.test_node, block, accepted=False, with_witness=True, reason='unexpected-witness')
# When the block is serialized without witness, validation fails because the transaction is # When the block is serialized without witness, validation fails because the transaction is
# invalid (transactions are always validated with SCRIPT_VERIFY_WITNESS so a segwit v0 transaction # invalid (transactions are always validated with SCRIPT_VERIFY_WITNESS so a segwit v0 transaction
@ -1343,9 +1332,9 @@ class SegWitTest(BitcoinTestFramework):
# Node will not be blinded to the transaction # Node will not be blinded to the transaction
self.std_node.announce_tx_and_wait_for_getdata(tx3) self.std_node.announce_tx_and_wait_for_getdata(tx3)
test_transaction_acceptance(self.nodes[1], self.std_node, tx3, True, False, b'tx-size') test_transaction_acceptance(self.nodes[1], self.std_node, tx3, True, False, 'tx-size')
self.std_node.announce_tx_and_wait_for_getdata(tx3) self.std_node.announce_tx_and_wait_for_getdata(tx3)
test_transaction_acceptance(self.nodes[1], self.std_node, tx3, True, False, b'tx-size') test_transaction_acceptance(self.nodes[1], self.std_node, tx3, True, False, 'tx-size')
# Remove witness stuffing, instead add extra witness push on stack # Remove witness stuffing, instead add extra witness push on stack
tx3.vout[0] = CTxOut(tx2.vout[0].nValue - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])) tx3.vout[0] = CTxOut(tx2.vout[0].nValue - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))
@ -1454,10 +1443,7 @@ class SegWitTest(BitcoinTestFramework):
tx3.rehash() tx3.rehash()
# Spending a higher version witness output is not allowed by policy, # Spending a higher version witness output is not allowed by policy,
# even with fRequireStandard=false. # even with fRequireStandard=false.
test_transaction_acceptance(self.nodes[0], self.test_node, tx3, with_witness=True, accepted=False) test_transaction_acceptance(self.nodes[0], self.test_node, tx3, with_witness=True, accepted=False, reason="reserved for soft-fork upgrades")
self.test_node.sync_with_ping()
with mininode_lock:
assert(b"reserved for soft-fork upgrades" in self.test_node.last_message["reject"].reason)
# Building a block with the transaction must be valid, however. # Building a block with the transaction must be valid, however.
block = self.build_next_block() block = self.build_next_block()
@ -1551,7 +1537,7 @@ class SegWitTest(BitcoinTestFramework):
tx2.rehash() tx2.rehash()
# Should fail policy test. # Should fail policy test.
test_transaction_acceptance(self.nodes[0], self.test_node, tx2, True, False, b'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)') test_transaction_acceptance(self.nodes[0], self.test_node, tx2, True, False, 'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)')
# But passes consensus. # But passes consensus.
block = self.build_next_block() block = self.build_next_block()
self.update_witness_block_with_transactions(block, [tx2]) self.update_witness_block_with_transactions(block, [tx2])
@ -1571,7 +1557,7 @@ class SegWitTest(BitcoinTestFramework):
sign_p2pk_witness_input(witness_program, tx3, 0, SIGHASH_ALL, tx2.vout[0].nValue, key) sign_p2pk_witness_input(witness_program, tx3, 0, SIGHASH_ALL, tx2.vout[0].nValue, key)
# Should fail policy test. # Should fail policy test.
test_transaction_acceptance(self.nodes[0], self.test_node, tx3, True, False, b'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)') test_transaction_acceptance(self.nodes[0], self.test_node, tx3, True, False, 'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)')
# But passes consensus. # But passes consensus.
block = self.build_next_block() block = self.build_next_block()
self.update_witness_block_with_transactions(block, [tx3]) self.update_witness_block_with_transactions(block, [tx3])
@ -1588,7 +1574,7 @@ class SegWitTest(BitcoinTestFramework):
sign_p2pk_witness_input(witness_program, tx4, 0, SIGHASH_ALL, tx3.vout[0].nValue, key) sign_p2pk_witness_input(witness_program, tx4, 0, SIGHASH_ALL, tx3.vout[0].nValue, key)
# Should fail policy test. # Should fail policy test.
test_transaction_acceptance(self.nodes[0], self.test_node, tx4, True, False, b'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)') test_transaction_acceptance(self.nodes[0], self.test_node, tx4, True, False, 'non-mandatory-script-verify-flag (Using non-compressed keys in segwit)')
block = self.build_next_block() block = self.build_next_block()
self.update_witness_block_with_transactions(block, [tx4]) self.update_witness_block_with_transactions(block, [tx4])
test_witness_block(self.nodes[0], self.test_node, block, accepted=True) test_witness_block(self.nodes[0], self.test_node, block, accepted=True)
@ -1825,7 +1811,7 @@ class SegWitTest(BitcoinTestFramework):
tx2.rehash() tx2.rehash()
# This will be rejected due to a policy check: # This will be rejected due to a policy check:
# No witness is allowed, since it is not a witness program but a p2sh program # No witness is allowed, since it is not a witness program but a p2sh program
test_transaction_acceptance(self.nodes[1], self.std_node, tx2, True, False, b'bad-witness-nonstandard') test_transaction_acceptance(self.nodes[1], self.std_node, tx2, True, False, 'bad-witness-nonstandard')
# If we send without witness, it should be accepted. # If we send without witness, it should be accepted.
test_transaction_acceptance(self.nodes[1], self.std_node, tx2, False, True) test_transaction_acceptance(self.nodes[1], self.std_node, tx2, False, True)
@ -1897,13 +1883,13 @@ class SegWitTest(BitcoinTestFramework):
# Testing native P2WSH # Testing native P2WSH
# Witness stack size, excluding witnessScript, over 100 is non-standard # Witness stack size, excluding witnessScript, over 100 is non-standard
p2wsh_txs[0].wit.vtxinwit[0].scriptWitness.stack = [pad] * 101 + [scripts[0]] p2wsh_txs[0].wit.vtxinwit[0].scriptWitness.stack = [pad] * 101 + [scripts[0]]
test_transaction_acceptance(self.nodes[1], self.std_node, p2wsh_txs[0], True, False, b'bad-witness-nonstandard') test_transaction_acceptance(self.nodes[1], self.std_node, p2wsh_txs[0], True, False, 'bad-witness-nonstandard')
# Non-standard nodes should accept # Non-standard nodes should accept
test_transaction_acceptance(self.nodes[0], self.test_node, p2wsh_txs[0], True, True) test_transaction_acceptance(self.nodes[0], self.test_node, p2wsh_txs[0], True, True)
# Stack element size over 80 bytes is non-standard # Stack element size over 80 bytes is non-standard
p2wsh_txs[1].wit.vtxinwit[0].scriptWitness.stack = [pad * 81] * 100 + [scripts[1]] p2wsh_txs[1].wit.vtxinwit[0].scriptWitness.stack = [pad * 81] * 100 + [scripts[1]]
test_transaction_acceptance(self.nodes[1], self.std_node, p2wsh_txs[1], True, False, b'bad-witness-nonstandard') test_transaction_acceptance(self.nodes[1], self.std_node, p2wsh_txs[1], True, False, 'bad-witness-nonstandard')
# Non-standard nodes should accept # Non-standard nodes should accept
test_transaction_acceptance(self.nodes[0], self.test_node, p2wsh_txs[1], True, True) test_transaction_acceptance(self.nodes[0], self.test_node, p2wsh_txs[1], True, True)
# Standard nodes should accept if element size is not over 80 bytes # Standard nodes should accept if element size is not over 80 bytes
@ -1917,16 +1903,16 @@ class SegWitTest(BitcoinTestFramework):
# witnessScript size at 3601 bytes is non-standard # witnessScript size at 3601 bytes is non-standard
p2wsh_txs[3].wit.vtxinwit[0].scriptWitness.stack = [pad, pad, pad, scripts[3]] p2wsh_txs[3].wit.vtxinwit[0].scriptWitness.stack = [pad, pad, pad, scripts[3]]
test_transaction_acceptance(self.nodes[1], self.std_node, p2wsh_txs[3], True, False, b'bad-witness-nonstandard') test_transaction_acceptance(self.nodes[1], self.std_node, p2wsh_txs[3], True, False, 'bad-witness-nonstandard')
# Non-standard nodes should accept # Non-standard nodes should accept
test_transaction_acceptance(self.nodes[0], self.test_node, p2wsh_txs[3], True, True) test_transaction_acceptance(self.nodes[0], self.test_node, p2wsh_txs[3], True, True)
# Repeating the same tests with P2SH-P2WSH # Repeating the same tests with P2SH-P2WSH
p2sh_txs[0].wit.vtxinwit[0].scriptWitness.stack = [pad] * 101 + [scripts[0]] p2sh_txs[0].wit.vtxinwit[0].scriptWitness.stack = [pad] * 101 + [scripts[0]]
test_transaction_acceptance(self.nodes[1], self.std_node, p2sh_txs[0], True, False, b'bad-witness-nonstandard') test_transaction_acceptance(self.nodes[1], self.std_node, p2sh_txs[0], True, False, 'bad-witness-nonstandard')
test_transaction_acceptance(self.nodes[0], self.test_node, p2sh_txs[0], True, True) test_transaction_acceptance(self.nodes[0], self.test_node, p2sh_txs[0], True, True)
p2sh_txs[1].wit.vtxinwit[0].scriptWitness.stack = [pad * 81] * 100 + [scripts[1]] p2sh_txs[1].wit.vtxinwit[0].scriptWitness.stack = [pad * 81] * 100 + [scripts[1]]
test_transaction_acceptance(self.nodes[1], self.std_node, p2sh_txs[1], True, False, b'bad-witness-nonstandard') test_transaction_acceptance(self.nodes[1], self.std_node, p2sh_txs[1], True, False, 'bad-witness-nonstandard')
test_transaction_acceptance(self.nodes[0], self.test_node, p2sh_txs[1], True, True) test_transaction_acceptance(self.nodes[0], self.test_node, p2sh_txs[1], True, True)
p2sh_txs[1].wit.vtxinwit[0].scriptWitness.stack = [pad * 80] * 100 + [scripts[1]] p2sh_txs[1].wit.vtxinwit[0].scriptWitness.stack = [pad * 80] * 100 + [scripts[1]]
test_transaction_acceptance(self.nodes[1], self.std_node, p2sh_txs[1], True, True) test_transaction_acceptance(self.nodes[1], self.std_node, p2sh_txs[1], True, True)
@ -1934,7 +1920,7 @@ class SegWitTest(BitcoinTestFramework):
test_transaction_acceptance(self.nodes[0], self.test_node, p2sh_txs[2], True, True) test_transaction_acceptance(self.nodes[0], self.test_node, p2sh_txs[2], True, True)
test_transaction_acceptance(self.nodes[1], self.std_node, p2sh_txs[2], True, True) test_transaction_acceptance(self.nodes[1], self.std_node, p2sh_txs[2], True, True)
p2sh_txs[3].wit.vtxinwit[0].scriptWitness.stack = [pad, pad, pad, scripts[3]] p2sh_txs[3].wit.vtxinwit[0].scriptWitness.stack = [pad, pad, pad, scripts[3]]
test_transaction_acceptance(self.nodes[1], self.std_node, p2sh_txs[3], True, False, b'bad-witness-nonstandard') test_transaction_acceptance(self.nodes[1], self.std_node, p2sh_txs[3], True, False, 'bad-witness-nonstandard')
test_transaction_acceptance(self.nodes[0], self.test_node, p2sh_txs[3], True, True) test_transaction_acceptance(self.nodes[0], self.test_node, p2sh_txs[3], True, True)
self.nodes[0].generate(1) # Mine and clean up the mempool of non-standard node self.nodes[0].generate(1) # Mine and clean up the mempool of non-standard node

View file

@ -425,8 +425,6 @@ class P2PDataStore(P2PInterface):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.reject_code_received = None
self.reject_reason_received = None
# store of blocks. key is block hash, value is a CBlock object # store of blocks. key is block hash, value is a CBlock object
self.block_store = {} self.block_store = {}
self.last_block_hash = '' self.last_block_hash = ''
@ -477,12 +475,7 @@ class P2PDataStore(P2PInterface):
if response is not None: if response is not None:
self.send_message(response) self.send_message(response)
def on_reject(self, message): def send_blocks_and_test(self, blocks, node, *, success=True, request_block=True, reject_reason=None, expect_disconnect=False, timeout=60):
"""Store reject reason and code for testing."""
self.reject_code_received = message.code
self.reject_reason_received = message.reason
def send_blocks_and_test(self, blocks, node, *, success=True, request_block=True, reject_code=None, reject_reason=None, timeout=60):
"""Send blocks to test node and test whether the tip advances. """Send blocks to test node and test whether the tip advances.
- add all blocks to our block_store - add all blocks to our block_store
@ -492,66 +485,59 @@ class P2PDataStore(P2PInterface):
ensure that any getdata messages are responded to ensure that any getdata messages are responded to
- if success is True: assert that the node's tip advances to the most recent block - if success is True: assert that the node's tip advances to the most recent block
- if success is False: assert that the node's tip doesn't advance - if success is False: assert that the node's tip doesn't advance
- if reject_code and reject_reason are set: assert that the correct reject message is received""" - if reject_reason is set: assert that the correct reject message is logged"""
with mininode_lock: with mininode_lock:
self.reject_code_received = None
self.reject_reason_received = None
for block in blocks: for block in blocks:
self.block_store[block.sha256] = block self.block_store[block.sha256] = block
self.last_block_hash = block.sha256 self.last_block_hash = block.sha256
self.send_message(msg_headers([CBlockHeader(blocks[-1])])) reject_reason = [reject_reason] if reject_reason else []
with node.assert_debug_log(expected_msgs=reject_reason):
self.send_message(msg_headers([CBlockHeader(blocks[-1])]))
if request_block: if request_block:
wait_until(lambda: blocks[-1].sha256 in self.getdata_requests, timeout=timeout, lock=mininode_lock) wait_until(lambda: blocks[-1].sha256 in self.getdata_requests, timeout=timeout, lock=mininode_lock)
if success: if expect_disconnect:
wait_until(lambda: node.getbestblockhash() == blocks[-1].hash, timeout=timeout) self.wait_for_disconnect()
else: else:
assert node.getbestblockhash() != blocks[-1].hash self.sync_with_ping()
if reject_code is not None: if success:
wait_until(lambda: self.reject_code_received == reject_code, lock=mininode_lock) wait_until(lambda: node.getbestblockhash() == blocks[-1].hash, timeout=timeout)
if reject_reason is not None: else:
wait_until(lambda: self.reject_reason_received == reject_reason, lock=mininode_lock) assert node.getbestblockhash() != blocks[-1].hash
def send_txs_and_test(self, txs, node, *, success=True, expect_disconnect=False, reject_code=None, reject_reason=None): def send_txs_and_test(self, txs, node, *, success=True, expect_disconnect=False, reject_reason=None):
"""Send txs to test node and test whether they're accepted to the mempool. """Send txs to test node and test whether they're accepted to the mempool.
- add all txs to our tx_store - add all txs to our tx_store
- send tx messages for all txs - send tx messages for all txs
- if success is True/False: assert that the txs are/are not accepted to the mempool - if success is True/False: assert that the txs are/are not accepted to the mempool
- if expect_disconnect is True: Skip the sync with ping - if expect_disconnect is True: Skip the sync with ping
- if reject_code and reject_reason are set: assert that the correct reject message is received.""" - if reject_reason is set: assert that the correct reject message is logged."""
with mininode_lock: with mininode_lock:
self.reject_code_received = None
self.reject_reason_received = None
for tx in txs: for tx in txs:
self.tx_store[tx.sha256] = tx self.tx_store[tx.sha256] = tx
for tx in txs: reject_reason = [reject_reason] if reject_reason else []
self.send_message(msg_tx(tx)) with node.assert_debug_log(expected_msgs=reject_reason):
if expect_disconnect:
self.wait_for_disconnect()
else:
self.sync_with_ping()
raw_mempool = node.getrawmempool()
if success:
# Check that all txs are now in the mempool
for tx in txs: for tx in txs:
assert tx.hash in raw_mempool, "{} not found in mempool".format(tx.hash) self.send_message(msg_tx(tx))
else:
# Check that none of the txs are now in the mempool
for tx in txs:
assert tx.hash not in raw_mempool, "{} tx found in mempool".format(tx.hash)
if reject_code is not None: if expect_disconnect:
wait_until(lambda: self.reject_code_received == reject_code, lock=mininode_lock) self.wait_for_disconnect()
if reject_reason is not None: else:
wait_until(lambda: self.reject_reason_received == reject_reason, lock=mininode_lock) self.sync_with_ping()
raw_mempool = node.getrawmempool()
if success:
# Check that all txs are now in the mempool
for tx in txs:
assert tx.hash in raw_mempool, "{} not found in mempool".format(tx.hash)
else:
# Check that none of the txs are now in the mempool
for tx in txs:
assert tx.hash not in raw_mempool, "{} tx found in mempool".format(tx.hash)