134 lines
6.2 KiB
Markdown
134 lines
6.2 KiB
Markdown
|
---
|
||
|
eip: 2666
|
||
|
title: Repricing of precompiles and Keccak256 function
|
||
|
author: Alex Vlasov (@shamatar)
|
||
|
discussions-to: https://ethereum-magicians.org/t/eip2666-global-precompiles-repricing-and-many-more-discussion-thread/4332
|
||
|
status: Stagnant
|
||
|
type: Standards Track
|
||
|
category: Core
|
||
|
created: 2020-05-22
|
||
|
requires: 1352, 2046, 2565
|
||
|
---
|
||
|
|
||
|
## Simple Summary
|
||
|
|
||
|
This EIP tries to set prices of certain precompiles and built-in EVM function to be in line with their performance, consumed resources and newer changes in EVM itself.
|
||
|
|
||
|
New price formulas are proposed for:
|
||
|
- SHA256 precompile (`0x02`)
|
||
|
- RIPEMD precompile (`0x03`)
|
||
|
- KECCAK256 opcode (`0x20`)
|
||
|
|
||
|
## Abstract
|
||
|
|
||
|
Costs of many precompiles and built-in functions are invalid at the current state of the clients. This EIP contains a list of changes to the pricing formulas to better reflect underlying computations' structure.
|
||
|
|
||
|
## Motivation
|
||
|
|
||
|
Historical pricing for these functions in EVM does not reflect inner structure of the underlying computations (inner structure of the hash functions).
|
||
|
|
||
|
- EIP-2046 changes a `STATICCALL (0xfa)` cost to precompile and it may be necessary to adjust costs of some precompiles that *may* have taken old large cost (`700` gas) into account and tried to compensate for it
|
||
|
- Some precompiles are overpriced and their pricing formulas do not reflect the structure of underlying functions
|
||
|
- Keccak256 built-in function (opcode) in EVM has pricing that does not reflect underlying hash function structure
|
||
|
|
||
|
## Specification
|
||
|
|
||
|
If `block_number >= X` set the gas cost of the following precompiles and Keccak256 opcode:
|
||
|
- SHA256 (precompile `0x02`): `10 + ((len(input) + 8)/64 + 1) * 9`
|
||
|
- RIPEMD (precompile `0x03`): `6 + ((len(input) + 8)/64 + 1) * 12`
|
||
|
- KECCAK256 (`0x20`): `13 + (len(input)/136 + 1)*15`
|
||
|
|
||
|
This EIP *ideally* requires that `MODEXP` repricing is [implemented](./eip-2565.md) to also accurately reflect that there is no implicit compensation for an old `STATICCALL (0xfa)` cost (pre-2046).
|
||
|
|
||
|
## Rationale
|
||
|
Cost of functions being executed must accurately reflect real CPU time spent on computations, so benchmarking was performed for current precompiles and Keccak256 function to measure running time versus input parameters.
|
||
|
|
||
|
### Detailed summary of repricing approach
|
||
|
|
||
|
This EIP relies on two facts:
|
||
|
- apriori knowledge of the inner strucute of the hash functions
|
||
|
- benchmarks provided by the client teams for some reasonable range of input lengths for random inputs (random byte strings of a given length)
|
||
|
|
||
|
### Benchmarks on the most popular clients
|
||
|
|
||
|
Necessary benchmarks for EIP-2666 were provided by the clients and raw form is assembled in [here](https://docs.google.com/spreadsheets/d/1aCQnk7prrp3Mbcf011BE5zZnkbc3Iw7QAixn6mLbKS0/edit?usp=sharing)
|
||
|
|
||
|
- SHA256 precompile
|
||
|
|
||
|
Currently it's `60` gas + `12` gas per `32` byte word (number of words is `ceil(len(input)/word_len)` here and in similar places. If there is no `floor` or `ceil` specifier all divisions below are integer divisions (floor divisions)). Proposed formula is `A * ((len(input) + 8) / 64 + 1) + B`, with coefficients below
|
||
|
|
||
|
| | | A | B |
|
||
|
|---|---|---|---|
|
||
|
| Geth | | 5 | 3 |
|
||
|
| OE | | 9 | 4 |
|
||
|
| Besu | | 5 | 10 |
|
||
|
| Nethermind | | 10 | 5 |
|
||
|
|
||
|
EIP-2666 proposes `A = 9`, `B = 10`. There are no large one-off costs in this precompile, so it's EIP-2046 - safe.
|
||
|
|
||
|
- RIPEMD precompile
|
||
|
|
||
|
Currently it's `600` gas + `120` gas per `32` byte word. Proposed formula is `A * ((len(input) + 8) / 64 + 1) + B`, with coefficients below
|
||
|
|
||
|
| | | A | B |
|
||
|
|---|---|---|---|
|
||
|
| Geth | | 12 | 6 |
|
||
|
| OE | | 8 | 2 |
|
||
|
| Besu | | 29 | 16 |
|
||
|
| Nethermind | | 10 | 6 |
|
||
|
|
||
|
EIP-2666 proposes `A = 12`, `B = 6`. There are no large one-off costs in this precompile, so it's EIP-2046 - safe. Besu expects to have performance improvements by the end of the year.
|
||
|
|
||
|
- Keccak256 performance
|
||
|
|
||
|
Currently it's `30` gas + `6` gas per `32` byte word. Proposed formula is `A * (len(input) / 136 + 1) + B`, with coefficients below
|
||
|
|
||
|
| | | A | B |
|
||
|
|---|---|---|---|
|
||
|
| Geth | | 13 | 13 |
|
||
|
| OE | | 15 | 2 |
|
||
|
| Besu | | 19 | 28 |
|
||
|
| Nethermind | | 16 | 3 |
|
||
|
|
||
|
EIP-2666 proposes `A = 15`, `B = 13`. There are no large one-off costs in this precompile, so it's EIP-2046 - safe. Besu expects to have performance improvements by the end of the year.
|
||
|
|
||
|
### Tooling and data
|
||
|
|
||
|
Reference material (from benchmarks of different clients) with raw data can be found [here](https://docs.google.com/spreadsheets/d/1aCQnk7prrp3Mbcf011BE5zZnkbc3Iw7QAixn6mLbKS0/edit?usp=sharing).
|
||
|
|
||
|
There is a repository available with inputs for benchmarking and precompiles testing [here](https://github.com/shamatar/bench_precompiles) that can be used by client teams to perform all the necessary measurements.
|
||
|
|
||
|
Raw Besu [benchmarks](https://gist.github.com/shemnon/0ddba91be501fa23291bdec9107fe99a).
|
||
|
|
||
|
### Note on formulas structure
|
||
|
|
||
|
There are terms in formulas that look like `A * 1` and those are explicitly not combined to the `B` coefficient to reflect that hash of an empty byte array requires to perform a round of hashing anyway.
|
||
|
|
||
|
## Backwards Compatibility
|
||
|
Precompile repricings has happened in a past and can be considered standard procedure. Gas costs of many contracts is expected to reduce that may break re-entrancy protection measures based on fixed gas costs. In any case, such protection should have never been considered good and final.
|
||
|
|
||
|
## Test Cases
|
||
|
|
||
|
Let's consider a simple example of Keccak256 hash of `0`, `64` and `160` bytes that can is a simple sanity check for implementation.
|
||
|
|
||
|
- Hash `0` bytes:
|
||
|
- Old price: `30 + 6 * ceil(0 / 32) = 30` gas
|
||
|
- New price: `15 * (0/136 + 1) + 13 = 28` gas
|
||
|
- Hash `64` bytes
|
||
|
- Old price: `30 + 6 * ceil(64 / 32) = 42` gas
|
||
|
- New price: `15 * (64/136 + 1) + 13 = 28` gas
|
||
|
- Hash `160` bytes
|
||
|
- Old price: `30 + 6 * ceil(160 / 32) = 60` gas
|
||
|
- New price: `15 * (160/136 + 1) + 13 = 43` gas
|
||
|
|
||
|
## Implementation
|
||
|
|
||
|
There is no reference implementation at the time of writing as it requires just a simple change of constants in major clients.
|
||
|
|
||
|
## Security Considerations
|
||
|
|
||
|
As described in backward compatibility section in some cases reduction of cost may allow e.g. re-entrancy that was not expected before, but we think that re-entrancy protection based on fixed gas costs is anyway flawed design decision.
|
||
|
|
||
|
## Copyright
|
||
|
Copyright and related rights waived via [CC0](../LICENSE.md).
|