Skip to content

Commit 0c577f2

Browse files
committed
Merge #8872: Remove block-request logic from INV message processing
037159c Remove block-request logic from INV message processing (Matt Corallo) 3451203 [qa] Respond to getheaders and do not assume a getdata on inv (Matt Corallo) d768f15 [qa] Make comptool push blocks instead of relying on inv-fetch (mrbandrews)
2 parents 2108911 + 037159c commit 0c577f2

File tree

5 files changed

+46
-31
lines changed

5 files changed

+46
-31
lines changed

qa/rpc-tests/p2p-compactblocks.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ def __init__(self):
2727
self.last_cmpctblock = None
2828
self.block_announced = False
2929
self.last_getdata = None
30+
self.last_getheaders = None
3031
self.last_getblocktxn = None
3132
self.last_block = None
3233
self.last_blocktxn = None
@@ -64,6 +65,9 @@ def on_inv(self, conn, message):
6465
def on_getdata(self, conn, message):
6566
self.last_getdata = message
6667

68+
def on_getheaders(self, conn, message):
69+
self.last_getheaders = message
70+
6771
def on_getblocktxn(self, conn, message):
6872
self.last_getblocktxn = message
6973

@@ -396,6 +400,9 @@ def test_compactblock_requests(self, node, test_node, version, segwit):
396400

397401
if announce == "inv":
398402
test_node.send_message(msg_inv([CInv(2, block.sha256)]))
403+
success = wait_until(lambda: test_node.last_getheaders is not None, timeout=30)
404+
assert(success)
405+
test_node.send_header_for_blocks([block])
399406
else:
400407
test_node.send_header_for_blocks([block])
401408
success = wait_until(lambda: test_node.last_getdata is not None, timeout=30)

qa/rpc-tests/p2p-segwit.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ def on_getdata(self, conn, message):
6464
self.getdataset.add(inv.hash)
6565
self.last_getdata = message
6666

67+
def on_getheaders(self, conn, message):
68+
self.last_getheaders = message
69+
6770
def on_pong(self, conn, message):
6871
self.last_pong = message
6972

@@ -97,6 +100,10 @@ def wait_for_getdata(self, timeout=60):
97100
test_function = lambda: self.last_getdata != None
98101
self.sync(test_function, timeout)
99102

103+
def wait_for_getheaders(self, timeout=60):
104+
test_function = lambda: self.last_getheaders != None
105+
self.sync(test_function, timeout)
106+
100107
def wait_for_inv(self, expected_inv, timeout=60):
101108
test_function = lambda: self.last_inv != expected_inv
102109
self.sync(test_function, timeout)
@@ -111,12 +118,15 @@ def announce_tx_and_wait_for_getdata(self, tx, timeout=60):
111118
def announce_block_and_wait_for_getdata(self, block, use_header, timeout=60):
112119
with mininode_lock:
113120
self.last_getdata = None
121+
self.last_getheaders = None
122+
msg = msg_headers()
123+
msg.headers = [ CBlockHeader(block) ]
114124
if use_header:
115-
msg = msg_headers()
116-
msg.headers = [ CBlockHeader(block) ]
117125
self.send_message(msg)
118126
else:
119127
self.send_message(msg_inv(inv=[CInv(2, block.sha256)]))
128+
self.wait_for_getheaders()
129+
self.send_message(msg)
120130
self.wait_for_getdata()
121131
return
122132

qa/rpc-tests/sendheaders.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -348,14 +348,13 @@ def run_test(self):
348348
if j == 0:
349349
# Announce via inv
350350
test_node.send_block_inv(tip)
351-
test_node.wait_for_getdata([tip], timeout=5)
351+
test_node.wait_for_getheaders(timeout=5)
352+
# Should have received a getheaders now
353+
test_node.send_header_for_blocks(blocks)
352354
# Test that duplicate inv's won't result in duplicate
353355
# getdata requests, or duplicate headers announcements
354-
inv_node.send_block_inv(tip)
355-
# Should have received a getheaders as well!
356-
test_node.send_header_for_blocks(blocks)
357-
test_node.wait_for_getdata([x.sha256 for x in blocks[0:-1]], timeout=5)
358-
[ inv_node.send_block_inv(x.sha256) for x in blocks[0:-1] ]
356+
[ inv_node.send_block_inv(x.sha256) for x in blocks ]
357+
test_node.wait_for_getdata([x.sha256 for x in blocks], timeout=5)
359358
inv_node.sync_with_ping()
360359
else:
361360
# Announce via headers

