ethereum / EIPs

The Ethereum Improvement Proposal repository
https://eips.ethereum.org/
Creative Commons Zero v1.0 Universal
12.83k stars 5.24k forks source link

ERC: Default Ethereum Name Registrar #26

Closed alexvandesande closed 7 years ago

alexvandesande commented 8 years ago
  ERC: 26 (based on issue number) or 3 (based on ERC)
  Title: Default Mist Name Registrar
  Author: Alex Van de Sande (avsa@ethdev.com)
  Status: Draft
  Type: Informational
  Created: 20-11.2015

Abstract

An important aspect of making ethereum Ðapps easily accessible is a name registry that will connect a human readable name to a hash for usage in IPFS/SWARM or any DHT system.

The name registrar is not meant to be the one and only name registrar on ethereum but rather a default registrar to be used by Mist to resolve names. It will be an user configurable setting.

Motivation

The goal of this contract is:

The system will consist of 4 main parts:

Hash Registrar

The registrar itself is the contract that stores the basic data. If more data is needed it can be stored in other contracts, using this one as the reference. It doesn't use the name directly to reference the registry but its data. Keeping the names as hashes instead of plaintext has two advantages: first it allows privacy by obscurity, meaning that if the name isn't known enough to be in a rainbow table then you can't really know who the information is about. Second, it allows a more general purpose and future proofing use of the contract, as it can be used to claim ownership on anything that can be translated into hash, like devices, files, texts and other uses we haven't thought about now.

function getAuction() constant returns (address auction)
function getElection() constant returns (address election)
function getCollector() constant returns (address collector)
function setCollector(address _newCollector) returns (bool success)

The registry is set at startup with the address of three other contracts, the Collector contract, Election Contract and Auction contract, that have special rights. Only the Election contract can change the collector. The others are unchangeable.

function getRegistry(bytes32 _hash) constant returns (address _owner, uint _renewalDate,  uint feesPaid, string _redirectAddress)

It uses a hash as an index and attributes these informations to it: an address that owns it; the expiration date of the registration; the amount of ether that the owner effectively paid to the registrar address as the process of renewal; a string which is the http, buzz or ipfs address of the app.

Other contracts might extend this functionality by simply creating a registry of extra information about a hash and then only allowing edits to it by checking this master contract for the owner address. For example, the wallet app might want to make a registry where a name is associated to an address (different from the owner), or if you want to have a secondary content hash for http links then a secondary contract could be deployed, only allowing edit access to the addresses on marked as owner on this contract.

function editRegistry(bytes32 _hash)

All the information on that hash can be edited by the owner of the address up to 48h before the renewal Date, and at that time the information is locked. After the expiration date, only the Auction Contract can change the owner of the hash.

function newRegistry(bytes32 _hash, string _redirectAddress, address _owner)

Only the Auction Contract can add new registries.

function ()

All funds given to the Registrar contract are redirected to the Collector Contract. These will not count towards the feesPaid.

function invalidateEntry(string _name)

The disadvantage of hashes as identifiers is that it literally allows anything, therefore making it impossible to create restrictions such as "names shorter than 6 letters can only be registered after 2017". This could be avoided by creating validity rules that need to be reported and if true will delete the entry, but this would require all those rules to be set at the first setup. Another way to do it is to grant the Collector Contract power to invalidate entries, but this would open the possibility of an evil collector contract censoring entries. Another solution is simply to allow any entries, but simply enforce those rules on the client: mist could be programmed to look at other contracts for special names

I'm open to more elegant solutions.

Auction Contract

The auction contract is set at startup of the Hash registrar, but since they are separated it is possible to clone a copy of the registrar contract and just change these variables.

The purpose of the auction contract is to receive bids for hashes and select a winner.

function startBid(bytes32 _newHash)

If _newHash is not registered to anyone this will create a new register, owned by 0x000 with a renewal date exactly 7 days after this function was executed. This allows a short time in which a Vickrey Auction can decide who is the first owner of the name.

The cost of start a bid can be defined by the collectorContract, but otherwise is kept at free.

function putSealedBid(bytes32 _sealedBid)

A sealed bid is just a message with the hash of the bid and some ether. The amount of ether sent on this step is also recorded, as long as the time in which the bid was put. The amount of ether can and should be higher than the amount bid, to protect the privacy of the bid. For the same reason, the bidder doesn't need to be the future owner.

The collectorContract, might define a deposit value that needs to be added on top of the put, but if it doesn't implement it then it's free.

function revealBid(bytes32 _sealedBid, bytes32 _biddedHash, address _owner, uint _bidPrice, uint _duration, string _salt)

_sealedBid is the hash saved on _sealedBid _biddedHash is the hash that the bidder wants to own _owner is the future owner of the hash, if the bid is successful. The bidder and the owner need not to be the same person _bidPrice is the maximum price the bidder is willing to pay for it _duration is the length of time (in days) the owner wants to renew it for. Must be longer than 180 and smaller than 3660. If this is the first time this hash is being bidder on then the _duration cannot be longer than 366, if it has been registered before then the _duration cannot be longer than twice the length of time that has passed since it was first registered, as to avoid very long registrations during the first years.

_salt is just a random string to prevent deanonimization of sealed bids by brute force

This action can be done by anyone. If the _sealedBid doesn't match the hash of all other parameters put together then the bid is not revealed, otherwise it's saved on the revealed bids. Collection contract.

Once a bid is revealed, the proposed setup is a closed bid Vickrey auction, where the highest bidder becomes the owner but only pays the second highest bid:

