Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
whqwjb
go-ethereum
提交
1776c717
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,体验更适合开发者的 AI 搜索 >>
提交
1776c717
编写于
5月 20, 2016
作者:
P
Péter Szilágyi
提交者:
Jeffrey Wilcke
5月 24, 2016
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[release 1.4.5] accounts/abi/bind, eth: rely on getCode for sanity checks, not estimate and call
(cherry picked from commit
1580ec18
)
上级
0f6e3e87
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
112 addition
and
28 deletion
+112
-28
accounts/abi/bind/backend.go
accounts/abi/bind/backend.go
+43
-6
accounts/abi/bind/backends/nil.go
accounts/abi/bind/backends/nil.go
+1
-0
accounts/abi/bind/backends/remote.go
accounts/abi/bind/backends/remote.go
+20
-0
accounts/abi/bind/backends/simulated.go
accounts/abi/bind/backends/simulated.go
+10
-0
accounts/abi/bind/base.go
accounts/abi/bind/base.go
+27
-0
eth/api.go
eth/api.go
+0
-15
eth/bind.go
eth/bind.go
+11
-7
未找到文件。
accounts/abi/bind/backend.go
浏览文件 @
1776c717
...
...
@@ -27,15 +27,16 @@ import (
// ErrNoCode is returned by call and transact operations for which the requested
// recipient contract to operate on does not exist in the state db or does not
// have any code associated with it (i.e. suicided).
//
// Please note, this error string is part of the RPC API and is expected by the
// native contract bindings to signal this particular error. Do not change this
// as it will break all dependent code!
var
ErrNoCode
=
errors
.
New
(
"no contract code at given address"
)
// ContractCaller defines the methods needed to allow operating with contract on a read
// only basis.
type
ContractCaller
interface
{
// HasCode checks if the contract at the given address has any code associated
// with it or not. This is needed to differentiate between contract internal
// errors and the local chain being out of sync.
HasCode
(
contract
common
.
Address
,
pending
bool
)
(
bool
,
error
)
// ContractCall executes an Ethereum contract call with the specified data as
// the input. The pending flag requests execution against the pending block, not
// the stable head of the chain.
...
...
@@ -55,6 +56,11 @@ type ContractTransactor interface {
// execution of a transaction.
SuggestGasPrice
()
(
*
big
.
Int
,
error
)
// HasCode checks if the contract at the given address has any code associated
// with it or not. This is needed to differentiate between contract internal
// errors and the local chain being out of sync.
HasCode
(
contract
common
.
Address
,
pending
bool
)
(
bool
,
error
)
// EstimateGasLimit tries to estimate the gas needed to execute a specific
// transaction based on the current pending state of the backend blockchain.
// There is no guarantee that this is the true gas limit requirement as other
...
...
@@ -68,7 +74,38 @@ type ContractTransactor interface {
// ContractBackend defines the methods needed to allow operating with contract
// on a read-write basis.
//
// This interface is essentially the union of ContractCaller and ContractTransactor
// but due to a bug in the Go compiler (https://github.com/golang/go/issues/6977),
// we cannot simply list it as the two interfaces. The other solution is to add a
// third interface containing the common methods, but that convolutes the user API
// as it introduces yet another parameter to require for initialization.
type
ContractBackend
interface
{
ContractCaller
ContractTransactor
// HasCode checks if the contract at the given address has any code associated
// with it or not. This is needed to differentiate between contract internal
// errors and the local chain being out of sync.
HasCode
(
contract
common
.
Address
,
pending
bool
)
(
bool
,
error
)
// ContractCall executes an Ethereum contract call with the specified data as
// the input. The pending flag requests execution against the pending block, not
// the stable head of the chain.
ContractCall
(
contract
common
.
Address
,
data
[]
byte
,
pending
bool
)
([]
byte
,
error
)
// PendingAccountNonce retrieves the current pending nonce associated with an
// account.
PendingAccountNonce
(
account
common
.
Address
)
(
uint64
,
error
)
// SuggestGasPrice retrieves the currently suggested gas price to allow a timely
// execution of a transaction.
SuggestGasPrice
()
(
*
big
.
Int
,
error
)
// EstimateGasLimit tries to estimate the gas needed to execute a specific
// transaction based on the current pending state of the backend blockchain.
// There is no guarantee that this is the true gas limit requirement as other
// transactions may be added or removed by miners, but it should provide a basis
// for setting a reasonable default.
EstimateGasLimit
(
sender
common
.
Address
,
contract
*
common
.
Address
,
value
*
big
.
Int
,
data
[]
byte
)
(
*
big
.
Int
,
error
)
// SendTransaction injects the transaction into the pending pool for execution.
SendTransaction
(
tx
*
types
.
Transaction
)
error
}
accounts/abi/bind/backends/nil.go
浏览文件 @
1776c717
...
...
@@ -38,6 +38,7 @@ func (*nilBackend) ContractCall(common.Address, []byte, bool) ([]byte, error) {
func
(
*
nilBackend
)
EstimateGasLimit
(
common
.
Address
,
*
common
.
Address
,
*
big
.
Int
,
[]
byte
)
(
*
big
.
Int
,
error
)
{
panic
(
"not implemented"
)
}
func
(
*
nilBackend
)
HasCode
(
common
.
Address
,
bool
)
(
bool
,
error
)
{
panic
(
"not implemented"
)
}
func
(
*
nilBackend
)
SuggestGasPrice
()
(
*
big
.
Int
,
error
)
{
panic
(
"not implemented"
)
}
func
(
*
nilBackend
)
PendingAccountNonce
(
common
.
Address
)
(
uint64
,
error
)
{
panic
(
"not implemented"
)
}
func
(
*
nilBackend
)
SendTransaction
(
*
types
.
Transaction
)
error
{
panic
(
"not implemented"
)
}
...
...
accounts/abi/bind/backends/remote.go
浏览文件 @
1776c717
...
...
@@ -111,6 +111,26 @@ func (b *rpcBackend) request(method string, params []interface{}) (json.RawMessa
return
res
.
Result
,
nil
}
// HasCode implements ContractVerifier.HasCode by retrieving any code associated
// with the contract from the remote node, and checking its size.
func
(
b
*
rpcBackend
)
HasCode
(
contract
common
.
Address
,
pending
bool
)
(
bool
,
error
)
{
// Execute the RPC code retrieval
block
:=
"latest"
if
pending
{
block
=
"pending"
}
res
,
err
:=
b
.
request
(
"eth_getCode"
,
[]
interface
{}{
contract
.
Hex
(),
block
})
if
err
!=
nil
{
return
false
,
err
}
var
hex
string
if
err
:=
json
.
Unmarshal
(
res
,
&
hex
);
err
!=
nil
{
return
false
,
err
}
// Convert the response back to a Go byte slice and return
return
len
(
common
.
FromHex
(
hex
))
>
0
,
nil
}
// ContractCall implements ContractCaller.ContractCall, delegating the execution of
// a contract call to the remote node, returning the reply to for local processing.
func
(
b
*
rpcBackend
)
ContractCall
(
contract
common
.
Address
,
data
[]
byte
,
pending
bool
)
([]
byte
,
error
)
{
...
...
accounts/abi/bind/backends/simulated.go
浏览文件 @
1776c717
...
...
@@ -78,6 +78,16 @@ func (b *SimulatedBackend) Rollback() {
b
.
pendingState
,
_
=
state
.
New
(
b
.
pendingBlock
.
Root
(),
b
.
database
)
}
// HasCode implements ContractVerifier.HasCode, checking whether there is any
// code associated with a certain account in the blockchain.
func
(
b
*
SimulatedBackend
)
HasCode
(
contract
common
.
Address
,
pending
bool
)
(
bool
,
error
)
{
if
pending
{
return
len
(
b
.
pendingState
.
GetCode
(
contract
))
>
0
,
nil
}
statedb
,
_
:=
b
.
blockchain
.
State
()
return
len
(
statedb
.
GetCode
(
contract
))
>
0
,
nil
}
// ContractCall implements ContractCaller.ContractCall, executing the specified
// contract with the given input data.
func
(
b
*
SimulatedBackend
)
ContractCall
(
contract
common
.
Address
,
data
[]
byte
,
pending
bool
)
([]
byte
,
error
)
{
...
...
accounts/abi/bind/base.go
浏览文件 @
1776c717
...
...
@@ -20,6 +20,7 @@ import (
"errors"
"fmt"
"math/big"
"sync/atomic"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
...
...
@@ -56,6 +57,9 @@ type BoundContract struct {
abi
abi
.
ABI
// Reflect based ABI to access the correct Ethereum methods
caller
ContractCaller
// Read interface to interact with the blockchain
transactor
ContractTransactor
// Write interface to interact with the blockchain
latestHasCode
uint32
// Cached verification that the latest state contains code for this contract
pendingHasCode
uint32
// Cached verification that the pending state contains code for this contract
}
// NewBoundContract creates a low level contract interface through which calls
...
...
@@ -96,6 +100,19 @@ func (c *BoundContract) Call(opts *CallOpts, result interface{}, method string,
if
opts
==
nil
{
opts
=
new
(
CallOpts
)
}
// Make sure we have a contract to operate on, and bail out otherwise
if
(
opts
.
Pending
&&
atomic
.
LoadUint32
(
&
c
.
pendingHasCode
)
==
0
)
||
(
!
opts
.
Pending
&&
atomic
.
LoadUint32
(
&
c
.
latestHasCode
)
==
0
)
{
if
code
,
err
:=
c
.
caller
.
HasCode
(
c
.
address
,
opts
.
Pending
);
err
!=
nil
{
return
err
}
else
if
!
code
{
return
ErrNoCode
}
if
opts
.
Pending
{
atomic
.
StoreUint32
(
&
c
.
pendingHasCode
,
1
)
}
else
{
atomic
.
StoreUint32
(
&
c
.
latestHasCode
,
1
)
}
}
// Pack the input, call and unpack the results
input
,
err
:=
c
.
abi
.
Pack
(
method
,
params
...
)
if
err
!=
nil
{
...
...
@@ -153,6 +170,16 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
}
gasLimit
:=
opts
.
GasLimit
if
gasLimit
==
nil
{
// Gas estimation cannot succeed without code for method invocations
if
contract
!=
nil
&&
atomic
.
LoadUint32
(
&
c
.
pendingHasCode
)
==
0
{
if
code
,
err
:=
c
.
transactor
.
HasCode
(
c
.
address
,
true
);
err
!=
nil
{
return
nil
,
err
}
else
if
!
code
{
return
nil
,
ErrNoCode
}
atomic
.
StoreUint32
(
&
c
.
pendingHasCode
,
1
)
}
// If the contract surely has code (or code is not needed), estimate the transaction
gasLimit
,
err
=
c
.
transactor
.
EstimateGasLimit
(
opts
.
From
,
contract
,
value
,
input
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to exstimate gas needed: %v"
,
err
)
...
...
eth/api.go
浏览文件 @
1776c717
...
...
@@ -52,15 +52,6 @@ import (
"golang.org/x/net/context"
)
// errNoCode is returned by call and transact operations for which the requested
// recipient contract to operate on does not exist in the state db or does not
// have any code associated with it (i.e. suicided).
//
// Please note, this error string is part of the RPC API and is expected by the
// native contract bindings to signal this particular error. Do not change this
// as it will break all dependent code!
var
errNoCode
=
errors
.
New
(
"no contract code at given address"
)
const
defaultGas
=
uint64
(
90000
)
// blockByNumber is a commonly used helper function which retrieves and returns
...
...
@@ -755,12 +746,6 @@ func (s *PublicBlockChainAPI) doCall(args CallArgs, blockNr rpc.BlockNumber) (st
}
stateDb
=
stateDb
.
Copy
()
// If there's no code to interact with, respond with an appropriate error
if
args
.
To
!=
nil
{
if
code
:=
stateDb
.
GetCode
(
*
args
.
To
);
len
(
code
)
==
0
{
return
"0x"
,
nil
,
errNoCode
}
}
// Retrieve the account state object to interact with
var
from
*
state
.
StateObject
if
args
.
From
==
(
common
.
Address
{})
{
...
...
eth/bind.go
浏览文件 @
1776c717
...
...
@@ -19,7 +19,6 @@ package eth
import
(
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
...
...
@@ -49,6 +48,17 @@ func NewContractBackend(eth *Ethereum) *ContractBackend {
}
}
// HasCode implements bind.ContractVerifier.HasCode by retrieving any code associated
// with the contract from the local API, and checking its size.
func
(
b
*
ContractBackend
)
HasCode
(
contract
common
.
Address
,
pending
bool
)
(
bool
,
error
)
{
block
:=
rpc
.
LatestBlockNumber
if
pending
{
block
=
rpc
.
PendingBlockNumber
}
out
,
err
:=
b
.
bcapi
.
GetCode
(
contract
,
block
)
return
len
(
common
.
FromHex
(
out
))
>
0
,
err
}
// ContractCall implements bind.ContractCaller executing an Ethereum contract
// call with the specified data as the input. The pending flag requests execution
// against the pending block, not the stable head of the chain.
...
...
@@ -64,9 +74,6 @@ func (b *ContractBackend) ContractCall(contract common.Address, data []byte, pen
}
// Execute the call and convert the output back to Go types
out
,
err
:=
b
.
bcapi
.
Call
(
args
,
block
)
if
err
==
errNoCode
{
err
=
bind
.
ErrNoCode
}
return
common
.
FromHex
(
out
),
err
}
...
...
@@ -95,9 +102,6 @@ func (b *ContractBackend) EstimateGasLimit(sender common.Address, contract *comm
Value
:
*
rpc
.
NewHexNumber
(
value
),
Data
:
common
.
ToHex
(
data
),
})
if
err
==
errNoCode
{
err
=
bind
.
ErrNoCode
}
return
out
.
BigInt
(),
err
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录