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
86cfc22c
Commit
86cfc22c
authored
9 years ago
by
Péter Szilágyi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
accounts/abi/bind: constructor, auth utils and various backends
parent
72826bb5
Changes
10
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
736 additions
and
267 deletions
+736
-267
abi.go
accounts/abi/abi.go
+27
-19
auth.go
accounts/abi/bind/auth.go
+53
-0
backend.go
accounts/abi/bind/backend.go
+4
-192
nil.go
accounts/abi/bind/backends/nil.go
+46
-0
remote.go
accounts/abi/bind/backends/remote.go
+202
-0
simulated.go
accounts/abi/bind/backends/simulated.go
+184
-0
base.go
accounts/abi/bind/base.go
+59
-7
bind.go
accounts/abi/bind/bind.go
+140
-37
bind_test.go
accounts/abi/bind/bind_test.go
+8
-8
main.go
cmd/abigen/main.go
+13
-4
No files found.
accounts/abi/abi.go
View file @
86cfc22c
...
...
@@ -30,8 +30,9 @@ import (
// invokable methods. It will allow you to type check function calls and
// packs data accordingly.
type
ABI
struct
{
Methods
map
[
string
]
Method
Events
map
[
string
]
Event
Constructor
Method
Methods
map
[
string
]
Method
Events
map
[
string
]
Event
}
// JSON returns a parsed ABI interface and error if it failed.
...
...
@@ -48,9 +49,7 @@ func JSON(reader io.Reader) (ABI, error) {
// tests, tests whether the given input would result in a successful
// call. Checks argument list count and matches input to `input`.
func
(
abi
ABI
)
pack
(
name
string
,
args
...
interface
{})
([]
byte
,
error
)
{
method
:=
abi
.
Methods
[
name
]
func
(
abi
ABI
)
pack
(
method
Method
,
args
...
interface
{})
([]
byte
,
error
)
{
// variable input is the output appended at the end of packed
// output. This is used for strings and bytes types input.
var
variableInput
[]
byte
...
...
@@ -61,7 +60,7 @@ func (abi ABI) pack(name string, args ...interface{}) ([]byte, error) {
// pack the input
packed
,
err
:=
input
.
Type
.
pack
(
a
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"`%s` %v"
,
n
ame
,
err
)
return
nil
,
fmt
.
Errorf
(
"`%s` %v"
,
method
.
N
ame
,
err
)
}
// check for a string or bytes input type
...
...
@@ -91,26 +90,31 @@ func (abi ABI) pack(name string, args ...interface{}) ([]byte, error) {
// Method ids are created from the first 4 bytes of the hash of the
// methods string signature. (signature = baz(uint32,string32))
func
(
abi
ABI
)
Pack
(
name
string
,
args
...
interface
{})
([]
byte
,
error
)
{
method
,
exist
:=
abi
.
Methods
[
name
]
if
!
exist
{
return
nil
,
fmt
.
Errorf
(
"method '%s' not found"
,
name
)
}
// Fetch the ABI of the requested method
var
method
Method
// start with argument count match
if
name
==
""
{
method
=
abi
.
Constructor
}
else
{
m
,
exist
:=
abi
.
Methods
[
name
]
if
!
exist
{
return
nil
,
fmt
.
Errorf
(
"method '%s' not found"
,
name
)
}
method
=
m
}
// Make sure arguments match up and pack them
if
len
(
args
)
!=
len
(
method
.
Inputs
)
{
return
nil
,
fmt
.
Errorf
(
"argument count mismatch: %d for %d"
,
len
(
args
),
len
(
method
.
Inputs
))
}
arguments
,
err
:=
abi
.
pack
(
name
,
args
...
)
arguments
,
err
:=
abi
.
pack
(
method
,
args
...
)
if
err
!=
nil
{
return
nil
,
err
}
// Set function id
packed
:=
abi
.
Methods
[
name
]
.
Id
()
packed
=
append
(
packed
,
arguments
...
)
return
packed
,
nil
// Pack up the method ID too if not a constructor and return
if
name
==
""
{
return
arguments
,
nil
}
return
append
(
method
.
Id
(),
arguments
...
),
nil
}
// toGoType parses the input and casts it to the proper type defined by the ABI
...
...
@@ -283,6 +287,10 @@ func (abi *ABI) UnmarshalJSON(data []byte) error {
abi
.
Events
=
make
(
map
[
string
]
Event
)
for
_
,
field
:=
range
fields
{
switch
field
.
Type
{
case
"constructor"
:
abi
.
Constructor
=
Method
{
Inputs
:
field
.
Inputs
,
}
// empty defaults to function according to the abi spec
case
"function"
,
""
:
abi
.
Methods
[
field
.
Name
]
=
Method
{
...
...
This diff is collapsed.
Click to expand it.
accounts/abi/bind/auth.go
0 → 100644
View file @
86cfc22c
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
bind
import
(
"errors"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
)
// NewTransactor is a utility method to easily create a transaction signer from
// an encrypted json key file and the associated passphrase.
func
NewTransactor
(
keyjson
string
,
passphrase
string
)
(
*
TransactOpts
,
error
)
{
key
,
err
:=
crypto
.
DecryptKey
([]
byte
(
keyjson
),
passphrase
)
if
err
!=
nil
{
return
nil
,
err
}
return
NewKeyedTransactor
(
key
),
nil
}
// NewKeyedTransactor is a utility method to easily create a transaction signer
// from a plain go-ethereum crypto key.
func
NewKeyedTransactor
(
key
*
crypto
.
Key
)
*
TransactOpts
{
return
&
TransactOpts
{
Account
:
key
.
Address
,
Signer
:
func
(
address
common
.
Address
,
tx
*
types
.
Transaction
)
(
*
types
.
Transaction
,
error
)
{
if
address
!=
key
.
Address
{
return
nil
,
errors
.
New
(
"not authorized to sign this account"
)
}
signature
,
err
:=
crypto
.
Sign
(
tx
.
SigHash
()
.
Bytes
(),
key
.
PrivateKey
)
if
err
!=
nil
{
return
nil
,
err
}
return
tx
.
WithSignature
(
signature
)
},
}
}
This diff is collapsed.
Click to expand it.
accounts/abi/bind/backend.go
View file @
86cfc22c
...
...
@@ -17,24 +17,19 @@
package
bind
import
(
"encoding/json"
"fmt"
"math/big"
"sync"
"sync/atomic"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
)
// ContractCaller defines the methods needed to allow operating with contract on a read
// only basis.
type
ContractCaller
interface
{
// ContractCall executes an Ethereum contract call with the specified data as
// the input.
ContractCall
(
contract
common
.
Address
,
data
[]
byte
)
([]
byte
,
error
)
// 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
)
}
// ContractTransactor defines the methods needed to allow operating with contract
...
...
@@ -50,7 +45,7 @@ type ContractTransactor interface {
GasPrice
()
(
*
big
.
Int
,
error
)
// GasLimit tries to estimate the gas needed to execute a specific transaction.
GasLimit
(
sender
,
contract
common
.
Address
,
value
*
big
.
Int
,
data
[]
byte
)
(
*
big
.
Int
,
error
)
GasLimit
(
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
(
*
types
.
Transaction
)
error
...
...
@@ -62,186 +57,3 @@ type ContractBackend interface {
ContractCaller
ContractTransactor
}
// 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.
type
nilBackend
struct
{}
func
(
*
nilBackend
)
ContractCall
(
common
.
Address
,
[]
byte
)
([]
byte
,
error
)
{
panic
(
"not implemented"
)
}
func
(
*
nilBackend
)
SendTransaction
(
*
types
.
Transaction
)
error
{
panic
(
"not implemented"
)
}
func
(
*
nilBackend
)
AccountNonce
(
common
.
Address
)
(
uint64
,
error
)
{
panic
(
"not implemented"
)
}
func
(
*
nilBackend
)
GasPrice
()
(
*
big
.
Int
,
error
)
{
panic
(
"not implemented"
)
}
func
(
*
nilBackend
)
GasLimit
(
common
.
Address
,
common
.
Address
,
*
big
.
Int
,
[]
byte
)
(
*
big
.
Int
,
error
)
{
panic
(
"not implemented"
)
}
// Helper backend for internal tests. Will panic on any invocation!
var
NilBackend
=
new
(
nilBackend
)
// 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.
//
// Note: The current implementation is a blocking one. This should be replaced
// by a proper async version when a real RPC client is created.
type
rpcBackend
struct
{
client
rpc
.
Client
// RPC client connection to interact with an API server
autoid
uint32
// ID number to use for the next API request
lock
sync
.
Mutex
// Singleton access until we get to request multiplexing
}
// NewRPCBackend creates a new binding backend to an RPC provider that can be
// used to interact with remote contracts.
func
NewRPCBackend
(
client
rpc
.
Client
)
ContractBackend
{
return
&
rpcBackend
{
client
:
client
,
}
}
// 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
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
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
}
// request forwards an API request to the RPC server, and parses the response.
//
// 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
()
// Ugly hack to serialize an empty list properly
if
params
==
nil
{
params
=
[]
interface
{}{}
}
// Assemble the request object
req
:=
&
request
{
JsonRpc
:
"2.0"
,
Id
:
int
(
atomic
.
AddUint32
(
&
backend
.
autoid
,
1
)),
Method
:
method
,
Params
:
params
,
}
if
err
:=
backend
.
client
.
Send
(
req
);
err
!=
nil
{
return
nil
,
err
}
res
:=
new
(
response
)
if
err
:=
backend
.
client
.
Recv
(
res
);
err
!=
nil
{
return
nil
,
err
}
if
len
(
res
.
Error
)
>
0
{
return
nil
,
fmt
.
Errorf
(
"remote error: %s"
,
string
(
res
.
Error
))
}
return
res
.
Result
,
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
)
([]
byte
,
error
)
{
// Pack up the request into an RPC argument
args
:=
struct
{
To
common
.
Address
`json:"to"`
Data
string
`json:"data"`
}{
To
:
contract
,
Data
:
common
.
ToHex
(
data
),
}
// Execute the RPC call and retrieve the response
res
,
err
:=
b
.
request
(
"eth_call"
,
[]
interface
{}{
args
,
"pending"
})
if
err
!=
nil
{
return
nil
,
err
}
var
hex
string
if
err
:=
json
.
Unmarshal
(
res
,
&
hex
);
err
!=
nil
{
return
nil
,
err
}
// Convert the response back to a Go byte slice and return
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
)
{
res
,
err
:=
b
.
request
(
"eth_getTransactionCount"
,
[]
interface
{}{
account
.
Hex
(),
"pending"
})
if
err
!=
nil
{
return
0
,
err
}
var
hex
string
if
err
:=
json
.
Unmarshal
(
res
,
&
hex
);
err
!=
nil
{
return
0
,
err
}
return
new
(
big
.
Int
)
.
SetBytes
(
common
.
FromHex
(
hex
))
.
Uint64
(),
nil
}
// GasPrice implements ContractTransactor.GasPrice, delegating the gas price
// oracle request to the remote node.
func
(
b
*
rpcBackend
)
GasPrice
()
(
*
big
.
Int
,
error
)
{
res
,
err
:=
b
.
request
(
"eth_gasPrice"
,
nil
)
if
err
!=
nil
{
return
nil
,
err
}
var
hex
string
if
err
:=
json
.
Unmarshal
(
res
,
&
hex
);
err
!=
nil
{
return
nil
,
err
}
return
new
(
big
.
Int
)
.
SetBytes
(
common
.
FromHex
(
hex
)),
nil
}
// GasLimit implements ContractTransactor.GasLimit, delegating the gas estimation
// to the remote node.
func
(
b
*
rpcBackend
)
GasLimit
(
sender
,
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"`
To
common
.
Address
`json:"to"`
Value
*
rpc
.
HexNumber
`json:"value"`
Data
string
`json:"data"`
}{
From
:
sender
,
To
:
contract
,
Data
:
common
.
ToHex
(
data
),
Value
:
rpc
.
NewHexNumber
(
value
),
}
// Execute the RPC call and retrieve the response
res
,
err
:=
b
.
request
(
"eth_estimateGas"
,
[]
interface
{}{
args
})
if
err
!=
nil
{
return
nil
,
err
}
var
hex
string
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
}
// Transact 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
{
return
err
}
res
,
err
:=
b
.
request
(
"eth_sendRawTransaction"
,
[]
interface
{}{
common
.
ToHex
(
data
)})
if
err
!=
nil
{
return
err
}
var
hex
string
if
err
:=
json
.
Unmarshal
(
res
,
&
hex
);
err
!=
nil
{
return
err
}
return
nil
}
This diff is collapsed.
Click to expand it.
accounts/abi/bind/backends/nil.go
0 → 100644
View file @
86cfc22c
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
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/types"
)
// 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.
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
)
{
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"
)
}
// 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.
func
NewNilBackend
()
bind
.
ContractBackend
{
return
new
(
nilBackend
)
}
This diff is collapsed.
Click to expand it.
accounts/abi/bind/backends/remote.go
0 → 100644
View file @
86cfc22c
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
backends
import
(
"encoding/json"
"fmt"
"math/big"
"sync"
"sync/atomic"
"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"
"github.com/ethereum/go-ethereum/rpc"
)
// 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.
//
// Note: The current implementation is a blocking one. This should be replaced
// by a proper async version when a real RPC client is created.
type
rpcBackend
struct
{
client
rpc
.
Client
// RPC client connection to interact with an API server
autoid
uint32
// ID number to use for the next API request
lock
sync
.
Mutex
// Singleton access until we get to request multiplexing
}
// NewRPCBackend creates a new binding backend to an RPC provider that can be
// used to interact with remote contracts.
func
NewRPCBackend
(
client
rpc
.
Client
)
bind
.
ContractBackend
{
return
&
rpcBackend
{
client
:
client
,
}
}
// 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
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
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
}
// request forwards an API request to the RPC server, and parses the response.
//
// 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
()
// Ugly hack to serialize an empty list properly
if
params
==
nil
{
params
=
[]
interface
{}{}
}
// Assemble the request object
req
:=
&
request
{
JsonRpc
:
"2.0"
,
Id
:
int
(
atomic
.
AddUint32
(
&
backend
.
autoid
,
1
)),
Method
:
method
,
Params
:
params
,
}
if
err
:=
backend
.
client
.
Send
(
req
);
err
!=
nil
{
return
nil
,
err
}
res
:=
new
(
response
)
if
err
:=
backend
.
client
.
Recv
(
res
);
err
!=
nil
{
return
nil
,
err
}
if
len
(
res
.
Error
)
>
0
{
return
nil
,
fmt
.
Errorf
(
"remote error: %s"
,
string
(
res
.
Error
))
}
return
res
.
Result
,
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
)
{
// Pack up the request into an RPC argument
args
:=
struct
{
To
common
.
Address
`json:"to"`
Data
string
`json:"data"`
}{
To
:
contract
,
Data
:
common
.
ToHex
(
data
),
}
// Execute the RPC call and retrieve the response
block
:=
"latest"
if
pending
{
block
=
"pending"
}
res
,
err
:=
b
.
request
(
"eth_call"
,
[]
interface
{}{
args
,
block
})
if
err
!=
nil
{
return
nil
,
err
}
var
hex
string
if
err
:=
json
.
Unmarshal
(
res
,
&
hex
);
err
!=
nil
{
return
nil
,
err
}
// Convert the response back to a Go byte slice and return
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
)
{
res
,
err
:=
b
.
request
(
"eth_getTransactionCount"
,
[]
interface
{}{
account
.
Hex
(),
"pending"
})
if
err
!=
nil
{
return
0
,
err
}
var
hex
string
if
err
:=
json
.
Unmarshal
(
res
,
&
hex
);
err
!=
nil
{
return
0
,
err
}
return
new
(
big
.
Int
)
.
SetBytes
(
common
.
FromHex
(
hex
))
.
Uint64
(),
nil
}
// GasPrice implements ContractTransactor.GasPrice, delegating the gas price
// oracle request to the remote node.
func
(
b
*
rpcBackend
)
GasPrice
()
(
*
big
.
Int
,
error
)
{
res
,
err
:=
b
.
request
(
"eth_gasPrice"
,
nil
)
if
err
!=
nil
{
return
nil
,
err
}
var
hex
string
if
err
:=
json
.
Unmarshal
(
res
,
&
hex
);
err
!=
nil
{
return
nil
,
err
}
return
new
(
big
.
Int
)
.
SetBytes
(
common
.
FromHex
(
hex
)),
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
)
{
// Pack up the request into an RPC argument
args
:=
struct
{
From
common
.
Address
`json:"from"`
To
*
common
.
Address
`json:"to"`
Value
*
rpc
.
HexNumber
`json:"value"`
Data
string
`json:"data"`
}{
From
:
sender
,
To
:
contract
,
Data
:
common
.
ToHex
(
data
),
Value
:
rpc
.
NewHexNumber
(
value
),
}
// Execute the RPC call and retrieve the response
res
,
err
:=
b
.
request
(
"eth_estimateGas"
,
[]
interface
{}{
args
})
if
err
!=
nil
{
return
nil
,
err
}
var
hex
string
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
}
// Transact 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
{
return
err
}
res
,
err
:=
b
.
request
(
"eth_sendRawTransaction"
,
[]
interface
{}{
common
.
ToHex
(
data
)})
if
err
!=
nil
{
return
err
}
var
hex
string
if
err
:=
json
.
Unmarshal
(
res
,
&
hex
);
err
!=
nil
{
return
err
}
return
nil
}
This diff is collapsed.
Click to expand it.
accounts/abi/bind/backends/simulated.go
0 → 100644
View file @
86cfc22c
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package
backends
import
(
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
)
// SimulatedBackend implements bind.ContractBackend, simulating a blockchain in
// the background. Its main purpose is to allow easily testing contract bindings.
type
SimulatedBackend
struct
{
database
ethdb
.
Database
// In memory database to store our testing data
blockchain
*
core
.
BlockChain
// Ethereum blockchain to handle the consensus
pendingBlock
*
types
.
Block
// Currently pending block that will be imported on request
pendingState
*
state
.
StateDB
// Currently pending state that will be the active on on request
}
// NewSimulatedBackend creates a new binding backend using a simulated blockchain
// for testing purposes.
func
NewSimulatedBackend
(
accounts
...
core
.
GenesisAccount
)
*
SimulatedBackend
{
database
,
_
:=
ethdb
.
NewMemDatabase
()
core
.
WriteGenesisBlockForTesting
(
database
,
accounts
...
)
blockchain
,
_
:=
core
.
NewBlockChain
(
database
,
new
(
core
.
FakePow
),
new
(
event
.
TypeMux
))
backend
:=
&
SimulatedBackend
{
database
:
database
,
blockchain
:
blockchain
,
}
backend
.
Rollback
()
return
backend
}
// Commit imports all the pending transactions as a single block and starts a
// fresh new state.
func
(
b
*
SimulatedBackend
)
Commit
()
{
if
_
,
err
:=
b
.
blockchain
.
InsertChain
([]
*
types
.
Block
{
b
.
pendingBlock
});
err
!=
nil
{
panic
(
err
)
// This cannot happen unless the simulator is wrong, fail in that case
}
b
.
Rollback
()
}
// Rollback aborts all pending transactions, reverting to the last committed state.
func
(
b
*
SimulatedBackend
)
Rollback
()
{
blocks
,
_
:=
core
.
GenerateChain
(
b
.
blockchain
.
CurrentBlock
(),
b
.
database
,
1
,
func
(
int
,
*
core
.
BlockGen
)
{})
b
.
pendingBlock
=
blocks
[
0
]
b
.
pendingState
,
_
=
state
.
New
(
b
.
pendingBlock
.
Root
(),
b
.
database
)
}
// 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
)
{
// Create a copy of the current state db to screw around with
var
(
block
*
types
.
Block
statedb
*
state
.
StateDB
)
if
pending
{
block
,
statedb
=
b
.
pendingBlock
,
b
.
pendingState
}
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
)
// Assemble the call invocation to measure the gas usage
msg
:=
callmsg
{
from
:
from
,
to
:
&
contract
,
gasPrice
:
new
(
big
.
Int
),
gasLimit
:
common
.
MaxBig
,
value
:
new
(
big
.
Int
),
data
:
data
,
}
// Execute the call and return
vmenv
:=
core
.
NewEnv
(
statedb
,
b
.
blockchain
,
msg
,
block
.
Header
())
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
)
{
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
)
{
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
)
{
// Create a copy of the currently pending state db to screw around with
var
(
block
=
b
.
pendingBlock
statedb
=
b
.
pendingState
.
Copy
()
)
// Set infinite balance to the a fake caller account
from
:=
statedb
.
GetOrNewStateObject
(
sender
)
from
.
SetBalance
(
common
.
MaxBig
)
// Assemble the call invocation to measure the gas usage
msg
:=
callmsg
{
from
:
from
,
to
:
contract
,
gasPrice
:
new
(
big
.
Int
),
gasLimit
:
common
.
MaxBig
,
value
:
value
,
data
:
data
,
}
// Execute the call and return
vmenv
:=
core
.
NewEnv
(
statedb
,
b
.
blockchain
,
msg
,
block
.
Header
())
gaspool
:=
new
(
core
.
GasPool
)
.
AddGas
(
common
.
MaxBig
)
_
,
gas
,
err
:=
core
.
ApplyMessage
(
vmenv
,
msg
,
gaspool
)
return
gas
,
err
}
// Transact 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
)
{
for
_
,
tx
:=
range
b
.
pendingBlock
.
Transactions
()
{
block
.
AddTx
(
tx
)
}
block
.
AddTx
(
tx
)
})
b
.
pendingBlock
=
blocks
[
0
]
b
.
pendingState
,
_
=
state
.
New
(
b
.
pendingBlock
.
Root
(),
b
.
database
)
return
nil
}
// callmsg implements core.Message to allow passing it as a transaction simulator.
type
callmsg
struct
{
from
*
state
.
StateObject
to
*
common
.
Address
gasLimit
*
big
.
Int
gasPrice
*
big
.
Int
value
*
big
.
Int
data
[]
byte
}
func
(
m
callmsg
)
From
()
(
common
.
Address
,
error
)
{
return
m
.
from
.
Address
(),
nil
}
func
(
m
callmsg
)
FromFrontier
()
(
common
.
Address
,
error
)
{
return
m
.
from
.
Address
(),
nil
}
func
(
m
callmsg
)
Nonce
()
uint64
{
return
m
.
from
.
Nonce
()
}
func
(
m
callmsg
)
To
()
*
common
.
Address
{
return
m
.
to
}
func
(
m
callmsg
)
GasPrice
()
*
big
.
Int
{
return
m
.
gasPrice
}
func
(
m
callmsg
)
Gas
()
*
big
.
Int
{
return
m
.
gasLimit
}
func
(
m
callmsg
)
Value
()
*
big
.
Int
{
return
m
.
value
}
func
(
m
callmsg
)
Data
()
[]
byte
{
return
m
.
data
}
This diff is collapsed.
Click to expand it.
accounts/abi/bind/base.go
View file @
86cfc22c
...
...
@@ -24,14 +24,21 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
)
// SignerFn is a signer function callback when a contract requires a method to
// sign the transaction before submission.
type
SignerFn
func
(
common
.
Address
,
*
types
.
Transaction
)
(
*
types
.
Transaction
,
error
)
// AuthOpts is the authorization data required to create a valid Ethereum transaction.
type
AuthOpts
struct
{
// CallOpts is the collection of options to fine tune a contract call request.
type
CallOpts
struct
{
Pending
bool
// Whether to operate on the pending state or the last known one
}
// TransactOpts is the collection of authorization data required to create a
// valid Ethereum transaction.
type
TransactOpts
struct
{
Account
common
.
Address
// Ethereum account to send the transaction from
Nonce
*
big
.
Int
// Nonce to use for the transaction execution (nil = use pending state)
Signer
SignerFn
// Method to use for signing the transaction (mandatory)
...
...
@@ -62,16 +69,43 @@ func NewBoundContract(address common.Address, abi abi.ABI, caller ContractCaller
}
}
// DeployContract deploys a contract onto the Ethereum blockchain and binds the
// deployment address with a Go wrapper.
func
DeployContract
(
opts
*
TransactOpts
,
abi
abi
.
ABI
,
bytecode
[]
byte
,
backend
ContractBackend
,
params
...
interface
{})
(
common
.
Address
,
*
types
.
Transaction
,
*
BoundContract
,
error
)
{
// Sanity check the authorization options
if
opts
==
nil
{
return
common
.
Address
{},
nil
,
nil
,
errors
.
New
(
"transaction options missing"
)
}
// Otherwise try to deploy the contract
c
:=
NewBoundContract
(
common
.
Address
{},
abi
,
backend
.
(
ContractCaller
),
backend
.
(
ContractTransactor
))
input
,
err
:=
c
.
abi
.
Pack
(
""
,
params
...
)
if
err
!=
nil
{
return
common
.
Address
{},
nil
,
nil
,
err
}
tx
,
err
:=
c
.
transact
(
opts
,
nil
,
append
(
bytecode
,
input
...
))
if
err
!=
nil
{
return
common
.
Address
{},
nil
,
nil
,
err
}
c
.
address
=
crypto
.
CreateAddress
(
opts
.
Account
,
tx
.
Nonce
())
return
c
.
address
,
tx
,
c
,
nil
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func
(
c
*
BoundContract
)
Call
(
result
interface
{},
method
string
,
params
...
interface
{})
error
{
func
(
c
*
BoundContract
)
Call
(
opts
*
CallOpts
,
result
interface
{},
method
string
,
params
...
interface
{})
error
{
// Don't crash on a lazy user
if
opts
==
nil
{
opts
=
new
(
CallOpts
)
}
// Pack the input, call and unpack the results
input
,
err
:=
c
.
abi
.
Pack
(
method
,
params
...
)
if
err
!=
nil
{
return
err
}
output
,
err
:=
c
.
caller
.
ContractCall
(
c
.
address
,
input
)
output
,
err
:=
c
.
caller
.
ContractCall
(
c
.
address
,
input
,
opts
.
Pending
)
if
err
!=
nil
{
return
err
}
...
...
@@ -80,11 +114,24 @@ func (c *BoundContract) Call(result interface{}, method string, params ...interf
// Transact invokes the (paid) contract method with params as input values and
// value as the fund transfer to the contract.
func
(
c
*
BoundContract
)
Transact
(
opts
*
AuthOpts
,
method
string
,
params
...
interface
{})
(
*
types
.
Transaction
,
error
)
{
func
(
c
*
BoundContract
)
Transact
(
opts
*
TransactOpts
,
method
string
,
params
...
interface
{})
(
*
types
.
Transaction
,
error
)
{
// Sanity check the authorization options
if
opts
==
nil
{
return
nil
,
errors
.
New
(
"transaction options missing"
)
}
// Otherwise pack up the parameters and invoke the contract
input
,
err
:=
c
.
abi
.
Pack
(
method
,
params
...
)
if
err
!=
nil
{
return
nil
,
err
}
return
c
.
transact
(
opts
,
&
c
.
address
,
input
)
}
// transact executes an actual transaction invocation, first deriving any missing
// authorization fields, and then scheduling the transaction for execution.
func
(
c
*
BoundContract
)
transact
(
opts
*
TransactOpts
,
contract
*
common
.
Address
,
input
[]
byte
)
(
*
types
.
Transaction
,
error
)
{
var
err
error
// Ensure a valid value field and resolve the account nonce
value
:=
opts
.
Value
if
value
==
nil
{
...
...
@@ -109,13 +156,18 @@ func (c *BoundContract) Transact(opts *AuthOpts, method string, params ...interf
}
gasLimit
:=
opts
.
GasLimit
if
gasLimit
==
nil
{
gasLimit
,
err
=
c
.
transactor
.
GasLimit
(
opts
.
Account
,
c
.
address
,
value
,
input
)
gasLimit
,
err
=
c
.
transactor
.
GasLimit
(
opts
.
Account
,
c
ontract
,
value
,
input
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to exstimate gas needed: %v"
,
err
)
}
}
// Create the transaction, sign it and schedule it for execution
rawTx
:=
types
.
NewTransaction
(
nonce
,
c
.
address
,
value
,
gasLimit
,
gasPrice
,
input
)
var
rawTx
*
types
.
Transaction
if
contract
==
nil
{
rawTx
=
types
.
NewContractCreation
(
nonce
,
value
,
gasLimit
,
gasPrice
,
input
)
}
else
{
rawTx
=
types
.
NewTransaction
(
nonce
,
c
.
address
,
value
,
gasLimit
,
gasPrice
,
input
)
}
if
opts
.
Signer
==
nil
{
return
nil
,
errors
.
New
(
"no signer to authorize the transaction with"
)
}
...
...
This diff is collapsed.
Click to expand it.
accounts/abi/bind/bind.go
View file @
86cfc22c
This diff is collapsed.
Click to expand it.
accounts/abi/bind/bind_test.go
View file @
86cfc22c
This diff is collapsed.
Click to expand it.
cmd/abigen/main.go
View file @
86cfc22c
...
...
@@ -27,9 +27,10 @@ import (
var
(
abiFlag
=
flag
.
String
(
"abi"
,
""
,
"Path to the Ethereum contract ABI json to bind"
)
binFlag
=
flag
.
String
(
"bin"
,
""
,
"Path to the Ethereum contract bytecode (generate deploy method)"
)
pkgFlag
=
flag
.
String
(
"pkg"
,
""
,
"Go package name to generate the binding into"
)
typFlag
=
flag
.
String
(
"type"
,
""
,
"Go struct name for the binding (default = package name)"
)
outFlag
=
flag
.
String
(
"out"
,
""
,
"Output path for the generated binding"
)
outFlag
=
flag
.
String
(
"out"
,
""
,
"Output path for the generated binding
(default = stdout)
"
)
)
func
main
()
{
...
...
@@ -44,17 +45,25 @@ func main() {
fmt
.
Printf
(
"No destination Go package specified (--pkg)
\n
"
)
os
.
Exit
(
-
1
)
}
//
Generate the contract binding
in
,
err
:=
ioutil
.
ReadFile
(
*
abiFlag
)
//
Read the ABI json from disk and optionally the contract bytecode too
abi
,
err
:=
ioutil
.
ReadFile
(
*
abiFlag
)
if
err
!=
nil
{
fmt
.
Printf
(
"Failed to read input ABI: %v
\n
"
,
err
)
os
.
Exit
(
-
1
)
}
bin
:=
[]
byte
{}
if
*
binFlag
!=
""
{
if
bin
,
err
=
ioutil
.
ReadFile
(
*
binFlag
);
err
!=
nil
{
fmt
.
Printf
(
"Failed to read input bytecode: %v
\n
"
,
err
)
os
.
Exit
(
-
1
)
}
}
// Generate the contract binding
kind
:=
*
typFlag
if
kind
==
""
{
kind
=
*
pkgFlag
}
code
,
err
:=
bind
.
Bind
(
string
(
in
),
*
pkgFlag
,
kind
)
code
,
err
:=
bind
.
Bind
(
string
(
abi
),
string
(
b
in
),
*
pkgFlag
,
kind
)
if
err
!=
nil
{
fmt
.
Printf
(
"Failed to generate ABI binding: %v
\n
"
,
err
)
os
.
Exit
(
-
1
)
...
...
This diff is collapsed.
Click to expand it.
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