EIPs/EIPS/eip-145.md

378 lines
11 KiB
Markdown
Raw Normal View History

---
2018-03-21 12:51:05 +00:00
eip: 145
title: Bitwise shifting instructions in EVM
2018-09-18 23:26:06 +00:00
author: Alex Beregszaszi (@axic), Paweł Bylica
type: Standards Track
2018-03-21 12:51:05 +00:00
category: Core
status: Final
2018-03-21 12:51:05 +00:00
created: 2017-02-13
---
2017-02-13 16:05:22 +00:00
## Simple Summary
To provide native bitwise shifting with cost on par with other arithmetic operations.
## Abstract
2017-09-22 13:04:45 +00:00
Native bitwise shifting instructions are introduced, which are more efficient processing wise on the host and are cheaper to use by a contract.
2017-02-13 16:05:22 +00:00
## Motivation
EVM is lacking bitwise shifting operators, but supports other logical and arithmetic operators. Shift operations can be implemented via arithmetic operators, but that has a higher cost and requires more processing time from the host. Implementing `SHL` and `SHR` using arithmetics cost each 35 gas, while the proposed instructions take 3 gas.
## Specification
The following instructions are introduced:
### `0x1b`: `SHL` (shift left)
2017-09-22 15:07:34 +00:00
The `SHL` instruction (shift left) pops 2 values from the stack, first `arg1` and then `arg2`, and pushes on the stack `arg2` shifted to the left by `arg1` number of bits. The result is equal to
2017-02-13 16:05:22 +00:00
```
(arg2 * 2^arg1) mod 2^256
2017-02-13 16:05:22 +00:00
```
Notes:
- The value (`arg2`) is interpreted as an unsigned number.
- The shift amount (`arg1`) is interpreted as an unsigned number.
- If the shift amount (`arg1`) is greater or equal 256 the result is 0.
- This is equivalent to `PUSH1 2 EXP MUL`.
2017-02-13 16:05:22 +00:00
### `0x1c`: `SHR` (logical shift right)
2017-09-22 15:07:34 +00:00
The `SHR` instruction (logical shift right) pops 2 values from the stack, first `arg1` and then `arg2`, and pushes on the stack `arg2` shifted to the right by `arg1` number of bits with zero fill. The result is equal to
2017-02-13 16:05:22 +00:00
```
floor(arg2 / 2^arg1)
2017-02-13 16:05:22 +00:00
```
Notes:
- The value (`arg2`) is interpreted as an unsigned number.
- The shift amount (`arg1`) is interpreted as an unsigned number.
- If the shift amount (`arg1`) is greater or equal 256 the result is 0.
- This is equivalent to `PUSH1 2 EXP DIV`.
2017-02-13 16:05:22 +00:00
### `0x1d`: `SAR` (arithmetic shift right)
2017-09-22 15:07:34 +00:00
The `SAR` instruction (arithmetic shift right) pops 2 values from the stack, first `arg1` and then `arg2`, and pushes on the stack `arg2` shifted to the right by `arg1` number of bits with sign extension. The result is equal to
2017-02-13 16:05:22 +00:00
```
floor(arg2 / 2^arg1)
2017-02-13 16:05:22 +00:00
```
Notes:
- The value (`arg2`) is interpreted as a signed number.
- The shift amount (`arg1`) is interpreted as an unsigned number.
- If the shift amount (`arg1`) is greater or equal 256 the result is 0 if `arg2` is non-negative or -1 if `arg2` is negative.
- This is **not** equivalent to `PUSH1 2 EXP SDIV`, since it rounds differently. See `SDIV(-1, 2) == 0`, while `SAR(-1, 1) == -1`.
2017-02-13 16:05:22 +00:00
2017-04-23 10:28:25 +00:00
The cost of the shift instructions is set at `verylow` tier (3 gas).
2017-02-13 16:05:22 +00:00
## Rationale
Instruction operands were chosen to fit the more natural use case of shifting a value already on the stack. This means the operand order is swapped compared to most arithmetic insturctions.
2017-02-13 16:05:22 +00:00
## Backwards Compatibility
The newly introduced instructions have no effect on bytecode created in the past.
## Test Cases
2018-01-30 21:28:24 +00:00
### `SHL` (shift left)
1. ```
PUSH 0x0000000000000000000000000000000000000000000000000000000000000001
PUSH 0x00
SHL
---
0x0000000000000000000000000000000000000000000000000000000000000001
```
2. ```
PUSH 0x0000000000000000000000000000000000000000000000000000000000000001
PUSH 0x01
SHL
---
0x0000000000000000000000000000000000000000000000000000000000000002
```
3. ```
PUSH 0x0000000000000000000000000000000000000000000000000000000000000001
PUSH 0xff
SHL
---
0x8000000000000000000000000000000000000000000000000000000000000000
```
4. ```
PUSH 0x0000000000000000000000000000000000000000000000000000000000000001
PUSH 0x0100
SHL
---
0x0000000000000000000000000000000000000000000000000000000000000000
```
5. ```
PUSH 0x0000000000000000000000000000000000000000000000000000000000000001
PUSH 0x0101
SHL
---
0x0000000000000000000000000000000000000000000000000000000000000000
```
6. ```
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0x00
SHL
---
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
```
7. ```
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0x01
SHL
---
0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
```
8. ```
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0xff
SHL
---
0x8000000000000000000000000000000000000000000000000000000000000000
```
9. ```
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0x0100
SHL
---
0x0000000000000000000000000000000000000000000000000000000000000000
```
10. ```
PUSH 0x0000000000000000000000000000000000000000000000000000000000000000
PUSH 0x01
SHL
---
0x0000000000000000000000000000000000000000000000000000000000000000
```
2018-01-31 16:51:59 +00:00
11. ```
PUSH 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0x01
SHL
---
0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
```
2018-01-30 21:28:24 +00:00
### `SHR` (logical shift right)
1. ```
PUSH 0x0000000000000000000000000000000000000000000000000000000000000001
PUSH 0x00
SHR
---
0x0000000000000000000000000000000000000000000000000000000000000001
```
2. ```
PUSH 0x0000000000000000000000000000000000000000000000000000000000000001
PUSH 0x01
SHR
---
0x0000000000000000000000000000000000000000000000000000000000000000
```
3. ```
PUSH 0x8000000000000000000000000000000000000000000000000000000000000000
PUSH 0x01
SHR
---
0x4000000000000000000000000000000000000000000000000000000000000000
```
4. ```
PUSH 0x8000000000000000000000000000000000000000000000000000000000000000
PUSH 0xff
SHR
---
0x0000000000000000000000000000000000000000000000000000000000000001
```
5. ```
PUSH 0x8000000000000000000000000000000000000000000000000000000000000000
PUSH 0x0100
SHR
---
0x0000000000000000000000000000000000000000000000000000000000000000
```
6. ```
PUSH 0x8000000000000000000000000000000000000000000000000000000000000000
PUSH 0x0101
SHR
---
0x0000000000000000000000000000000000000000000000000000000000000000
```
7. ```
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0x00
SHR
---
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
```
8. ```
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0x01
SHR
---
0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
```
9. ```
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0xff
SHR
---
0x0000000000000000000000000000000000000000000000000000000000000001
```
10. ```
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0x0100
SHR
---
0x0000000000000000000000000000000000000000000000000000000000000000
```
11. ```
PUSH 0x0000000000000000000000000000000000000000000000000000000000000000
PUSH 0x01
SHR
---
0x0000000000000000000000000000000000000000000000000000000000000000
```
### `SAR` (arithmetic shift right)
1. ```
PUSH 0x0000000000000000000000000000000000000000000000000000000000000001
PUSH 0x00
SAR
---
0x0000000000000000000000000000000000000000000000000000000000000001
```
2. ```
PUSH 0x0000000000000000000000000000000000000000000000000000000000000001
PUSH 0x01
SAR
---
0x0000000000000000000000000000000000000000000000000000000000000000
```
3. ```
PUSH 0x8000000000000000000000000000000000000000000000000000000000000000
PUSH 0x01
SAR
---
2018-02-02 17:20:04 +00:00
0xc000000000000000000000000000000000000000000000000000000000000000
2018-01-30 21:28:24 +00:00
```
4. ```
PUSH 0x8000000000000000000000000000000000000000000000000000000000000000
PUSH 0xff
SAR
---
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
```
5. ```
PUSH 0x8000000000000000000000000000000000000000000000000000000000000000
PUSH 0x0100
SAR
---
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
```
6. ```
PUSH 0x8000000000000000000000000000000000000000000000000000000000000000
PUSH 0x0101
SAR
---
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
```
7. ```
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0x00
SAR
---
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
```
8. ```
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0x01
SAR
---
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
```
9. ```
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0xff
SAR
---
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
```
10. ```
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0x0100
SAR
---
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
```
11. ```
PUSH 0x0000000000000000000000000000000000000000000000000000000000000000
PUSH 0x01
SAR
---
0x0000000000000000000000000000000000000000000000000000000000000000
```
12. ```
PUSH 0x4000000000000000000000000000000000000000000000000000000000000000
PUSH 0xfe
SAR
---
0x0000000000000000000000000000000000000000000000000000000000000001
```
13. ```
PUSH 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0xf8
SAR
---
0x000000000000000000000000000000000000000000000000000000000000007f
```
2018-01-31 16:51:59 +00:00
14. ```
PUSH 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0xfe
SAR
---
0x0000000000000000000000000000000000000000000000000000000000000001
```
15. ```
PUSH 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0xff
SAR
---
0x0000000000000000000000000000000000000000000000000000000000000000
```
16. ```
PUSH 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0x0100
2018-01-31 16:51:59 +00:00
SAR
---
0x0000000000000000000000000000000000000000000000000000000000000000
```
2018-01-30 21:28:24 +00:00
2017-02-13 16:05:22 +00:00
## Implementation
Client support:
- cpp-ethereum: https://github.com/ethereum/cpp-ethereum/pull/4054
2017-02-13 16:05:22 +00:00
Compiler support:
2017-09-22 13:04:45 +00:00
- Solidity/LLL: https://github.com/ethereum/solidity/pull/2541
2017-02-13 16:05:22 +00:00
2018-03-22 18:51:52 +00:00
## Tests
Sources:
- https://github.com/ethereum/tests/tree/develop/src/GeneralStateTestsFiller/stShift
Filled Tests:
- https://github.com/ethereum/tests/tree/develop/GeneralStateTests/stShift
- https://github.com/ethereum/tests/tree/develop/BlockchainTests/GeneralStateTests/stShift
2017-02-13 16:05:22 +00:00
## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).