#include<cstdio>
#include<vector>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;

#define mp make_pair
#define fi first
#define se second
#define pb push_back
typedef double db;
const db eps=1e-6;
const db pi=acos(-1.0);

int sign(db k){//-----------
    if (k>eps) return 1; else if (k<-eps) return -1; return 0;
}
int cmp(db k1,db k2){return sign(k1-k2);}  //-----------
struct point{
    db x,y;
    // point (double _x =0,double _y=0){x=_x;y=_y;}//------
    // point operator + (const point &k1) const {return point(k1.x+x,k1.y+y);}//------
    // point operator - (const point &k1) const {return point(x-k1.x,y-k1.y);}//------
    // point operator * (db k1) const  {return point(x*k1,y*k1);};//--------
    // point operator / (db k1) const{return point(x/k1,y/k1);}
    point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}  //两个点相加-----
    point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}  //两个点相减------
    point operator * (db k1) const{return (point){x*k1,y*k1};}  //与原点的距离扩大k1倍-------
    point operator / (db k1) const{return (point){x/k1,y/k1};}  //与原点的距离缩小k1倍
    int operator == (const point &k1) const{return cmp(x,k1.x)==0&&cmp(y,k1.y)==0;}  //判断两个点相等
    point turn(db k1){return (point){x*cos(k1)-y*sin(k1),x*sin(k1)+y*cos(k1)};} // 绕原点逆时针旋转
    point turn2(db k1, point p){return p+((*this)-p).turn(k1);}//绕p逆时针旋转k1度
    point turn90(){return (point){-y,x};}   //逆时针旋转90度
    //在点k1左边返回1 相等时在下边返回1  根据（x，y）排序-------------
    bool operator < (const point k1) const{
        int a=cmp(y,k1.y);
        if (a==-1) return 1; else if (a==1) return 0; else return cmp(x,k1.x)==-1;
    }
    db abs(){return sqrt(x*x+y*y);}//返回距离原点欧式距离
    db abs2(){return x*x+y*y;}  //返回距离原点欧式距离的平方
    db dis(point k1){return ((*this)-k1).abs();}    //返回两个点之间的欧式距离
    point unit(){db w=abs(); return (point){x/w,y/w};}  //返回单位向量
    void scan(){double k1,k2; scanf("%lf%lf",&k1,&k2); x=k1; y=k2;} //输入一个点--------
    void print(){printf("%.f %.f\n",x,y);}    //输出一个点--------
    db getw(){return atan2(y,x);}   //返回方位角  取值[-π，π]
    //如果 x>=0&&y>=0 不变，其他关于原点对称
    point getdel(){if (sign(x)==-1||(sign(x)==0&&sign(y)==-1)) return (*this)*(-1); else return (*this);}
};
void solve(vector < point > A)
{
    int s = A.size();
    for(int i = 0; i <s; i++)
        A[i].print();
}
db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;}    //叉积-----
vector<point> ConvexHull(vector<point>A,int flag=1){ // 计算凸包  flag=0 不严格 flag=1 严格即不可以相等
    int n=A.size(); vector<point>ans(n*2);
    sort(A.begin(),A.end()); int now=-1;
    for (int i=0;i<A.size();i++){
        while (now>0&&sign(cross(ans[now]-ans[now-1],A[i]-ans[now-1]))<flag) now--;
        ans[++now]=A[i];
    } int pre=now;
    for (int i=n-2;i>=0;i--){
        while (now>pre&&sign(cross(ans[now]-ans[now-1],A[i]-ans[now-1]))<flag) now--;
        ans[++now]=A[i];
    } ans.resize(now); return ans;
}
db convexDiameter(vector<point>A){//凸包直径，点集直径
    int now=0,n=A.size(); db ans=0;
    for (int i=0;i<A.size();i++){
        now=max(now,i);
        while (1){
            db k1=A[i].dis(A[now%n]),k2=A[i].dis(A[(now+1)%n]);
            ans=max(ans,max(k1,k2)); if (k2>k1) now++; else break;
        }
    }
    return ans;
}
vector < point > ans;
int main()
{
    int n;
    ans.clear();
    scanf("%d", &n);
    for(int i = 0; i < n;i++)
    {
        point a;
        a.scan();
        ans.push_back(a);
    }
    ans = ConvexHull(ans,0);
    db d = convexDiameter(ans);
    printf("%.12f\n",d);
    return 0;
}



Measured memory_bytes: 7648