qa/rpc-tests/test_framework/comptool.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ def send_getheaders(self):
111111
m.locator = self.block_store.get_locator(self.bestblockhash)
112112
self.conn.send_message(m)
113113

114+
def send_header(self, header):
115+
m = msg_headers()
116+
m.headers.append(header)
117+
self.conn.send_message(m)
118+
114119
# This assumes BIP31
115120
def send_ping(self, nonce):
116121
self.pingMap[nonce] = True
@@ -345,15 +350,25 @@ def run(self):
345350
# Either send inv's to each node and sync, or add
346351
# to invqueue for later inv'ing.
347352
if (test_instance.sync_every_block):
348-
[ c.cb.send_inv(block) for c in self.connections ]
349-
self.sync_blocks(block.sha256, 1)
353+
# if we expect success, send inv and sync every block
354+
# if we expect failure, just push the block and see what happens.
355+
if outcome == True:
356+
[ c.cb.send_inv(block) for c in self.connections ]
357+
self.sync_blocks(block.sha256, 1)
358+
else:
359+
[ c.send_message(msg_block(block)) for c in self.connections ]
360+
[ c.cb.send_ping(self.ping_counter) for c in self.connections ]
361+
self.wait_for_pings(self.ping_counter)
362+
self.ping_counter += 1
350363
if (not self.check_results(tip, outcome)):
351364
raise AssertionError("Test failed at test %d" % test_number)
352365
else:
353366
invqueue.append(CInv(2, block.sha256))
354367
elif isinstance(b_or_t, CBlockHeader):
355368
block_header = b_or_t
356369
self.block_store.add_header(block_header)
370+
[ c.cb.send_header(block_header) for c in self.connections ]
371+
357372
else: # Tx test runner
358373
assert(isinstance(b_or_t, CTransaction))
359374
tx = b_or_t

src/main.cpp

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5370,28 +5370,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
53705370
if (inv.type == MSG_BLOCK) {
53715371
UpdateBlockAvailability(pfrom->GetId(), inv.hash);
53725372
if (!fAlreadyHave && !fImporting && !fReindex && !mapBlocksInFlight.count(inv.hash)) {
5373-
// First request the headers preceding the announced block. In the normal fully-synced
5374-
// case where a new block is announced that succeeds the current tip (no reorganization),
5375-
// there are no such headers.
5376-
// Secondly, and only when we are close to being synced, we request the announced block directly,
5377-
// to avoid an extra round-trip. Note that we must *first* ask for the headers, so by the
5378-
// time the block arrives, the header chain leading up to it is already validated. Not
5379-
// doing this will result in the received block being rejected as an orphan in case it is
5380-
// not a direct successor.
5373+
// We used to request the full block here, but since headers-announcements are now the
5374+
// primary method of announcement on the network, and since, in the case that a node
5375+
// fell back to inv we probably have a reorg which we should get the headers for first,
5376+
// we now only provide a getheaders response here. When we receive the headers, we will
5377+
// then ask for the blocks we need.
53815378
connman.PushMessage(pfrom, NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), inv.hash);
5382-
CNodeState *nodestate = State(pfrom->GetId());
5383-
if (CanDirectFetch(chainparams.GetConsensus()) &&
5384-
nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER &&
5385-
(!IsWitnessEnabled(chainActive.Tip(), chainparams.GetConsensus()) || State(pfrom->GetId())->fHaveWitness)) {
5386-
inv.type |= nFetchFlags;
5387-
if (nodestate->fSupportsDesiredCmpctVersion)
5388-
vToFetch.push_back(CInv(MSG_CMPCT_BLOCK, inv.hash));
5389-
else
5390-
vToFetch.push_back(inv);
5391-
// Mark block as in flight already, even though the actual "getdata" message only goes out
5392-
// later (within the same cs_main lock, though).
5393-
MarkBlockAsInFlight(pfrom->GetId(), inv.hash, chainparams.GetConsensus());
5394-
}
53955379
LogPrint("net", "getheaders (%d) %s to peer=%d\n", pindexBestHeader->nHeight, inv.hash.ToString(), pfrom->id);
53965380
}
53975381
}

0 commit comments

Comments
 (0)