Should a bid be considered invalid if it's revealed earlier than 48h of the renewal date?

Bids revealed too early might affect the game strategy and will influence the price to be paid. In the other hand a deleted bid might mean that someone will lose his property without the correct asking price. Since losing a domain name is harsher than someone overpaying for it, then I suggest that there should not be an obligatory reveal period, only a suggested 24h window.

The collector contract can set a function that will determine a fee to be paid by the bidders, but otherwise it will default to free.

function revealBid(bytes32 _sealedBid, bytes32 _biddedHash, address _owner, uint _bidPrice, uint _duration, string _salt)

A bid can only be removed by the original owner and only earlier than 48 hours before the renewal date.

function finalizeAuction(bytes32 _biddedHash)

This action can be only executed after the renewalDate has passed. Anyone can call it, so it could be scheduled with the alarm clock.

If owner has not changed, then an amount of ether equivalent to _bidPrice/ _duration * K will be sent to the Collectors Contract and the remaining amount will be sent back to the original bidder. The amount paid will be registered at feesPaid. The renewal date will be set at the last renewal data + _duration.

If the owner has changed then amount of priceToBePaid will be sent to the previous owner, and a fee calculated by priceToBePaid * K / _duration will be sent to the collectors contract and registered as feesPaid. Otherwise a user could keep a name indefinitely by simply selling it to itself. The renewal date will be set at the last renewal data + _duration.

function cleanOldBids()

Deletes any unsealed bids that are older than the maximum duration time that any name can accept and forwards the ether to the Collector.

Collector contract

The Collector Address is an address that receives all the funds collected in auctions and has a special right to change the K factor. The purpose of the name registry auction is not to make a profit but to allow the optimal distribution of names, to prevent name squatting while still allowing cheap and easy access to registering a name. The cost of the renewal is given by the market price of the total price, divided by K. If K is too low it might allow name squatting, but if it's too high it can make keeping names too expensive.

The collector contract can also define fees related to bidding, in order to fight spam. The collector contract can determine which rules are broken in order to consider a registry invalid (short names could only be registered after a few years, etc)

How exactly the Collector contract changes the K factor or spends its funds is not defined here, as the contract itself is a changeable parameter elected by the Election Contract.

My proposal is that the first Collector contract be just a "Boomerang contract", a contract that simply keeps all ether sent to it and then send them back after 1 year. This will allow the funds to be safely kept for a period while the community build tools and DAOs for the collector contract for the first election. Since they can always elect the 0x address, then if the community wants to do so they can still vote to burn all the ether collected during the first year.

Election Contract

The election contract has the special right to change the collector address. The exact workings of the election, as well as their frequency is not yet defined here and is open to discussions.

One important issue is that it's impossible to tell which are the entities behind each name, if they coordinate with each other or if they are owned by other entities, therefore the concept of anti-sybil (and to a point anti-coercion) mechanisms does not really apply here. Also, the job of the Collector Contract is basically to define the use of it's own funds and how to raise or lower the "tax rate" on new names, therefore it's only natural that the weights of the votes should be based barely on the amount of funds each name has sent to the contract during their last renewing period.

A user that bought four names four 1 ether each and a user that bought a single name for 4 ethers have contributed the same amount to the collector contract and therefore should have the same right to decide how the funds are spent. If the system favours the former (like quadratic voting does) will stimulate users to buy tons of small names they are not going to use, a system that favours the latter will stimulate users to double bid on their own names to pay higher taxes and therefore get more voting power. Both will would be contrary to the whole purpose of the name registrar.

The suggested voting mechanism is a mix of approved voting with Liquid democracy, as follows:

function setDelegate(string32 _ownedHash, address _delegate)

Instead of voting directly, a voter instead can decide to appoint a delegate. The contract verifies that the msg.sender is the owner of the _ownedHash and then moves his voter weight ('feesPaid') to the new _delegate

function unsetDelegate(string32 _ownedHash)

The voter removes his vote to his delegate and states that wants to vote himself.

function setVote(address[] approvedCandidates)

The voter selects an array of contracts he approves for the job of Collector Contract. These remain static and can be changed anytime. If you

function tallyVotes()

Instead of a fixed election cycle, votes can be counted at anytime if someone feels voter's preference have changed enough. The cost of counting the votes is paid by the function caller. First the function will calculate the voter's weight by the sum of his 'feesPaid' and the weight of all voters that delegate their vote into him. Votes can be delegated forward a finite number of time (3, 5 or 7, depending on gas costs).

Then all addresses the voter approved will be receive an equal number of votes as his weight. The Address with a higher number of approvals will be selected as the new Collector Contract, effectively immediately.

Acknowledgements

People who contributed to this proposal, in no particular order: @nagydani & @zelig (with their research for the swarm name registrar), @vbuterin (for insights in elections), @gavofyork (who designed the first name registrar ), @yann300 and @arkpar (who implemented the current name registrar), @pipermerriam & @nmushegian (for their great insights at DevCon1) and @ryepdx (that is implementing the maker registry) and @danielnovy (auctions Ðapp at consensys)

Smithgift commented 8 years ago

Question: How are the names bought in the first place in this system? It seems that if it's an auction with sealed bids it ends up first-come-first-serve.

alexvandesande commented 8 years ago

@Smithgift good point. One way to do it would simply be that if a bid was unsealed for a new name then a registry is created with no owner and with a renewal date set for 7 days after that. This would make all new names go to a normal vickrey auction.

Smithgift commented 8 years ago

@alexvandesande That seems logical, yes. Perhaps there should be a simple function to just start a function for a new name, because you might as well bid just a tiny amount to start the auction and make the true bid later.

