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
6609d45e
Commit
6609d45e
authored
Jun 11, 2015
by
Jeffrey Wilcke
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1228 from obscuren/vm-optimisations
core/vm: optimisations
parents
13bd452f
37111aa4
Changes
16
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
200 additions
and
159 deletions
+200
-159
main.go
cmd/evm/main.go
+10
-0
admin.go
cmd/geth/admin.go
+5
-2
block_processor.go
core/block_processor.go
+8
-2
chain_manager.go
core/chain_manager.go
+4
-1
execution.go
core/execution.go
+0
-4
state_object.go
core/state/state_object.go
+16
-0
state_transition.go
core/state_transition.go
+4
-0
context.go
core/vm/context.go
+4
-4
environment.go
core/vm/environment.go
+16
-0
logger.go
core/vm/logger.go
+46
-0
stack.go
core/vm/stack.go
+5
-1
virtual_machine.go
core/vm/virtual_machine.go
+0
-2
vm.go
core/vm/vm.go
+60
-140
vm_env.go
core/vm_env.go
+11
-0
worker.go
miner/worker.go
+2
-1
vm.go
tests/helper/vm.go
+9
-2
No files found.
cmd/evm/main.go
View file @
6609d45e
...
...
@@ -59,6 +59,7 @@ func main() {
logger
.
AddLogSystem
(
logger
.
NewStdLogSystem
(
os
.
Stdout
,
log
.
LstdFlags
,
logger
.
LogLevel
(
*
loglevel
)))
vm
.
Debug
=
true
db
,
_
:=
ethdb
.
NewMemDatabase
()
statedb
:=
state
.
New
(
common
.
Hash
{},
db
)
sender
:=
statedb
.
CreateAccount
(
common
.
StringToAddress
(
"sender"
))
...
...
@@ -80,6 +81,8 @@ func main() {
fmt
.
Println
(
string
(
statedb
.
Dump
()))
}
vm
.
StdErrFormat
(
vmenv
.
StructLogs
())
var
mem
runtime
.
MemStats
runtime
.
ReadMemStats
(
&
mem
)
fmt
.
Printf
(
"vm took %v
\n
"
,
time
.
Since
(
tstart
))
...
...
@@ -104,6 +107,7 @@ type VMEnv struct {
depth
int
Gas
*
big
.
Int
time
int64
logs
[]
vm
.
StructLog
}
func
NewEnv
(
state
*
state
.
StateDB
,
transactor
common
.
Address
,
value
*
big
.
Int
)
*
VMEnv
{
...
...
@@ -133,6 +137,12 @@ func (self *VMEnv) GetHash(n uint64) common.Hash {
}
return
common
.
Hash
{}
}
func
(
self
*
VMEnv
)
AddStructLog
(
log
vm
.
StructLog
)
{
self
.
logs
=
append
(
self
.
logs
,
log
)
}
func
(
self
*
VMEnv
)
StructLogs
()
[]
vm
.
StructLog
{
return
self
.
logs
}
func
(
self
*
VMEnv
)
AddLog
(
log
*
state
.
Log
)
{
self
.
state
.
AddLog
(
log
)
}
...
...
cmd/geth/admin.go
View file @
6609d45e
...
...
@@ -271,9 +271,12 @@ func (js *jsre) debugBlock(call otto.FunctionCall) otto.Value {
}
tstart
:=
time
.
Now
()
old
:=
vm
.
Debug
vm
.
Debug
=
true
if
len
(
call
.
ArgumentList
)
>
1
{
vm
.
Debug
,
_
=
call
.
Argument
(
1
)
.
ToBoolean
()
}
_
,
err
=
js
.
ethereum
.
BlockProcessor
()
.
RetryProcess
(
block
)
if
err
!=
nil
{
fmt
.
Println
(
err
)
...
...
core/block_processor.go
View file @
6609d45e
...
...
@@ -151,11 +151,17 @@ func (sm *BlockProcessor) RetryProcess(block *types.Block) (logs state.Logs, err
return
nil
,
ParentError
(
header
.
ParentHash
)
}
parent
:=
sm
.
bc
.
GetBlock
(
header
.
ParentHash
)
if
!
sm
.
Pow
.
Verify
(
block
)
{
// FIXME Change to full header validation. See #1225
errch
:=
make
(
chan
bool
)
go
func
()
{
errch
<-
sm
.
Pow
.
Verify
(
block
)
}()
logs
,
err
=
sm
.
processWithParent
(
block
,
parent
)
if
!<-
errch
{
return
nil
,
ValidationError
(
"Block's nonce is invalid (= %x)"
,
block
.
Nonce
)
}
return
sm
.
processWithParent
(
block
,
parent
)
return
logs
,
err
}
// Process block will attempt to process the given block's transactions and applies them
...
...
core/chain_manager.go
View file @
6609d45e
...
...
@@ -567,6 +567,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
go
verifyNonces
(
self
.
pow
,
chain
,
nonceQuit
,
nonceDone
)
defer
close
(
nonceQuit
)
txcount
:=
0
for
i
,
block
:=
range
chain
{
bstart
:=
time
.
Now
()
// Wait for block i's nonce to be verified before processing
...
...
@@ -625,6 +626,8 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
return
i
,
err
}
txcount
+=
len
(
block
.
Transactions
())
cblock
:=
self
.
currentBlock
// Compare the TD of the last known block in the canonical chain to make sure it's greater.
// At this point it's possible that a different chain (fork) becomes the new canonical chain.
...
...
@@ -683,7 +686,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
if
(
stats
.
queued
>
0
||
stats
.
processed
>
0
||
stats
.
ignored
>
0
)
&&
bool
(
glog
.
V
(
logger
.
Info
))
{
tend
:=
time
.
Since
(
tstart
)
start
,
end
:=
chain
[
0
],
chain
[
len
(
chain
)
-
1
]
glog
.
Infof
(
"imported %d block(s) (%d queued %d ignored) in
%v. #%v [%x / %x]
\n
"
,
stats
.
processed
,
stats
.
queued
,
stats
.
ignored
,
tend
,
end
.
Number
(),
start
.
Hash
()
.
Bytes
()[
:
4
],
end
.
Hash
()
.
Bytes
()[
:
4
])
glog
.
Infof
(
"imported %d block(s) (%d queued %d ignored) in
cluding %d txs in %v. #%v [%x / %x]
\n
"
,
stats
.
processed
,
stats
.
queued
,
stats
.
ignored
,
txcount
,
tend
,
end
.
Number
(),
start
.
Hash
()
.
Bytes
()[
:
4
],
end
.
Hash
()
.
Bytes
()[
:
4
])
}
go
self
.
eventMux
.
Post
(
queueEvent
)
...
...
core/execution.go
View file @
6609d45e
...
...
@@ -2,7 +2,6 @@ package core
import
(
"math/big"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
...
...
@@ -49,8 +48,6 @@ func (self *Execution) Create(caller vm.ContextRef) (ret []byte, err error, acco
}
func
(
self
*
Execution
)
exec
(
contextAddr
*
common
.
Address
,
code
[]
byte
,
caller
vm
.
ContextRef
)
(
ret
[]
byte
,
err
error
)
{
start
:=
time
.
Now
()
env
:=
self
.
env
evm
:=
self
.
evm
if
env
.
Depth
()
>
int
(
params
.
CallCreateDepth
.
Int64
())
{
...
...
@@ -96,7 +93,6 @@ func (self *Execution) exec(contextAddr *common.Address, code []byte, caller vm.
context
.
SetCallCode
(
contextAddr
,
code
)
ret
,
err
=
evm
.
Run
(
context
,
self
.
input
)
evm
.
Printf
(
"message call took %v"
,
time
.
Since
(
start
))
.
Endl
()
if
err
!=
nil
{
env
.
State
()
.
Set
(
snapshot
)
}
...
...
core/state/state_object.go
View file @
6609d45e
...
...
@@ -336,6 +336,22 @@ func (self *StateObject) Nonce() uint64 {
return
self
.
nonce
}
func
(
self
*
StateObject
)
EachStorage
(
cb
func
(
key
,
value
[]
byte
))
{
// When iterating over the storage check the cache first
for
h
,
v
:=
range
self
.
storage
{
cb
([]
byte
(
h
),
v
.
Bytes
())
}
it
:=
self
.
State
.
trie
.
Iterator
()
for
it
.
Next
()
{
// ignore cached values
key
:=
self
.
State
.
trie
.
GetKey
(
it
.
Key
)
if
_
,
ok
:=
self
.
storage
[
string
(
key
)];
!
ok
{
cb
(
key
,
it
.
Value
)
}
}
}
//
// Encoding
//
...
...
core/state_transition.go
View file @
6609d45e
...
...
@@ -223,6 +223,10 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er
return
nil
,
nil
,
InvalidTxError
(
err
)
}
if
vm
.
Debug
{
vm
.
StdErrFormat
(
vmenv
.
StructLogs
())
}
self
.
refundGas
()
self
.
state
.
AddBalance
(
self
.
coinbase
,
new
(
big
.
Int
)
.
Mul
(
self
.
gasUsed
(),
self
.
gasPrice
))
...
...
core/vm/context.go
View file @
6609d45e
...
...
@@ -49,13 +49,13 @@ func NewContext(caller ContextRef, object ContextRef, value, gas, price *big.Int
return
c
}
func
(
c
*
Context
)
GetOp
(
n
*
big
.
Int
)
OpCode
{
func
(
c
*
Context
)
GetOp
(
n
uint64
)
OpCode
{
return
OpCode
(
c
.
GetByte
(
n
))
}
func
(
c
*
Context
)
GetByte
(
n
*
big
.
Int
)
byte
{
if
n
.
Cmp
(
big
.
NewInt
(
int64
(
len
(
c
.
Code
))))
<
0
{
return
c
.
Code
[
n
.
Int64
()
]
func
(
c
*
Context
)
GetByte
(
n
uint64
)
byte
{
if
n
<
uint64
(
len
(
c
.
Code
))
{
return
c
.
Code
[
n
]
}
return
0
...
...
core/vm/environment.go
View file @
6609d45e
...
...
@@ -8,6 +8,8 @@ import (
"github.com/ethereum/go-ethereum/core/state"
)
// Environment is is required by the virtual machine to get information from
// it's own isolated environment. For an example see `core.VMEnv`
type
Environment
interface
{
State
()
*
state
.
StateDB
...
...
@@ -20,6 +22,8 @@ type Environment interface {
GasLimit
()
*
big
.
Int
Transfer
(
from
,
to
Account
,
amount
*
big
.
Int
)
error
AddLog
(
*
state
.
Log
)
AddStructLog
(
StructLog
)
StructLogs
()
[]
StructLog
VmType
()
Type
...
...
@@ -31,6 +35,18 @@ type Environment interface {
Create
(
me
ContextRef
,
data
[]
byte
,
gas
,
price
,
value
*
big
.
Int
)
([]
byte
,
error
,
ContextRef
)
}
// StructLog is emited to the Environment each cycle and lists information about the curent internal state
// prior to the execution of the statement.
type
StructLog
struct
{
Pc
uint64
Op
OpCode
Gas
*
big
.
Int
GasCost
*
big
.
Int
Memory
[]
byte
Stack
[]
*
big
.
Int
Storage
map
[
common
.
Hash
][]
byte
}
type
Account
interface
{
SubBalance
(
amount
*
big
.
Int
)
AddBalance
(
amount
*
big
.
Int
)
...
...
core/vm/logger.go
0 → 100644
View file @
6609d45e
package
vm
import
(
"fmt"
"os"
"unicode/utf8"
"github.com/ethereum/go-ethereum/common"
)
func
StdErrFormat
(
logs
[]
StructLog
)
{
fmt
.
Fprintf
(
os
.
Stderr
,
"VM Stats %d ops
\n
"
,
len
(
logs
))
for
_
,
log
:=
range
logs
{
fmt
.
Fprintf
(
os
.
Stderr
,
"PC %08d: %s GAS: %v COST: %v
\n
"
,
log
.
Pc
,
log
.
Op
,
log
.
Gas
,
log
.
GasCost
)
fmt
.
Fprintln
(
os
.
Stderr
,
"STACK ="
,
len
(
log
.
Stack
))
for
i
:=
len
(
log
.
Stack
)
-
1
;
i
>=
0
;
i
--
{
fmt
.
Fprintf
(
os
.
Stderr
,
"%04d: %x
\n
"
,
len
(
log
.
Stack
)
-
i
-
1
,
common
.
LeftPadBytes
(
log
.
Stack
[
i
]
.
Bytes
(),
32
))
}
const
maxMem
=
10
addr
:=
0
fmt
.
Fprintln
(
os
.
Stderr
,
"MEM ="
,
len
(
log
.
Memory
))
for
i
:=
0
;
i
+
16
<=
len
(
log
.
Memory
)
&&
addr
<
maxMem
;
i
+=
16
{
data
:=
log
.
Memory
[
i
:
i
+
16
]
str
:=
fmt
.
Sprintf
(
"%04d: % x "
,
addr
*
16
,
data
)
for
_
,
r
:=
range
data
{
if
r
==
0
{
str
+=
"."
}
else
if
utf8
.
ValidRune
(
rune
(
r
))
{
str
+=
fmt
.
Sprintf
(
"%s"
,
string
(
r
))
}
else
{
str
+=
"?"
}
}
addr
++
fmt
.
Fprintln
(
os
.
Stderr
,
str
)
}
fmt
.
Fprintln
(
os
.
Stderr
,
"STORAGE ="
,
len
(
log
.
Storage
))
for
h
,
item
:=
range
log
.
Storage
{
fmt
.
Fprintf
(
os
.
Stderr
,
"%x: %x
\n
"
,
h
,
common
.
LeftPadBytes
(
item
,
32
))
}
fmt
.
Fprintln
(
os
.
Stderr
)
}
}
core/vm/stack.go
View file @
6609d45e
...
...
@@ -5,7 +5,7 @@ import (
"math/big"
)
func
new
S
tack
()
*
stack
{
func
new
s
tack
()
*
stack
{
return
&
stack
{}
}
...
...
@@ -14,6 +14,10 @@ type stack struct {
ptr
int
}
func
(
st
*
stack
)
Data
()
[]
*
big
.
Int
{
return
st
.
data
[
:
st
.
ptr
]
}
func
(
st
*
stack
)
push
(
d
*
big
.
Int
)
{
// NOTE push limit (1024) is checked in baseCheck
stackItem
:=
new
(
big
.
Int
)
.
Set
(
d
)
...
...
core/vm/virtual_machine.go
View file @
6609d45e
...
...
@@ -3,6 +3,4 @@ package vm
type
VirtualMachine
interface
{
Env
()
Environment
Run
(
context
*
Context
,
data
[]
byte
)
([]
byte
,
error
)
Printf
(
string
,
...
interface
{})
VirtualMachine
Endl
()
VirtualMachine
}
core/vm/vm.go
View file @
6609d45e
This diff is collapsed.
Click to expand it.
core/vm_env.go
View file @
6609d45e
...
...
@@ -16,6 +16,8 @@ type VMEnv struct {
depth
int
chain
*
ChainManager
typ
vm
.
Type
// structured logging
logs
[]
vm
.
StructLog
}
func
NewEnv
(
state
*
state
.
StateDB
,
chain
*
ChainManager
,
msg
Message
,
block
*
types
.
Block
)
*
VMEnv
{
...
...
@@ -47,6 +49,7 @@ func (self *VMEnv) GetHash(n uint64) common.Hash {
return
common
.
Hash
{}
}
func
(
self
*
VMEnv
)
AddLog
(
log
*
state
.
Log
)
{
self
.
state
.
AddLog
(
log
)
}
...
...
@@ -68,3 +71,11 @@ func (self *VMEnv) Create(me vm.ContextRef, data []byte, gas, price, value *big.
exe
:=
NewExecution
(
self
,
nil
,
data
,
gas
,
price
,
value
)
return
exe
.
Create
(
me
)
}
func
(
self
*
VMEnv
)
StructLogs
()
[]
vm
.
StructLog
{
return
self
.
logs
}
func
(
self
*
VMEnv
)
AddStructLog
(
log
vm
.
StructLog
)
{
self
.
logs
=
append
(
self
.
logs
,
log
)
}
miner/worker.go
View file @
6609d45e
...
...
@@ -270,7 +270,6 @@ func (self *worker) wait() {
func
(
self
*
worker
)
push
()
{
if
atomic
.
LoadInt32
(
&
self
.
mining
)
==
1
{
self
.
current
.
block
.
Header
()
.
GasUsed
=
self
.
current
.
totalUsedGas
self
.
current
.
block
.
SetRoot
(
self
.
current
.
state
.
Root
())
// push new work to agents
...
...
@@ -510,6 +509,8 @@ func (self *worker) commitTransactions(transactions types.Transactions) {
current
.
tcount
++
}
}
self
.
current
.
block
.
Header
()
.
GasUsed
=
self
.
current
.
totalUsedGas
}
func
(
self
*
worker
)
commitTransaction
(
tx
*
types
.
Transaction
)
error
{
...
...
tests/helper/vm.go
View file @
6609d45e
...
...
@@ -27,9 +27,8 @@ type Env struct {
difficulty
*
big
.
Int
gasLimit
*
big
.
Int
logs
state
.
Logs
vmTest
bool
logs
[]
vm
.
StructLog
}
func
NewEnv
(
state
*
state
.
StateDB
)
*
Env
{
...
...
@@ -38,6 +37,14 @@ func NewEnv(state *state.StateDB) *Env {
}
}
func
(
self
*
Env
)
StructLogs
()
[]
vm
.
StructLog
{
return
self
.
logs
}
func
(
self
*
Env
)
AddStructLog
(
log
vm
.
StructLog
)
{
self
.
logs
=
append
(
self
.
logs
,
log
)
}
func
NewEnvFromMap
(
state
*
state
.
StateDB
,
envValues
map
[
string
]
string
,
exeValues
map
[
string
]
string
)
*
Env
{
env
:=
NewEnv
(
state
)
...
...
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