Skip to content
This repository has been archived by the owner on May 17, 2023. It is now read-only.

Latest commit

 

History

History
166 lines (132 loc) · 10.2 KB

eip-2390.md

File metadata and controls

166 lines (132 loc) · 10.2 KB
eip title author discussions-to status type category created requires ( * optional)
2390
Geo-ENS
James Choncholas <[email protected]>
Draft
Standards Track
ERC
2019-11-15
EIP137, EIP165, EIP1062, EIP1185

Simple Summary

GeoDNS, but for ENS! Allows for location specific responses to ENS queries from resolver contracts.

Abstract

This EIP specifies an ENS resolver interface for geographically specific address resolution. This permits associating a human-readable name with an address associated with a specific geographic location. Geographic resolution can extended beyond ENS address resolvers (EIP137) to DNS resolvers (EIP1185), ABI resolvers (EIP1062), and any more to be created.

Motivation

There are many use cases for traditional GeoDNS systems, like Amazon's Route53, in the centralized web. These use cases include proximity-based load balancing and serving content specific to the geographic location of the query. Unfortunately the ENS specification does not provide a mechanism for geo-specific resolution. ENS can respond to queries with IP addresses (as described in EIP1185) however there is no way to respond to geo-specific queries. This EIP proposes a standard to give the ENS system geo-proximal awareness to serve a similar purpose as GeoDNS.

Mimicking GeoDNS is not the only purpose of this EIP. This interface specification extends the utility of GeoENS beyond plain GeoDNS. For example, GeoENS is useful to locate digital resources (like smart contracts) that represent physical objects in the real world. More examples include:

  • Using ENS to do geo-specific IP queries as described in EIP1185.
  • Smart contract managing access to a physical object associated with a specific location.
  • ENS + IPFS web hosting (as described in EIP1162) with content translated to the native language of the query source.
  • Tokenizing objects with a physical location.

Specification

This EIP proposes a new interface to ENS resolvers such that geo-spacial information can be recorded and retrieved from the blockchain. The interface changes are described below for "address resolvers" described in EIP137 however the idea applies to any record described in EIP1185 and EIP1062, namely DNS Resolvers, Text Resolvers, ABI Resolvers, etc.

function geoAddr(bytes32 node, uint64 geohash, uint64 precisionMask) returns (address[] memory ret)

Query the resolver contract for a specific node and location described by a location. The geohash is masked by the precisionMask to describe a physical region much like a square on a map. All resources (contract addresses, IP addresses, ABIs, TEXT records, etc.) matching the node and within the region are returned.

function setGeoAddr(bytes32 node, uint64 geohash, address addr)

Sets a resource (contract address, IP, ABI, TEXT, etc.) by node and geohash. Geohashes must be unique per node. Write default initialized resource value, like address(0), to remove a resource from the resolver.

geohash

Geohashes is typically encoded in base 32 characters, as described https://en.m.wikipedia.org/wiki/Geohash#Algorithm_and_example. While these could be represented using a string, it is more efficient to represent a geohash as a 64 bit unsigned integer. This reduces gas usage during transactions. More information regarding efficiency can be found in the implementation section.

There are different ways to search geographic data using geohashes. First, a single query using a geohash of reduced precision will search a box shaped geographic region. Searching in a circular shaped region is slightly more complex as it requires multiple queries. Algorithms to do so, like https://github.com/ashwin711/proximityhash, can be left to the reader to explore.

Rationale

Because of the decentralized nature of ENS, geo-specific resolution is different than traditional GeoDNS. GeoDNS works as follows. DNS queries are identified by their source IP address. This IP is looked up in a database like GeoIP2 from MaxMind which maps the IP address to a location. This method of locating the source of a query is error prone and unreliable. If the GeoIP database is out of date, queried locations can be vastly different than their true location. GeoENS does not rely on a database because the user includes a location in their query.

An additional shortcoming of traditional DNS is the fact that there is no way to return a list of servers in a certain proximity. This is paramount for uses cases that require discovering the resource with the lowest latency. GeoENS allows a list of resources, like IP addresses, to be gathered within a specific location. Then a client to determine themselves which resource has the lowest latency.

Another benefit of GeoENS is that queries can be made for any location. Traditional DNS will only return the resource assigned to a query's provenance. GeoENS does not correlate a query's source with a location, allowing the entire globe to be queried from one location.

Lastly, publicly facing GeoDNS services do not give fine granularity control over geographic regions for GeoDNS queries. Cloud based DNS services like Amazon's Route 53 only allow specifying geographic regions at the granularity of a State in the United States. This course granularity could be due to the unreliability of the underlying databases mapping IP to location. GeoENS on the other hand gives 64 bits of geohash resolution which is sub-meter accuracy.

Backwards Compatibility

This EIP does not introduce issues with backwards compatibility.

Test Cases

See https://github.com/james-choncholas/geoens/tree/master/test

Implementation

This single owner address resolver, written in Solidity, implements the specifications outlined above. The same idea presented here can be applied to public resolvers as specified in EIP137. Note that geohashes are passed and stored using 64 bit unsigned integers. Using integers instead of strings for geohashes is more performant, especially in the geomap mapping. For comparison purposes, see https://github.com/james-choncholas/geoens/tree/master/contracts/StringOwnedGeoENSResolver.sol for the inefficient string implementation.

pragma solidity >=0.4.21 <0.6.0;

contract OwnedGeoENSResolver {
    // Other code

    bytes4 constant ERC165ID = 0x01ffc9a7;
    bytes4 constant ERC2390ID = 0xc5505b25;
    uint constant MAX_ADDR_RETURNS = 64;
    mapping(uint64=>address) geomap;
    address public owner = msg.sender;

    event AddrChanged(bytes32 indexed node, uint64 geohash, address addr);

    modifier isOwner() {
        require(msg.sender == owner);
        _;
    }

    function geoAddr(bytes32 node, uint64 geohash, uint64 precisionMask) external view returns (address[] memory ret) {
        bytes32(node); // single node georesolver ignores node

        ret = new address[](MAX_ADDR_RETURNS);
        uint ret_i = 0;

        for(uint64 i=(geohash & precisionMask); i<= geohash + ~precisionMask; i++) {
            if (geomap[i] != address(0)) {
                ret[ret_i] = geomap[i];
                ret_i ++;
            }
            if (ret_i > MAX_ADDR_RETURNS) break;
        }

        return ret;
    }

    function setGeoAddr(bytes32 node, uint64 geohash, address addr) external isOwner() {
        // single node georesolver ignores node
        geomap[geohash] = addr;
        emit AddrChanged(node, geohash, addr);
    }

    function supportsInterface(bytes4 interfaceID) external pure returns (bool) {
        return interfaceID ==  ERC165ID || interfaceID == ERC2390ID;
    }

    function() external payable {
        revert();
    }
}

Copyright

Copyright and related rights waived via CC0.