@@ -45,37 +45,76 @@ type operation struct {
45
45
}
46
46
47
47
var (
48
- frontierInstructionSet = newFrontierInstructionSet ()
49
- homesteadInstructionSet = newHomesteadInstructionSet ()
50
- tangerineWhistleInstructionSet = newTangerineWhistleInstructionSet ()
51
- spuriousDragonInstructionSet = newSpuriousDragonInstructionSet ()
52
- byzantiumInstructionSet = newByzantiumInstructionSet ()
53
- constantinopleInstructionSet = newConstantinopleInstructionSet ()
54
- istanbulInstructionSet = newIstanbulInstructionSet ()
55
- berlinInstructionSet = newBerlinInstructionSet ()
56
- londonInstructionSet = newLondonInstructionSet ()
57
- mergeInstructionSet = newMergeInstructionSet ()
48
+ FrontierInstructionSet = newFrontierInstructionSet ()
49
+ HomesteadInstructionSet = newHomesteadInstructionSet ()
50
+ TangerineWhistleInstructionSet = newTangerineWhistleInstructionSet ()
51
+ SpuriousDragonInstructionSet = newSpuriousDragonInstructionSet ()
52
+ ByzantiumInstructionSet = newByzantiumInstructionSet ()
53
+ ConstantinopleInstructionSet = newConstantinopleInstructionSet ()
54
+ IstanbulInstructionSet = newIstanbulInstructionSet ()
55
+ BerlinInstructionSet = newBerlinInstructionSet ()
56
+ LondonInstructionSet = newLondonInstructionSet ()
57
+ MergeInstructionSet = newMergeInstructionSet ()
58
58
)
59
59
60
60
// JumpTable contains the EVM opcodes supported at a given fork.
61
61
type JumpTable [256 ]* operation
62
62
63
- func validate (jt JumpTable ) JumpTable {
63
+ // DefaultJumpTable defines the default jump table used by the EVM interpreter.
64
+ func DefaultJumpTable (rules params.Rules ) (jumpTable * JumpTable ) {
65
+ switch {
66
+ case rules .IsMerge :
67
+ jumpTable = & MergeInstructionSet
68
+ case rules .IsLondon :
69
+ jumpTable = & LondonInstructionSet
70
+ case rules .IsBerlin :
71
+ jumpTable = & BerlinInstructionSet
72
+ case rules .IsIstanbul :
73
+ jumpTable = & IstanbulInstructionSet
74
+ case rules .IsConstantinople :
75
+ jumpTable = & ConstantinopleInstructionSet
76
+ case rules .IsByzantium :
77
+ jumpTable = & ByzantiumInstructionSet
78
+ case rules .IsEIP158 :
79
+ jumpTable = & SpuriousDragonInstructionSet
80
+ case rules .IsEIP150 :
81
+ jumpTable = & TangerineWhistleInstructionSet
82
+ case rules .IsHomestead :
83
+ jumpTable = & HomesteadInstructionSet
84
+ default :
85
+ jumpTable = & FrontierInstructionSet
86
+ }
87
+
88
+ return jumpTable
89
+ }
90
+
91
+ // Validate checks if all the operations are set and if they are valid according to the
92
+ // interpreter assumptions.
93
+ func (jt JumpTable ) Validate () error {
64
94
for i , op := range jt {
65
95
if op == nil {
66
- panic ( fmt .Sprintf ("op %#x is not set" , i ) )
96
+ return fmt .Errorf ("op %#x is not set" , i )
67
97
}
98
+
68
99
// The interpreter has an assumption that if the memorySize function is
69
100
// set, then the dynamicGas function is also set. This is a somewhat
70
101
// arbitrary assumption, and can be removed if we need to -- but it
71
102
// allows us to avoid a condition check. As long as we have that assumption
72
103
// in there, this little sanity check prevents us from merging in a
73
104
// change which violates it.
74
105
if op .memorySize != nil && op .dynamicGas == nil {
75
- panic ( fmt .Sprintf ("op %v has dynamic memory but not dynamic gas" , OpCode (i ).String () ))
106
+ return fmt .Errorf ("op %v has dynamic memory but not dynamic gas" , OpCode (i ).String ())
76
107
}
77
108
}
78
- return jt
109
+
110
+ return nil
111
+ }
112
+
113
+ // MustValidate panics if the operations are not valid.
114
+ func (jt JumpTable ) MustValidate () {
115
+ if err := jt .Validate (); err != nil {
116
+ panic (err )
117
+ }
79
118
}
80
119
81
120
func newMergeInstructionSet () JumpTable {
@@ -86,7 +125,8 @@ func newMergeInstructionSet() JumpTable {
86
125
minStack : minStack (0 , 1 ),
87
126
maxStack : maxStack (0 , 1 ),
88
127
}
89
- return validate (instructionSet )
128
+ instructionSet .MustValidate ()
129
+ return instructionSet
90
130
}
91
131
92
132
// newLondonInstructionSet returns the frontier, homestead, byzantium,
@@ -95,15 +135,17 @@ func newLondonInstructionSet() JumpTable {
95
135
instructionSet := newBerlinInstructionSet ()
96
136
enable3529 (& instructionSet ) // EIP-3529: Reduction in refunds https://eips.ethereum.org/EIPS/eip-3529
97
137
enable3198 (& instructionSet ) // Base fee opcode https://eips.ethereum.org/EIPS/eip-3198
98
- return validate (instructionSet )
138
+ instructionSet .MustValidate ()
139
+ return instructionSet
99
140
}
100
141
101
142
// newBerlinInstructionSet returns the frontier, homestead, byzantium,
102
143
// contantinople, istanbul, petersburg and berlin instructions.
103
144
func newBerlinInstructionSet () JumpTable {
104
145
instructionSet := newIstanbulInstructionSet ()
105
146
enable2929 (& instructionSet ) // Access lists for trie accesses https://eips.ethereum.org/EIPS/eip-2929
106
- return validate (instructionSet )
147
+ instructionSet .MustValidate ()
148
+ return instructionSet
107
149
}
108
150
109
151
// newIstanbulInstructionSet returns the frontier, homestead, byzantium,
@@ -115,7 +157,8 @@ func newIstanbulInstructionSet() JumpTable {
115
157
enable1884 (& instructionSet ) // Reprice reader opcodes - https://eips.ethereum.org/EIPS/eip-1884
116
158
enable2200 (& instructionSet ) // Net metered SSTORE - https://eips.ethereum.org/EIPS/eip-2200
117
159
118
- return validate (instructionSet )
160
+ instructionSet .MustValidate ()
161
+ return instructionSet
119
162
}
120
163
121
164
// newConstantinopleInstructionSet returns the frontier, homestead,
@@ -154,7 +197,8 @@ func newConstantinopleInstructionSet() JumpTable {
154
197
maxStack : maxStack (4 , 1 ),
155
198
memorySize : memoryCreate2 ,
156
199
}
157
- return validate (instructionSet )
200
+ instructionSet .MustValidate ()
201
+ return instructionSet
158
202
}
159
203
160
204
// newByzantiumInstructionSet returns the frontier, homestead and
@@ -190,14 +234,16 @@ func newByzantiumInstructionSet() JumpTable {
190
234
maxStack : maxStack (2 , 0 ),
191
235
memorySize : memoryRevert ,
192
236
}
193
- return validate (instructionSet )
237
+ instructionSet .MustValidate ()
238
+ return instructionSet
194
239
}
195
240
196
241
// EIP 158 a.k.a Spurious Dragon
197
242
func newSpuriousDragonInstructionSet () JumpTable {
198
243
instructionSet := newTangerineWhistleInstructionSet ()
199
244
instructionSet [EXP ].dynamicGas = gasExpEIP158
200
- return validate (instructionSet )
245
+ instructionSet .MustValidate ()
246
+ return instructionSet
201
247
}
202
248
203
249
// EIP 150 a.k.a Tangerine Whistle
@@ -210,7 +256,8 @@ func newTangerineWhistleInstructionSet() JumpTable {
210
256
instructionSet [CALL ].constantGas = params .CallGasEIP150
211
257
instructionSet [CALLCODE ].constantGas = params .CallGasEIP150
212
258
instructionSet [DELEGATECALL ].constantGas = params .CallGasEIP150
213
- return validate (instructionSet )
259
+ instructionSet .MustValidate ()
260
+ return instructionSet
214
261
}
215
262
216
263
// newHomesteadInstructionSet returns the frontier and homestead
@@ -225,7 +272,8 @@ func newHomesteadInstructionSet() JumpTable {
225
272
maxStack : maxStack (6 , 1 ),
226
273
memorySize : memoryDelegateCall ,
227
274
}
228
- return validate (instructionSet )
275
+ instructionSet .MustValidate ()
276
+ return instructionSet
229
277
}
230
278
231
279
// newFrontierInstructionSet returns the frontier instructions
@@ -1041,5 +1089,18 @@ func newFrontierInstructionSet() JumpTable {
1041
1089
}
1042
1090
}
1043
1091
1044
- return validate (tbl )
1092
+ tbl .MustValidate ()
1093
+ return tbl
1094
+ }
1095
+
1096
+ // CopyJumpTable creates copy of the operations from the provided source JumpTable.
1097
+ func CopyJumpTable (source * JumpTable ) * JumpTable {
1098
+ dest := * source
1099
+ for i , op := range source {
1100
+ if op != nil {
1101
+ opCopy := * op
1102
+ dest [i ] = & opCopy
1103
+ }
1104
+ }
1105
+ return & dest
1045
1106
}
0 commit comments