aboutsummaryrefslogtreecommitdiffstats
path: root/accounts/abi/abi.go
diff options
context:
space:
mode:
authorRJ Catalano <catalanor0220@gmail.com>2017-10-17 19:07:08 +0800
committerFelix Lange <fjl@users.noreply.github.com>2017-10-17 19:07:08 +0800
commitdec8bba9d4c5fcb3dd7e51f0f794b3e895c7f52d (patch)
tree7e4713ca276ac1a2cef7cd2dd19dcf8c6fd1f6c4 /accounts/abi/abi.go
parente9295163aa25479e817efee4aac23eaeb7554bba (diff)
downloadgo-tangerine-dec8bba9d4c5fcb3dd7e51f0f794b3e895c7f52d.tar
go-tangerine-dec8bba9d4c5fcb3dd7e51f0f794b3e895c7f52d.tar.gz
go-tangerine-dec8bba9d4c5fcb3dd7e51f0f794b3e895c7f52d.tar.bz2
go-tangerine-dec8bba9d4c5fcb3dd7e51f0f794b3e895c7f52d.tar.lz
go-tangerine-dec8bba9d4c5fcb3dd7e51f0f794b3e895c7f52d.tar.xz
go-tangerine-dec8bba9d4c5fcb3dd7e51f0f794b3e895c7f52d.tar.zst
go-tangerine-dec8bba9d4c5fcb3dd7e51f0f794b3e895c7f52d.zip
accounts/abi: improve type handling, add event support (#14743)
Diffstat (limited to 'accounts/abi/abi.go')
-rw-r--r--accounts/abi/abi.go115
1 files changed, 16 insertions, 99 deletions
diff --git a/accounts/abi/abi.go b/accounts/abi/abi.go
index 2a06d474b..205dc300b 100644
--- a/accounts/abi/abi.go
+++ b/accounts/abi/abi.go
@@ -20,10 +20,6 @@ import (
"encoding/json"
"fmt"
"io"
- "reflect"
- "strings"
-
- "github.com/ethereum/go-ethereum/common"
)
// The ABI holds information about a contract's context and available
@@ -76,106 +72,27 @@ func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) {
return append(method.Id(), arguments...), nil
}
-// these variable are used to determine certain types during type assertion for
-// assignment.
-var (
- r_interSlice = reflect.TypeOf([]interface{}{})
- r_hash = reflect.TypeOf(common.Hash{})
- r_bytes = reflect.TypeOf([]byte{})
- r_byte = reflect.TypeOf(byte(0))
-)
-
// Unpack output in v according to the abi specification
-func (abi ABI) Unpack(v interface{}, name string, output []byte) error {
- var method = abi.Methods[name]
-
- if len(output) == 0 {
- return fmt.Errorf("abi: unmarshalling empty output")
- }
-
- // make sure the passed value is a pointer
- valueOf := reflect.ValueOf(v)
- if reflect.Ptr != valueOf.Kind() {
- return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
+func (abi ABI) Unpack(v interface{}, name string, output []byte) (err error) {
+ if err = bytesAreProper(output); err != nil {
+ return err
}
-
- var (
- value = valueOf.Elem()
- typ = value.Type()
- )
-
- if len(method.Outputs) > 1 {
- switch value.Kind() {
- // struct will match named return values to the struct's field
- // names
- case reflect.Struct:
- for i := 0; i < len(method.Outputs); i++ {
- marshalledValue, err := toGoType(i, method.Outputs[i], output)
- if err != nil {
- return err
- }
- reflectValue := reflect.ValueOf(marshalledValue)
-
- for j := 0; j < typ.NumField(); j++ {
- field := typ.Field(j)
- // TODO read tags: `abi:"fieldName"`
- if field.Name == strings.ToUpper(method.Outputs[i].Name[:1])+method.Outputs[i].Name[1:] {
- if err := set(value.Field(j), reflectValue, method.Outputs[i]); err != nil {
- return err
- }
- }
- }
- }
- case reflect.Slice:
- if !value.Type().AssignableTo(r_interSlice) {
- return fmt.Errorf("abi: cannot marshal tuple in to slice %T (only []interface{} is supported)", v)
- }
-
- // if the slice already contains values, set those instead of the interface slice itself.
- if value.Len() > 0 {
- if len(method.Outputs) > value.Len() {
- return fmt.Errorf("abi: cannot marshal in to slices of unequal size (require: %v, got: %v)", len(method.Outputs), value.Len())
- }
-
- for i := 0; i < len(method.Outputs); i++ {
- marshalledValue, err := toGoType(i, method.Outputs[i], output)
- if err != nil {
- return err
- }
- reflectValue := reflect.ValueOf(marshalledValue)
- if err := set(value.Index(i).Elem(), reflectValue, method.Outputs[i]); err != nil {
- return err
- }
- }
- return nil
- }
-
- // create a new slice and start appending the unmarshalled
- // values to the new interface slice.
- z := reflect.MakeSlice(typ, 0, len(method.Outputs))
- for i := 0; i < len(method.Outputs); i++ {
- marshalledValue, err := toGoType(i, method.Outputs[i], output)
- if err != nil {
- return err
- }
- z = reflect.Append(z, reflect.ValueOf(marshalledValue))
- }
- value.Set(z)
- default:
- return fmt.Errorf("abi: cannot unmarshal tuple in to %v", typ)
- }
-
+ // since there can't be naming collisions with contracts and events,
+ // we need to decide whether we're calling a method or an event
+ var unpack unpacker
+ if method, ok := abi.Methods[name]; ok {
+ unpack = method
+ } else if event, ok := abi.Events[name]; ok {
+ unpack = event
} else {
- marshalledValue, err := toGoType(0, method.Outputs[0], output)
- if err != nil {
- return err
- }
- if err := set(value, reflect.ValueOf(marshalledValue), method.Outputs[0]); err != nil {
- return err
- }
+ return fmt.Errorf("abi: could not locate named method or event.")
}
- return nil
+ // requires a struct to unpack into for a tuple return...
+ if unpack.isTupleReturn() {
+ return unpack.tupleUnpack(v, output)
+ }
+ return unpack.singleUnpack(v, output)
}
func (abi *ABI) UnmarshalJSON(data []byte) error {