Example #1
0
File: peer.py Project: zchn/py-evm
    async def ensure_same_side_on_dao_fork(self, peer: BasePeer) -> 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.vm_configuration:
            if not issubclass(vm_class, HomesteadVM):
                continue
            elif not vm_class.support_dao_fork:
                break
            elif start_block > vm_class.dao_fork_block_number:
                # VM comes after the fork, so stop checking
                break

            start_block = vm_class.dao_fork_block_number - 1

            try:
                headers = await 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(
                    "Timed out waiting for DAO fork header from {}: {}".format(
                        peer, err)) from err
            except MalformedMessage as err:
                raise DAOForkCheckFailure(
                    "Malformed message while doing DAO fork check with {0}: {1}"
                    .format(
                        peer,
                        err,
                    )) from err
            except ValidationError as err:
                raise DAOForkCheckFailure(
                    "Invalid header response during DAO fork check: {}".format(
                        err)) from err

            if len(headers) != 2:
                raise DAOForkCheckFailure(
                    "Peer %s failed to return DAO fork check headers".format(
                        peer))
            else:
                parent, header = headers

            try:
                vm_class.validate_header(header, parent, check_seal=True)
            except EthValidationError as err:
                raise DAOForkCheckFailure(
                    "Peer failed DAO fork check validation: {}".format(err))
Example #2
0
    async def ensure_same_side_on_dao_fork(
        self, peer: BasePeer
    ) -> List[Tuple[protocol.Command, protocol._DecodedMsgType]]:
        """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.
        """
        msgs = []
        for start_block, vm_class in self.vm_configuration:
            if not issubclass(vm_class, HomesteadVM):
                continue
            elif not vm_class.support_dao_fork:
                break
            elif start_block > vm_class.dao_fork_block_number:
                # VM comes after the fork, so stop checking
                break

            start_block = vm_class.dao_fork_block_number - 1
            max_headers = 2
            reverse = False
            peer.request_block_headers(start_block, max_headers,
                                       reverse)  # type: ignore
            start = time.time()
            try:
                while True:
                    elapsed = int(time.time() - start)
                    remaining_timeout = max(
                        0, CHAIN_SPLIT_CHECK_TIMEOUT - elapsed)
                    cmd, msg = await self.wait(peer.read_msg(),
                                               timeout=remaining_timeout)
                    if isinstance(cmd, protocol.BaseBlockHeaders):
                        headers = cmd.extract_headers(msg)
                        break
                    else:
                        msgs.append((cmd, msg))
                        continue
            except (TimeoutError, PeerConnectionLost) as e:
                raise DAOForkCheckFailure(
                    "Timed out waiting for DAO fork header from {}: {}".format(
                        peer, e))

            try:
                validate_header_response(start_block, max_headers, reverse,
                                         headers)
                parent, header = headers
                vm_class.validate_header(header, parent, check_seal=True)
            except ValidationError as e:
                raise DAOForkCheckFailure(
                    "Peer failed DAO fork check validation: {}".format(e))

        return msgs
Example #3
0
    async def ensure_same_side_on_dao_fork(
        self, peer: BasePeer
    ) -> List[Tuple[protocol.Command, protocol._DecodedMsgType]]:
        """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.
        """
        from trinity.protocol.base_block_headers import BaseBlockHeaders
        msgs = []
        for start_block, vm_class in self.vm_configuration:
            if not issubclass(vm_class, HomesteadVM):
                continue
            elif not vm_class.support_dao_fork:
                break
            elif start_block > vm_class.dao_fork_block_number:
                # VM comes after the fork, so stop checking
                break

            start_block = vm_class.dao_fork_block_number - 1
            # TODO: This can be either an `ETHPeer` or an `LESPeer`.  Will be
            # fixed once full awaitable request API is completed.
            request = peer.request_block_headers(  # type: ignore
                start_block,
                max_headers=2,
                reverse=False,
            )
            start = time.time()
            try:
                while True:
                    elapsed = int(time.time() - start)
                    remaining_timeout = max(
                        0, CHAIN_SPLIT_CHECK_TIMEOUT - elapsed)
                    cmd, msg = await self.wait(peer.read_msg(),
                                               timeout=remaining_timeout)
                    if isinstance(cmd, BaseBlockHeaders):
                        headers = cmd.extract_headers(msg)
                        break
                    else:
                        msgs.append((cmd, msg))
                        continue
            except (TimeoutError, PeerConnectionLost) as err:
                raise DAOForkCheckFailure(
                    "Timed out waiting for DAO fork header from {}: {}".format(
                        peer, err))
            except MalformedMessage as err:
                raise DAOForkCheckFailure(
                    "Malformed message while doing DAO fork check with {0}: {1}"
                    .format(
                        peer,
                        err,
                    )) from err

            try:
                request.validate_headers(headers)
            except ValidationError as err:
                raise DAOForkCheckFailure(
                    "Invalid header response during DAO fork check: {}".format(
                        err))

            if len(headers) != 2:
                raise DAOForkCheckFailure(
                    "Peer failed to return all requested headers for DAO fork check"
                )
            else:
                parent, header = headers

            try:
                vm_class.validate_header(header, parent, check_seal=True)
            except EthValidationError as err:
                raise DAOForkCheckFailure(
                    "Peer failed DAO fork check validation: {}".format(err))

        return msgs