accounts/abi/bind, cmd/abigen: port to templates, bind to solidity
This commit is contained in:
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
Reference in New Issue
Block a user