Today the network was hit by a transaction spam attack that repeatedly called the EXTCODESIZE opcode (see trace sample). here), the ~50,000 disk fetches required to process a transaction result in blocks that take up to 20-60 seconds to validate. As a result, the block generation rate was reduced by a factor of 2-3 during the attack. There were no consensus failures (e.g. network forks) and neither the network nor its clients were completely disrupted at any point. The attacks have since largely stopped and the network is currently recovering.
A short-term solution is for users, including miners, enterprise users (including exchanges), and individuals, to run geth using the flag.
–cache 1024 –targetgaslimit 1500000 –gasprice 20000000000
Or parity with flags:
–cache-size-db 1024 –gas-floor-target 1500000 –gasprice 20000000000 –gas-cap 1500000
This (i) reduces the number of disk reads a node must perform by increasing the cache size, and (ii) reduces the maximum processing time of a block by a similar factor by lowering the gas limit by ~3x.
In the medium term (e.g. a few days to a week), we are actively working on a number of fixes to the Go client that could provide more reliable solutions to current issues and mitigate the risk of similar attacks. These include:
- If the miner encounters a block taking more than 5 seconds to process, we will make a change to the miner software that automatically reduces the gas limit target by a factor of 2 temporarily, allowing a similar adjustment to what was adjusted today to occur automatically (see here For pull requests, this is a minor strategy change and not a soft fork or hard fork.)
- Numerical adjustments to cache settings
- Add additional cache
- Added additional cache specifically for EXTCODESIZE (since the contract being read is ~18KB long, EXTCODESIZE reads are likely to be several orders of magnitude slower than other IO-heavy operations)
- An on-disk cache that can store state values more quickly, e.g. O(log(n)) speedup) accessed
We are also exploring options to replace the leveldb database with a more performant and optimized database for our use cases, but that change will not be happening anytime soon. The Parity team is working on performance improvements ourselves.
In the long term, there are also low-level protocol changes that can be explored. For example, it may be wise to add a feature to Metropolis that increases the gas cost of opcodes that require read operations, such as reading account status (SLOAD, EXTCODESIZE, CALL, etc.), especially reading external accounts. It may seem like just increasing the gas cost of all these operations to at least 500 would be sufficient, but care must be taken to avoid breaking any existing contracts (e.g. implementing them simultaneously). EIP 90 will be sufficient).
This sets a much lower cap on the maximum number of bytes a transaction can read, increasing safety against all potential attacks of this kind and reducing the size of the Merkle proof, improving security for both light clients and sharding. effect. Currently we are focused on more immediate software level changes. However, in the long term, such proposals should be discussed and contract developers should be aware that these kinds of changes may occur.