Skip to content

Commit 1404e68

Browse files
committed
test: Add various low-level p2p tests
Adaptation of btc@fa4c29bc1d2425f861845bae4f3816d9817e622a with some needed customizations for us.
1 parent 8aaf7e1 commit 1404e68

File tree

3 files changed

+46
-17
lines changed

3 files changed

+46
-17
lines changed

src/net_processing.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,7 +1352,7 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR
13521352
if (vInv.size() > MAX_INV_SZ) {
13531353
LOCK(cs_main);
13541354
Misbehaving(pfrom->GetId(), 20);
1355-
return error("message inv size() = %u", vInv.size());
1355+
return error("peer=%d message inv size() = %u", pfrom->GetId(), vInv.size());
13561356
}
13571357

13581358
LOCK(cs_main);
@@ -1402,7 +1402,7 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR
14021402
if (vInv.size() > MAX_INV_SZ) {
14031403
LOCK(cs_main);
14041404
Misbehaving(pfrom->GetId(), 20);
1405-
return error("message getdata size() = %u", vInv.size());
1405+
return error("peer=%d message getdata size() = %u", pfrom->GetId(), vInv.size());
14061406
}
14071407

14081408
if (vInv.size() != 1)
@@ -2021,7 +2021,7 @@ bool ProcessMessages(CNode* pfrom, CConnman& connman, std::atomic<bool>& interru
20212021
// Read header
20222022
CMessageHeader& hdr = msg.hdr;
20232023
if (!hdr.IsValid(Params().MessageStart())) {
2024-
LogPrint(BCLog::NET, "PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->id);
2024+
LogPrint(BCLog::NET, "PROCESSMESSAGE: ERRORS IN HEADER '%s' peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->id);
20252025
return fMoreWork;
20262026
}
20272027
std::string strCommand = hdr.GetCommand();

test/functional/p2p_invalid_messages.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@
88
import sys
99

1010
from test_framework import messages
11-
from test_framework.mininode import P2PDataStore, NetworkThread
11+
from test_framework.mininode import (
12+
NetworkThread,
13+
P2PDataStore,
14+
P2PInterface,
15+
)
1216
from test_framework.test_framework import PivxTestFramework
1317

1418

@@ -47,6 +51,7 @@ def run_test(self):
4751
self.test_checksum()
4852
self.test_size()
4953
self.test_command()
54+
self.test_large_inv()
5055

5156
node = self.nodes[0]
5257
self.node = node
@@ -199,6 +204,16 @@ def test_command(self):
199204
conn.sync_with_ping(timeout=1)
200205
self.nodes[0].disconnect_p2ps()
201206

207+
def test_large_inv(self): # future: add Misbehaving value check, first invalid message raise it to 20, second to 40.
208+
conn = self.nodes[0].add_p2p_connection(P2PInterface())
209+
with self.nodes[0].assert_debug_log(['ERROR: peer=5 message inv size() = 50001']):
210+
msg = messages.msg_inv([messages.CInv(1, 1)] * 50001)
211+
conn.send_and_ping(msg)
212+
with self.nodes[0].assert_debug_log(['ERROR: peer=5 message getdata size() = 50001']):
213+
msg = messages.msg_getdata([messages.CInv(1, 1)] * 50001)
214+
conn.send_and_ping(msg)
215+
self.nodes[0].disconnect_p2ps()
216+
202217
def _tweak_msg_data_size(self, message, wrong_size):
203218
"""
204219
Return a raw message based on another message but with an incorrect data size in

test/functional/p2p_invalid_tx.py

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@
1313
CTxIn,
1414
CTxOut,
1515
)
16-
from test_framework.mininode import P2PDataStore, network_thread_join
16+
from test_framework.mininode import P2PDataStore
1717
from test_framework.script import (
1818
CScript,
1919
OP_NOTIF,
2020
OP_TRUE,
21+
OP_DROP
2122
)
2223
from test_framework.test_framework import PivxTestFramework
2324
from test_framework.util import (
@@ -47,15 +48,11 @@ def reconnect_p2p(self, **kwargs):
4748
self.nodes[0].disconnect_p2ps()
4849
self.bootstrap_p2p(**kwargs)
4950

50-
def new_spend_tx(self, prev_hash, prev_n, values):
51-
"""Create a CTransaction spending COutPoint(prev_hash, prev_n)
52-
53-
each amount specified in the 'values' list is sent to an
54-
anyone-can-spend script"""
51+
def new_spend_tx(self, prev_hash, prev_n, tx_outs):
52+
"""Create a CTransaction spending COutPoint(prev_hash, prev_n) to the CTxOut-list tx_outs."""
5553
tx = CTransaction()
5654
tx.vin.append(CTxIn(outpoint=COutPoint(prev_hash, prev_n)))
57-
for value in values:
58-
tx.vout.append(CTxOut(nValue=value, scriptPubKey=CScript([OP_TRUE])))
55+
tx.vout = tx_outs
5956
tx.calc_sha256()
6057
return tx
6158

@@ -93,21 +90,22 @@ def run_test(self):
9390
self.reconnect_p2p(num_connections=2)
9491

9592
self.log.info('Test orphan transaction handling ... ')
93+
SCRIPT_PUB_KEY_OP_TRUE = CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])
9694
# Create a root transaction that we withhold until all dependend transactions
9795
# are sent out and in the orphan cache
98-
tx_withhold = self.new_spend_tx(block1.vtx[0].sha256, 0, [50 * COIN - 12000])
96+
tx_withhold = self.new_spend_tx(block1.vtx[0].sha256, 0, [CTxOut(nValue=50 * COIN - 12000, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE)])
9997

10098
# Our first orphan tx with 3 outputs to create further orphan txs
101-
tx_orphan_1 = self.new_spend_tx(tx_withhold.sha256, 0, [10 * COIN] * 3)
99+
tx_orphan_1 = self.new_spend_tx(tx_withhold.sha256, 0, [CTxOut(nValue=10 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE)] * 3)
102100

103101
# A valid transaction with low fee
104-
tx_orphan_2_no_fee = self.new_spend_tx(tx_orphan_1.sha256, 0, [10 * COIN])
102+
tx_orphan_2_no_fee = self.new_spend_tx(tx_orphan_1.sha256, 0, [CTxOut(nValue=10 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE)])
105103

106104
# A valid transaction with sufficient fee
107-
tx_orphan_2_valid = self.new_spend_tx(tx_orphan_1.sha256, 1, [10 * COIN - 12000])
105+
tx_orphan_2_valid = self.new_spend_tx(tx_orphan_1.sha256, 1, [CTxOut(nValue=10 * COIN - 12000, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE)])
108106

109107
# An invalid transaction with negative fee
110-
tx_orphan_2_invalid = self.new_spend_tx(tx_orphan_1.sha256, 2, [11 * COIN])
108+
tx_orphan_2_invalid = self.new_spend_tx(tx_orphan_1.sha256, 2, [CTxOut(nValue=11 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE)])
111109

112110
self.log.info('Send the orphans ... ')
113111
# Send valid orphan txs from p2ps[0]
@@ -139,6 +137,22 @@ def run_test(self):
139137
#wait_until(lambda: 1 == len(node.getpeerinfo()), timeout=12) # p2ps[1] is no longer connected
140138
assert_equal(expected_mempool, set(node.getrawmempool()))
141139

140+
self.log.info('Test orphan pool overflow')
141+
orphan_tx_pool = [CTransaction() for _ in range(101)]
142+
for i in range(len(orphan_tx_pool)):
143+
orphan_tx_pool[i].vin.append(CTxIn(outpoint=COutPoint(i, 333)))
144+
orphan_tx_pool[i].vout.append(CTxOut(nValue=11 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
145+
146+
with node.assert_debug_log(['mapOrphan overflow, removed 1 tx']):
147+
node.p2p.send_txs_and_test(orphan_tx_pool, node, success=False)
148+
149+
rejected_parent = CTransaction()
150+
rejected_parent.vin.append(CTxIn(outpoint=COutPoint(tx_orphan_2_invalid.sha256, 0)))
151+
rejected_parent.vout.append(CTxOut(nValue=11 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
152+
rejected_parent.rehash()
153+
with node.assert_debug_log(['not keeping orphan with rejected parents {}'.format(rejected_parent.hash)]):
154+
node.p2p.send_txs_and_test([rejected_parent], node, success=False)
155+
142156

143157
if __name__ == '__main__':
144158
InvalidTxRequestTest().main()

0 commit comments

Comments
 (0)