aboutsummaryrefslogtreecommitdiff
path: root/accounts/abi
diff options
context:
space:
mode:
Diffstat (limited to 'accounts/abi')
-rw-r--r--accounts/abi/abi.go192
-rw-r--r--accounts/abi/argument.go365
-rw-r--r--accounts/abi/bind/auth.go96
-rw-r--r--accounts/abi/bind/backend.go112
-rw-r--r--accounts/abi/bind/backends/simulated.go523
-rw-r--r--accounts/abi/bind/base.go366
-rw-r--r--accounts/abi/bind/bind.go558
-rw-r--r--accounts/abi/bind/template.go616
-rw-r--r--accounts/abi/bind/topics.go241
-rw-r--r--accounts/abi/bind/util.go76
-rw-r--r--accounts/abi/doc.go26
-rw-r--r--accounts/abi/error.go84
-rw-r--r--accounts/abi/event.go77
-rw-r--r--accounts/abi/method.go90
-rw-r--r--accounts/abi/numbers.go44
-rw-r--r--accounts/abi/pack.go81
-rw-r--r--accounts/abi/reflect.go226
-rw-r--r--accounts/abi/type.go348
-rw-r--r--accounts/abi/unpack.go295
19 files changed, 4416 insertions, 0 deletions
diff --git a/accounts/abi/abi.go b/accounts/abi/abi.go
new file mode 100644
index 0000000..7af6685
--- /dev/null
+++ b/accounts/abi/abi.go
@@ -0,0 +1,192 @@
+// Copyright 2015 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 abi
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+
+ "github.com/ava-labs/go-ethereum/common"
+)
+
+// The ABI holds information about a contract's context and available
+// invokable methods. It will allow you to type check function calls and
+// packs data accordingly.
+type ABI struct {
+ Constructor Method
+ Methods map[string]Method
+ Events map[string]Event
+}
+
+// JSON returns a parsed ABI interface and error if it failed.
+func JSON(reader io.Reader) (ABI, error) {
+ dec := json.NewDecoder(reader)
+
+ var abi ABI
+ if err := dec.Decode(&abi); err != nil {
+ return ABI{}, err
+ }
+
+ return abi, nil
+}
+
+// Pack the given method name to conform the ABI. Method call's data
+// will consist of method_id, args0, arg1, ... argN. Method id consists
+// of 4 bytes and arguments are all 32 bytes.
+// 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) {
+ // Fetch the ABI of the requested method
+ if name == "" {
+ // constructor
+ arguments, err := abi.Constructor.Inputs.Pack(args...)
+ if err != nil {
+ return nil, err
+ }
+ return arguments, nil
+ }
+ method, exist := abi.Methods[name]
+ if !exist {
+ return nil, fmt.Errorf("method '%s' not found", name)
+ }
+ arguments, err := method.Inputs.Pack(args...)
+ if err != nil {
+ return nil, err
+ }
+ // Pack up the method ID too if not a constructor and return
+ return append(method.ID(), arguments...), nil
+}
+
+// Unpack output in v according to the abi specification
+func (abi ABI) Unpack(v interface{}, name string, data []byte) (err error) {
+ if len(data) == 0 {
+ return fmt.Errorf("abi: unmarshalling empty output")
+ }
+ // since there can't be naming collisions with contracts and events,
+ // we need to decide whether we're calling a method or an event
+ if method, ok := abi.Methods[name]; ok {
+ if len(data)%32 != 0 {
+ return fmt.Errorf("abi: improperly formatted output: %s - Bytes: [%+v]", string(data), data)
+ }
+ return method.Outputs.Unpack(v, data)
+ }
+ if event, ok := abi.Events[name]; ok {
+ return event.Inputs.Unpack(v, data)
+ }
+ return fmt.Errorf("abi: could not locate named method or event")
+}
+
+// UnpackIntoMap unpacks a log into the provided map[string]interface{}
+func (abi ABI) UnpackIntoMap(v map[string]interface{}, name string, data []byte) (err error) {
+ if len(data) == 0 {
+ return fmt.Errorf("abi: unmarshalling empty output")
+ }
+ // since there can't be naming collisions with contracts and events,
+ // we need to decide whether we're calling a method or an event
+ if method, ok := abi.Methods[name]; ok {
+ if len(data)%32 != 0 {
+ return fmt.Errorf("abi: improperly formatted output")
+ }
+ return method.Outputs.UnpackIntoMap(v, data)
+ }
+ if event, ok := abi.Events[name]; ok {
+ return event.Inputs.UnpackIntoMap(v, data)
+ }
+ return fmt.Errorf("abi: could not locate named method or event")
+}
+
+// UnmarshalJSON implements json.Unmarshaler interface
+func (abi *ABI) UnmarshalJSON(data []byte) error {
+ var fields []struct {
+ Type string
+ Name string
+ Constant bool
+ Anonymous bool
+ Inputs []Argument
+ Outputs []Argument
+ }
+ if err := json.Unmarshal(data, &fields); err != nil {
+ return err
+ }
+ abi.Methods = make(map[string]Method)
+ 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", "":
+ name := field.Name
+ _, ok := abi.Methods[name]
+ for idx := 0; ok; idx++ {
+ name = fmt.Sprintf("%s%d", field.Name, idx)
+ _, ok = abi.Methods[name]
+ }
+ abi.Methods[name] = Method{
+ Name: name,
+ RawName: field.Name,
+ Const: field.Constant,
+ Inputs: field.Inputs,
+ Outputs: field.Outputs,
+ }
+ case "event":
+ name := field.Name
+ _, ok := abi.Events[name]
+ for idx := 0; ok; idx++ {
+ name = fmt.Sprintf("%s%d", field.Name, idx)
+ _, ok = abi.Events[name]
+ }
+ abi.Events[name] = Event{
+ Name: name,
+ RawName: field.Name,
+ Anonymous: field.Anonymous,
+ Inputs: field.Inputs,
+ }
+ }
+ }
+
+ return nil
+}
+
+// MethodById looks up a method by the 4-byte id
+// returns nil if none found
+func (abi *ABI) MethodById(sigdata []byte) (*Method, error) {
+ if len(sigdata) < 4 {
+ return nil, fmt.Errorf("data too short (%d bytes) for abi method lookup", len(sigdata))
+ }
+ for _, method := range abi.Methods {
+ if bytes.Equal(method.ID(), sigdata[:4]) {
+ return &method, nil
+ }
+ }
+ return nil, fmt.Errorf("no method with id: %#x", sigdata[:4])
+}
+
+// EventByID looks an event up by its topic hash in the
+// ABI and returns nil if none found.
+func (abi *ABI) EventByID(topic common.Hash) (*Event, error) {
+ for _, event := range abi.Events {
+ if bytes.Equal(event.ID().Bytes(), topic.Bytes()) {
+ return &event, nil
+ }
+ }
+ return nil, fmt.Errorf("no event with id: %#x", topic.Hex())
+}
diff --git a/accounts/abi/argument.go b/accounts/abi/argument.go
new file mode 100644
index 0000000..4dae586
--- /dev/null
+++ b/accounts/abi/argument.go
@@ -0,0 +1,365 @@
+// Copyright 2015 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 abi
+
+import (
+ "encoding/json"
+ "fmt"
+ "reflect"
+ "strings"
+)
+
+// Argument holds the name of the argument and the corresponding type.
+// Types are used when packing and testing arguments.
+type Argument struct {
+ Name string
+ Type Type
+ Indexed bool // indexed is only used by events
+}
+
+type Arguments []Argument
+
+type ArgumentMarshaling struct {
+ Name string
+ Type string
+ Components []ArgumentMarshaling
+ Indexed bool
+}
+
+// UnmarshalJSON implements json.Unmarshaler interface
+func (argument *Argument) UnmarshalJSON(data []byte) error {
+ var arg ArgumentMarshaling
+ err := json.Unmarshal(data, &arg)
+ if err != nil {
+ return fmt.Errorf("argument json err: %v", err)
+ }
+
+ argument.Type, err = NewType(arg.Type, arg.Components)
+ if err != nil {
+ return err
+ }
+ argument.Name = arg.Name
+ argument.Indexed = arg.Indexed
+
+ return nil
+}
+
+// LengthNonIndexed returns the number of arguments when not counting 'indexed' ones. Only events
+// can ever have 'indexed' arguments, it should always be false on arguments for method input/output
+func (arguments Arguments) LengthNonIndexed() int {
+ out := 0
+ for _, arg := range arguments {
+ if !arg.Indexed {
+ out++
+ }
+ }
+ return out
+}
+
+// NonIndexed returns the arguments with indexed arguments filtered out
+func (arguments Arguments) NonIndexed() Arguments {
+ var ret []Argument
+ for _, arg := range arguments {
+ if !arg.Indexed {
+ ret = append(ret, arg)
+ }
+ }
+ return ret
+}
+
+// isTuple returns true for non-atomic constructs, like (uint,uint) or uint[]
+func (arguments Arguments) isTuple() bool {
+ return len(arguments) > 1
+}
+
+// Unpack performs the operation hexdata -> Go format
+func (arguments Arguments) Unpack(v interface{}, data []byte) error {
+ // make sure the passed value is arguments pointer
+ if reflect.Ptr != reflect.ValueOf(v).Kind() {
+ return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
+ }
+ marshalledValues, err := arguments.UnpackValues(data)
+ if err != nil {
+ return err
+ }
+ if arguments.isTuple() {
+ return arguments.unpackTuple(v, marshalledValues)
+ }
+ return arguments.unpackAtomic(v, marshalledValues[0])
+}
+
+// UnpackIntoMap performs the operation hexdata -> mapping of argument name to argument value
+func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte) error {
+ marshalledValues, err := arguments.UnpackValues(data)
+ if err != nil {
+ return err
+ }
+
+ return arguments.unpackIntoMap(v, marshalledValues)
+}
+
+// unpack sets the unmarshalled value to go format.
+// Note the dst here must be settable.
+func unpack(t *Type, dst interface{}, src interface{}) error {
+ var (
+ dstVal = reflect.ValueOf(dst).Elem()
+ srcVal = reflect.ValueOf(src)
+ )
+ tuple, typ := false, t
+ for {
+ if typ.T == SliceTy || typ.T == ArrayTy {
+ typ = typ.Elem
+ continue
+ }
+ tuple = typ.T == TupleTy
+ break
+ }
+ if !tuple {
+ return set(dstVal, srcVal)
+ }
+
+ // Dereferences interface or pointer wrapper
+ dstVal = indirectInterfaceOrPtr(dstVal)
+
+ switch t.T {
+ case TupleTy:
+ if dstVal.Kind() != reflect.Struct {
+ return fmt.Errorf("abi: invalid dst value for unpack, want struct, got %s", dstVal.Kind())
+ }
+ fieldmap, err := mapArgNamesToStructFields(t.TupleRawNames, dstVal)
+ if err != nil {
+ return err
+ }
+ for i, elem := range t.TupleElems {
+ fname := fieldmap[t.TupleRawNames[i]]
+ field := dstVal.FieldByName(fname)
+ if !field.IsValid() {
+ return fmt.Errorf("abi: field %s can't found in the given value", t.TupleRawNames[i])
+ }
+ if err := unpack(elem, field.Addr().Interface(), srcVal.Field(i).Interface()); err != nil {
+ return err
+ }
+ }
+ return nil
+ case SliceTy:
+ if dstVal.Kind() != reflect.Slice {
+ return fmt.Errorf("abi: invalid dst value for unpack, want slice, got %s", dstVal.Kind())
+ }
+ slice := reflect.MakeSlice(dstVal.Type(), srcVal.Len(), srcVal.Len())
+ for i := 0; i < slice.Len(); i++ {
+ if err := unpack(t.Elem, slice.Index(i).Addr().Interface(), srcVal.Index(i).Interface()); err != nil {
+ return err
+ }
+ }
+ dstVal.Set(slice)
+ case ArrayTy:
+ if dstVal.Kind() != reflect.Array {
+ return fmt.Errorf("abi: invalid dst value for unpack, want array, got %s", dstVal.Kind())
+ }
+ array := reflect.New(dstVal.Type()).Elem()
+ for i := 0; i < array.Len(); i++ {
+ if err := unpack(t.Elem, array.Index(i).Addr().Interface(), srcVal.Index(i).Interface()); err != nil {
+ return err
+ }
+ }
+ dstVal.Set(array)
+ }
+ return nil
+}
+
+// unpackIntoMap unpacks marshalledValues into the provided map[string]interface{}
+func (arguments Arguments) unpackIntoMap(v map[string]interface{}, marshalledValues []interface{}) error {
+ // Make sure map is not nil
+ if v == nil {
+ return fmt.Errorf("abi: cannot unpack into a nil map")
+ }
+
+ for i, arg := range arguments.NonIndexed() {
+ v[arg.Name] = marshalledValues[i]
+ }
+ return nil
+}
+
+// unpackAtomic unpacks ( hexdata -> go ) a single value
+func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues interface{}) error {
+ if arguments.LengthNonIndexed() == 0 {
+ return nil
+ }
+ argument := arguments.NonIndexed()[0]
+ elem := reflect.ValueOf(v).Elem()
+
+ if elem.Kind() == reflect.Struct && argument.Type.T != TupleTy {
+ fieldmap, err := mapArgNamesToStructFields([]string{argument.Name}, elem)
+ if err != nil {
+ return err
+ }
+ field := elem.FieldByName(fieldmap[argument.Name])
+ if !field.IsValid() {
+ return fmt.Errorf("abi: field %s can't be found in the given value", argument.Name)
+ }
+ return unpack(&argument.Type, field.Addr().Interface(), marshalledValues)
+ }
+ return unpack(&argument.Type, elem.Addr().Interface(), marshalledValues)
+}
+
+// unpackTuple unpacks ( hexdata -> go ) a batch of values.
+func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interface{}) error {
+ var (
+ value = reflect.ValueOf(v).Elem()
+ typ = value.Type()
+ kind = value.Kind()
+ )
+ if err := requireUnpackKind(value, typ, kind, arguments); err != nil {
+ return err
+ }
+
+ // If the interface is a struct, get of abi->struct_field mapping
+ var abi2struct map[string]string
+ if kind == reflect.Struct {
+ var (
+ argNames []string
+ err error
+ )
+ for _, arg := range arguments.NonIndexed() {
+ argNames = append(argNames, arg.Name)
+ }
+ abi2struct, err = mapArgNamesToStructFields(argNames, value)
+ if err != nil {
+ return err
+ }
+ }
+ for i, arg := range arguments.NonIndexed() {
+ switch kind {
+ case reflect.Struct:
+ field := value.FieldByName(abi2struct[arg.Name])
+ if !field.IsValid() {
+ return fmt.Errorf("abi: field %s can't be found in the given value", arg.Name)
+ }
+ if err := unpack(&arg.Type, field.Addr().Interface(), marshalledValues[i]); err != nil {
+ return err
+ }
+ case reflect.Slice, reflect.Array:
+ if value.Len() < i {
+ return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", len(arguments), value.Len())
+ }
+ v := value.Index(i)
+ if err := requireAssignable(v, reflect.ValueOf(marshalledValues[i])); err != nil {
+ return err
+ }
+ if err := unpack(&arg.Type, v.Addr().Interface(), marshalledValues[i]); err != nil {
+ return err
+ }
+ default:
+ return fmt.Errorf("abi:[2] cannot unmarshal tuple in to %v", typ)
+ }
+ }
+ return nil
+
+}
+
+// UnpackValues can be used to unpack ABI-encoded hexdata according to the ABI-specification,
+// without supplying a struct to unpack into. Instead, this method returns a list containing the
+// values. An atomic argument will be a list with one element.
+func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) {
+ retval := make([]interface{}, 0, arguments.LengthNonIndexed())
+ virtualArgs := 0
+ for index, arg := range arguments.NonIndexed() {
+ marshalledValue, err := toGoType((index+virtualArgs)*32, arg.Type, data)
+ if arg.Type.T == ArrayTy && !isDynamicType(arg.Type) {
+ // If we have a static array, like [3]uint256, these are coded as
+ // just like uint256,uint256,uint256.
+ // This means that we need to add two 'virtual' arguments when
+ // we count the index from now on.
+ //
+ // Array values nested multiple levels deep are also encoded inline:
+ // [2][3]uint256: uint256,uint256,uint256,uint256,uint256,uint256
+ //
+ // Calculate the full array size to get the correct offset for the next argument.
+ // Decrement it by 1, as the normal index increment is still applied.
+ virtualArgs += getTypeSize(arg.Type)/32 - 1
+ } else if arg.Type.T == TupleTy && !isDynamicType(arg.Type) {
+ // If we have a static tuple, like (uint256, bool, uint256), these are
+ // coded as just like uint256,bool,uint256
+ virtualArgs += getTypeSize(arg.Type)/32 - 1
+ }
+ if err != nil {
+ return nil, err
+ }
+ retval = append(retval, marshalledValue)
+ }
+ return retval, nil
+}
+
+// PackValues performs the operation Go format -> Hexdata
+// It is the semantic opposite of UnpackValues
+func (arguments Arguments) PackValues(args []interface{}) ([]byte, error) {
+ return arguments.Pack(args...)
+}
+
+// Pack performs the operation Go format -> Hexdata
+func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
+ // Make sure arguments match up and pack them
+ abiArgs := arguments
+ if len(args) != len(abiArgs) {
+ return nil, fmt.Errorf("argument count mismatch: %d for %d", len(args), len(abiArgs))
+ }
+ // variable input is the output appended at the end of packed
+ // output. This is used for strings and bytes types input.
+ var variableInput []byte
+
+ // input offset is the bytes offset for packed output
+ inputOffset := 0
+ for _, abiArg := range abiArgs {
+ inputOffset += getTypeSize(abiArg.Type)
+ }
+ var ret []byte
+ for i, a := range args {
+ input := abiArgs[i]
+ // pack the input
+ packed, err := input.Type.pack(reflect.ValueOf(a))
+ if err != nil {
+ return nil, err
+ }
+ // check for dynamic types
+ if isDynamicType(input.Type) {
+ // set the offset
+ ret = append(ret, packNum(reflect.ValueOf(inputOffset))...)
+ // calculate next offset
+ inputOffset += len(packed)
+ // append to variable input
+ variableInput = append(variableInput, packed...)
+ } else {
+ // append the packed value to the input
+ ret = append(ret, packed...)
+ }
+ }
+ // append the variable input at the end of the packed input
+ ret = append(ret, variableInput...)
+
+ return ret, nil
+}
+
+// ToCamelCase converts an under-score string to a camel-case string
+func ToCamelCase(input string) string {
+ parts := strings.Split(input, "_")
+ for i, s := range parts {
+ if len(s) > 0 {
+ parts[i] = strings.ToUpper(s[:1]) + s[1:]
+ }
+ }
+ return strings.Join(parts, "")
+}
diff --git a/accounts/abi/bind/auth.go b/accounts/abi/bind/auth.go
new file mode 100644
index 0000000..c916cc4
--- /dev/null
+++ b/accounts/abi/bind/auth.go
@@ -0,0 +1,96 @@
+// 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 (
+ "crypto/ecdsa"
+ "errors"
+ "io"
+ "io/ioutil"
+
+ "github.com/ava-labs/coreth/accounts"
+ "github.com/ava-labs/coreth/accounts/external"
+ "github.com/ava-labs/coreth/accounts/keystore"
+ "github.com/ava-labs/coreth/core/types"
+ "github.com/ava-labs/go-ethereum/common"
+ "github.com/ava-labs/go-ethereum/crypto"
+)
+
+// NewTransactor is a utility method to easily create a transaction signer from
+// an encrypted json key stream and the associated passphrase.
+func NewTransactor(keyin io.Reader, passphrase string) (*TransactOpts, error) {
+ json, err := ioutil.ReadAll(keyin)
+ if err != nil {
+ return nil, err
+ }
+ key, err := keystore.DecryptKey(json, passphrase)
+ if err != nil {
+ return nil, err
+ }
+ return NewKeyedTransactor(key.PrivateKey), nil
+}
+
+// NewKeyStoreTransactor is a utility method to easily create a transaction signer from
+// an decrypted key from a keystore
+func NewKeyStoreTransactor(keystore *keystore.KeyStore, account accounts.Account) (*TransactOpts, error) {
+ return &TransactOpts{
+ From: account.Address,
+ Signer: func(signer types.Signer, address common.Address, tx *types.Transaction) (*types.Transaction, error) {
+ if address != account.Address {
+ return nil, errors.New("not authorized to sign this account")
+ }
+ signature, err := keystore.SignHash(account, signer.Hash(tx).Bytes())
+ if err != nil {
+ return nil, err
+ }
+ return tx.WithSignature(signer, signature)
+ },
+ }, nil
+}
+
+// NewKeyedTransactor is a utility method to easily create a transaction signer
+// from a single private key.
+func NewKeyedTransactor(key *ecdsa.PrivateKey) *TransactOpts {
+ keyAddr := crypto.PubkeyToAddress(key.PublicKey)
+ return &TransactOpts{
+ From: keyAddr,
+ Signer: func(signer types.Signer, address common.Address, tx *types.Transaction) (*types.Transaction, error) {
+ if address != keyAddr {
+ return nil, errors.New("not authorized to sign this account")
+ }
+ signature, err := crypto.Sign(signer.Hash(tx).Bytes(), key)
+ if err != nil {
+ return nil, err
+ }
+ return tx.WithSignature(signer, signature)
+ },
+ }
+}
+
+// NewClefTransactor is a utility method to easily create a transaction signer
+// with a clef backend.
+func NewClefTransactor(clef *external.ExternalSigner, account accounts.Account) *TransactOpts {
+ return &TransactOpts{
+ From: account.Address,
+ Signer: func(signer types.Signer, address common.Address, transaction *types.Transaction) (*types.Transaction, error) {
+ if address != account.Address {
+ return nil, errors.New("not authorized to sign this account")
+ }
+ return clef.SignTx(account, transaction, nil) // Clef enforces its own chain id
+ },
+ }
+}
diff --git a/accounts/abi/bind/backend.go b/accounts/abi/bind/backend.go
new file mode 100644
index 0000000..556394f
--- /dev/null
+++ b/accounts/abi/bind/backend.go
@@ -0,0 +1,112 @@
+// Copyright 2015 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 (
+ "context"
+ "errors"
+ "math/big"
+
+ "github.com/ava-labs/coreth/core/types"
+ "github.com/ava-labs/go-ethereum"
+ "github.com/ava-labs/go-ethereum/common"
+)
+
+var (
+ // 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).
+ ErrNoCode = errors.New("no contract code at given address")
+
+ // This error is raised when attempting to perform a pending state action
+ // on a backend that doesn't implement PendingContractCaller.
+ ErrNoPendingState = errors.New("backend does not support pending state")
+
+ // This error is returned by WaitDeployed if contract creation leaves an
+ // empty contract behind.
+ ErrNoCodeAfterDeploy = errors.New("no contract code after deployment")
+)
+
+// ContractCaller defines the methods needed to allow operating with contract on a read
+// only basis.
+type ContractCaller interface {
+ // CodeAt returns the code of the given account. This is needed to differentiate
+ // between contract internal errors and the local chain being out of sync.
+ CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error)
+ // ContractCall executes an Ethereum contract call with the specified data as the
+ // input.
+ CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error)
+}
+
+// PendingContractCaller defines methods to perform contract calls on the pending state.
+// Call will try to discover this interface when access to the pending state is requested.
+// If the backend does not support the pending state, Call returns ErrNoPendingState.
+type PendingContractCaller interface {
+ // PendingCodeAt returns the code of the given account in the pending state.
+ PendingCodeAt(ctx context.Context, contract common.Address) ([]byte, error)
+ // PendingCallContract executes an Ethereum contract call against the pending state.
+ PendingCallContract(ctx context.Context, call ethereum.CallMsg) ([]byte, error)
+}
+
+// ContractTransactor defines the methods needed to allow operating with contract
+// on a write only basis. Beside the transacting method, the remainder are helpers
+// used when the user does not provide some needed values, but rather leaves it up
+// to the transactor to decide.
+type ContractTransactor interface {
+ // PendingCodeAt returns the code of the given account in the pending state.
+ PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error)
+ // PendingNonceAt retrieves the current pending nonce associated with an account.
+ PendingNonceAt(ctx context.Context, account common.Address) (uint64, error)
+ // SuggestGasPrice retrieves the currently suggested gas price to allow a timely
+ // execution of a transaction.
+ SuggestGasPrice(ctx context.Context) (*big.Int, error)
+ // EstimateGas 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.
+ EstimateGas(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error)
+ // SendTransaction injects the transaction into the pending pool for execution.
+ SendTransaction(ctx context.Context, tx *types.Transaction) error
+}
+
+// ContractFilterer defines the methods needed to access log events using one-off
+// queries or continuous event subscriptions.
+type ContractFilterer interface {
+ // FilterLogs executes a log filter operation, blocking during execution and
+ // returning all the results in one batch.
+ //
+ // TODO(karalabe): Deprecate when the subscription one can return past data too.
+ FilterLogs(ctx context.Context, query ethereum.FilterQuery) ([]types.Log, error)
+
+ // SubscribeFilterLogs creates a background log filtering operation, returning
+ // a subscription immediately, which can be used to stream the found events.
+ SubscribeFilterLogs(ctx context.Context, query ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error)
+}
+
+// DeployBackend wraps the operations needed by WaitMined and WaitDeployed.
+type DeployBackend interface {
+ TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error)
+ CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error)
+}
+
+// ContractBackend defines the methods needed to work with contracts on a read-write basis.
+type ContractBackend interface {
+ ContractCaller
+ ContractTransactor
+ ContractFilterer
+}
diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go
new file mode 100644
index 0000000..88610a4
--- /dev/null
+++ b/accounts/abi/bind/backends/simulated.go
@@ -0,0 +1,523 @@
+// Copyright 2015 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 (
+ "context"
+ "errors"
+ "fmt"
+ "math/big"
+ "sync"
+ "time"
+
+ "github.com/ava-labs/coreth/accounts/abi/bind"
+ "github.com/ava-labs/coreth/consensus/ethash"
+ "github.com/ava-labs/coreth/core"
+ "github.com/ava-labs/coreth/core/bloombits"
+ "github.com/ava-labs/coreth/core/rawdb"
+ "github.com/ava-labs/coreth/core/state"
+ "github.com/ava-labs/coreth/core/types"
+ "github.com/ava-labs/coreth/core/vm"
+ "github.com/ava-labs/coreth/params"
+ "github.com/ava-labs/coreth/rpc"
+ "github.com/ava-labs/go-ethereum"
+ "github.com/ava-labs/go-ethereum/common"
+ "github.com/ava-labs/go-ethereum/common/math"
+ "github.com/ava-labs/go-ethereum/eth/filters"
+ "github.com/ava-labs/go-ethereum/ethdb"
+ "github.com/ava-labs/go-ethereum/event"
+)
+
+// This nil assignment ensures compile time that SimulatedBackend implements bind.ContractBackend.
+var _ bind.ContractBackend = (*SimulatedBackend)(nil)
+
+var (
+ errBlockNumberUnsupported = errors.New("simulatedBackend cannot access blocks other than the latest block")
+ errGasEstimationFailed = errors.New("gas required exceeds allowance or always failing transaction")
+)
+
+// 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
+
+ mu sync.Mutex
+ 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
+
+ events *filters.EventSystem // Event system for filtering log events live
+
+ config *params.ChainConfig
+}
+
+// NewSimulatedBackendWithDatabase creates a new binding backend based on the given database
+// and uses a simulated blockchain for testing purposes.
+func NewSimulatedBackendWithDatabase(database ethdb.Database, alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend {
+ genesis := core.Genesis{Config: params.AllEthashProtocolChanges, GasLimit: gasLimit, Alloc: alloc}
+ genesis.MustCommit(database)
+ blockchain, _ := core.NewBlockChain(database, nil, genesis.Config, ethash.NewFaker(), vm.Config{}, nil)
+
+ backend := &SimulatedBackend{
+ database: database,
+ blockchain: blockchain,
+ config: genesis.Config,
+ events: filters.Ne