Example #1
0
    async def ensure_same_side_on_dao_fork(self) -> None:
        """Ensure we're on the same side of the DAO fork as the given peer.

        In order to do that we have to request the DAO fork block and its parent, but while we
        wait for that we may receive other messages from the peer, which are returned so that they
        can be re-added to our subscribers' queues when the peer is finally added to the pool.
        """
        for start_block, vm_class in self.peer.context.vm_configuration:
            if not issubclass(vm_class, HomesteadVM):
                continue
            elif not vm_class.support_dao_fork:
                break
            elif start_block > vm_class.get_dao_fork_block_number():
                # VM comes after the fork, so stop checking
                break

            dao_fork_num = vm_class.get_dao_fork_block_number()
            start_block = cast(BlockNumber, dao_fork_num - 1)

            try:
                headers = await self.peer.chain_api.get_block_headers(
                    start_block,
                    max_headers=2,
                    reverse=False,
                    timeout=CHAIN_SPLIT_CHECK_TIMEOUT,
                )

            except (asyncio.TimeoutError, PeerConnectionLost) as err:
                raise DAOForkCheckFailure(
                    f"Timed out waiting for DAO fork header from {self.peer}: {err}"
                ) from err
            except ValidationError as err:
                raise DAOForkCheckFailure(
                    f"Invalid header response during DAO fork check: {err}"
                ) from err

            if len(headers) != 2:
                tip_header = await self._get_tip_header()
                if tip_header.block_number < dao_fork_num:
                    self.logger.debug(
                        f"{self.peer} has tip {tip_header!r}, and returned {headers!r} "
                        "at DAO fork #{dao_fork_num}. Peer seems to be syncing..."
                    )
                    return
                else:
                    raise DAOForkCheckFailure(
                        f"{self.peer} has tip {tip_header!r}, but only returned {headers!r} "
                        "at DAO fork #{dao_fork_num}. Peer seems to be witholding DAO headers..."
                    )
            else:
                parent, header = headers

            try:
                vm_class.validate_header(header, parent, check_seal=True)
            except ValidationError as err:
                raise DAOForkCheckFailure(
                    f"{self.peer} failed DAO fork check validation: {err}")
Example #2
0
    async def validate_remote_dao_fork_block(self) -> None:
        for start_block, vm_class in self.peer.context.vm_configuration:
            if not issubclass(vm_class, HomesteadVM):
                continue
            elif not vm_class.support_dao_fork:
                break
            elif start_block > vm_class.get_dao_fork_block_number():
                # VM comes after the fork, so stop checking
                break

            dao_fork_num = vm_class.get_dao_fork_block_number()
            start_block = cast(BlockNumber, dao_fork_num - 1)

            try:
                headers = await self.peer.chain_api.get_block_headers(
                    start_block,
                    max_headers=2,
                    reverse=False,
                    timeout=CHAIN_SPLIT_CHECK_TIMEOUT,
                )

            except (asyncio.TimeoutError, PeerConnectionLost) as err:
                raise DAOForkCheckFailure(
                    f"Timed out waiting for DAO fork header from {self.peer}: {err}"
                ) from err
            except ValidationError as err:
                raise DAOForkCheckFailure(
                    f"Invalid header response during DAO fork check: {err}"
                ) from err

            if len(headers) != 2:
                tip_header = await self._get_tip_header()
                if tip_header.block_number < dao_fork_num:
                    self.logger.debug(
                        f"{self.peer} has tip {tip_header!r}, and returned {headers!r} "
                        "at DAO fork #{dao_fork_num}. Peer seems to be syncing..."
                    )
                    return
                else:
                    raise DAOForkCheckFailure(
                        f"{self.peer} has tip {tip_header!r}, but only returned {headers!r} "
                        "at DAO fork #{dao_fork_num}. Peer seems to be witholding DAO headers..."
                    )
            else:
                parent, header = headers

            try:
                vm_class.validate_header(header, parent)
            except ValidationError as err:
                raise DAOForkCheckFailure(
                    f"{self.peer} failed DAO fork check validation: {err}")
Example #3
0
    async def ensure_same_side_on_dao_fork(self) -> None:
        """Ensure we're on the same side of the DAO fork as the given peer.

        In order to do that we have to request the DAO fork block and its parent, but while we
        wait for that we may receive other messages from the peer, which are returned so that they
        can be re-added to our subscribers' queues when the peer is finally added to the pool.
        """
        for start_block, vm_class in self.peer.context.vm_configuration:
            if not issubclass(vm_class, HomesteadVM):
                continue
            elif not vm_class.support_dao_fork:
                break
            elif start_block > vm_class.get_dao_fork_block_number():
                # VM comes after the fork, so stop checking
                break

            start_block = vm_class.get_dao_fork_block_number() - 1

            try:
                headers = await self.peer.requests.get_block_headers(  # type: ignore
                    start_block,
                    max_headers=2,
                    reverse=False,
                    timeout=CHAIN_SPLIT_CHECK_TIMEOUT,
                )

            except (TimeoutError, PeerConnectionLost) as err:
                raise DAOForkCheckFailure(
                    f"Timed out waiting for DAO fork header from {self.peer}: {err}"
                ) from err
            except ValidationError as err:
                raise DAOForkCheckFailure(
                    f"Invalid header response during DAO fork check: {err}"
                ) from err

            if len(headers) != 2:
                raise DAOForkCheckFailure(
                    f"{self.peer} failed to return DAO fork check headers")
            else:
                parent, header = headers

            try:
                vm_class.validate_header(header, parent, check_seal=True)
            except ValidationError as err:
                raise DAOForkCheckFailure(
                    f"{self.peer} failed DAO fork check validation: {err}")
Example #4
0
    async def _get_tip_header(self) -> BlockHeader:
        try:
            headers = await self.peer.chain_api.get_block_headers(
                self.peer.head_info.head_hash,
                max_headers=1,
                timeout=CHAIN_SPLIT_CHECK_TIMEOUT,
            )

        except (asyncio.TimeoutError, PeerConnectionLost) as err:
            raise DAOForkCheckFailure(
                f"Timed out waiting for tip header from {self.peer}: {err}"
            ) from err
        except ValidationError as err:
            raise DAOForkCheckFailure(
                f"Invalid header response for tip header during DAO fork check: {err}"
            ) from err
        else:
            if len(headers) != 1:
                raise DAOForkCheckFailure(
                    f"{self.peer} returned {headers!r} when asked for tip")
            else:
                return headers[0]