diff options
Diffstat (limited to 'accounts/abi/bind/backends')
-rw-r--r-- | accounts/abi/bind/backends/nil.go | 11 | ||||
-rw-r--r-- | accounts/abi/bind/backends/remote.go | 66 | ||||
-rw-r--r-- | accounts/abi/bind/backends/simulated.go | 33 |
3 files changed, 65 insertions, 45 deletions
diff --git a/accounts/abi/bind/backends/nil.go b/accounts/abi/bind/backends/nil.go index 8b1f9d63e..3b1e6dce7 100644 --- a/accounts/abi/bind/backends/nil.go +++ b/accounts/abi/bind/backends/nil.go @@ -24,6 +24,9 @@ import ( "github.com/ethereum/go-ethereum/core/types" ) +// This nil assignment ensures compile time that nilBackend implements bind.ContractBackend. +var _ bind.ContractBackend = (*nilBackend)(nil) + // nilBackend implements bind.ContractBackend, but panics on any method call. // Its sole purpose is to support the binding tests to construct the generated // wrappers without calling any methods on them. @@ -32,12 +35,12 @@ type nilBackend struct{} func (*nilBackend) ContractCall(common.Address, []byte, bool) ([]byte, error) { panic("not implemented") } -func (*nilBackend) GasLimit(common.Address, *common.Address, *big.Int, []byte) (*big.Int, error) { +func (*nilBackend) EstimateGasLimit(common.Address, *common.Address, *big.Int, []byte) (*big.Int, error) { panic("not implemented") } -func (*nilBackend) GasPrice() (*big.Int, error) { panic("not implemented") } -func (*nilBackend) AccountNonce(common.Address) (uint64, error) { panic("not implemented") } -func (*nilBackend) SendTransaction(*types.Transaction) 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") } // NewNilBackend creates a new binding backend that can be used for instantiation // but will panic on any invocation. Its sole purpose is to help testing. diff --git a/accounts/abi/bind/backends/remote.go b/accounts/abi/bind/backends/remote.go index 7177809bb..8e990f076 100644 --- a/accounts/abi/bind/backends/remote.go +++ b/accounts/abi/bind/backends/remote.go @@ -30,6 +30,9 @@ import ( "github.com/ethereum/go-ethereum/rpc" ) +// This nil assignment ensures compile time that rpcBackend implements bind.ContractBackend. +var _ bind.ContractBackend = (*rpcBackend)(nil) + // rpcBackend implements bind.ContractBackend, and acts as the data provider to // Ethereum contracts bound to Go structs. It uses an RPC connection to delegate // all its functionality. @@ -53,16 +56,16 @@ func NewRPCBackend(client rpc.Client) bind.ContractBackend { // request is a JSON RPC request package assembled internally from the client // method calls. type request struct { - JsonRpc string `json:"jsonrpc"` // Version of the JSON RPC protocol, always set to 2.0 - Id int `json:"id"` // Auto incrementing ID number for this request + JSONRPC string `json:"jsonrpc"` // Version of the JSON RPC protocol, always set to 2.0 + ID int `json:"id"` // Auto incrementing ID number for this request Method string `json:"method"` // Remote procedure name to invoke on the server Params []interface{} `json:"params"` // List of parameters to pass through (keep types simple) } // response is a JSON RPC response package sent back from the API server. type response struct { - JsonRpc string `json:"jsonrpc"` // Version of the JSON RPC protocol, always set to 2.0 - Id int `json:"id"` // Auto incrementing ID number for this request + JSONRPC string `json:"jsonrpc"` // Version of the JSON RPC protocol, always set to 2.0 + ID int `json:"id"` // Auto incrementing ID number for this request Error json.RawMessage `json:"error"` // Any error returned by the remote side Result json.RawMessage `json:"result"` // Whatever the remote side sends us in reply } @@ -71,9 +74,9 @@ type response struct { // // This is currently painfully non-concurrent, but it will have to do until we // find the time for niceties like this :P -func (backend *rpcBackend) request(method string, params []interface{}) (json.RawMessage, error) { - backend.lock.Lock() - defer backend.lock.Unlock() +func (b *rpcBackend) request(method string, params []interface{}) (json.RawMessage, error) { + b.lock.Lock() + defer b.lock.Unlock() // Ugly hack to serialize an empty list properly if params == nil { @@ -81,16 +84,16 @@ func (backend *rpcBackend) request(method string, params []interface{}) (json.Ra } // Assemble the request object req := &request{ - JsonRpc: "2.0", - Id: int(atomic.AddUint32(&backend.autoid, 1)), + JSONRPC: "2.0", + ID: int(atomic.AddUint32(&b.autoid, 1)), Method: method, Params: params, } - if err := backend.client.Send(req); err != nil { + if err := b.client.Send(req); err != nil { return nil, err } res := new(response) - if err := backend.client.Recv(res); err != nil { + if err := b.client.Recv(res); err != nil { return nil, err } if len(res.Error) > 0 { @@ -127,9 +130,9 @@ func (b *rpcBackend) ContractCall(contract common.Address, data []byte, pending return common.FromHex(hex), nil } -// AccountNonce implements ContractTransactor.AccountNonce, delegating the -// current account nonce retrieval to the remote node. -func (b *rpcBackend) AccountNonce(account common.Address) (uint64, error) { +// PendingAccountNonce implements ContractTransactor.PendingAccountNonce, delegating +// the current account nonce retrieval to the remote node. +func (b *rpcBackend) PendingAccountNonce(account common.Address) (uint64, error) { res, err := b.request("eth_getTransactionCount", []interface{}{account.Hex(), "pending"}) if err != nil { return 0, err @@ -138,12 +141,16 @@ func (b *rpcBackend) AccountNonce(account common.Address) (uint64, error) { if err := json.Unmarshal(res, &hex); err != nil { return 0, err } - return new(big.Int).SetBytes(common.FromHex(hex)).Uint64(), nil + nonce, ok := new(big.Int).SetString(hex, 0) + if !ok { + return 0, fmt.Errorf("invalid nonce hex: %s", hex) + } + return nonce.Uint64(), nil } -// GasPrice implements ContractTransactor.GasPrice, delegating the gas price -// oracle request to the remote node. -func (b *rpcBackend) GasPrice() (*big.Int, error) { +// SuggestGasPrice implements ContractTransactor.SuggestGasPrice, delegating the +// gas price oracle request to the remote node. +func (b *rpcBackend) SuggestGasPrice() (*big.Int, error) { res, err := b.request("eth_gasPrice", nil) if err != nil { return nil, err @@ -152,12 +159,16 @@ func (b *rpcBackend) GasPrice() (*big.Int, error) { if err := json.Unmarshal(res, &hex); err != nil { return nil, err } - return new(big.Int).SetBytes(common.FromHex(hex)), nil + price, ok := new(big.Int).SetString(hex, 0) + if !ok { + return nil, fmt.Errorf("invalid price hex: %s", hex) + } + return price, nil } -// GasLimit implements ContractTransactor.GasLimit, delegating the gas estimation -// to the remote node. -func (b *rpcBackend) GasLimit(sender common.Address, contract *common.Address, value *big.Int, data []byte) (*big.Int, error) { +// EstimateGasLimit implements ContractTransactor.EstimateGasLimit, delegating +// the gas estimation to the remote node. +func (b *rpcBackend) EstimateGasLimit(sender common.Address, contract *common.Address, value *big.Int, data []byte) (*big.Int, error) { // Pack up the request into an RPC argument args := struct { From common.Address `json:"from"` @@ -179,12 +190,15 @@ func (b *rpcBackend) GasLimit(sender common.Address, contract *common.Address, v if err := json.Unmarshal(res, &hex); err != nil { return nil, err } - // Convert the response back to a Go byte slice and return - return new(big.Int).SetBytes(common.FromHex(hex)), nil + estimate, ok := new(big.Int).SetString(hex, 0) + if !ok { + return nil, fmt.Errorf("invalid estimate hex: %s", hex) + } + return estimate, nil } -// Transact implements ContractTransactor.SendTransaction, delegating the raw -// transaction injection to the remote node. +// SendTransaction implements ContractTransactor.SendTransaction, delegating the +// raw transaction injection to the remote node. func (b *rpcBackend) SendTransaction(tx *types.Transaction) error { data, err := rlp.EncodeToBytes(tx) if err != nil { diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index 17a0ed7fe..18e8481c5 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -19,6 +19,7 @@ package backends import ( "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" @@ -27,6 +28,9 @@ import ( "github.com/ethereum/go-ethereum/event" ) +// This nil assignment ensures compile time that SimulatedBackend implements bind.ContractBackend. +var _ bind.ContractBackend = (*SimulatedBackend)(nil) + // SimulatedBackend implements bind.ContractBackend, simulating a blockchain in // the background. Its main purpose is to allow easily testing contract bindings. type SimulatedBackend struct { @@ -79,13 +83,11 @@ func (b *SimulatedBackend) ContractCall(contract common.Address, data []byte, pe statedb *state.StateDB ) if pending { - block, statedb = b.pendingBlock, b.pendingState + block, statedb = b.pendingBlock, b.pendingState.Copy() } else { block = b.blockchain.CurrentBlock() statedb, _ = b.blockchain.State() } - statedb = statedb.Copy() - // Set infinite balance to the a fake caller account from := statedb.GetOrNewStateObject(common.Address{}) from.SetBalance(common.MaxBig) @@ -100,28 +102,29 @@ func (b *SimulatedBackend) ContractCall(contract common.Address, data []byte, pe data: data, } // Execute the call and return - vmenv := core.NewEnv(statedb, b.blockchain, msg, block.Header()) + vmenv := core.NewEnv(statedb, b.blockchain, msg, block.Header(), nil) gaspool := new(core.GasPool).AddGas(common.MaxBig) out, _, err := core.ApplyMessage(vmenv, msg, gaspool) return out, err } -// AccountNonce implements ContractTransactor.AccountNonce, retrieving the nonce -// currently pending for the account. -func (b *SimulatedBackend) AccountNonce(account common.Address) (uint64, error) { +// PendingAccountNonce implements ContractTransactor.PendingAccountNonce, retrieving +// the nonce currently pending for the account. +func (b *SimulatedBackend) PendingAccountNonce(account common.Address) (uint64, error) { return b.pendingState.GetOrNewStateObject(account).Nonce(), nil } -// GasPrice implements ContractTransactor.GasPrice. Since the simulated chain -// doens't have miners, we just return a gas price of 1 for any call. -func (b *SimulatedBackend) GasPrice() (*big.Int, error) { +// SuggestGasPrice implements ContractTransactor.SuggestGasPrice. Since the simulated +// chain doens't have miners, we just return a gas price of 1 for any call. +func (b *SimulatedBackend) SuggestGasPrice() (*big.Int, error) { return big.NewInt(1), nil } -// GasLimit implements ContractTransactor.GasLimit, executing the requested code -// against the currently pending block/state and returning the used gas. -func (b *SimulatedBackend) GasLimit(sender common.Address, contract *common.Address, value *big.Int, data []byte) (*big.Int, error) { +// EstimateGasLimit implements ContractTransactor.EstimateGasLimit, executing the +// requested code against the currently pending block/state and returning the used +// gas. +func (b *SimulatedBackend) EstimateGasLimit(sender common.Address, contract *common.Address, value *big.Int, data []byte) (*big.Int, error) { // Create a copy of the currently pending state db to screw around with var ( block = b.pendingBlock @@ -142,14 +145,14 @@ func (b *SimulatedBackend) GasLimit(sender common.Address, contract *common.Addr data: data, } // Execute the call and return - vmenv := core.NewEnv(statedb, b.blockchain, msg, block.Header()) + vmenv := core.NewEnv(statedb, b.blockchain, msg, block.Header(), nil) gaspool := new(core.GasPool).AddGas(common.MaxBig) _, gas, err := core.ApplyMessage(vmenv, msg, gaspool) return gas, err } -// Transact implements ContractTransactor.SendTransaction, delegating the raw +// SendTransaction implements ContractTransactor.SendTransaction, delegating the raw // transaction injection to the remote node. func (b *SimulatedBackend) SendTransaction(tx *types.Transaction) error { blocks, _ := core.GenerateChain(b.blockchain.CurrentBlock(), b.database, 1, func(number int, block *core.BlockGen) { |