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
94903d57
Unverified
Commit
94903d57
authored
Aug 24, 2017
by
rjl493456442
Committed by
Péter Szilágyi
Oct 02, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
internal, accounts, eth: utilize vm failed flag to help gas estimation
parent
f86c4177
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
33 additions
and
28 deletions
+33
-28
simulated.go
accounts/abi/bind/backends/simulated.go
+13
-11
api.go
eth/api.go
+2
-2
api.go
internal/ethapi/api.go
+18
-15
No files found.
accounts/abi/bind/backends/simulated.go
View file @
94903d57
...
...
@@ -168,7 +168,7 @@ func (b *SimulatedBackend) CallContract(ctx context.Context, call ethereum.CallM
if
err
!=
nil
{
return
nil
,
err
}
rval
,
_
,
err
:=
b
.
callContract
(
ctx
,
call
,
b
.
blockchain
.
CurrentBlock
(),
state
)
rval
,
_
,
_
,
err
:=
b
.
callContract
(
ctx
,
call
,
b
.
blockchain
.
CurrentBlock
(),
state
)
return
rval
,
err
}
...
...
@@ -178,7 +178,7 @@ func (b *SimulatedBackend) PendingCallContract(ctx context.Context, call ethereu
defer
b
.
mu
.
Unlock
()
defer
b
.
pendingState
.
RevertToSnapshot
(
b
.
pendingState
.
Snapshot
())
rval
,
_
,
err
:=
b
.
callContract
(
ctx
,
call
,
b
.
pendingBlock
,
b
.
pendingState
)
rval
,
_
,
_
,
err
:=
b
.
callContract
(
ctx
,
call
,
b
.
pendingBlock
,
b
.
pendingState
)
return
rval
,
err
}
...
...
@@ -204,8 +204,11 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
defer
b
.
mu
.
Unlock
()
// Binary search the gas requirement, as it may be higher than the amount used
var
lo
,
hi
uint64
if
call
.
Gas
!=
nil
{
var
(
lo
uint64
=
params
.
TxGas
-
1
hi
uint64
)
if
call
.
Gas
!=
nil
&&
call
.
Gas
.
Uint64
()
>=
params
.
TxGas
{
hi
=
call
.
Gas
.
Uint64
()
}
else
{
hi
=
b
.
pendingBlock
.
GasLimit
()
.
Uint64
()
...
...
@@ -216,11 +219,11 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
call
.
Gas
=
new
(
big
.
Int
)
.
SetUint64
(
mid
)
snapshot
:=
b
.
pendingState
.
Snapshot
()
_
,
gas
,
err
:=
b
.
callContract
(
ctx
,
call
,
b
.
pendingBlock
,
b
.
pendingState
)
_
,
_
,
failed
,
err
:=
b
.
callContract
(
ctx
,
call
,
b
.
pendingBlock
,
b
.
pendingState
)
b
.
pendingState
.
RevertToSnapshot
(
snapshot
)
// If the transaction became invalid or
used all the gas (failed)
, raise the gas limit
if
err
!=
nil
||
gas
.
Cmp
(
call
.
Gas
)
==
0
{
// If the transaction became invalid or
execution failed
, raise the gas limit
if
err
!=
nil
||
failed
{
lo
=
mid
continue
}
...
...
@@ -232,7 +235,7 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
// callContract implemens common code between normal and pending contract calls.
// state is modified during execution, make sure to copy it if necessary.
func
(
b
*
SimulatedBackend
)
callContract
(
ctx
context
.
Context
,
call
ethereum
.
CallMsg
,
block
*
types
.
Block
,
statedb
*
state
.
StateDB
)
([]
byte
,
*
big
.
Int
,
error
)
{
func
(
b
*
SimulatedBackend
)
callContract
(
ctx
context
.
Context
,
call
ethereum
.
CallMsg
,
block
*
types
.
Block
,
statedb
*
state
.
StateDB
)
([]
byte
,
*
big
.
Int
,
bool
,
error
)
{
// Ensure message is initialized properly.
if
call
.
GasPrice
==
nil
{
call
.
GasPrice
=
big
.
NewInt
(
1
)
...
...
@@ -254,9 +257,8 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
// about the transaction and calling mechanisms.
vmenv
:=
vm
.
NewEVM
(
evmContext
,
statedb
,
b
.
config
,
vm
.
Config
{})
gaspool
:=
new
(
core
.
GasPool
)
.
AddGas
(
math
.
MaxBig256
)
// TODO utilize returned failed flag to help gas estimation.
ret
,
gasUsed
,
_
,
_
,
err
:=
core
.
NewStateTransition
(
vmenv
,
msg
,
gaspool
)
.
TransitionDb
()
return
ret
,
gasUsed
,
err
ret
,
gasUsed
,
_
,
failed
,
err
:=
core
.
NewStateTransition
(
vmenv
,
msg
,
gaspool
)
.
TransitionDb
()
return
ret
,
gasUsed
,
failed
,
err
}
// SendTransaction updates the pending block to include the given transaction.
...
...
eth/api.go
View file @
94903d57
...
...
@@ -523,8 +523,7 @@ func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, txHash common.
// Run the transaction with tracing enabled.
vmenv
:=
vm
.
NewEVM
(
context
,
statedb
,
api
.
config
,
vm
.
Config
{
Debug
:
true
,
Tracer
:
tracer
})
// TODO utilize failed flag
ret
,
gas
,
_
,
err
:=
core
.
ApplyMessage
(
vmenv
,
msg
,
new
(
core
.
GasPool
)
.
AddGas
(
tx
.
Gas
()))
ret
,
gas
,
failed
,
err
:=
core
.
ApplyMessage
(
vmenv
,
msg
,
new
(
core
.
GasPool
)
.
AddGas
(
tx
.
Gas
()))
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"tracing failed: %v"
,
err
)
}
...
...
@@ -532,6 +531,7 @@ func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, txHash common.
case
*
vm
.
StructLogger
:
return
&
ethapi
.
ExecutionResult
{
Gas
:
gas
,
Failed
:
failed
,
ReturnValue
:
fmt
.
Sprintf
(
"%x"
,
ret
),
StructLogs
:
ethapi
.
FormatLogs
(
tracer
.
StructLogs
()),
},
nil
...
...
internal/ethapi/api.go
View file @
94903d57
...
...
@@ -580,12 +580,12 @@ type CallArgs struct {
Data
hexutil
.
Bytes
`json:"data"`
}
func
(
s
*
PublicBlockChainAPI
)
doCall
(
ctx
context
.
Context
,
args
CallArgs
,
blockNr
rpc
.
BlockNumber
,
vmCfg
vm
.
Config
)
([]
byte
,
*
big
.
Int
,
error
)
{
func
(
s
*
PublicBlockChainAPI
)
doCall
(
ctx
context
.
Context
,
args
CallArgs
,
blockNr
rpc
.
BlockNumber
,
vmCfg
vm
.
Config
)
([]
byte
,
*
big
.
Int
,
bool
,
error
)
{
defer
func
(
start
time
.
Time
)
{
log
.
Debug
(
"Executing EVM call finished"
,
"runtime"
,
time
.
Since
(
start
))
}(
time
.
Now
())
state
,
header
,
err
:=
s
.
b
.
StateAndHeaderByNumber
(
ctx
,
blockNr
)
if
state
==
nil
||
err
!=
nil
{
return
nil
,
common
.
Big0
,
err
return
nil
,
common
.
Big0
,
false
,
err
}
// Set sender address or use a default if none specified
addr
:=
args
.
From
...
...
@@ -623,7 +623,7 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
// Get a new instance of the EVM.
evm
,
vmError
,
err
:=
s
.
b
.
GetEVM
(
ctx
,
msg
,
state
,
header
,
vmCfg
)
if
err
!=
nil
{
return
nil
,
common
.
Big0
,
err
return
nil
,
common
.
Big0
,
false
,
err
}
// Wait for the context to be done and cancel the evm. Even if the
// EVM has finished, cancelling may be done (repeatedly)
...
...
@@ -635,26 +635,28 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
// Setup the gas pool (also for unmetered requests)
// and apply the message.
gp
:=
new
(
core
.
GasPool
)
.
AddGas
(
math
.
MaxBig256
)
// TODO utilize failed flag to help gas estimation
res
,
gas
,
_
,
err
:=
core
.
ApplyMessage
(
evm
,
msg
,
gp
)
res
,
gas
,
failed
,
err
:=
core
.
ApplyMessage
(
evm
,
msg
,
gp
)
if
err
:=
vmError
();
err
!=
nil
{
return
nil
,
common
.
Big0
,
err
return
nil
,
common
.
Big0
,
false
,
err
}
return
res
,
gas
,
err
return
res
,
gas
,
failed
,
err
}
// Call executes the given transaction on the state for the given block number.
// It doesn't make and changes in the state/blockchain and is useful to execute and retrieve values.
func
(
s
*
PublicBlockChainAPI
)
Call
(
ctx
context
.
Context
,
args
CallArgs
,
blockNr
rpc
.
BlockNumber
)
(
hexutil
.
Bytes
,
error
)
{
result
,
_
,
err
:=
s
.
doCall
(
ctx
,
args
,
blockNr
,
vm
.
Config
{
DisableGasMetering
:
true
})
result
,
_
,
_
,
err
:=
s
.
doCall
(
ctx
,
args
,
blockNr
,
vm
.
Config
{
DisableGasMetering
:
true
})
return
(
hexutil
.
Bytes
)(
result
),
err
}
// EstimateGas returns an estimate of the amount of gas needed to execute the given transaction.
func
(
s
*
PublicBlockChainAPI
)
EstimateGas
(
ctx
context
.
Context
,
args
CallArgs
)
(
*
hexutil
.
Big
,
error
)
{
// Binary search the gas requirement, as it may be higher than the amount used
var
lo
,
hi
uint64
if
(
*
big
.
Int
)(
&
args
.
Gas
)
.
Sign
()
!=
0
{
var
(
lo
uint64
=
params
.
TxGas
-
1
hi
uint64
)
if
(
*
big
.
Int
)(
&
args
.
Gas
)
.
Uint64
()
>=
params
.
TxGas
{
hi
=
(
*
big
.
Int
)(
&
args
.
Gas
)
.
Uint64
()
}
else
{
// Retrieve the current pending block to act as the gas ceiling
...
...
@@ -669,10 +671,10 @@ func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (*
mid
:=
(
hi
+
lo
)
/
2
(
*
big
.
Int
)(
&
args
.
Gas
)
.
SetUint64
(
mid
)
_
,
gas
,
err
:=
s
.
doCall
(
ctx
,
args
,
rpc
.
PendingBlockNumber
,
vm
.
Config
{})
_
,
_
,
failed
,
err
:=
s
.
doCall
(
ctx
,
args
,
rpc
.
PendingBlockNumber
,
vm
.
Config
{})
// If the transaction became invalid or
used all the gas (failed)
, raise the gas limit
if
err
!=
nil
||
gas
.
Cmp
((
*
big
.
Int
)(
&
args
.
Gas
))
==
0
{
// If the transaction became invalid or
execution failed
, raise the gas limit
if
err
!=
nil
||
failed
{
lo
=
mid
continue
}
...
...
@@ -683,10 +685,11 @@ func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (*
}
// ExecutionResult groups all structured logs emitted by the EVM
// while replaying a transaction in debug mode as well as t
he amount of
// gas used and the return value
// while replaying a transaction in debug mode as well as t
ransaction
//
execution status, the amount of
gas used and the return value
type
ExecutionResult
struct
{
Gas
*
big
.
Int
`json:"gas"`
Failed
bool
`json:"failed"`
ReturnValue
string
`json:"returnValue"`
StructLogs
[]
StructLogRes
`json:"structLogs"`
}
...
...
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