Computation And Turing-Completeness
An important note is that the Ethereum virtual machine is Turing-complete; this means
that EVM code can encode any computation that can be conceivably carried out, including
infinite loops. EVM code allows looping in two ways. First, there is a JUMP instruction that
allows the program to jump back to a previous spot in the code, and a JUMPI instruction
to do conditional jumping, allowing for statements like while x < 27: x = x * 2 .
Second, contracts can call other contracts, potentially allowing for looping through
recursion. This naturally leads to a problem: can malicious users essentially shut miners
and full nodes down by forcing them to enter into an infinite loop? The issue arises
because of a problem in computer science known as the halting problem: there is no way
to tell, in the general case, whether or not a given program will ever halt.
As described in the state transition section, our solution works by requiring a transaction
to set a maximum number of computational steps that it is allowed to take, and if
execution takes longer computation is reverted but fees are still paid. Messages work in
the same way. To show the motivation behind our solution, consider the following
examples:
An attacker creates a contract which runs an infinite loop, and then sends a transaction
activating that loop to the miner. The miner will process the transaction, running the
infinite loop, and wait for it to run out of gas. Even though the execution runs out of gas
and stops halfway through, the transaction is still valid and the miner still claims the fee
from the attacker for each computational step.
An attacker creates a very long infinite loop with the intent of forcing the miner to keep
computing for such a long time that by the time computation finishes a few more
blocks will have come out and it will not be possible for the miner to include the
transaction to claim the fee. However, the attacker will be required to submit a value
for STARTGAS limiting the number of computational steps that execution can take, so
the miner will know ahead of time that the computation will take an excessively large
number of steps.
An attacker sees a contract with code of some form like
send(A,contract.storage[A]); contract.storage[A] = 0 , and sends a
transaction with just enough gas to run the first step but not the second (ie. making a
withdrawal but not letting the balance go down). The contract author does not need to
worry about protecting against such attacks, because if execution stops halfway