As Micah mentioned, the scheme you describe can probably be frontrun, Lets say Alice is the victim, Bob is an evil miner, and C is the ENS contract.
A sends a commit transaction to C saying “I want the domain ‘q=obfuscated(Z.eth, salt)’”. Then A sends a reveal transaction “here is my money for q, and btw here is my secret salt that makes q open up to Z.eth”. Evil miner Bob sees this reveal tx hit mempool, does the computation to find Z, and then makes two transactions (instead of one), a valid commit of his own and a valid reveal of his own. Either Bob inserts these two txs into mempool with a higher gas price than alice, or colludes with miners to get his txs into the block first, and he wins the name instead of her.
So you have to order by commit time, which becomes harder, and additionally, commit-reveal is still problematic in some cases because just knowing that someone is committing to a certain contract may leak valuable information. In the context of ENS this may not matter as much, since you can obfuscate within the commit which specific domain is desired… but our research group at IC3 has done some thinking about this topic in the general case, and what we came up with was a technique we call submarine sends. We also have an open source project to develop a library called libsubmarine that we would like to be portable and reusable for the community to start solving this problem in smart contracts. It isn’t ready for prime-time yet, but may be ready by the time that ENS is ready for launch.
The way we do it requires 4 transactions right now (though I suspect you could do it in two if you optimized a bit), I’ll try to summarize briefly, though I might skip some minor details. There’s more detailed documentation on the ReadMe on Github, admittedly we haven’t done an awesome job of documentation but we’re trying to focus on polishing the library up to scratch.
- You generate a TXUnlock off chain. This is a transaction from a random address you do not own the private key for. You generate it by filling in the target ENS smart contract as your To: address and the value of your bid as the amount, maybe some arbitrary data as well, then instead of signing the signature with a private key you own, you
generate r and s values which are random numbers derived from keccak256(witness, data, random nonce for randomness, etc). This gets you something that looks like a valid transaction, if the commit address which is ecrecover(r,s) actually had enough money to carry it out, so you don’t broadcast it.
- The first thing you do on chain is commit, you send the required amount of money + a little extra for gas costs to the commit address. This looks a send of money to a random new address, which happens a fair amount as it is, so it provides cover. Additionally this has the nice property that you’re not sending this transaction to the ENS contract so at this point the miners have no idea that you’re actually trying to make a bid.
- Now you reveal. You tell the library what block and tx index your commit happened in. You also tell during this part the witness/ENS name you want. The library stores this information.
- Now you have a challenge period. The purpose of this is to allow anyone else watching the network to call BS on your commitment. This is to prevent an attacker from claiming a commitment that doesn’t exist, or claiming that a previous non-related Tx is a commitment (when in fact it was not). Anyone who sees this can verify the validity of commitments and if a commitment is invalid submit a merkle proof to the library to prove that the referenced commitment is invalid; in this case the prover is rewarded and the commitment is slashed.
- Finally after the challenge period is over you make a finalize call, and the ENS contract can safely allocate the domain to the bidder.
(One important note: we rely on the blockhash() solidity call so our implementation has the explicit requirement that the distance between commit and reveal must be less than 256 blocks)
As you can see there’s a fair bit of overhead. You may decide preventing frontrunning on ENS isn’t worth the overhead. But if you decide to use our library or roll your own solution you may want to reference our code since we’ve already been trying to solve the problem in the general case.