Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
whqwjb
go-ethereum
提交
3d123bcd
G
go-ethereum
项目概览
whqwjb
/
go-ethereum
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
go-ethereum
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
3d123bcd
编写于
8月 15, 2017
作者:
J
Jeffrey Wilcke
提交者:
Péter Szilágyi
8月 15, 2017
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
core/vm: implement metropolis static call opcode
上级
9facf642
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
153 addition
and
3 deletion
+153
-3
core/vm/evm.go
core/vm/evm.go
+45
-0
core/vm/gas_table.go
core/vm/gas_table.go
+27
-0
core/vm/instructions.go
core/vm/instructions.go
+32
-1
core/vm/interpreter.go
core/vm/interpreter.go
+16
-0
core/vm/jump_table.go
core/vm/jump_table.go
+23
-2
core/vm/memory_table.go
core/vm/memory_table.go
+7
-0
core/vm/opcodes.go
core/vm/opcodes.go
+3
-0
未找到文件。
core/vm/evm.go
浏览文件 @
3d123bcd
...
...
@@ -245,6 +245,51 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
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.
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
{
...
...
core/vm/gas_table.go
浏览文件 @
3d123bcd
...
...
@@ -423,6 +423,33 @@ func gasDelegateCall(gt params.GasTable, evm *EVM, contract *Contract, stack *St
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
)
{
return
GasFastestStep
,
nil
}
...
...
core/vm/instructions.go
浏览文件 @
3d123bcd
...
...
@@ -17,6 +17,7 @@
package
vm
import
(
"errors"
"fmt"
"math/big"
...
...
@@ -28,7 +29,8 @@ import (
)
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
)
{
...
...
@@ -656,6 +658,35 @@ func opDelegateCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, st
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
)
{
offset
,
size
:=
stack
.
pop
(),
stack
.
pop
()
ret
:=
memory
.
GetPtr
(
offset
.
Int64
(),
size
.
Int64
())
...
...
core/vm/interpreter.go
浏览文件 @
3d123bcd
...
...
@@ -69,6 +69,8 @@ func NewInterpreter(evm *EVM, cfg Config) *Interpreter {
// we'll set the default jump table.
if
!
cfg
.
JumpTable
[
STOP
]
.
valid
{
switch
{
case
evm
.
ChainConfig
()
.
IsMetropolis
(
evm
.
BlockNumber
)
:
cfg
.
JumpTable
=
metropolisInstructionSet
case
evm
.
ChainConfig
()
.
IsHomestead
(
evm
.
BlockNumber
)
:
cfg
.
JumpTable
=
homesteadInstructionSet
default
:
...
...
@@ -85,6 +87,19 @@ func NewInterpreter(evm *EVM, cfg Config) *Interpreter {
}
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
}
...
...
@@ -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
// 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
)
{
// Increment the call depth which is restricted to 1024
in
.
evm
.
depth
++
defer
func
()
{
in
.
evm
.
depth
--
}()
...
...
core/vm/jump_table.go
浏览文件 @
3d123bcd
...
...
@@ -56,10 +56,26 @@ type operation struct {
}
var
(
frontierInstructionSet
=
NewFrontierInstructionSet
()
homesteadInstructionSet
=
NewHomesteadInstructionSet
()
frontierInstructionSet
=
NewFrontierInstructionSet
()
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
// instructions that can be executed during the homestead phase.
func
NewHomesteadInstructionSet
()
[
256
]
operation
{
...
...
@@ -810,6 +826,7 @@ func NewFrontierInstructionSet() [256]operation {
validateStack
:
makeStackFunc
(
2
,
0
),
memorySize
:
memoryLog
,
valid
:
true
,
writes
:
true
,
},
LOG1
:
{
execute
:
makeLog
(
1
),
...
...
@@ -817,6 +834,7 @@ func NewFrontierInstructionSet() [256]operation {
validateStack
:
makeStackFunc
(
3
,
0
),
memorySize
:
memoryLog
,
valid
:
true
,
writes
:
true
,
},
LOG2
:
{
execute
:
makeLog
(
2
),
...
...
@@ -824,6 +842,7 @@ func NewFrontierInstructionSet() [256]operation {
validateStack
:
makeStackFunc
(
4
,
0
),
memorySize
:
memoryLog
,
valid
:
true
,
writes
:
true
,
},
LOG3
:
{
execute
:
makeLog
(
3
),
...
...
@@ -831,6 +850,7 @@ func NewFrontierInstructionSet() [256]operation {
validateStack
:
makeStackFunc
(
5
,
0
),
memorySize
:
memoryLog
,
valid
:
true
,
writes
:
true
,
},
LOG4
:
{
execute
:
makeLog
(
4
),
...
...
@@ -838,6 +858,7 @@ func NewFrontierInstructionSet() [256]operation {
validateStack
:
makeStackFunc
(
6
,
0
),
memorySize
:
memoryLog
,
valid
:
true
,
writes
:
true
,
},
CREATE
:
{
execute
:
opCreate
,
...
...
core/vm/memory_table.go
浏览文件 @
3d123bcd
...
...
@@ -74,6 +74,13 @@ func memoryDelegateCall(stack *Stack) *big.Int {
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
{
return
calcMemSize
(
stack
.
Back
(
0
),
stack
.
Back
(
1
))
}
...
...
core/vm/opcodes.go
浏览文件 @
3d123bcd
...
...
@@ -201,6 +201,7 @@ const (
CALLCODE
RETURN
DELEGATECALL
STATICCALL
=
0xfa
SELFDESTRUCT
=
0xff
)
...
...
@@ -355,6 +356,7 @@ var opCodeToString = map[OpCode]string{
RETURN
:
"RETURN"
,
CALLCODE
:
"CALLCODE"
,
DELEGATECALL
:
"DELEGATECALL"
,
STATICCALL
:
"STATICCALL"
,
SELFDESTRUCT
:
"SELFDESTRUCT"
,
PUSH
:
"PUSH"
,
...
...
@@ -405,6 +407,7 @@ var stringToOp = map[string]OpCode{
"CALLDATASIZE"
:
CALLDATASIZE
,
"CALLDATACOPY"
:
CALLDATACOPY
,
"DELEGATECALL"
:
DELEGATECALL
,
"STATICCALL"
:
STATICCALL
,
"CODESIZE"
:
CODESIZE
,
"CODECOPY"
:
CODECOPY
,
"GASPRICE"
:
GASPRICE
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录