diff --git a/tests/core/utils/test_root_tracker.py b/tests/core/utils/test_root_tracker.py index 9115367a3a..a11e825b17 100644 --- a/tests/core/utils/test_root_tracker.py +++ b/tests/core/utils/test_root_tracker.py @@ -114,7 +114,6 @@ def binary_parent(node): st.integers(min_value=0, max_value=6), min_size=3, )) -#@settings(max_examples=20000) def test_prune_reinsert_root_tracking_binary_tree(element_flipping): tracker = RootTracker() diff --git a/trinity/sync/common/headers.py b/trinity/sync/common/headers.py index 382069387c..698ea7896a 100644 --- a/trinity/sync/common/headers.py +++ b/trinity/sync/common/headers.py @@ -492,6 +492,17 @@ async def new_sync_headers( if False: yield + @abstractmethod + async def clear_buffer(self) -> None: + """ + Whatever headers have been received until now, dump them all and restart. + This is a last resort, to be used only when a consumer seems to receive + headers out of other and decides they have no other option besides reset. + + It wastes a lot of previously completed work. + """ + pass + @abstractmethod def get_target_header_hash(self) -> Hash32: pass diff --git a/trinity/sync/full/chain.py b/trinity/sync/full/chain.py index 80365010c8..228a96ef67 100644 --- a/trinity/sync/full/chain.py +++ b/trinity/sync/full/chain.py @@ -456,7 +456,10 @@ async def _launch_prerequisite_tasks(self) -> None: tasks as they become available. """ get_headers_coro = self._header_syncer.new_sync_headers(HEADER_QUEUE_SIZE_TARGET) + + # Track the highest registered block header by number, purely for stats/logging highest_block_num = -1 + async for headers in self.wait_iter(get_headers_coro): try: # We might end up with duplicates that can be safely ignored. @@ -477,9 +480,12 @@ async def _launch_prerequisite_tasks(self) -> None: self.db.coro_get_block_header_by_hash(headers[0].parent_hash) ) except HeaderNotFound: - await self._log_header_link_failure(headers[0], highest_block_num) + await self._log_missing_parent(headers[0], highest_block_num) + + # Nowhere to go from here, reset and try again await self._header_syncer.clear_buffer() - # wait for new headers to come back in from a restarted skeleton sync + + # Don't try to process `headers`, wait for new ones to come in continue # This appears to be a fork, since the parent header is persisted, @@ -510,7 +516,7 @@ async def _launch_prerequisite_tasks(self) -> None: highest_block_num = max(headers[-1].block_number, highest_block_num) - async def _log_header_link_failure(self, first_header: BlockHeader, highest_block_num) -> None: + async def _log_missing_parent(self, first_header: BlockHeader, highest_block_num: int) -> None: self.logger.warning("Parent missing for header %r, restarting header sync", first_header) block_num = first_header.block_number try: