Beispiel #1
0
 async def get_sync_start_block(self, peer: LESPeer,
                                head_info: les.HeadInfo) -> int:
     chain_head = await self.headerdb.coro_get_canonical_head()
     last_peer_announcement = self._last_processed_announcements.get(peer)
     if chain_head.block_number == GENESIS_BLOCK_NUMBER:
         start_block = GENESIS_BLOCK_NUMBER
     elif last_peer_announcement is None:
         # It's the first time we hear from this peer, need to figure out which headers to
         # get from it.  We can't simply fetch headers starting from our current head
         # number because there may have been a chain reorg, so we fetch some headers prior
         # to our head from the peer, and insert any missing ones in our DB, essentially
         # making our canonical chain identical to the peer's up to
         # chain_head.block_number.
         oldest_ancestor_to_consider = max(
             0, chain_head.block_number - peer.max_headers_fetch + 1)
         try:
             headers = await self.fetch_headers(oldest_ancestor_to_consider,
                                                peer)
         except EmptyGetBlockHeadersReply:
             raise LESAnnouncementProcessingError(
                 "No common ancestors found between us and {}".format(peer))
         except TooManyTimeouts:
             raise LESAnnouncementProcessingError(
                 "Too many timeouts when fetching headers from {}".format(
                     peer))
         for header in headers:
             await self.headerdb.coro_persist_header(header)
         start_block = chain_head.block_number
     else:
         start_block = last_peer_announcement.block_number - head_info.reorg_depth
     return start_block
Beispiel #2
0
 async def _import_headers_from_peer(self, headers, peer):
     """
     :return: the block number of the new tip after importing the header
     """
     new_tip = None
     for header in headers:
         try:
             await self._validate_header(header)
         except ValidationError as exc:
             raise LESAnnouncementProcessingError("Peer {} sent invalid header {}: {}".format(
                 peer,
                 header,
                 exc,
             ))
         else:
             await self.wait(self.headerdb.coro_persist_header(header))
             new_tip = header.block_number
     return new_tip
Beispiel #3
0
    async def process_announcement(self, peer: LESPeer, head_info: les.HeadInfo) -> None:
        if await self.chaindb.coro_header_exists(head_info.block_hash):
            self.logger.debug(
                "Skipping processing of %s from %s as head has already been fetched",
                head_info, peer)
            return

        start_block = await self.get_sync_start_block(peer, head_info)
        while start_block < head_info.block_number:
            try:
                # We should use "start_block + 1" here, but we always re-fetch the last synced
                # block to work around https://github.com/ethereum/go-ethereum/issues/15447
                batch = await self.fetch_headers(start_block, peer)
            except TooManyTimeouts:
                raise LESAnnouncementProcessingError(
                    "Too many timeouts when fetching headers from {}".format(peer))
            for header in batch:
                await self.chaindb.coro_persist_header(header)
                start_block = header.block_number
            self.logger.info("synced headers up to #%s", start_block)