My concern with bidding on hashes as hashes is that the value of, say, 0xcfe33df56932be08b97194721e1d28638ed2f677728b2ffd617bd710fec0952d is not obvious to the average user. As it is, that's the sha3 hash of "wedding-shoes.eth", which I expect (should ethereum become popular and .eth become a TLD) to go for thousands of dollars. Being a Vickrey auction, this is a lesser issue, as you might as well bid the maximum amount you'd pay whether or not someone else will enter.

Making rainbow tables of potentially valuable hashes from dictionaries, web scraping, and Markov chains, then going after any auction with that hash is a potential strategy under this system.

I'm more concerned that random troll-bidding on new auctions will lead to unpleasantness for the actual bidder. If I want some odd new domain name now, I can just buy it. But if I have to fight a troll who's just bidding for the sake of taking whatever it is from me, it certainly feels worse, even if I may effectively pay less. The obvious counter-strategy is to spam the auction contract with new hashes until the trolls are bankrupt.

Also, the fixed election schedule could be broken by the current beneficiaries of the collector voting to transfer the collector to... an identical collector. That would reset the election time.

pirapira commented 8 years ago

For imposing certain rules on entries ("short names only after 2017"), how about asking the Collector Contract every time an entry is edited or added? Then, newRegistry and editRegistry would call collector.request_entry(string _hash, string _new_redirectAddres, bool _edit) returns (bool allowed) to see if the new entry is allowed. The Collector can even redirect request_entry call to a dynamically specified another contract, and change rules from time to time, but once an entry is registered, the Collector cannot invalidate the entry freely.

Smithgift commented 8 years ago

@pirapira But how would the Collector know whether, say, 0x78ec64bb8319a432962e79252a373554ecd3cec759e53c41c3111c40b45127b3 is the hash of a short name or a long name?

alexvandesande commented 8 years ago

@smithgift Thais What I mean by "privacy by obscurity", of course everyone can figure out the market price of the "Apple" name, I don't see that as a problem. They just can't spider and know the price of all obscure names.

Also, notice that there would be no dots. In this case you'd be buying just the name wedding-shoes and you can use any subdomain for that. This rule is easy to enforce because most will simply not honor any name with a dot, always looking for the top level domain first.

We are still discussing what "top level domain" even means in this content which is why I prefer not even register short names for the time being. Will it be .eth? Will anyone be able to register whatever?

rabbit commented 8 years ago

This would be easier for me to analyze if I understood the goals of the effort better; what use cases must be covered, what use cases are intentionally not covered. Is privacy a goal here? It's stated that human readable names are a goal in the abstract but is that possible without sanitizing inputs? Why is reverse lookup not a goal?

ghost commented 8 years ago

Good proposal. Thanks for writing that up!

