Exemple #1
0
        async def peer_action(peer: ws.WSChiaConnection):

            peer_info = peer.get_peer_info()
            version = peer.get_version()
            if peer_info is not None and version is not None:
                self.version_cache.append((peer_info.host, version))
            # Ask peer for peers
            response = await peer.request_peers(
                full_node_protocol.RequestPeers(), timeout=3)
            # Add peers to DB
            if isinstance(response, full_node_protocol.RespondPeers):
                self.peers_retrieved.append(response)
            peer_info = peer.get_peer_info()
            tries = 0
            got_peak = False
            while tries < 25:
                tries += 1
                if peer_info is None:
                    break
                if peer_info in self.with_peak:
                    got_peak = True
                    break
                await asyncio.sleep(0.1)
            if not got_peak and peer_info is not None and self.crawl_store is not None:
                await self.crawl_store.peer_connected_hostname(
                    peer_info.host, False)
            await peer.close()
Exemple #2
0
 async def on_connect(self, peer: ws.WSChiaConnection):
     if (
         peer.is_outbound is False
         and peer.peer_server_port is not None
         and peer.connection_type is NodeType.FULL_NODE
         and self.server._local_type is NodeType.FULL_NODE
         and self.address_manager is not None
     ):
         timestamped_peer_info = TimestampedPeerInfo(
             peer.peer_host,
             peer.peer_server_port,
             uint64(int(time.time())),
         )
         await self.address_manager.add_to_new_table([timestamped_peer_info], peer.get_peer_info(), 0)
         if self.relay_queue is not None:
             self.relay_queue.put_nowait((timestamped_peer_info, 1))
     if (
         peer.is_outbound
         and peer.peer_server_port is not None
         and peer.connection_type is NodeType.FULL_NODE
         and (self.server._local_type is NodeType.FULL_NODE or self.server._local_type is NodeType.WALLET)
         and self.address_manager is not None
     ):
         msg = make_msg(ProtocolMessageTypes.request_peers, full_node_protocol.RequestPeers())
         await peer.send_message(msg)
Exemple #3
0
 async def respond_peers(self, request: full_node_protocol.RespondPeers, peer: WSChiaConnection):
     if not self.wallet_node.has_full_node():
         self.log.info(f"Wallet received {len(request.peer_list)} peers.")
         await self.wallet_node.wallet_peers.respond_peers(request, peer.get_peer_info(), True)
     else:
         self.log.info(f"Wallet received {len(request.peer_list)} peers, but ignoring, since we have a full node.")
         await self.wallet_node.wallet_peers.ensure_is_closed()
     return None
Exemple #4
0
    async def respond_peers_introducer(
            self, request: introducer_protocol.RespondPeersIntroducer,
            peer: WSChiaConnection):
        if self.wallet_node.wallet_peers is not None:
            await self.wallet_node.wallet_peers.respond_peers(
                request, peer.get_peer_info(), False)

        if peer is not None and peer.connection_type is NodeType.INTRODUCER:
            await peer.close()
Exemple #5
0
    async def respond_peers(self, request: full_node_protocol.RespondPeers,
                            peer: WSChiaConnection):
        if self.wallet_node.wallet_peers is None:
            return None

        self.log.info(f"Wallet received {len(request.peer_list)} peers.")
        await self.wallet_node.wallet_peers.respond_peers(
            request, peer.get_peer_info(), True)

        return None
 async def update_peer_timestamp_on_message(self,
                                            peer: ws.WSChiaConnection):
     if (peer.is_outbound and peer.peer_server_port is not None
             and peer.connection_type is NodeType.FULL_NODE
             and self.server._local_type is NodeType.FULL_NODE
             and self.address_manager is not None):
         peer_info = peer.get_peer_info()
         if peer_info is None:
             return None
         if peer_info.host not in self.connection_time_pretest:
             self.connection_time_pretest[peer_info.host] = time.time()
         if time.time() - self.connection_time_pretest[
                 peer_info.host] > 600:
             self.connection_time_pretest[peer_info.host] = time.time()
             await self.address_manager.connect(peer_info)
Exemple #7
0
 async def new_peak(self, request: full_node_protocol.NewPeak,
                    peer: ws.WSChiaConnection):
     try:
         peer_info = peer.get_peer_info()
         tls_version = peer.get_tls_version()
         if tls_version is None:
             tls_version = "unknown"
         if peer_info is None:
             return
         if request.height >= self.minimum_height:
             if self.crawl_store is not None:
                 await self.crawl_store.peer_connected_hostname(
                     peer_info.host, True, tls_version)
         self.with_peak.add(peer_info)
     except Exception as e:
         self.log.error(
             f"Exception: {e}. Traceback: {traceback.format_exc()}.")
Exemple #8
0
    async def incoming_connection(self, request):
        if request.remote in self.banned_peers and time.time(
        ) < self.banned_peers[request.remote]:
            self.log.warning(
                f"Peer {request.remote} is banned, refusing connection")
            return None
        ws = web.WebSocketResponse(max_msg_size=50 * 1024 * 1024)
        await ws.prepare(request)
        close_event = asyncio.Event()
        cert_bytes = request.transport._ssl_protocol._extra[
            "ssl_object"].getpeercert(True)
        der_cert = x509.load_der_x509_certificate(cert_bytes)
        peer_id = bytes32(der_cert.fingerprint(hashes.SHA256()))
        if peer_id == self.node_id:
            return ws
        connection: Optional[WSChiaConnection] = None
        try:
            connection = WSChiaConnection(
                self._local_type,
                ws,
                self._port,
                self.log,
                False,
                False,
                request.remote,
                self.incoming_messages,
                self.connection_closed,
                peer_id,
                self._inbound_rate_limit_percent,
                self._outbound_rate_limit_percent,
                close_event,
            )
            handshake = await connection.perform_handshake(
                self._network_id,
                protocol_version,
                self._port,
                self._local_type,
            )

            assert handshake is True
            # Limit inbound connections to config's specifications.
            if not self.accept_inbound_connections(
                    connection.connection_type) and not is_in_network(
                        connection.peer_host, self.exempt_peer_networks):
                self.log.info(
                    f"Not accepting inbound connection: {connection.get_peer_info()}.Inbound limit reached."
                )
                await connection.close()
                close_event.set()
            else:
                await self.connection_added(connection, self.on_connect)
                if self._local_type is NodeType.INTRODUCER and connection.connection_type is NodeType.FULL_NODE:
                    self.introducer_peers.add(connection.get_peer_info())
        except ProtocolError as e:
            if connection is not None:
                await connection.close(self.invalid_protocol_ban_seconds,
                                       WSCloseCode.PROTOCOL_ERROR, e.code)
            if e.code == Err.INVALID_HANDSHAKE:
                self.log.warning(
                    "Invalid handshake with peer. Maybe the peer is running old software."
                )
                close_event.set()
            elif e.code == Err.INCOMPATIBLE_NETWORK_ID:
                self.log.warning(
                    "Incompatible network ID. Maybe the peer is on another network"
                )
                close_event.set()
            elif e.code == Err.SELF_CONNECTION:
                close_event.set()
            else:
                error_stack = traceback.format_exc()
                self.log.error(
                    f"Exception {e}, exception Stack: {error_stack}")
                close_event.set()
        except Exception as e:
            if connection is not None:
                await connection.close(
                    ws_close_code=WSCloseCode.PROTOCOL_ERROR,
                    error=Err.UNKNOWN)
            error_stack = traceback.format_exc()
            self.log.error(f"Exception {e}, exception Stack: {error_stack}")
            close_event.set()

        await close_event.wait()
        return ws