async def _periodically_self_advertise_and_clean_data(self): while not self.is_closed: try: try: await asyncio.sleep(24 * 3600) except asyncio.CancelledError: return None # Clean up known nodes for neighbours every 24 hours. async with self.lock: for neighbour in list(self.neighbour_known_peers.keys()): self.neighbour_known_peers[neighbour].clear() # Self advertise every 24 hours. peer = await self.server.get_peer_info() if peer is None: continue timestamped_peer = [ TimestampedPeerInfo( peer.host, peer.port, uint64(int(time.time())), ) ] msg = make_msg( ProtocolMessageTypes.respond_peers, full_node_protocol.RespondPeers(timestamped_peer), ) await self.server.send_to_all([msg], NodeType.FULL_NODE) async with self.lock: for host in list(self.received_count_from_peers.keys()): self.received_count_from_peers[host] = 0 except Exception as e: self.log.error(f"Exception in self advertise: {e}") self.log.error(f"Traceback: {traceback.format_exc()}")
async def _query_dns(self, dns_address): try: if self.default_port is None: self.log.error( "Network id not supported in NETWORK_ID_DEFAULT_PORTS neither in config. Skipping DNS query." ) return if self.resolver is None: self.log.warn( "Skipping DNS query: asyncresolver not initialized.") return peers: List[TimestampedPeerInfo] = [] result = await self.resolver.resolve(qname=dns_address, lifetime=30) for ip in result: peers.append( TimestampedPeerInfo( ip.to_text(), self.default_port, 0, )) self.log.info(f"Received {len(peers)} peers from DNS seeder.") if len(peers) == 0: return await self._respond_peers_common( full_node_protocol.RespondPeers(peers), None, False) except Exception as e: self.log.warn(f"querying DNS introducer failed: {e}")
async def _address_relay(self): while not self.is_closed: try: try: relay_peer, num_peers = await self.relay_queue.get() except asyncio.CancelledError: return None relay_peer_info = PeerInfo(relay_peer.host, relay_peer.port) if not relay_peer_info.is_valid(): continue # https://en.bitcoin.it/wiki/Satoshi_Client_Node_Discovery#Address_Relay connections = self.server.get_full_node_connections() hashes = [] cur_day = int(time.time()) // (24 * 60 * 60) for connection in connections: peer_info = connection.get_peer_info() if peer_info is None: continue cur_hash = int.from_bytes( bytes( std_hash( self.key.to_bytes(32, byteorder="big") + peer_info.get_key() + cur_day.to_bytes(3, byteorder="big") ) ), byteorder="big", ) hashes.append((cur_hash, connection)) hashes.sort(key=lambda x: x[0]) for index, (_, connection) in enumerate(hashes): if index >= num_peers: break peer_info = connection.get_peer_info() pair = (peer_info.host, peer_info.port) async with self.lock: if pair in self.neighbour_known_peers and relay_peer.host in self.neighbour_known_peers[pair]: continue if pair not in self.neighbour_known_peers: self.neighbour_known_peers[pair] = set() self.neighbour_known_peers[pair].add(relay_peer.host) if connection.peer_node_id is None: continue msg = make_msg( ProtocolMessageTypes.respond_peers, full_node_protocol.RespondPeers([relay_peer]), ) await connection.send_message(msg) except Exception as e: self.log.error(f"Exception in address relay: {e}") self.log.error(f"Traceback: {traceback.format_exc()}")
async def _query_dns(self, dns_address): try: peers: List[TimestampedPeerInfo] = [] result = await self.resolver.resolve(qname=dns_address, lifetime=30) for ip in result: peers.append( TimestampedPeerInfo( ip.to_text(), 8444, 0, ) ) self.log.info(f"Received {len(peers)} peers from DNS seeder.") if len(peers) == 0: return await self._respond_peers_common(full_node_protocol.RespondPeers(peers), None, False) except Exception as e: self.log.error(f"Exception while querying DNS server: {e}")
async def request_peers(self, peer_info: PeerInfo): try: # Prevent a fingerprint attack: do not send peers to inbound connections. # This asymmetric behavior for inbound and outbound connections was introduced # to prevent a fingerprinting attack: an attacker can send specific fake addresses # to users' AddrMan and later request them by sending getaddr messages. # Making nodes which are behind NAT and can only make outgoing connections ignore # the request_peers message mitigates the attack. if self.address_manager is None: return None peers = await self.address_manager.get_peers() await self.add_peers_neighbour(peers, peer_info) msg = make_msg( ProtocolMessageTypes.respond_peers, full_node_protocol.RespondPeers(peers), ) return msg except Exception as e: self.log.error(f"Request peers exception: {e}")
uint32(2759248594), bytes32( bytes.fromhex( "51f2e23ac76179d69bc9232420f47e2a332b8c2495c24ceef7f730feb53c9117") ), uint8(167), vdf_info, vdf_proof, ) request_peers = full_node_protocol.RequestPeers() timestamped_peer_info = TimestampedPeerInfo("127.0.0.1", uint16(8444), uint64(10796)) respond_peers = full_node_protocol.RespondPeers([timestamped_peer_info]) ## WALLET PROTOCOL request_puzzle_solution = wallet_protocol.RequestPuzzleSolution( bytes32( bytes.fromhex( "6edddb46bd154f50566b49c95812e0f1131a0a7162630349fc8d1d696e463e47") ), uint32(3905474497), ) program = Program.from_serialized_program( SerializedProgram.from_bytes( bytes.fromhex( "ff01ffff33ffa0f8912302fb33b8188046662785704afc3dd945074e4b45499a7173946e044695ff8203e880ffff33ffa03eaa52e850322dbc281c6b922e9d8819c7b4120ee054c4aa79db50be516a2bcaff8207d08080" )), )