Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
155795be
Unverified
Commit
155795be
authored
Dec 14, 2021
by
Martin Holst Swende
Committed by
GitHub
Dec 14, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core/vm: avoid memory expansion check for trivial ops (#24048)
parent
adec878c
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
54 additions
and
40 deletions
+54
-40
interpreter.go
core/vm/interpreter.go
+25
-31
jump_table.go
core/vm/jump_table.go
+29
-9
No files found.
core/vm/interpreter.go
View file @
155795be
...
@@ -181,62 +181,56 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
...
@@ -181,62 +181,56 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
// Capture pre-execution values for tracing.
// Capture pre-execution values for tracing.
logged
,
pcCopy
,
gasCopy
=
false
,
pc
,
contract
.
Gas
logged
,
pcCopy
,
gasCopy
=
false
,
pc
,
contract
.
Gas
}
}
// Get the operation from the jump table and validate the stack to ensure there are
// Get the operation from the jump table and validate the stack to ensure there are
// enough stack items available to perform the operation.
// enough stack items available to perform the operation.
op
=
contract
.
GetOp
(
pc
)
op
=
contract
.
GetOp
(
pc
)
operation
:=
in
.
cfg
.
JumpTable
[
op
]
operation
:=
in
.
cfg
.
JumpTable
[
op
]
cost
=
operation
.
constantGas
// For tracing
// Validate stack
// Validate stack
if
sLen
:=
stack
.
len
();
sLen
<
operation
.
minStack
{
if
sLen
:=
stack
.
len
();
sLen
<
operation
.
minStack
{
return
nil
,
&
ErrStackUnderflow
{
stackLen
:
sLen
,
required
:
operation
.
minStack
}
return
nil
,
&
ErrStackUnderflow
{
stackLen
:
sLen
,
required
:
operation
.
minStack
}
}
else
if
sLen
>
operation
.
maxStack
{
}
else
if
sLen
>
operation
.
maxStack
{
return
nil
,
&
ErrStackOverflow
{
stackLen
:
sLen
,
limit
:
operation
.
maxStack
}
return
nil
,
&
ErrStackOverflow
{
stackLen
:
sLen
,
limit
:
operation
.
maxStack
}
}
}
// Static portion of gas
if
!
contract
.
UseGas
(
cost
)
{
cost
=
operation
.
constantGas
// For tracing
if
!
contract
.
UseGas
(
operation
.
constantGas
)
{
return
nil
,
ErrOutOfGas
return
nil
,
ErrOutOfGas
}
}
var
memorySize
uint64
// calculate the new memory size and expand the memory to fit
// the operation
// Memory check needs to be done prior to evaluating the dynamic gas portion,
// to detect calculation overflows
if
operation
.
memorySize
!=
nil
{
memSize
,
overflow
:=
operation
.
memorySize
(
stack
)
if
overflow
{
return
nil
,
ErrGasUintOverflow
}
// memory is expanded in words of 32 bytes. Gas
// is also calculated in words.
if
memorySize
,
overflow
=
math
.
SafeMul
(
toWordSize
(
memSize
),
32
);
overflow
{
return
nil
,
ErrGasUintOverflow
}
}
// Dynamic portion of gas
// consume the gas and return an error if not enough gas is available.
// cost is explicitly set so that the capture state defer method can get the proper cost
if
operation
.
dynamicGas
!=
nil
{
if
operation
.
dynamicGas
!=
nil
{
// All ops with a dynamic memory usage also has a dynamic gas cost.
var
memorySize
uint64
// calculate the new memory size and expand the memory to fit
// the operation
// Memory check needs to be done prior to evaluating the dynamic gas portion,
// to detect calculation overflows
if
operation
.
memorySize
!=
nil
{
memSize
,
overflow
:=
operation
.
memorySize
(
stack
)
if
overflow
{
return
nil
,
ErrGasUintOverflow
}
// memory is expanded in words of 32 bytes. Gas
// is also calculated in words.
if
memorySize
,
overflow
=
math
.
SafeMul
(
toWordSize
(
memSize
),
32
);
overflow
{
return
nil
,
ErrGasUintOverflow
}
}
// Consume the gas and return an error if not enough gas is available.
// cost is explicitly set so that the capture state defer method can get the proper cost
var
dynamicCost
uint64
var
dynamicCost
uint64
dynamicCost
,
err
=
operation
.
dynamicGas
(
in
.
evm
,
contract
,
stack
,
mem
,
memorySize
)
dynamicCost
,
err
=
operation
.
dynamicGas
(
in
.
evm
,
contract
,
stack
,
mem
,
memorySize
)
cost
+=
dynamicCost
//
total cost, for debug
tracing
cost
+=
dynamicCost
//
for
tracing
if
err
!=
nil
||
!
contract
.
UseGas
(
dynamicCost
)
{
if
err
!=
nil
||
!
contract
.
UseGas
(
dynamicCost
)
{
return
nil
,
ErrOutOfGas
return
nil
,
ErrOutOfGas
}
}
if
memorySize
>
0
{
mem
.
Resize
(
memorySize
)
}
}
}
if
memorySize
>
0
{
mem
.
Resize
(
memorySize
)
}
if
in
.
cfg
.
Debug
{
if
in
.
cfg
.
Debug
{
in
.
cfg
.
Tracer
.
CaptureState
(
pc
,
op
,
gasCopy
,
cost
,
callContext
,
in
.
returnData
,
in
.
evm
.
depth
,
err
)
in
.
cfg
.
Tracer
.
CaptureState
(
pc
,
op
,
gasCopy
,
cost
,
callContext
,
in
.
returnData
,
in
.
evm
.
depth
,
err
)
logged
=
true
logged
=
true
}
}
// execute the operation
// execute the operation
res
,
err
=
operation
.
execute
(
&
pc
,
in
,
callContext
)
res
,
err
=
operation
.
execute
(
&
pc
,
in
,
callContext
)
if
err
!=
nil
{
if
err
!=
nil
{
break
break
}
}
...
...
core/vm/jump_table.go
View file @
155795be
...
@@ -17,6 +17,8 @@
...
@@ -17,6 +17,8 @@
package
vm
package
vm
import
(
import
(
"fmt"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/params"
)
)
...
@@ -57,13 +59,31 @@ var (
...
@@ -57,13 +59,31 @@ var (
// JumpTable contains the EVM opcodes supported at a given fork.
// JumpTable contains the EVM opcodes supported at a given fork.
type
JumpTable
[
256
]
*
operation
type
JumpTable
[
256
]
*
operation
func
validate
(
jt
JumpTable
)
JumpTable
{
for
i
,
op
:=
range
jt
{
if
op
==
nil
{
panic
(
fmt
.
Sprintf
(
"op 0x%x is not set"
,
i
))
}
// The interpreter has an assumption that if the memorySize function is
// set, then the dynamicGas function is also set. This is a somewhat
// arbitrary assumption, and can be removed if we need to -- but it
// allows us to avoid a condition check. As long as we have that assumption
// in there, this little sanity check prevents us from merging in a
// change which violates it.
if
op
.
memorySize
!=
nil
&&
op
.
dynamicGas
==
nil
{
panic
(
fmt
.
Sprintf
(
"op %v has dynamic memory but not dynamic gas"
,
OpCode
(
i
)
.
String
()))
}
}
return
jt
}
// newLondonInstructionSet returns the frontier, homestead, byzantium,
// newLondonInstructionSet returns the frontier, homestead, byzantium,
// contantinople, istanbul, petersburg, berlin and london instructions.
// contantinople, istanbul, petersburg, berlin and london instructions.
func
newLondonInstructionSet
()
JumpTable
{
func
newLondonInstructionSet
()
JumpTable
{
instructionSet
:=
newBerlinInstructionSet
()
instructionSet
:=
newBerlinInstructionSet
()
enable3529
(
&
instructionSet
)
// EIP-3529: Reduction in refunds https://eips.ethereum.org/EIPS/eip-3529
enable3529
(
&
instructionSet
)
// EIP-3529: Reduction in refunds https://eips.ethereum.org/EIPS/eip-3529
enable3198
(
&
instructionSet
)
// Base fee opcode https://eips.ethereum.org/EIPS/eip-3198
enable3198
(
&
instructionSet
)
// Base fee opcode https://eips.ethereum.org/EIPS/eip-3198
return
instructionSet
return
validate
(
instructionSet
)
}
}
// newBerlinInstructionSet returns the frontier, homestead, byzantium,
// newBerlinInstructionSet returns the frontier, homestead, byzantium,
...
@@ -71,7 +91,7 @@ func newLondonInstructionSet() JumpTable {
...
@@ -71,7 +91,7 @@ func newLondonInstructionSet() JumpTable {
func
newBerlinInstructionSet
()
JumpTable
{
func
newBerlinInstructionSet
()
JumpTable
{
instructionSet
:=
newIstanbulInstructionSet
()
instructionSet
:=
newIstanbulInstructionSet
()
enable2929
(
&
instructionSet
)
// Access lists for trie accesses https://eips.ethereum.org/EIPS/eip-2929
enable2929
(
&
instructionSet
)
// Access lists for trie accesses https://eips.ethereum.org/EIPS/eip-2929
return
instructionSet
return
validate
(
instructionSet
)
}
}
// newIstanbulInstructionSet returns the frontier, homestead, byzantium,
// newIstanbulInstructionSet returns the frontier, homestead, byzantium,
...
@@ -83,7 +103,7 @@ func newIstanbulInstructionSet() JumpTable {
...
@@ -83,7 +103,7 @@ func newIstanbulInstructionSet() JumpTable {
enable1884
(
&
instructionSet
)
// Reprice reader opcodes - https://eips.ethereum.org/EIPS/eip-1884
enable1884
(
&
instructionSet
)
// Reprice reader opcodes - https://eips.ethereum.org/EIPS/eip-1884
enable2200
(
&
instructionSet
)
// Net metered SSTORE - https://eips.ethereum.org/EIPS/eip-2200
enable2200
(
&
instructionSet
)
// Net metered SSTORE - https://eips.ethereum.org/EIPS/eip-2200
return
instructionSet
return
validate
(
instructionSet
)
}
}
// newConstantinopleInstructionSet returns the frontier, homestead,
// newConstantinopleInstructionSet returns the frontier, homestead,
...
@@ -122,7 +142,7 @@ func newConstantinopleInstructionSet() JumpTable {
...
@@ -122,7 +142,7 @@ func newConstantinopleInstructionSet() JumpTable {
maxStack
:
maxStack
(
4
,
1
),
maxStack
:
maxStack
(
4
,
1
),
memorySize
:
memoryCreate2
,
memorySize
:
memoryCreate2
,
}
}
return
instructionSet
return
validate
(
instructionSet
)
}
}
// newByzantiumInstructionSet returns the frontier, homestead and
// newByzantiumInstructionSet returns the frontier, homestead and
...
@@ -158,14 +178,14 @@ func newByzantiumInstructionSet() JumpTable {
...
@@ -158,14 +178,14 @@ func newByzantiumInstructionSet() JumpTable {
maxStack
:
maxStack
(
2
,
0
),
maxStack
:
maxStack
(
2
,
0
),
memorySize
:
memoryRevert
,
memorySize
:
memoryRevert
,
}
}
return
instructionSet
return
validate
(
instructionSet
)
}
}
// EIP 158 a.k.a Spurious Dragon
// EIP 158 a.k.a Spurious Dragon
func
newSpuriousDragonInstructionSet
()
JumpTable
{
func
newSpuriousDragonInstructionSet
()
JumpTable
{
instructionSet
:=
newTangerineWhistleInstructionSet
()
instructionSet
:=
newTangerineWhistleInstructionSet
()
instructionSet
[
EXP
]
.
dynamicGas
=
gasExpEIP158
instructionSet
[
EXP
]
.
dynamicGas
=
gasExpEIP158
return
instructionSet
return
validate
(
instructionSet
)
}
}
...
@@ -179,7 +199,7 @@ func newTangerineWhistleInstructionSet() JumpTable {
...
@@ -179,7 +199,7 @@ func newTangerineWhistleInstructionSet() JumpTable {
instructionSet
[
CALL
]
.
constantGas
=
params
.
CallGasEIP150
instructionSet
[
CALL
]
.
constantGas
=
params
.
CallGasEIP150
instructionSet
[
CALLCODE
]
.
constantGas
=
params
.
CallGasEIP150
instructionSet
[
CALLCODE
]
.
constantGas
=
params
.
CallGasEIP150
instructionSet
[
DELEGATECALL
]
.
constantGas
=
params
.
CallGasEIP150
instructionSet
[
DELEGATECALL
]
.
constantGas
=
params
.
CallGasEIP150
return
instructionSet
return
validate
(
instructionSet
)
}
}
// newHomesteadInstructionSet returns the frontier and homestead
// newHomesteadInstructionSet returns the frontier and homestead
...
@@ -194,7 +214,7 @@ func newHomesteadInstructionSet() JumpTable {
...
@@ -194,7 +214,7 @@ func newHomesteadInstructionSet() JumpTable {
maxStack
:
maxStack
(
6
,
1
),
maxStack
:
maxStack
(
6
,
1
),
memorySize
:
memoryDelegateCall
,
memorySize
:
memoryDelegateCall
,
}
}
return
instructionSet
return
validate
(
instructionSet
)
}
}
// newFrontierInstructionSet returns the frontier instructions
// newFrontierInstructionSet returns the frontier instructions
...
@@ -1010,5 +1030,5 @@ func newFrontierInstructionSet() JumpTable {
...
@@ -1010,5 +1030,5 @@ func newFrontierInstructionSet() JumpTable {
}
}
}
}
return
tbl
return
validate
(
tbl
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment