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
3d123bcd
Unverified
Commit
3d123bcd
authored
Aug 15, 2017
by
Jeffrey Wilcke
Committed by
Péter Szilágyi
Aug 15, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core/vm: implement metropolis static call opcode
parent
9facf642
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
153 additions
and
3 deletions
+153
-3
evm.go
core/vm/evm.go
+45
-0
gas_table.go
core/vm/gas_table.go
+27
-0
instructions.go
core/vm/instructions.go
+32
-1
interpreter.go
core/vm/interpreter.go
+16
-0
jump_table.go
core/vm/jump_table.go
+23
-2
memory_table.go
core/vm/memory_table.go
+7
-0
opcodes.go
core/vm/opcodes.go
+3
-0
No files found.
core/vm/evm.go
View file @
3d123bcd
...
@@ -245,6 +245,51 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
...
@@ -245,6 +245,51 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
return
ret
,
contract
.
Gas
,
err
return
ret
,
contract
.
Gas
,
err
}
}
func
(
evm
*
EVM
)
StaticCall
(
caller
ContractRef
,
addr
common
.
Address
,
input
[]
byte
,
gas
uint64
)
(
ret
[]
byte
,
leftOverGas
uint64
,
err
error
)
{
if
evm
.
vmConfig
.
NoRecursion
&&
evm
.
depth
>
0
{
return
nil
,
gas
,
nil
}
// Depth check execution. Fail if we're trying to execute above the
// limit.
if
evm
.
depth
>
int
(
params
.
CallCreateDepth
)
{
return
nil
,
gas
,
ErrDepth
}
// make sure the readonly is only set if we aren't in readonly yet
// this makes also sure that the readonly flag isn't removed for
// child calls.
if
!
evm
.
interpreter
.
readonly
{
evm
.
interpreter
.
readonly
=
true
defer
func
()
{
evm
.
interpreter
.
readonly
=
false
}()
}
var
(
to
=
AccountRef
(
addr
)
snapshot
=
evm
.
StateDB
.
Snapshot
()
)
if
!
evm
.
StateDB
.
Exist
(
addr
)
{
return
nil
,
gas
,
nil
}
// initialise a new contract and set the code that is to be used by the
// EVM. The contract is a scoped evmironment for this execution context
// only.
contract
:=
NewContract
(
caller
,
to
,
new
(
big
.
Int
),
gas
)
contract
.
SetCallCode
(
&
addr
,
evm
.
StateDB
.
GetCodeHash
(
addr
),
evm
.
StateDB
.
GetCode
(
addr
))
ret
,
err
=
evm
.
interpreter
.
Run
(
snapshot
,
contract
,
input
)
// When an error was returned by the EVM or when setting the creation code
// above we revert to the snapshot and consume any gas remaining. Additionally
// when we're in homestead this also counts for code storage gas errors.
if
err
!=
nil
{
contract
.
UseGas
(
contract
.
Gas
)
evm
.
StateDB
.
RevertToSnapshot
(
snapshot
)
}
return
ret
,
contract
.
Gas
,
err
}
// Create creates a new contract using code as deployment code.
// Create creates a new contract using code as deployment code.
func
(
evm
*
EVM
)
Create
(
caller
ContractRef
,
code
[]
byte
,
gas
uint64
,
value
*
big
.
Int
)
(
ret
[]
byte
,
contractAddr
common
.
Address
,
leftOverGas
uint64
,
err
error
)
{
func
(
evm
*
EVM
)
Create
(
caller
ContractRef
,
code
[]
byte
,
gas
uint64
,
value
*
big
.
Int
)
(
ret
[]
byte
,
contractAddr
common
.
Address
,
leftOverGas
uint64
,
err
error
)
{
if
evm
.
vmConfig
.
NoRecursion
&&
evm
.
depth
>
0
{
if
evm
.
vmConfig
.
NoRecursion
&&
evm
.
depth
>
0
{
...
...
core/vm/gas_table.go
View file @
3d123bcd
...
@@ -423,6 +423,33 @@ func gasDelegateCall(gt params.GasTable, evm *EVM, contract *Contract, stack *St
...
@@ -423,6 +423,33 @@ func gasDelegateCall(gt params.GasTable, evm *EVM, contract *Contract, stack *St
return
gas
,
nil
return
gas
,
nil
}
}
func
gasStaticCall
(
gt
params
.
GasTable
,
evm
*
EVM
,
contract
*
Contract
,
stack
*
Stack
,
mem
*
Memory
,
memorySize
uint64
)
(
uint64
,
error
)
{
gas
,
err
:=
memoryGasCost
(
mem
,
memorySize
)
if
err
!=
nil
{
return
0
,
err
}
var
overflow
bool
if
gas
,
overflow
=
math
.
SafeAdd
(
gas
,
gt
.
Calls
);
overflow
{
return
0
,
errGasUintOverflow
}
cg
,
err
:=
callGas
(
gt
,
contract
.
Gas
,
gas
,
stack
.
Back
(
0
))
if
err
!=
nil
{
return
0
,
err
}
// Replace the stack item with the new gas calculation. This means that
// either the original item is left on the stack or the item is replaced by:
// (availableGas - gas) * 63 / 64
// We replace the stack item so that it's available when the opCall instruction is
// called.
stack
.
data
[
stack
.
len
()
-
1
]
=
new
(
big
.
Int
)
.
SetUint64
(
cg
)
if
gas
,
overflow
=
math
.
SafeAdd
(
gas
,
cg
);
overflow
{
return
0
,
errGasUintOverflow
}
return
gas
,
nil
}
func
gasPush
(
gt
params
.
GasTable
,
evm
*
EVM
,
contract
*
Contract
,
stack
*
Stack
,
mem
*
Memory
,
memorySize
uint64
)
(
uint64
,
error
)
{
func
gasPush
(
gt
params
.
GasTable
,
evm
*
EVM
,
contract
*
Contract
,
stack
*
Stack
,
mem
*
Memory
,
memorySize
uint64
)
(
uint64
,
error
)
{
return
GasFastestStep
,
nil
return
GasFastestStep
,
nil
}
}
...
...
core/vm/instructions.go
View file @
3d123bcd
...
@@ -17,6 +17,7 @@
...
@@ -17,6 +17,7 @@
package
vm
package
vm
import
(
import
(
"errors"
"fmt"
"fmt"
"math/big"
"math/big"
...
@@ -28,7 +29,8 @@ import (
...
@@ -28,7 +29,8 @@ import (
)
)
var
(
var
(
bigZero
=
new
(
big
.
Int
)
bigZero
=
new
(
big
.
Int
)
errWriteProtection
=
errors
.
New
(
"evm: write protection"
)
)
)
func
opAdd
(
pc
*
uint64
,
evm
*
EVM
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
Stack
)
([]
byte
,
error
)
{
func
opAdd
(
pc
*
uint64
,
evm
*
EVM
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
Stack
)
([]
byte
,
error
)
{
...
@@ -656,6 +658,35 @@ func opDelegateCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, st
...
@@ -656,6 +658,35 @@ func opDelegateCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, st
return
ret
,
nil
return
ret
,
nil
}
}
func
opStaticCall
(
pc
*
uint64
,
evm
*
EVM
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
Stack
)
([]
byte
,
error
)
{
// pop gas
gas
:=
stack
.
pop
()
.
Uint64
()
// pop address
addr
:=
stack
.
pop
()
// pop input size and offset
inOffset
,
inSize
:=
stack
.
pop
(),
stack
.
pop
()
// pop return size and offset
retOffset
,
retSize
:=
stack
.
pop
(),
stack
.
pop
()
address
:=
common
.
BigToAddress
(
addr
)
// Get the arguments from the memory
args
:=
memory
.
Get
(
inOffset
.
Int64
(),
inSize
.
Int64
())
ret
,
returnGas
,
err
:=
evm
.
StaticCall
(
contract
,
address
,
args
,
gas
)
if
err
!=
nil
{
stack
.
push
(
new
(
big
.
Int
))
}
else
{
stack
.
push
(
big
.
NewInt
(
1
))
memory
.
Set
(
retOffset
.
Uint64
(),
retSize
.
Uint64
(),
ret
)
}
contract
.
Gas
+=
returnGas
evm
.
interpreter
.
intPool
.
put
(
addr
,
inOffset
,
inSize
,
retOffset
,
retSize
)
return
ret
,
nil
}
func
opReturn
(
pc
*
uint64
,
evm
*
EVM
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
Stack
)
([]
byte
,
error
)
{
func
opReturn
(
pc
*
uint64
,
evm
*
EVM
,
contract
*
Contract
,
memory
*
Memory
,
stack
*
Stack
)
([]
byte
,
error
)
{
offset
,
size
:=
stack
.
pop
(),
stack
.
pop
()
offset
,
size
:=
stack
.
pop
(),
stack
.
pop
()
ret
:=
memory
.
GetPtr
(
offset
.
Int64
(),
size
.
Int64
())
ret
:=
memory
.
GetPtr
(
offset
.
Int64
(),
size
.
Int64
())
...
...
core/vm/interpreter.go
View file @
3d123bcd
...
@@ -69,6 +69,8 @@ func NewInterpreter(evm *EVM, cfg Config) *Interpreter {
...
@@ -69,6 +69,8 @@ func NewInterpreter(evm *EVM, cfg Config) *Interpreter {
// we'll set the default jump table.
// we'll set the default jump table.
if
!
cfg
.
JumpTable
[
STOP
]
.
valid
{
if
!
cfg
.
JumpTable
[
STOP
]
.
valid
{
switch
{
switch
{
case
evm
.
ChainConfig
()
.
IsMetropolis
(
evm
.
BlockNumber
)
:
cfg
.
JumpTable
=
metropolisInstructionSet
case
evm
.
ChainConfig
()
.
IsHomestead
(
evm
.
BlockNumber
)
:
case
evm
.
ChainConfig
()
.
IsHomestead
(
evm
.
BlockNumber
)
:
cfg
.
JumpTable
=
homesteadInstructionSet
cfg
.
JumpTable
=
homesteadInstructionSet
default
:
default
:
...
@@ -85,6 +87,19 @@ func NewInterpreter(evm *EVM, cfg Config) *Interpreter {
...
@@ -85,6 +87,19 @@ func NewInterpreter(evm *EVM, cfg Config) *Interpreter {
}
}
func
(
in
*
Interpreter
)
enforceRestrictions
(
op
OpCode
,
operation
operation
,
stack
*
Stack
)
error
{
func
(
in
*
Interpreter
)
enforceRestrictions
(
op
OpCode
,
operation
operation
,
stack
*
Stack
)
error
{
if
in
.
evm
.
chainRules
.
IsMetropolis
{
if
in
.
readonly
{
// if the interpreter is operating in readonly mode, make sure no
// state-modifying operation is performed. The 4th stack item
// for a call operation is the value. Transfering value from one
// account to the others means the state is modified and should also
// return with an error.
if
operation
.
writes
||
((
op
==
CALL
||
op
==
CALLCODE
)
&&
stack
.
Back
(
3
)
.
BitLen
()
>
0
)
{
return
errWriteProtection
}
}
}
return
nil
return
nil
}
}
...
@@ -95,6 +110,7 @@ func (in *Interpreter) enforceRestrictions(op OpCode, operation operation, stack
...
@@ -95,6 +110,7 @@ func (in *Interpreter) enforceRestrictions(op OpCode, operation operation, stack
// considered a revert-and-consume-all-gas operation. No error specific checks
// considered a revert-and-consume-all-gas operation. No error specific checks
// should be handled to reduce complexity and errors further down the in.
// should be handled to reduce complexity and errors further down the in.
func
(
in
*
Interpreter
)
Run
(
snapshot
int
,
contract
*
Contract
,
input
[]
byte
)
(
ret
[]
byte
,
err
error
)
{
func
(
in
*
Interpreter
)
Run
(
snapshot
int
,
contract
*
Contract
,
input
[]
byte
)
(
ret
[]
byte
,
err
error
)
{
// Increment the call depth which is restricted to 1024
in
.
evm
.
depth
++
in
.
evm
.
depth
++
defer
func
()
{
in
.
evm
.
depth
--
}()
defer
func
()
{
in
.
evm
.
depth
--
}()
...
...
core/vm/jump_table.go
View file @
3d123bcd
...
@@ -56,10 +56,26 @@ type operation struct {
...
@@ -56,10 +56,26 @@ type operation struct {
}
}
var
(
var
(
frontierInstructionSet
=
NewFrontierInstructionSet
()
frontierInstructionSet
=
NewFrontierInstructionSet
()
homesteadInstructionSet
=
NewHomesteadInstructionSet
()
homesteadInstructionSet
=
NewHomesteadInstructionSet
()
metropolisInstructionSet
=
NewMetropolisInstructionSet
()
)
)
// NewMetropolisInstructionSet returns the frontier, homestead and
// metropolis instructions.
func
NewMetropolisInstructionSet
()
[
256
]
operation
{
// instructions that can be executed during the homestead phase.
instructionSet
:=
NewHomesteadInstructionSet
()
instructionSet
[
STATICCALL
]
=
operation
{
execute
:
opStaticCall
,
gasCost
:
gasStaticCall
,
validateStack
:
makeStackFunc
(
6
,
1
),
memorySize
:
memoryStaticCall
,
valid
:
true
,
}
return
instructionSet
}
// NewHomesteadInstructionSet returns the frontier and homestead
// NewHomesteadInstructionSet returns the frontier and homestead
// instructions that can be executed during the homestead phase.
// instructions that can be executed during the homestead phase.
func
NewHomesteadInstructionSet
()
[
256
]
operation
{
func
NewHomesteadInstructionSet
()
[
256
]
operation
{
...
@@ -810,6 +826,7 @@ func NewFrontierInstructionSet() [256]operation {
...
@@ -810,6 +826,7 @@ func NewFrontierInstructionSet() [256]operation {
validateStack
:
makeStackFunc
(
2
,
0
),
validateStack
:
makeStackFunc
(
2
,
0
),
memorySize
:
memoryLog
,
memorySize
:
memoryLog
,
valid
:
true
,
valid
:
true
,
writes
:
true
,
},
},
LOG1
:
{
LOG1
:
{
execute
:
makeLog
(
1
),
execute
:
makeLog
(
1
),
...
@@ -817,6 +834,7 @@ func NewFrontierInstructionSet() [256]operation {
...
@@ -817,6 +834,7 @@ func NewFrontierInstructionSet() [256]operation {
validateStack
:
makeStackFunc
(
3
,
0
),
validateStack
:
makeStackFunc
(
3
,
0
),
memorySize
:
memoryLog
,
memorySize
:
memoryLog
,
valid
:
true
,
valid
:
true
,
writes
:
true
,
},
},
LOG2
:
{
LOG2
:
{
execute
:
makeLog
(
2
),
execute
:
makeLog
(
2
),
...
@@ -824,6 +842,7 @@ func NewFrontierInstructionSet() [256]operation {
...
@@ -824,6 +842,7 @@ func NewFrontierInstructionSet() [256]operation {
validateStack
:
makeStackFunc
(
4
,
0
),
validateStack
:
makeStackFunc
(
4
,
0
),
memorySize
:
memoryLog
,
memorySize
:
memoryLog
,
valid
:
true
,
valid
:
true
,
writes
:
true
,
},
},
LOG3
:
{
LOG3
:
{
execute
:
makeLog
(
3
),
execute
:
makeLog
(
3
),
...
@@ -831,6 +850,7 @@ func NewFrontierInstructionSet() [256]operation {
...
@@ -831,6 +850,7 @@ func NewFrontierInstructionSet() [256]operation {
validateStack
:
makeStackFunc
(
5
,
0
),
validateStack
:
makeStackFunc
(
5
,
0
),
memorySize
:
memoryLog
,
memorySize
:
memoryLog
,
valid
:
true
,
valid
:
true
,
writes
:
true
,
},
},
LOG4
:
{
LOG4
:
{
execute
:
makeLog
(
4
),
execute
:
makeLog
(
4
),
...
@@ -838,6 +858,7 @@ func NewFrontierInstructionSet() [256]operation {
...
@@ -838,6 +858,7 @@ func NewFrontierInstructionSet() [256]operation {
validateStack
:
makeStackFunc
(
6
,
0
),
validateStack
:
makeStackFunc
(
6
,
0
),
memorySize
:
memoryLog
,
memorySize
:
memoryLog
,
valid
:
true
,
valid
:
true
,
writes
:
true
,
},
},
CREATE
:
{
CREATE
:
{
execute
:
opCreate
,
execute
:
opCreate
,
...
...
core/vm/memory_table.go
View file @
3d123bcd
...
@@ -74,6 +74,13 @@ func memoryDelegateCall(stack *Stack) *big.Int {
...
@@ -74,6 +74,13 @@ func memoryDelegateCall(stack *Stack) *big.Int {
return
math
.
BigMax
(
x
,
y
)
return
math
.
BigMax
(
x
,
y
)
}
}
func
memoryStaticCall
(
stack
*
Stack
)
*
big
.
Int
{
x
:=
calcMemSize
(
stack
.
Back
(
4
),
stack
.
Back
(
5
))
y
:=
calcMemSize
(
stack
.
Back
(
2
),
stack
.
Back
(
3
))
return
math
.
BigMax
(
x
,
y
)
}
func
memoryReturn
(
stack
*
Stack
)
*
big
.
Int
{
func
memoryReturn
(
stack
*
Stack
)
*
big
.
Int
{
return
calcMemSize
(
stack
.
Back
(
0
),
stack
.
Back
(
1
))
return
calcMemSize
(
stack
.
Back
(
0
),
stack
.
Back
(
1
))
}
}
...
...
core/vm/opcodes.go
View file @
3d123bcd
...
@@ -201,6 +201,7 @@ const (
...
@@ -201,6 +201,7 @@ const (
CALLCODE
CALLCODE
RETURN
RETURN
DELEGATECALL
DELEGATECALL
STATICCALL
=
0xfa
SELFDESTRUCT
=
0xff
SELFDESTRUCT
=
0xff
)
)
...
@@ -355,6 +356,7 @@ var opCodeToString = map[OpCode]string{
...
@@ -355,6 +356,7 @@ var opCodeToString = map[OpCode]string{
RETURN
:
"RETURN"
,
RETURN
:
"RETURN"
,
CALLCODE
:
"CALLCODE"
,
CALLCODE
:
"CALLCODE"
,
DELEGATECALL
:
"DELEGATECALL"
,
DELEGATECALL
:
"DELEGATECALL"
,
STATICCALL
:
"STATICCALL"
,
SELFDESTRUCT
:
"SELFDESTRUCT"
,
SELFDESTRUCT
:
"SELFDESTRUCT"
,
PUSH
:
"PUSH"
,
PUSH
:
"PUSH"
,
...
@@ -405,6 +407,7 @@ var stringToOp = map[string]OpCode{
...
@@ -405,6 +407,7 @@ var stringToOp = map[string]OpCode{
"CALLDATASIZE"
:
CALLDATASIZE
,
"CALLDATASIZE"
:
CALLDATASIZE
,
"CALLDATACOPY"
:
CALLDATACOPY
,
"CALLDATACOPY"
:
CALLDATACOPY
,
"DELEGATECALL"
:
DELEGATECALL
,
"DELEGATECALL"
:
DELEGATECALL
,
"STATICCALL"
:
STATICCALL
,
"CODESIZE"
:
CODESIZE
,
"CODESIZE"
:
CODESIZE
,
"CODECOPY"
:
CODECOPY
,
"CODECOPY"
:
CODECOPY
,
"GASPRICE"
:
GASPRICE
,
"GASPRICE"
:
GASPRICE
,
...
...
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