Vitalik Buterin on Empty Accounts and the Ethereum State
Ethereum’s latest fork, Spurious Dragon, executed on November 22nd as planned. After a minor hiccup lead to a temporary consensus issue between the two major Ethereum clients, Geth and Parity, the clients were updated, the issue was solved, and the hard fork rolled along. This recent fork put a stop to denial of service (DoS) attacks on the network, as well as debloated the network by deleting empty accounts leftover from previous DoS attacks.
Over the weekend, Vitalik Buterin took to reddit to answer many Ethereum users and enthusiasts’ questions on “why the state needed to be cleared.” The state, otherwise known as the Ethereum tree (trie), is a set of information that represents the “current state” of a system; determining whether or not a transaction is valid, and the effect of the transaction on the network. A block in the Ethereum blockchain has a header, a list of transactions, and a list of uncle blocks. The header contains the information (root hash) that’s used to validate a transaction. This list of transactions is assembled in a special data tree-like structure called the Ethereum tree. The Ethereum tree is, more simply, a data structure that holds a “dictionary” of abstract data. If a block consists of empty transactions with an empty data structure, this “clogs” up the tree.
For a little more clarification on the state, when Ethereum underwent a barrage of DoS attacks back in September, it created a large number of empty accounts within the Ethereum network (the state). Empty accounts have the same functional equivalency to nonexistent accounts, however, unlike nonexistent accounts, empty accounts waste hard drive space, increase sync time, and slows down processing time. The Spurious Dragon fork was a solution to clearing out these empty accounts.
Here is Vitalik Buterin’s full explanation on clearing the state, and what users need to do:
Why does the state need to be cleared?
During the denial of service attacks in October, the attacker exploited a protocol flaw to very cheaply create a large number of empty accounts in the ethereum state. This was done by repeatedly using the SUICIDE opcode's ether transfer functionality to "poke" a new account into existence, and then repeatedly calling the same contract over and over again within a single transaction until it gets deleted. This method was able to create a new account at a cost of only 90 gas, and the attacker created ~19 million empty accounts in total before the EIP 150 hard fork in October made it no longer possible to do this.
What is an empty account?
An empty account is an account that has zero balance, nonce and code. Empty accounts are functionally equivalent to nonexistent accounts with the exception of a few gas calculations, and empty accounts can easily be turned into nonempty accounts by simply sending any amount of ether to them. Theoretically, if miners accept transactions with zero fees, even sending a transaction from an empty or nonexistent account is possible. The only practical difference is that empty accounts need to be stored in the Ethereum state tree, whereas nonexistent accounts do not.
What's wrong with having 19 million empty accounts in the state tree?
- They waste hard drive space
- They increase sync time, especially fast sync and warp sync
- They slow down transaction processing, as it becomes much harder to store much or all of the state in RAM and so many more disk accesses are needed.
What are we doing to remove them?
The Spurious Dragon hard fork introduced a new protocol rule, by which (i) no new empty accounts can be created (any operation which previously would have created an empty account instead leaves the account nonexistent), and (ii) one can "poke" empty accounts to delete them.
In the short term, this introduces a way to remove these accounts. In the medium term, once all empty accounts are deleted, this simplifies the Ethereum protocol specification, as there is no longer a concept of account "existence" that implementations must keep track of; instead, whether or not an account needs to be stored in the state tree can be directly inferred from the account's balance, nonce and code.
The fork was been implemented earlier this week. Now, we need to send ~40,000 transactions to the Ethereum network with the goal of running loops that "poke" all of the empty accounts that the attacker created so as to remove them.
The spam is slowing my node down. Did you have to use this method? Why not just have an in-protocol sweep that deletes every account automatically?
The reason why these transactions are slowing nodes down to the extent that they are is that every poke deletes an account, which requires ~5-10 writes to the database on disk. Any procedure which did the same thing over time would have had the same effect. One could imagine a procedure that simply regenerates a new state from scratch, and this may have been more efficient, but this would have been much more complex to code and test and would have had even higher risks of consensus failure.
Is this a DoS attack that could later be used by an attacker?
No. Once all empty accounts are cleared, further pokes to accounts have no effect if they do not transfer value, and value-transferring calls are charged an additional 9000 gas so they cannot be done cheaply; at that point, it will not be possible to use this technique to create transactions that are slow to process.
How long is this going to take?
So far, about 4 million empty accounts have already been cleared, and about 15 million remain. We expect the process to take about a week.
Where can I watch the clearing process taking place?
The clearing contract is here: https://etherscan.io/address/0xa43ebd8939d8328f5858119a3fb65f65c864c6dd. You can watch the transactions coming in on ethstats here: https://ethstats.net/. Note that clearing may not be running 24/7; sometimes it may stop for a few minutes or hours for various technical reasons, and this is not cause for immediate concern.
Does this affect immutability?
No. Because empty accounts are now functionally equivalent to nonexistent accounts with the exception of how they are factored into the state tree root, the account deletion process otherwise has no effect on the "meaning" of anything in the ethereum state. Any account that had ether before still has that ether, any account that had maker coins before still has those maker coins, and the execution rules of all contracts are exactly the same. If an account gets deleted, then sending any amount of ether to that account restores that account and the ether and other assets in that account can be spent as normal.
What do I need to do?
Make sure your node is updated. If your computer does not have an SSD, consider taking this opportunity to check out the geth light client, as HDDs are very slow to read and write from disk. Otherwise, the effect for you will be fairly minimal.