#include <cmath>
#include <cstdio>
#include <vector>
#include <algorithm>

int dcmp(double x) {
    static double eps = 1e-8;
    return (x > eps) - (x < -eps);
}

struct vec{
    double x, y;

    vec(double _x=0, double _y=0)
        :x(_x), y(_y) {}

    vec operator- () const{ return vec(-x, -y); }
    
    vec operator+ (const vec& v) const{ return vec(x+v.x, y+v.y); }
    vec operator- (const vec& v) const{ return vec(x-v.x, y-v.y); }
    vec operator* (double c) const{ return vec(x*c, y*c); }
    vec operator/ (double c) const{ return vec(x/c, y/c); }

    double dot(const vec& v) const{ return x*v.x + y*v.y; }
    double cross(const vec& v) const{ return x*v.y - y*v.x; }

    double len2() const{ return x*x + y*y; }
    double len() const{ return sqrt(len2()); }
    
    vec& norm() { return *this = *this / len(); }
    vec& rot(double rad) {
        return  *this = vec(x*cos(rad) - y*sin(rad), x*sin(rad) + y*cos(rad));
    }

    bool operator< (const vec& v) const{
        return dcmp(x-v.x) < 0 || (dcmp(x-v.x)==0 && dcmp(y-v.y) < 0);
    }
};

struct line{
    vec u, v; // u + x*v

    line() {}
    line(vec _u, vec _v)
        :u(_u), v(_v) {}

    vec get(double x) {
        return u + v * x;
    }
};

line makeline(vec a, vec b) {
    return line(a, b - a);
}

bool on_left(line l, vec u) {
    return dcmp(l.v.cross(u - l.u)) > 0;
}

vec line_intersection(line a, line b) {
    return b.u + b.v * b.v.cross(b.u-a.u) / a.v.cross(b.v);
}

bool segment_intersection(vec a, vec b, vec c, vec d) {
    line x = line(a, b-a), y = line(c, d-c);
    return on_left(x, c) != on_left(x, d) && on_left(y, a) != on_left(y, b);
}

std::vector<vec> convex_hull(std::vector<vec> p) {
    std::sort(p.begin(), p.end());
    std::vector<vec> ch;
    for (size_t i = 0; i < p.size(); ++i) {
        while (ch.size() > 1 && on_left(makeline(ch[ch.size()-2], p[i]), ch[ch.size()-1]))
            ch.pop_back();
        ch.push_back(p[i]);
    }
    size_t k = ch.size();
    for (int i = p.size() - 2; i >= 0; --i) {
        while (ch.size() > k && on_left(makeline(ch[ch.size()-2], p[i]), ch[ch.size()-1]))
            ch.pop_back();
        ch.push_back(p[i]);
    }
    ch.pop_back();
    return ch;
}

std::pair<vec, vec> convex_diameter(const std::vector<vec> &p) {
    int xmax = 0, xmin = 0, n = p.size();
    for (int i = 1; i < n; ++i) {
        if (p[i].x > p[xmax].x) xmax = i;
        if (p[i].x < p[xmin].x) xmin = i;
    }
    
    int i = xmax, j = xmin;
    int u = xmax, v = xmin;
    double ans = (p[xmax] - p[xmin]).len2();
    
    do {
        if ((p[i] - p[(i + 1) % n]).cross(p[j] - p[(j + 1) % n]) < 0) i = (i + 1) % n;
        else j = (j + 1) % n;

        double dist = (p[i] - p[j]).len2();
        if (dist > ans) {
            ans = dist;
            u = i; v = j;
        }
    }while(i != xmax || j != xmin);
    return std::make_pair(p[u], p[v]);
}

// end template

int main() {
    std::vector<vec> p;
    int n;
    double x,y;
    for(scanf("%d",&n);n--;p.push_back(vec(x, y)))
        scanf("%lf%lf",&x,&y);
    std::pair<vec, vec> pp = convex_diameter(p);
    printf("%f\n", (pp.first - pp.second).len());
    return 0;
}



Measured memory_bytes: 4504