If the bid new owner is not the current owner, K is 1, otherwise (if it's the owner renewing the ownership) then K is a factor set by the Collector Contract.

It might be better to make K=100 in the new owner case and adjust the formula to be (K * _bidPrice / _duration) / 100. This would allow for a scenario where the Collector Contract wants to make it cheaper for the current owner to keep their domain than for a new owner to take it.

My proposal is that the first Collector contract be just a "Boomerang contract", a contract that simply keeps all ether sent to it and then send them back after 1 year... Since they can always elect the 0x address, then if the community wants to do so they can still vote to burn all the ether collected during the first year.

Just a point of clarification: when a new collector contract is voted in, I assume the old one sends its balance on to the new one. Is that correct?

Also, is this namereg to have support for parsing paths at all, akin to the ENS system previously proposed? I see that this proposal handles auctioning TLDs, which is great, but I don't see anything to suggest how structured data might be handled.

Finally, it's a minor pet peeve of mine that domains as they are now have their elements arranged in order of reverse importance, contrary to the rest of any given URL. (E.g., http://google.com should be http://com/google and http://ether.fund/tool/converter should be http://fund/ether/tool/converter). This seems to me like an opportunity to correct that error. I imagine this is probably an unpopular opinion, of course, but I figured I might as well voice it.

Thanks again for starting this conversation. It's good to have all this written out.

janx commented 8 years ago

Should a bid be considered invalid if it's revealed earlier than 48h of the renewal date?

Bids revealed too early might affect the game strategy and will influence the price to be paid. In the other hand a deleted bid might mean that someone will lose his property without the correct asking price. Since losing a domain name is harsher than someone overpaying for it, then I suggest that there should not be an obligatory reveal period, only a suggested 24h window.

What if 'early revealer' needs to pay some penalty? In such case the value of putSealedBid transaction would be at least _bidPrice + fees + deposit, where deposit calculation is another question.

pirapira commented 8 years ago

@Smithgift

But how would the Collector know whether, say, 0x78ec64bb8319a432962e79252a373554ecd3cec759e53c41c3111c40b45127b3 is the hash of a short name or a long name?

Um, maybe by computing hashes of the shortest names and keeping them (at least we can cover one-character names). Now I see the trade-off between "enforcing policy" and "privacy by obscurity". I have no good answer.

alexvandesande commented 8 years ago

@rabbit the I expanded the text with a "motivation" section

@ryepdx I realised that I'm actually doing the K calculation completely wrong: the duration you want to keep your domain until renewal should not have an influence on the price you pay to buy it , only to renew it. So I think the correct way would be to have the renewal calculation that th e"bid" of the current owner should be calculated as bid = fee paid * K / duration. This means that if you would sell your name at 1000 ether, would like to renew it for 3 years and the current fee is set at 0.5% per year, then you need to send 15 ether to renew it. Anyone who bids more than that will buy it from you, independently of his duration. Maybe whenever a domain changes owners the duration should be always set at 1 year and then can be renewed for up to twice the previous amount every time.

when a new collector contract is voted in, I assume the old one sends its balance on to the new one.

Since any contract can be elected, that cannot be controlled. The new one simply starts receiving the fees from the renewal. The advantage of using a boomerang is that the new one would also be getting any revenue that was sent from a year previously

Also, is this namereg to have support for parsing paths at all, akin to the ENS system previously proposed?

Watching your talk you mention a lot of great extra information that you will need for many use cases, including how to parse sub registries, some of which I don't understand them myself. The needs of swarm/ipfs also require other kinds of extra information attached to a name, like a hash of the content in cases that the address doesn't provide that.

So I thought that instead of trying to cover all possible use cases it would make more sense to be minimal: the "master" registry only saves a few basic information like the current owner, the renewal data and how much he paid in fees, etc. If you need extra information you can create a contract with extra fields that reads the owner from the master contract and then gives them the right to edit and add information about his owned hash.

Finally, it's a minor pet peeve of mine that domains as they are now have their elements arranged in order of reverse importance, contrary to the rest of any given URL.

You are not the first one to bring that up, actually @gavofyork wanted to put domains exactly as you describe. I see the point and like the idea, but there are some limitations: a slash cannot be used as a separator, since it's important for the browser to differentiate between subdomains and subfolders. Also, inverting the domain subdomain order requires some modification of the core chromium server that we are using. Also I'm a bit afraid of creating user confusion and risk of phishing attack for a user that would see secure.bankofamerica.com and even a tech savvy user might think that this page belonged to bank of america.

In Mist I am using a compromise solution: Im separating the display of the url from the editing. When you click and mouse over the url, the text displays the url bar exactly as traditional web (http://ether.fund/tool/converter). In all other moments the url bar displays it in the hierarchical order using triangles as separators: fund ‣ ether ‣ tool ‣ converter

I think it's a good compromise of usability and security.

@Smithgift all possible six letter names are in the order of billions, this would make the contract incredibly expensive.

Another solution is simply to ignore it and enforce that on the client, but this is a permanent solution. For example, if you type a name with a dot in mist, it would automatically detect the top level domain and look into that, so mist effectively ignores all names with a dot in the middle. This doesn't mean you can't register them, just means that they aren't used. The trouble with fewer letters is that I'd like to use the same system to names with 6, 5 or even a single letter in the future (if we don't come up with a better solution by then) but if that's the case we would have to use a second contract to store those as the contract will accept them no matter what.

Smithgift commented 8 years ago

@alexvandesande That was what I was getting at. There's no practical way for the contract to go.

I've decided to call the "bid on any new hash that's auctioned in the hope someone wants it" strategy bobcatting. It's like wildcatting in the oil industry, except you have no idea what you actually bought and you might have gotten hit by a countertroll's nonsense hash. ("INSTEAD OF VALUABLE HASH, RECEIVED BOBCAT.")

On more thought, a sophisticated bobcatter would examine the transaction history of the account that started the auction. If it's a seemingly independent account buying one or two hashes, it's possibly someone's username or something, so go for it. A sophisticated countertroll would attempt to create more "independent" accounts to fool bobcatters, which is in turn an incentive for superior bobcatter algorithms (i.e. if it's funded from a mixer, it's more likely to be a countertroll.) There's probably interesting game-theoretical analysis behind all this which I am not qualified to do.

This all said, an auction like this is far better, troll-feline-wise, than a first-come-first-serve system, because you can at least outbid the bobcatter. In first-come-first-serve, the bobcatter just tries to preempt your transaction with higher gas prices or the like, and if he does he wins.

chriseth commented 8 years ago

Please use bytes32 as the type of a (256 bit) hash. string is reserved for utf-8 encoded data - if you need to store variable-length binary data, use bytes.

alexvandesande commented 8 years ago

@chriseth thanks, updated it!

@Smithgift Great point.

Let's say that a BobCatter would bid 10 ethers on random new bids being put. Since bidding is free, they would be able to own a bunch of new names for a year for less than 10.1 ether each, and they would be able to renew them for another year always for 0.1 ether (assuming a 1% per year fee), while being guaranteed that these names would alway sell for at least 10 ether each. The next year he can pay only 0.1 ether more and then these names will have twice the initial asking price and by analysing traffic coming to these names they could probably figure out the original name or at least its popularity.

The main issue I see here isn't even the name squatter holding a lot of popular names, but a worse consequence is that by bidding on all new names he is guaranteeing to make it more difficult for people who just want their own name for cheap to own it, and increasing the price for those who get it successfully: suddenly you can't get a uncommon name for free like originally envisioned, since all auctions are being bid on.

A potential solution would probably come from making bids non free, specially if you are bidding completely outside the market price: having deposits that you get back under certain conditions, incurring costs if you put the second bid (therefore increasing the price paid), etc.

Maybe a solution would be, instead of trying to come up with a solution to these problems right now, parametrize all these options as functions controlled by the collector contract. So for example, the secondary bid might pay a fee of X, which is a function of the total price made on the collector contract. If the collector contract doesn't implement that function then the fee is 0, but its up to them.

This gives the collector contract more power, but I believe that as long as it's controlling some limited auction parameters and cannot take names away, then it's a controlled power..

Smithgift commented 8 years ago

@alexvandesande

I think penalizing a second bid hurts spiders but helps bobcatters. If a bobcatter sees some random account unseal a bid to start an auction, the bobcatter knows exactly how much to bid to win, and the legitimate user will have to pay a second-bid penalty.

Suppose that the cost to start an auction is miniscule. Say, a new auction starts simply by calling a function, no bid necessary. Counterintuitively, the bobcatters will be at a disadvantage against a countertroll force, because the countertrolls could start absurd numbers of auctions to screen auctions by true users, and if the bobcatters go after every auction they go bankrupt. Unfortunately, this may lead to severe network spam, depending on how big the bobcat-countertroll conflict grows.

NINJA EDIT: But in that situation, spider-squatters are probably going to spam the network with starting auctions on valuable names before anyone realizes that they're valuable.

I realized there's an additional stumbling block to the countertrolls. They have to spend as much ETH on a new auction as a true user would, or the bobcatter instantly knows it's a countertroll. The true user strategy is then to spend less on a bid so that they look like a countertroll, but then there's a disincentive to bid what the name is actually worth.

alexvandesande commented 8 years ago

@smithgift bobcats, counter trolls, spiders, our fauna is getting richer!

I agree that to initiate a new bid should be a different function, with no information on price. I edited the proposal to reflect that.

Now the other points I would still keep the principle appointed earlier: parametricize all those fees, prices, taxes, deposits, etc so that these can be experimented by the collector contract.

On Nov 22, 2015, at 12:16, Smithgift notifications@github.com wrote:

@alexvandesande

I think penalizing a second bid hurts spiders but helps bobcatters. If a bobcatter sees some random account unseal a bid to start an auction, the bobcatter knows exactly how much to bid to win, and the legitimate user will have to pay a second-bid penalty.

Suppose that the cost to start an auction is miniscule. Say, a new auction starts simply by calling a function, no bid necessary. Counterintuitively, the bobcatters will be at a disadvantage against a countertroll force, because the countertrolls could start absurd numbers of auctions to screen auctions by true users, and if the bobcatters go after every auction they go bankrupt. Unfortunately, this may lead to severe network spam, depending on how big the bobcat-countertroll conflict grows.

NINJA EDIT: But in that situation, spider-squatters are probably going to spam the network with starting auctions on valuable names before anyone realizes that they're valuable.

I realized there's an additional stumbling block to the countertrolls. They have to spend as much ETH on a new auction as a true user would, or the bobcatter instantly knows it's a countertroll. The true user strategy is then to spend less on a bid so that they look like a countertroll, but then there's a disincentive to bid what the name is actually worth.

— Reply to this email directly or view it on GitHub.

alexvandesande commented 8 years ago

About valuables names being quickly auctioned by spiders: there's no way to prevent it, there will be a gold rush of the best valid names. The reason duration is measured in days not years is so users can change their renewal date so most of them won't be having an anniversary at the same time.

Sent from my iPhone

On Nov 22, 2015, at 12:16, Smithgift notifications@github.com wrote:

@alexvandesande

I think penalizing a second bid hurts spiders but helps bobcatters. If a bobcatter sees some random account unseal a bid to start an auction, the bobcatter knows exactly how much to bid to win, and the legitimate user will have to pay a second-bid penalty.

Suppose that the cost to start an auction is miniscule. Say, a new auction starts simply by calling a function, no bid necessary. Counterintuitively, the bobcatters will be at a disadvantage against a countertroll force, because the countertrolls could start absurd numbers of auctions to screen auctions by true users, and if the bobcatters go after every auction they go bankrupt. Unfortunately, this may lead to severe network spam, depending on how big the bobcat-countertroll conflict grows.

NINJA EDIT: But in that situation, spider-squatters are probably going to spam the network with starting auctions on valuable names before anyone realizes that they're valuable.

I realized there's an additional stumbling block to the countertrolls. They have to spend as much ETH on a new auction as a true user would, or the bobcatter instantly knows it's a countertroll. The true user strategy is then to spend less on a bid so that they look like a countertroll, but then there's a disincentive to bid what the name is actually worth.

— Reply to this email directly or view it on GitHub.

Smithgift commented 8 years ago

I think the collector setting parameters like that is a good idea, too. "Collector" seems to be a less accurate name, but I'm not sure what else it could be called without sounding centralized.

alexvandesande commented 8 years ago

Comes from tax collector. It's not a manager or Administrador as it can't change name owners or ban people. Accepting suggestions.

On Nov 22, 2015, at 18:46, Smithgift notifications@github.com wrote:

I think the collector setting parameters like that is a good idea, too. "Collector" seems to be a less accurate name, but I'm not sure what else it could be called without sounding centralized.

— Reply to this email directly or view it on GitHub.

zelig commented 8 years ago

I still believe that a two layer system may be better, namely to have a Hash-to-Hash registrar (which maps sha(domain_name) to sha(content)) and a Hash-to-URLhint map which maps to URL hints. The url hint can just be a scheme name (or even one byte schemecode), this is enough for content (hash) addressed systems like IPFS or swarm which can simply update content by only resetting the hash map. To save even more, one could even have a default scheme so that say if a content hash has no URLhint entry, it is interpreted as a swarm hash. You may not want to commit to the content hash. So if a domain has no content hash but has a urlhint it is considered an insecure redirect. This allowswedding-shoesto redirect toaugur/markets/is-the-wedding-shoes-worth-more-than-USD1000` :) Not entirely clear to me what information the distinction between registering namehash->urlhint or contenthash->urlhint should convey.

My more general reservation is that both IPFS and Swarm already supports name resolution, both could use (the same) contract on the blockchain, and http provides DNS, so I am not entirely convinced having a mist central resolution is even necessary. I would just register protocol schemes (bzz, ipns) with electron url handler and simply pass the url to the scheme handler as is leaving the scheme do their preferred name reg lookups. The namereg for a scheme could use an ethereum smart contract (an instance of the registry template contract). This is obviously the case with swarm. In my view this is cleaner and more modular.

zelig commented 8 years ago

Also, is this namereg to have support for parsing paths at all, akin to the ENS system previously proposed? I see that this proposal handles auctioning TLDs, which is great, but I don't see anything to suggest how structured data might be handled.

@ryepdx They do not need to be handled, in fact they should not be. Only domains should register on the blockchain. The domains point to a manifest file (routing table of sorts) with all your paths mapped to hashes (arranged in a trie for a recursive lookup in case of huge indexes). Since the manifest contains the hashes and itself is content addressed, an entire webservers all static routes can be integrity protected with a single entry in the registry.

zelig commented 8 years ago

@rabbit I agree. The usecase of reverse lookups are important. However, those that want to be in the phonebook so to say, can register their names with the string sent as a parameter in the transaction. This can then be logged with NewEntry(name, name_hash), which is cheaper. Then any off chain service can process the logs and create a phonebook (index of namehashes or content hashes), the most uptodate version is always registered as say bzz://phonebook. Note that it is trivial to verify that a reverse lookup entry is correct so if they are phony phone books, they will soon lose reputation.

zelig commented 8 years ago

If we keep the standard that we use this same namereg to register contract info belonging to a contract then the best way to do it is to index by contract code as name (as it is currently done in geth natspec implementation, see https://github.com/ethereum/go-ethereum/blob/develop/common/natspec/natspec.go#L107) (and see swarm dns-oid: https://github.com/ethersphere/go-ethereum/blob/bzz/bzz/api.go#L393). A consequence of this is that your browser will automatically serve as contract code reverse lookup. bzz://<contract_code_hex> will resolve to the contract info json file (showing the source, compiler version and params which allows contract source verification for instance)

zelig commented 8 years ago

i think subdomain ordering is silly but i would suggest conforming to url standard so that existing url parsing libs can be used on our addresses in dapps. pragmatic decisions like this matter a lot in adoption

frozeman commented 8 years ago

I see it as follows:

Special links like contract addresses, should be prefixed with contract:, like currently for emails, bitcoin or skype numbers (mailto:, bitcoin:, skype:). So it would be:
eth://contract:0x123456789098765432...

This would show a JSON with all the necessary stored information about a contract (Interface, natspec, source)

zelig commented 8 years ago

done in Mist, so not every node needs to implement the same registry behaviour [though debateable]

yes I debate this. As I said if they support IPNS or Swarm anyway, their resolver is already supported In fact duplicating the resolvers code in mist is a bad idea. But defining a great scheme specific namereg template contract is very important.

So once again. If I use IPFS and have a name already registered with methods other than the ethereum contract, I still want it to be available in mist, so we will need to proxy the name to IPFS scheme handler anyway (which, in geth, will probably be done by swarm as well) unless you reimplement the entire IPFS name resolution in mist. Conversely if i register my ipfs hash with the ethereum namereg, I also want other (non-ethereum) users of IPFS to see this, which means ethereum-IPFS name resolution should be implemented as part of IPFS anyway.

alexvandesande commented 8 years ago

@zelig Contract names, url hints and content hashes: I think all of those should be separate contracts. Maybe I'll remove all info from registry except owner and renewal date and let all use cases be handled by their own contract.

So you can have a contract that pairs hashes > hashes and another for hashes > url hints and another for hashes > eth address and so on. Those entries can only be edited by the owner account held on the main registry contract.

This allows greater extensibility but at the cost of the user having to do more transactions to register basic information.

I don't understand the point of name register duplication: if you have already registered a name in IPFS or swarm that uses a completely different set of rules you'll obviously need to register again, there's no going around it.

I don't particularly like the structure eth://contract:0xdeadbeef but this isn't the place to have this discussion in my opinion.

frozeman commented 8 years ago

@zelig Why is it done twice? bzz:// then shouldn't lookup a namereg, as it only needs to resolve the given hashes to a file. We could also add a ipfs:// which only resolves to ifs hashes. This was the only real namereg is used in eth:// and all other protocols are protocol specific to one transport layer, like swarm or ipfs.

This is exactly what we should want it we want to be modular. Each module (bzz, eth) has its specifies a way to resolve things, and bzz:// shouldn't be the all in one solution. the eth:// registry is that (like http://, which can resolve to many things)

@alexvandesande concerning the contract:, this is to follow the browsers standard for specific actions. So click gin a link like this could actually open a specific mist popup, showing information about this contract.

We should follow the browsers standards, because thats the tools we have available and we have a lady a great way to extend them.

zelig commented 8 years ago

@frozeman we are going round and round. Please sit back and read my arguments again please.

bzz:// then shouldn't lookup a namereg well it does, and so does ipns

@alexvandesande

I don't understand the point of name register duplication: if you have already registered a name in IPFS or swarm that uses a completely different set of rules you'll obviously need to register again, there's no going around it.

? in order for what to happen? for my dapp to be displayed in Mist? Why? That would be rather unkind.

alexvandesande commented 8 years ago

@zelig

for my dapp to be displayed in Mist? Why?

Because namereg has a very specific auction model for resolving names. You can't circumvent it by registering it elsewhere.

If Bob registers "foobar" in swarm, Alice registers it on the Mist name reg and Eve registers it on ipfs, who owns it? From Mist's perspective, Alice, obviously, because it's the only one that it looks for.

Maybe we are talking about registering something else?

zelig commented 8 years ago

@alexvandesande if they write bzz://foobar bzz wins, if they write ipns://foobar.eth then ipfs, and not sure what mist name reg would be good for. Don't get me wrong I want to use your contract (auction model) in swarm and ipfs but mist does not need to implement the resolver.

alexvandesande commented 8 years ago

UPDATE: Election

I added this text to the end, describing a proposal on how elections would work.

The suggested voting mechanism is a mix of approved voting with Liquid democracy, as follows:

function setDelegate(string32 _ownedHash, address _delegate)

Instead of voting directly, a voter instead can decide to appoint a delegate. The contract verifies that the msg.sender is the owner of the _ownedHash and then moves his voter weight ('feesPaid') to the new _delegate

function unsetDelegate(string32 _ownedHash)

The voter removes his vote to his delegate and states that wants to vote himself.

function setVote(address[] approvedCandidates)

The voter selects an array of contracts he approves for the job of Collector Contract. These remain static and can be changed anytime. If you

function tallyVotes()

Instead of a fixed election cycle, votes can be counted at anytime if someone feels voter's preference have changed enough. The cost of counting the votes is paid by the function caller. First the function will calculate the voter's weight by the sum of his 'feesPaid' and the weight of all voters that delegate their vote into him. Votes can be delegated forward a finite number of time (3, 5 or 7, depending on gas costs).

Then all addresses the voter approved will be receive an equal number of votes as his weight. The Address with a higher number of approvals will be selected as the new Collector Contract, effectively immediately.

Smithgift commented 8 years ago

What should be the auction contract's response to two equal highest bids?

alexvandesande commented 8 years ago

@Smithgift select whichever was put first (date of putting sealed, not revealed)? Sounds like a case that can be avoided by bidders adding cents to their bids.

Smithgift commented 8 years ago

@alexvandesande I agree with "whichever was first." There will always be a definite winner under that rule.

Smithgift commented 8 years ago

I thought of a simple and powerful countertroll tactic, albeit that it's a little odd on the user part.

Suppose starting auctions is extremely cheap, and a philanthropic large ETH-holder decides to stand up and Fight the Bobcat Menace! He sets up a domain "faucet" which starts hundreds of new auctions a day. Almost all are worthless. However, anyone may suggest a hash to the faucet, and it will eventually be shoved out to the auction contract. A bobcatter can't tell which of the flood of auctions are the countertroll's, and which are the true hashes among them. It doesn't matter to the user, however, because all they want is that the auction gets started.

There are counter-counter measures, such as a bobcatter attacking (DDoS, say) the faucet, or impersonating a countertroll running such a faucet to collect potentially valuable hashes, and so on. At some point, bobcattery like that crosses from antisocial behavior into actual lawbreaking, though.

EDIT: The logical conclusion of this tactic is for everyone to spam the blockchain when they want to start an auction. Some may spend more or less in "camoflage" hashes. There's probably a Nash equilibrium between the amount the bobcatters have to spend and the amount of ETH true users waste in trying to hide from them.

ethers commented 8 years ago

This EIP should have an Implementation section; pls link to the code when it is ready.

frozeman commented 8 years ago

@ethers just to be overly correct. Its not an EIP ;) Its trying to find a consensus about a standard and requesting comments. (ERC) @alexvandesande Though we should add a proper contract tho.

pipermerriam commented 8 years ago

This is potentially relevant to the implementation of this system.

https://ldpreload.com/blog/names-to-reserve

taoteh1221 commented 8 years ago

I think buying new / unregistered names and renewing names should be some relatively fixed price (maybe some equation based off gas price), and have a 10 year maximum, like the internet domain name registry system is today...but of course have auctions to sell a name as you propose. Maybe even the auction part could use "auction / buy now" format like eBay uses? These methods are tried and true and widely used.

taoteh1221 commented 8 years ago

I also think new / unregistered name purchases and renewing names should be a miner reward, like transaction fees are today. This is a great incentive for people to mine / stake tokens.

Smithgift commented 8 years ago

@taoteh1221: The issue with fixed price domains is that an attacker can create a transaction with higher gas price, purchasing the same name, and chances are that transaction will execute first. So we'd end up with a kind of auction system anyway.

taoteh1221 commented 8 years ago

@Smithgift I see. Sorry I'm still mostly a web2 guy ATM (that may change somewhat soon). Maybe a separate contract could be setup that is called by the registrar contract, with an algorithm fully devoted to storing an average gas price on X number of randomly selected blocks with a timestamp no older than X days? Any TX fees required for contract-to-contract communication could be funded at least partially by new / renewed name registrations (with the rest of the reg fee going to the miner of the first block it confirmed on).

alexvandesande commented 8 years ago

@Smithgift fixed price encourages squatting. We want to encourage utility. I agree on the fixed maximum: I would say the maximum should be twice the current age of the domain to at most 10 years, so a new domain will need more frequent auctions.

tymat commented 8 years ago

I think doing namespaces would be a good inroad to making this compatible with existing web standards. Something along the lines of io.digix.goldtokens. Some external 3rd party service Oraclize.It can be used to validate domain ownership like requiring the domain owner to put a file on a web server or adding domain TXT records that can be verified by Oraclize.It. This would avoid any type of disputes.

alexvandesande commented 8 years ago

One of the suggestions I've had was to do a series of configurable name registries that are called one after the other. So if registry A doesn't have the name then check B then C and so on. This of course only applies to top level domains, all other domains are derived from there.

Your proposal would be a good example on how this could work, so if you add oraclize domain checker then it would first check if top level domain was assigned on the internet already. If it was, then it would use the same oraclize api to resolve the second level domain into an address or IP. If the top level domain isn't assigned (and since we plan to only allow 5+ letter words in the beginning it would be most of them) then it checks with the mist registrar then with any other configurable registrar.

That would work well!

On Fri, Feb 19, 2016 at 11:39 AM, Anthony Eufemio notifications@github.com wrote:

I think doing namespaces would be a good inroad to making this compatible with existing web standards. Something along the lines of io.digix.goldtokens. Some external 3rd party service Oraclize.It can be used to validate domain ownership like requiring the domain owner to put a file on a web server or adding domain TXT records that can be verified by Oraclize.It. This would avoid any type of disputes.

— Reply to this email directly or view it on GitHub https://github.com/ethereum/EIPs/issues/26#issuecomment-186216119.

Alex Van de Sande UX Designer

frozeman commented 8 years ago

As far as i know it would take a whole 2 blocks roundtrip before oracalize can get any information into the blockchain, which would be requested... Not sure if that works for a domain lookup :)

alexvandesande commented 8 years ago

In this particular case oraclize could simply store information on all top level domains which is a finite number and doable. Once oraclize comes back and tells to treat it as a web domain we could simply treat the remaining as www address.

On Fri, Feb 19, 2016 at 12:40 PM, Fabian Vogelsteller < notifications@github.com> wrote:

As far as i know it would take a whole 2 blocks roundtrip before oracalize can get any information into the blockchain, which would be requested... Not sure if that works for a domain lookup :)

— Reply to this email directly or view it on GitHub https://github.com/ethereum/EIPs/issues/26#issuecomment-186239742.

Alex Van de Sande UX Designer

JohnDorien1 commented 8 years ago

I do strongly disagree with a number of points included in this: 1: A new auction for each renewal will kill small businesses. Simple reason, they can easily be overbid by anyone with more funds. In result it is not worth for a small to medium business at all to register a name here. 2: This system massively favours the rich. I favourize have squatters some more names than only a hand full of whales owning all names. Squatters might sell their names more likely as long as they are in profit, and at a general lower price than a high-price-bought domain by a whale, so its better for the ecosystem. If a high-end name like google will have a higher price, you have an average user having more funds instead of a whale having even more funds. Very benefical for the ecosystem. 3: The hashing; This is a high limitation for not-so-technical-versatile users. I do see the general advantage, but the downside of usability is too heavy 4: Renewal periods: They should be fixed, and non-changing. There might be an added option to "release" a domain that is not needed anymore, but changing times that require the renewal are definitely worst possible option - again, thinking mostly of possible businesses on here. 5: In any way this is implemented, it should take over all the currently registered names and their owners from the current registrar

Cryptix23 commented 8 years ago

Hi everyone in this discussion. I came here based on suggestion of @alexvandesande after we had a discussion on gitter about the namereg topic. I strongly agree with @JohnDorien1 about the points he underlined regarding those sides of nameregistrar business. As I tried to explain and point out an Auction based system (blind or whatever) would only favour those who holds extremely big capitals (both in ETH or BTC or FIAT) whom would be able to overbid every auction with disadvantage of little and medium users. After reasoning on this topic for about a week i think that is far better having "little squatters" of names instead of Big whales/multicorporation being able to buy everything. @JohnDorien1 explained this very well

Squatters might sell their names more likely as long as they are in profit, and at a general lower price than a high-price-bought domain by a whale, so its better for the ecosystem. If a high-end name like google will have a higher price, you have an average user having more funds instead of a whale having even more funds. Very benefical for the ecosystem.

I was also pointing out how is needed a "default hardcoded" namereg contract (as is now :) ). Of course we need to leave the chance to change it with their preferred or personal one to the end users, but is important (regarding ETH user-friendliness) having a sort of default namereg for non-skilled users (that sooner or later will represent the majority of the ETH ecosystem). I explained where the big issue could come from:

Bob, Alice and Frank are ETH users. Bob and Alice wants to make a trasaction between them. Bob has registered a name "Bob" for its own address "0x987..." and Alice registered it own name "Alice" for her address "0x3c4..." . Luckily there is a "default hardcoded" namereg so they have registered the names on the same "namereg network". Then Bob say to Alice to send 1 ETH to him using his name "Bob" instead of the address. Alice sends 1 ETH to "Bob" instead of using the address and everything goes fine.

Now imagine if no default hardcoded namereg would exist: Bob & Alice are newbie users, Frank is a pro-user. Bob and Alice register their names to their addresses BUT they make the mistakes of using two different nameregs to do so. Then Frank register the name "Bob" on Alice's namereg and the name "Alice" in the Bob's namereg. So Bob and Alice wants to make the 1 ETH transaction. But unfortuanatly since they are newbies made such mistakes of having registered the names on 2 different registars. Frank then can tries to impersonate of one them and i.e. he can convince Bob to send coins towards name "Alice" on Bob's namereg. Bob knows that Alice has effectively registered an "Alice" name to her address but he doesn't know about the different nameregs mistake. So when he sends 1 ETH to "Alice" this will arrive insted to Frank's address named "Alice" on the Bob's namereg network.

This is just one example of how not having a default hardcoded namereg could mine the newbies usability of such functionality.

If any change to namereg will be made such radically at least try to keep in mind also the point n° 5 of @JohnDorien1 post above.

My regards.