net_processing: drop MaybePunishNodeForTx

Do not discourage nodes even when they send us consensus invalid
transactions.

Because we do not discourage nodes for transactions we consider
non-standard, we don't get any DoS protection from this check in
adversarial scenarios, so remove the check entirely both to simplify the
code and reduce the risk of splitting the network due to changes in tx
relay policy.

NOTE: Backport required additional adjustment in test/functional/p2p_invalid_tx

Github-Pull: #33050
Rebased-From: 266dd0e10d
This commit is contained in:
Anthony Towns
2025-07-23 10:50:33 +10:00
committed by Luke Dashjr
parent f24291bd96
commit 65bcbbc538
4 changed files with 16 additions and 49 deletions

View File

@@ -89,7 +89,7 @@ class BadTxTemplate:
class OutputMissing(BadTxTemplate):
reject_reason = "bad-txns-vout-empty"
expect_disconnect = True
expect_disconnect = False
def get_tx(self):
tx = CTransaction()
@@ -100,7 +100,7 @@ class OutputMissing(BadTxTemplate):
class InputMissing(BadTxTemplate):
reject_reason = "bad-txns-vin-empty"
expect_disconnect = True
expect_disconnect = False
# We use a blank transaction here to make sure
# it is interpreted as a non-witness transaction.
@@ -149,7 +149,7 @@ class BadInputOutpointIndex(BadTxTemplate):
class DuplicateInput(BadTxTemplate):
reject_reason = 'bad-txns-inputs-duplicate'
expect_disconnect = True
expect_disconnect = False
def get_tx(self):
tx = CTransaction()
@@ -162,7 +162,7 @@ class DuplicateInput(BadTxTemplate):
class PrevoutNullInput(BadTxTemplate):
reject_reason = 'bad-txns-prevout-null'
expect_disconnect = True
expect_disconnect = False
def get_tx(self):
tx = CTransaction()
@@ -188,7 +188,7 @@ class NonexistentInput(BadTxTemplate):
class SpendTooMuch(BadTxTemplate):
reject_reason = 'bad-txns-in-belowout'
expect_disconnect = True
expect_disconnect = False
def get_tx(self):
return create_tx_with_script(
@@ -197,7 +197,7 @@ class SpendTooMuch(BadTxTemplate):
class CreateNegative(BadTxTemplate):
reject_reason = 'bad-txns-vout-negative'
expect_disconnect = True
expect_disconnect = False
def get_tx(self):
return create_tx_with_script(self.spend_tx, 0, amount=-1)
@@ -205,7 +205,7 @@ class CreateNegative(BadTxTemplate):
class CreateTooLarge(BadTxTemplate):
reject_reason = 'bad-txns-vout-toolarge'
expect_disconnect = True
expect_disconnect = False
def get_tx(self):
return create_tx_with_script(self.spend_tx, 0, amount=MAX_MONEY + 1)
@@ -213,7 +213,7 @@ class CreateTooLarge(BadTxTemplate):
class CreateSumTooLarge(BadTxTemplate):
reject_reason = 'bad-txns-txouttotal-toolarge'
expect_disconnect = True
expect_disconnect = False
def get_tx(self):
tx = create_tx_with_script(self.spend_tx, 0, amount=MAX_MONEY)
@@ -224,7 +224,7 @@ class CreateSumTooLarge(BadTxTemplate):
class InvalidOPIFConstruction(BadTxTemplate):
reject_reason = "mandatory-script-verify-flag-failed (Invalid OP_IF construction)"
expect_disconnect = True
expect_disconnect = False
valid_in_block = True
def get_tx(self):
@@ -266,7 +266,7 @@ def getDisabledOpcodeTemplate(opcode):
class NonStandardAndInvalid(BadTxTemplate):
"""A non-standard transaction which is also consensus-invalid should return the consensus error."""
reject_reason = "mandatory-script-verify-flag-failed (OP_RETURN was encountered)"
expect_disconnect = True
expect_disconnect = False
valid_in_block = False
def get_tx(self):

View File

@@ -73,7 +73,7 @@ class InvalidTxRequestTest(BitcoinTestFramework):
tx = template.get_tx()
node.p2ps[0].send_txs_and_test(
[tx], node, success=False,
expect_disconnect=template.expect_disconnect,
expect_disconnect=False,
reject_reason=template.reject_reason,
)
@@ -144,7 +144,6 @@ class InvalidTxRequestTest(BitcoinTestFramework):
# tx_orphan_2_no_fee, because it has too low fee (p2ps[0] is not disconnected for relaying that tx)
# tx_orphan_2_invalid, because it has negative fee (p2ps[1] is disconnected for relaying that tx)
self.wait_until(lambda: 1 == len(node.getpeerinfo()), timeout=12) # p2ps[1] is no longer connected
assert_equal(expected_mempool, set(node.getrawmempool()))
self.log.info('Test orphan pool overflow')
@@ -165,7 +164,7 @@ class InvalidTxRequestTest(BitcoinTestFramework):
node.p2ps[0].send_txs_and_test([rejected_parent], node, success=False)
self.log.info('Test that a peer disconnection causes erase its transactions from the orphan pool')
with node.assert_debug_log(['Erased 100 orphan transaction(s) from peer=26']):
with node.assert_debug_log(['Erased 100 orphan transaction(s) from peer=']):
self.reconnect_p2p(num_connections=1)
self.log.info('Test that a transaction in the orphan pool is included in a new tip block causes erase this transaction from the orphan pool')

View File

@@ -251,8 +251,10 @@ class PackageRelayTest(BitcoinTestFramework):
assert tx_orphan_bad_wit.rehash() not in node_mempool
# 5. Have the other peer send the tx too, so that tx_orphan_bad_wit package is attempted.
bad_orphan_sender.send_message(msg_tx(low_fee_parent["tx"]))
bad_orphan_sender.wait_for_disconnect()
bad_orphan_sender.send_and_ping(msg_tx(low_fee_parent["tx"]))
# The bad orphan sender should not be disconnected.
bad_orphan_sender.sync_with_ping()
# The peer that didn't provide the orphan should not be disconnected.
parent_sender.sync_with_ping()