Skip to content

Commit 96c64ec

Browse files
committed
test: add case for full askfor set.
1 parent d495d27 commit 96c64ec

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

test/functional/p2p_invalid_messages.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,13 @@
1212
P2PDataStore,
1313
P2PInterface,
1414
)
15+
from test_framework.messages import CTxIn, COutPoint, msg_mnping
1516
from test_framework.test_framework import PivxTestFramework
1617
from test_framework.util import (
18+
assert_equal,
1719
hex_str_to_bytes,
1820
)
21+
from random import getrandbits
1922

2023
MSG_LIMIT = 2 * 1024 * 1024 # 2MB, per MAX_PROTOCOL_MESSAGE_LENGTH
2124
VALID_DATA_LIMIT = MSG_LIMIT - 5 # Account for the 5-byte length prefix
@@ -39,6 +42,19 @@ class SenderOfAddrV2(P2PInterface):
3942
def wait_for_sendaddrv2(self):
4043
self.wait_until(lambda: 'sendaddrv2' in self.last_message)
4144

45+
class InvReceiver(P2PInterface):
46+
47+
def __init__(self):
48+
super().__init__()
49+
self.vec_mnp = {}
50+
self.getdata_count = 0
51+
52+
def on_getdata(self, message):
53+
for inv in message.inv:
54+
if inv.type == 15: # MNPING
55+
self.send_message(self.vec_mnp[inv.hash])
56+
self.getdata_count+=1
57+
4258
class InvalidMessagesTest(PivxTestFramework):
4359
def set_test_params(self):
4460
self.num_nodes = 1
@@ -55,6 +71,7 @@ def run_test(self):
5571
self.test_addrv2_unrecognized_network()
5672
self.test_large_inv()
5773
self.test_resource_exhaustion()
74+
self.test_fill_askfor()
5875

5976
def test_magic_bytes(self):
6077
conn = self.nodes[0].add_p2p_connection(P2PDataStore())
@@ -187,6 +204,33 @@ def test_large_inv(self):
187204
conn.send_and_ping(msg)
188205
self.nodes[0].disconnect_p2ps()
189206

207+
def test_fill_askfor(self):
208+
self.nodes[0].generate(1) # IBD
209+
conn = self.nodes[0].add_p2p_connection(InvReceiver())
210+
invs = []
211+
blockhash = int(self.nodes[0].getbestblockhash(), 16)
212+
for _ in range(50000):
213+
mnp = msg_mnping(CTxIn(COutPoint(getrandbits(256))), blockhash, int(time.time()))
214+
conn.vec_mnp[mnp.get_hash()] = mnp
215+
invs.append(messages.CInv(15, mnp.get_hash()))
216+
assert_equal(len(conn.vec_mnp), 50000)
217+
assert_equal(len(invs), 50000)
218+
msg = messages.msg_inv(invs)
219+
conn.send_message(msg)
220+
221+
time.sleep(20) # wait a bit
222+
assert_equal(conn.getdata_count, 50000)
223+
224+
# Prior #2611 the node was blocking any follow-up request.
225+
mnp = msg_mnping(CTxIn(COutPoint(getrandbits(256))), getrandbits(256), int(time.time()))
226+
conn.vec_mnp[mnp.get_hash()] = mnp
227+
msg = messages.msg_inv([messages.CInv(15, mnp.get_hash())])
228+
conn.send_and_ping(msg)
229+
time.sleep(3)
230+
231+
assert_equal(conn.getdata_count, 50001)
232+
self.nodes[0].disconnect_p2ps()
233+
190234
def test_resource_exhaustion(self):
191235
conn = self.nodes[0].add_p2p_connection(P2PDataStore())
192236
conn2 = self.nodes[0].add_p2p_connection(P2PDataStore())

test/functional/test_framework/messages.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,6 +1149,41 @@ def __repr__(self):
11491149
return "msg_getblocks(locator=%s hashstop=%064x)" \
11501150
% (repr(self.locator), self.hashstop)
11511151

1152+
class msg_mnping:
1153+
command = b"mnp"
1154+
1155+
def __init__(self, _vin, _blockhash, _sigtime):
1156+
self.vin = _vin
1157+
self.blockhash = _blockhash
1158+
self.sigtime = _sigtime
1159+
self.vch_sig = b""
1160+
self.mess_version = 1
1161+
self.cached_hash = b""
1162+
1163+
def deserialize(self, f):
1164+
self.vin.deserialize(f)
1165+
self.blockhash = deser_uint256(f)
1166+
self.sigtime = struct.unpack("<q", f.read(8))[0]
1167+
self.vch_sig = deser_string(f)
1168+
self.mess_version = struct.unpack("<i", f.read(4))[0]
1169+
1170+
def serialize(self):
1171+
r = b""
1172+
r += self.vin.serialize()
1173+
r += ser_uint256(self.blockhash)
1174+
r += struct.pack("<q", self.sigtime)
1175+
r += ser_string(self.vch_sig)
1176+
r += struct.pack("<I", self.mess_version)
1177+
return r
1178+
1179+
def get_hash(self):
1180+
if self.cached_hash == b"":
1181+
self.cached_hash = uint256_from_str(hash256(self.serialize()))
1182+
return self.cached_hash
1183+
1184+
def __repr__(self):
1185+
return "msg_mnping(vin=%s blockhash=%064x)" \
1186+
% (repr(self.vin), self.blockhash)
11521187

11531188
class msg_tx:
11541189
command = b"tx"

0 commit comments

Comments
 (0)