> Again, let’s design a simple smart contract. This time Alice wants to play a guessing game. Alice puts 5 Ether in her contract. That ETH goes to the person that guesses closest to the number she’s thinking of. Alice calls commit with the hash of the number, so she can’t change her mind. Anyone else can call guess to submit a guess. After 2 blocks Alice calls reveal to tell everyone what the number is.
This scheme is not unsafe because of miners. Transactions are public. As soon as Alice’s “reveal” message is published to the network, everyone can submit guesses using the revealed number. And miners are incentivized to include whichever transaction pays the highest fee, which means the transaction fee of the guessing transactions published after the “reveal” transaction will converge with the prize sum.
Alice’s commit transaction needs to specify some block height after which further guesses are ignored, and then publish the “reveal” message some (safe) number of blocks after this.
Full disclosure: tech lead on Keep (the project whose blog this is posted to), and the post is by one of our advisors.
You're right that this particular example has other downsides. The goal was to present the simplest examples of some attacks and issues that are easy to miss when doing blockchain programming. As I mentioned in another comment (https://news.ycombinator.com/item?id=16144892), the important thing is that, as a developer for a given chain, you need to be aware of the pitfalls of your chain (keeping in mind some apply across chains) so you can design around them. That includes the pitfall you described---everything is public, and that introduces some careful decisions that need to be made when building smart contracts. That one is pretty widely discussed; on the other hand, we hadn't seen any other content with a basic introduction to the pitfalls around miner misbehavior, so we felt James's post was super valuable.
I think a key piece of it is the last paragraph:
> Miners aren’t your friends or enemies — they’re a force of nature in our consensus systems. Systems that fail to plan around this will eventually lose out to clever miners.
We've built many systems today that fail to take into account the dangers of ignoring security, and we're starting to pay the price. Public blockchain apps will need to be careful to have a decent understanding of the threats, especially since many of these threats have the potential to be even more directly tied to money than security issues in current systems. The more important (you consider) your system, the more important it is that your threat model include entities that are required for your system to function, like miners.
So in the same way a competent web programmer understands CSRF and XSS, a competent backend programmer understands SQL injection, and a competent node programmer understands concurrency vs. parallelism, there's a whole new set of paradigms (and interview questions!) that competent blockchain programmers will need to know.
The is-blockchain-hype-or-here-to-stay debate will unambiguously be settled if OWASP ever publishes a top-10 blockchain programming list.
> ...there's a whole new set of paradigms (and interview questions!) that competent blockchain programmers will need to know.
Yes, "paradigms" in the sense that broken bones and multiresistent germ infections are technically both "injuries" and can be fixed by "healing".
I think securing code against random accidents or even against specific, well-known vulnerabilities is something entirely different than writing a program for a processor that actively works against you.
We're realizing this right now in the context of adversarial code with Meltdown/Spectre and Rowhammer. I think this is a similar but even worse situation.
> Alice’s commit transaction needs to specify some block height after which further guesses are ignored, and then publish the “reveal” message some (safe) number of blocks after this.
I think this is unsafe as well. Noted that since everyone can verify the real answer, there is no point for Alice to reveal it. As a result, as soon as anyone submits the correct answer, the miners can cheat and replace the answer as their own.
After some degree of thinking, I find that it is quite difficult to design a secure smart contract such guessing game. I haven’t find a way can fulfill all following security properties: (a) the Alice has to pay for the first person who finds the correct answer; (b) that person can only collect reward after showing the the correct answer; and (c) the miner cannot cheat.
I wonder if anyone has a solution for the above problem. Also, if such solution exists, we can actually use it to implement the RSA challenge [1] in smart contract.
One solution is to formulate the contract so that guessers submit a hash of (guess, nonce). The contract records each submission. A few blocks after the submission deadline, Alice reveals the correct answer. Then submitters of correct guesses send another message to the contract with their nonce. The contract gives the reward to the person who submitted a correct guess the earliest.
You can solve that with additional step:
1. Alice send the challenge.
2. You submit the answered, encrypted.
3. After you verify that your answer was included in a block, you post the private key you used for the encrypted answer.
4. Profit
I think the miner can cheat in step 3. After you submit your private key as a transaction, the miner can delay it to be included in the blockchain for arbitrary time. During which, the miner can use your private key to decrypt your answer submit in step 2. And resubmit their version of the answer.
That won't help him much, since my answer is already published in the blockchain when he will publish his answer.It is trivial to see that my answer was published first.
If the commitment uses a salt, it won’t be possible for anyone to verify guesses before Alice publishes the reveal message (which would include the salt).
In any case, the blog post has Alice rewarding whoever comes closest, not whoever guesses the exact value. For a sufficiently large range of numbers (e.g. 128 bits), you wouldn’t really need a salt since the probability of anyone guessing the exact value would be negligible.
This surely is a very bad thing. I'm not saying programming smart contracts should be trivial. Or maybe I am.
I guess the thing is - for Ethereum to have any chance of surviving it needs to be simple to write simple contracts. Easy things should be easy and hard things should be possible. And footguns should be removed from the language...
Hey, author here. Yeah, several of the example contracts are insecure in other ways. Or just plain bad ideas. I decided against providing implementations because I was worried people wouldn't understand that.
> And miners are incentivized to include whichever transaction pays the highest fee, which means the transaction fee of the guessing transactions published after the “reveal” transaction will converge with the prize sum.
Except the miner can simply include the transactions but add its own guess before all of them - so the miner would collect the fees and the guessing game prize.
This scheme is not unsafe because of miners. Transactions are public. As soon as Alice’s “reveal” message is published to the network, everyone can submit guesses using the revealed number. And miners are incentivized to include whichever transaction pays the highest fee, which means the transaction fee of the guessing transactions published after the “reveal” transaction will converge with the prize sum.
Alice’s commit transaction needs to specify some block height after which further guesses are ignored, and then publish the “reveal” message some (safe) number of blocks after this.