17
17
package vm
18
18
19
19
import (
20
+ "fmt"
21
+
20
22
"github.com/ethereum/go-ethereum/params"
21
23
)
22
24
@@ -65,21 +67,39 @@ var (
65
67
// JumpTable contains the EVM opcodes supported at a given fork.
66
68
type JumpTable [256 ]* operation
67
69
70
+ func validate (jt JumpTable ) JumpTable {
71
+ for i , op := range jt {
72
+ if op == nil {
73
+ continue
74
+ }
75
+ // The interpreter has an assumption that if the memorySize function is
76
+ // set, then the dynamicGas function is also set. This is a somewhat
77
+ // arbitrary assumption, and can be removed if we need to -- but it
78
+ // allows us to avoid a condition check. As long as we have that assumption
79
+ // in there, this little sanity check prevents us from merging in a
80
+ // change which violates it.
81
+ if op .memorySize != nil && op .dynamicGas == nil {
82
+ panic (fmt .Sprintf ("op %v has dynamic memory but not dynamic gas" , OpCode (i ).String ()))
83
+ }
84
+ }
85
+ return jt
86
+ }
87
+
68
88
func newCancunInstructionSet () JumpTable {
69
89
instructionSet := newShanghaiInstructionSet ()
70
90
enable4844 (& instructionSet ) // EIP-4844 (BLOBHASH opcode)
71
91
enable7516 (& instructionSet ) // EIP-7516 (BLOBBASEFEE opcode)
72
92
enable1153 (& instructionSet ) // EIP-1153 "Transient Storage"
73
93
enable5656 (& instructionSet ) // EIP-5656 (MCOPY opcode)
74
94
enable6780 (& instructionSet ) // EIP-6780 SELFDESTRUCT only in same transaction
75
- return instructionSet
95
+ return validate ( instructionSet )
76
96
}
77
97
78
98
func newShanghaiInstructionSet () JumpTable {
79
99
instructionSet := newLondonInstructionSet ()
80
100
enable3855 (& instructionSet ) // PUSH0 instruction
81
101
enable3860 (& instructionSet ) // Limit and meter initcode
82
- return instructionSet
102
+ return validate ( instructionSet )
83
103
}
84
104
85
105
// newLondonInstructionSet returns the frontier, homestead, byzantium,
@@ -88,15 +108,15 @@ func newLondonInstructionSet() JumpTable {
88
108
instructionSet := newBerlinInstructionSet ()
89
109
enable3529 (& instructionSet ) // EIP-3529: Reduction in refunds https://eips.ethereum.org/EIPS/eip-3529
90
110
enable3198 (& instructionSet ) // Base fee opcode https://eips.ethereum.org/EIPS/eip-3198
91
- return instructionSet
111
+ return validate ( instructionSet )
92
112
}
93
113
94
114
// newBerlinInstructionSet returns the frontier, homestead, byzantium,
95
115
// contantinople, istanbul, petersburg and berlin instructions.
96
116
func newBerlinInstructionSet () JumpTable {
97
117
instructionSet := newIstanbulInstructionSet ()
98
118
enable2929 (& instructionSet ) // Access lists for trie accesses https://eips.ethereum.org/EIPS/eip-2929
99
- return instructionSet
119
+ return validate ( instructionSet )
100
120
}
101
121
102
122
// newIstanbulInstructionSet returns the frontier, homestead, byzantium,
@@ -108,7 +128,7 @@ func newIstanbulInstructionSet() JumpTable {
108
128
enable1884 (& instructionSet ) // Reprice reader opcodes - https://eips.ethereum.org/EIPS/eip-1884
109
129
enable2200 (& instructionSet ) // Net metered SSTORE - https://eips.ethereum.org/EIPS/eip-2200
110
130
111
- return instructionSet
131
+ return validate ( instructionSet )
112
132
}
113
133
114
134
// newConstantinopleInstructionSet returns the frontier, homestead,
@@ -149,7 +169,7 @@ func newConstantinopleInstructionSet() JumpTable {
149
169
writes : true ,
150
170
returns : true ,
151
171
}
152
- return instructionSet
172
+ return validate ( instructionSet )
153
173
}
154
174
155
175
// newByzantiumInstructionSet returns the frontier, homestead and
@@ -188,14 +208,14 @@ func newByzantiumInstructionSet() JumpTable {
188
208
reverts : true ,
189
209
returns : true ,
190
210
}
191
- return instructionSet
211
+ return validate ( instructionSet )
192
212
}
193
213
194
214
// EIP 158 a.k.a Spurious Dragon
195
215
func newSpuriousDragonInstructionSet () JumpTable {
196
216
instructionSet := newTangerineWhistleInstructionSet ()
197
217
instructionSet [EXP ].dynamicGas = gasExpEIP158
198
- return instructionSet
218
+ return validate ( instructionSet )
199
219
200
220
}
201
221
@@ -209,7 +229,7 @@ func newTangerineWhistleInstructionSet() JumpTable {
209
229
instructionSet [CALL ].constantGas = params .CallGasEIP150
210
230
instructionSet [CALLCODE ].constantGas = params .CallGasEIP150
211
231
instructionSet [DELEGATECALL ].constantGas = params .CallGasEIP150
212
- return instructionSet
232
+ return validate ( instructionSet )
213
233
}
214
234
215
235
// newHomesteadInstructionSet returns the frontier and homestead
@@ -225,13 +245,13 @@ func newHomesteadInstructionSet() JumpTable {
225
245
memorySize : memoryDelegateCall ,
226
246
returns : true ,
227
247
}
228
- return instructionSet
248
+ return validate ( instructionSet )
229
249
}
230
250
231
251
// newFrontierInstructionSet returns the frontier instructions
232
252
// that can be executed during the frontier phase.
233
253
func newFrontierInstructionSet () JumpTable {
234
- return JumpTable {
254
+ tlb := JumpTable {
235
255
STOP : {
236
256
execute : opStop ,
237
257
constantGas : 0 ,
@@ -1049,6 +1069,7 @@ func newFrontierInstructionSet() JumpTable {
1049
1069
writes : true ,
1050
1070
},
1051
1071
}
1072
+ return validate (tlb )
1052
1073
}
1053
1074
1054
1075
func copyJumpTable (source * JumpTable ) * JumpTable {
0 commit comments