Skip to content

Commit ccd6647

Browse files
authored
Merge pull request ethereum#619 from carver/header-skipping-unification
Header skipping unification
2 parents 7870760 + 8486aaa commit ccd6647

File tree

2 files changed

+32
-36
lines changed

2 files changed

+32
-36
lines changed

trinity/_utils/headers.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,28 @@ async def _skip_complete_headers_iterator(
7575
the remaining headers.
7676
"""
7777
iter_headers = iter(headers)
78+
# for logging:
79+
first_discarded = None
80+
last_discarded = None
81+
num_discarded = 0
7882
for header in iter_headers:
7983
is_present = await completion_check(header)
8084
if is_present:
81-
logger.debug("Discarding header that we already have: %s", header)
85+
if first_discarded is None:
86+
first_discarded = header
87+
else:
88+
last_discarded = header
89+
num_discarded += 1
8290
else:
8391
yield header
8492
break
8593

94+
logger.debug(
95+
"Discarding %d headers that we already have: %s...%s",
96+
num_discarded,
97+
first_discarded,
98+
last_discarded,
99+
)
100+
86101
for header in iter_headers:
87102
yield header

trinity/sync/common/chain.py

Lines changed: 16 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@
4141
BaseService,
4242
)
4343

44+
from trinity._utils.headers import (
45+
skip_complete_headers,
46+
)
4447
from trinity.chains.base import BaseAsyncChain
4548
from trinity.db.eth1.header import BaseAsyncHeaderDB
4649
from trinity.protocol.common.peer import (
@@ -109,7 +112,7 @@ async def next_header_batch(self) -> AsyncIterator[Tuple[BlockHeader, ...]]:
109112
# When we start the sync with a peer, we always request up to MAX_REORG_DEPTH extra
110113
# headers before our current head's number, in case there were chain reorgs since the last
111114
# time _sync() was called. All of the extra headers that are already present in our DB
112-
# will be discarded by _fetch_missing_headers() so we don't unnecessarily process them
115+
# will be discarded by skip_complete_headers() so we don't unnecessarily process them
113116
# again.
114117
start_at = max(GENESIS_BLOCK_NUMBER + 1, head.block_number - MAX_REORG_DEPTH)
115118
while self.is_operational:
@@ -121,12 +124,10 @@ async def next_header_batch(self) -> AsyncIterator[Tuple[BlockHeader, ...]]:
121124
all_headers = await self.wait(self._request_headers(peer, start_at))
122125
if last_received_header is None:
123126
# Skip over existing headers on the first run-through
124-
headers = tuple(
125-
# The inner list comprehension is needed because async_generators
126-
# cannot be cast to a tuple.
127-
[header async for header in self._get_missing_tail(all_headers)]
127+
new_headers = await self.wait(
128+
skip_complete_headers(all_headers, self.logger, self.db.coro_header_exists)
128129
)
129-
if len(headers) == 0 and len(all_headers) > 0:
130+
if len(new_headers) == 0 and len(all_headers) > 0:
130131
head = await self.wait(self.db.coro_get_canonical_head())
131132
start_at = max(
132133
all_headers[-1].block_number + 1,
@@ -140,8 +141,8 @@ async def next_header_batch(self) -> AsyncIterator[Tuple[BlockHeader, ...]]:
140141
)
141142
continue
142143
else:
143-
headers = all_headers
144-
self.logger.debug2('sync received new headers: %s', headers)
144+
new_headers = all_headers
145+
self.logger.debug2('sync received new headers: %s', new_headers)
145146
except OperationCancelled:
146147
self.logger.info("Sync with %s completed", peer)
147148
break
@@ -157,7 +158,7 @@ async def next_header_batch(self) -> AsyncIterator[Tuple[BlockHeader, ...]]:
157158
await peer.disconnect(DisconnectReason.useless_peer)
158159
break
159160

160-
if not headers:
161+
if not new_headers:
161162
if last_received_header is None:
162163
request_parent = head
163164
else:
@@ -177,7 +178,7 @@ async def next_header_batch(self) -> AsyncIterator[Tuple[BlockHeader, ...]]:
177178
self.logger.info("Got no new headers from %s, aborting sync", peer)
178179
break
179180

180-
first = headers[0]
181+
first = new_headers[0]
181182
first_parent = None
182183
if last_received_header is None:
183184
# on the first request, make sure that the earliest ancestor has a parent in our db
@@ -205,27 +206,27 @@ async def next_header_batch(self) -> AsyncIterator[Tuple[BlockHeader, ...]]:
205206
"Got new header chain from %s: %s..%s",
206207
peer,
207208
first,
208-
headers[-1],
209+
new_headers[-1],
209210
)
210211
try:
211212
await self.chain.coro_validate_chain(
212213
last_received_header or first_parent,
213-
headers,
214+
new_headers,
214215
self._seal_check_random_sample_rate,
215216
)
216217
except ValidationError as e:
217218
self.logger.warning("Received invalid headers from %s, disconnecting: %s", peer, e)
218219
await peer.disconnect(DisconnectReason.subprotocol_error)
219220
break
220221

221-
for header in headers:
222+
for header in new_headers:
222223
head_td += header.difficulty
223224

224225
# Setting the latest header hash for the peer, before queuing header processing tasks
225226
self._target_header_hash = peer.head_hash
226227

227-
yield headers
228-
last_received_header = headers[-1]
228+
yield new_headers
229+
last_received_header = new_headers[-1]
229230
self.sync_progress = self.sync_progress.update_current_block(
230231
last_received_header.block_number,
231232
)
@@ -243,26 +244,6 @@ async def _request_headers(
243244
reverse=False,
244245
)
245246

246-
async def _get_missing_tail(
247-
self,
248-
headers: Tuple[BlockHeader, ...]) -> AsyncIterator[BlockHeader]:
249-
"""
250-
We only want headers that are missing, so we iterate over the list
251-
until we find the first missing header, after which we return all of
252-
the remaining headers.
253-
"""
254-
iter_headers = iter(headers)
255-
for header in iter_headers:
256-
is_present = await self.wait(self.db.coro_header_exists(header.hash))
257-
if is_present:
258-
self.logger.debug("Discarding header that we already have: %s", header)
259-
else:
260-
yield header
261-
break
262-
263-
for header in iter_headers:
264-
yield header
265-
266247

267248
class BaseBlockImporter(ABC):
268249
@abstractmethod

0 commit comments

Comments
 (0)