Skip to content
This repository was archived by the owner on Feb 9, 2025. It is now read-only.

Commit 3bab1de

Browse files
chfastchrisethAndrei Maiboroda
committed
article: Apply suggestions from review
Co-Authored-By: chriseth <[email protected]> Co-Authored-By: Andrei Maiboroda <[email protected]>
1 parent c3bfb09 commit 3bab1de

File tree

1 file changed

+45
-38
lines changed

1 file changed

+45
-38
lines changed

docs/efficient_gas_calculation_algorithm.md

Lines changed: 45 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@ Let's start by defining some basic and universal instructions' parameters.
1111
1. Base gas cost.
1212

1313
This is the static gas cost of instructions. Some instructions may have
14-
additional cost depending on their operand values - these have to be
15-
handled individually during the instruction execution.
14+
_additional_ cost depending on their operand values and/or the environment
15+
— these have to be handled individually during the instruction execution.
16+
The _final_ cost is never less than the _base_ cost.
1617

1718
2. Stack height requirement.
1819

1920
This is the minimum stack height (number of items on the stack)
20-
required for the instruction execution.
21+
required prior to the instruction execution.
2122

2223
3. Stack height change.
2324

@@ -36,45 +37,49 @@ Examples:
3637
| CALL | 700 | 7 | -6 |
3738

3839

39-
## Basic blocks
40+
## Basic instruction blocks
4041

41-
A _basic block_ is a sequence of instructions that are executed "straight-line"
42-
without being interrupted by jumps. I.e. they are nodes in the _control flow graph_.
42+
A _basic instruction block_ is a sequence of "straight-line" instructions
43+
without jumps and jumpdests in the middle.
44+
Jumpdests are only allowed at the entry, jumps at the exit.
45+
Basic blocks are nodes in the _control flow graph_.
46+
See [Basic Block] in Wikipedia.
4347

44-
The name "basic block" has been taken from LLVM. Other names are: just "block"
45-
in wasm or "subroutine" in subroutine-threaded interpreters.
48+
In EVM there are simple rules to identify basic instruction block boundaries:
4649

47-
In EVM there are simple rules to identify basic block boundaries:
50+
1. A basic instruction block _starts_ right before:
51+
- the first instruction in the code,
52+
- `JUMPDEST` instruction.
4853

49-
1. The following instructions _end_ a basic block:
54+
2. A basic instruction block _ends_ after the "terminator" instructions:
5055
- `JUMP`,
5156
- `JUMPI`,
5257
- `STOP`,
5358
- `RETURN`,
5459
- `REVERT`,
55-
- `SELFDESTRUCT`,
56-
- an instruction directly preceding `JUMPDEST`.
60+
- `SELFDESTRUCT`.
5761

58-
2. The following instructions _start_ a basic block:
59-
- `JUMPDEST`,
60-
- the first instruction in the code,
61-
- an instruction directly after an instruction that has ended previous basic block.
62+
A basic instruction block is a shortest sequence of instructions such that
63+
a basic block starts before the first instruction and ends after the last.
6264

65+
In some cases multiple of the above rules can apply to single basic instruction
66+
block boundary.
6367

6468
## Algorithm
6569

66-
The algorithm for calculating gas and checking stack requirements precomputes
67-
the values for basic blocks and during execution the checks are done once per block.
70+
The algorithm for calculating gas and checking stack requirements pre-computes
71+
the values for basic instruction blocks and during execution the checks
72+
are done only once per instruction block.
6873

6974
### Collecting requirements for basic blocks
7075

71-
For a basic block we need to collect following information:
76+
For a basic block we need to collect the following information:
7277

73-
- total base gas required by instructions,
74-
- the stack height required (the minimum stack height needed to execute
75-
all instructions in the block),
76-
- ~~the start-to-end stack height change~~,
77-
- the relative maximum stack height.
78+
- total **base gas cost** of all instructions,
79+
- the **stack height required** (the minimum stack height needed to execute all
80+
instructions in the block),
81+
- the **maximum stack height growth** relative to the stack height at block
82+
start.
7883

7984
This is done as follows:
8085

@@ -83,26 +88,26 @@ This is done as follows:
8388

8489
```python
8590
class Instruction:
86-
gas_required = 0
91+
base_gas_cost = 0
8792
stack_required = 0
8893
stack_change = 0
8994

9095
class BasicBlock:
91-
gas_required = 0
96+
base_gas_cost = 0
9297
stack_required = 0
93-
stack_change = 0 # FIXME: We don't have too keep it.
94-
stack_max = 0
98+
stack_max_growth = 0
9599

96100
def collect_basic_block_requirements(basic_block):
101+
stack_change = 0
97102
for instruction in basic_block:
98-
basic_block.gas_required += instruction.gas_required
103+
basic_block.base_gas_cost += instruction.base_gas_cost
99104

100-
current_stack_required = instruction.stack_required - basic_block.stack_change
105+
current_stack_required = instruction.stack_required - stack_change
101106
basic_block.stack_required = max(basic_block.stack_required, current_stack_required)
102107

103-
basic_block.stack_change += instruction.stack_change
108+
stack_change += instruction.stack_change
104109

105-
basic_block.stack_max = max(basic_block.stack_max, basic_block.stack_change)
110+
basic_block.stack_max_growth = max(basic_block.stack_max_growth, stack_change)
106111
```
107112

108113
### Checking basic block requirements
@@ -116,22 +121,22 @@ class ExecutionState:
116121
stack = []
117122

118123
def check_basic_block_requirements(state, basic_block):
119-
state.gas_left -= basic_block.gas_required
124+
state.gas_left -= basic_block.base_gas_cost
120125
if state.gas_left < 0:
121126
raise OutOfGas()
122127

123128
if len(state.stack) < basic_block.stack_required:
124129
raise StackUnderflow()
125130

126-
if len(state.stack) + basic_block.stack_max > 1024:
131+
if len(state.stack) + basic_block.stack_max_growth > 1024:
127132
raise StackOverflow()
128133
```
129134

130135
## Misc
131136

132137
### EVM may terminate earlier
133138

134-
Because requirements for a whole basic blocks are checked up front, the instructions
139+
Because requirements for a whole basic block are checked up front, the instructions
135140
that have observable external effects might not be executed although they would be
136141
executed if the gas counting would have been done per instruction.
137142
This is not a consensus issue because the execution terminates with a "hard" exception
@@ -140,17 +145,19 @@ or terminate with a different exception type.
140145

141146
### Current "gas left" value
142147

143-
In EVMJIT also `GAS` and _call_ instructions begin a basic block. This is because
148+
In EVMJIT additional instructions that begin a basic block are `GAS` and any of the _call_ instructions. This is because
144149
these instructions need to know the precise _gas left_ counter value.
145150
However, in evmone this problem has been solved without additional blocks splitting
146151
by attaching the correction value to the mentioned instructions.
147152

153+
### Undefined instructions
148154

155+
Undefined instructions have base gas cost 0 and not stack requirements.
149156

150157

151158

152159

160+
[Basic Block]: https://en.wikipedia.org/wiki/Basic_block
153161

154162

155-
156-
163+

0 commit comments

Comments
 (0)