From 9becba5540540bc37d4ad5eaaf7e4c1937a6542f Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Fri, 10 Nov 2017 00:08:28 +0100 Subject: accounts/abi: fix event tupleUnpack Event.tupleUnpack doesn't handle correctly Indexed arguments, hence it can't unpack an event with indexed arguments. --- accounts/abi/event.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'accounts/abi/event.go') diff --git a/accounts/abi/event.go b/accounts/abi/event.go index bd1098d87..0d3c3c4fa 100644 --- a/accounts/abi/event.go +++ b/accounts/abi/event.go @@ -65,13 +65,13 @@ func (e Event) tupleUnpack(v interface{}, output []byte) error { return fmt.Errorf("abi: cannot unmarshal tuple in to %v", typ) } - j := 0 - for i := 0; i < len(e.Inputs); i++ { - input := e.Inputs[i] + i, j := -1, 0 + for _, input := range e.Inputs { if input.Indexed { // can't read, continue continue } + i++ marshalledValue, err := toGoType((i+j)*32, input.Type, output) if err != nil { return err @@ -88,22 +88,22 @@ func (e Event) tupleUnpack(v interface{}, output []byte) error { for j := 0; j < typ.NumField(); j++ { field := typ.Field(j) // TODO read tags: `abi:"fieldName"` - if field.Name == strings.ToUpper(e.Inputs[i].Name[:1])+e.Inputs[i].Name[1:] { - if err := set(value.Field(j), reflectValue, e.Inputs[i]); err != nil { + if field.Name == strings.ToUpper(input.Name[:1])+input.Name[1:] { + if err := set(value.Field(j), reflectValue, input); 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(e.Inputs), value.Len()) + return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", i, value.Len()) } v := value.Index(i) if v.Kind() != reflect.Ptr && v.Kind() != reflect.Interface { return fmt.Errorf("abi: cannot unmarshal %v in to %v", v.Type(), reflectValue.Type()) } reflectValue := reflect.ValueOf(marshalledValue) - if err := set(v.Elem(), reflectValue, e.Inputs[i]); err != nil { + if err := set(v.Elem(), reflectValue, input); err != nil { return err } default: -- cgit From 0ed8b838a991f81f79cc6ed4fa961c563203a7a2 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Fri, 10 Nov 2017 02:30:26 +0100 Subject: accounts/abi: fix event unpack into slice + The event slice unpacker doesn't correctly extract element from the slice. The indexed arguments are not ignored as they should be (the data offset should not include the indexed arguments). + The `Elem()` call in the slice unpack doesn't work. The Slice related tests fails because of that. + the check in the loop are suboptimal and have been extracted out of the loop. + extracted common code from event and method tupleUnpack --- accounts/abi/event.go | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'accounts/abi/event.go') diff --git a/accounts/abi/event.go b/accounts/abi/event.go index 0d3c3c4fa..b67bc96a8 100644 --- a/accounts/abi/event.go +++ b/accounts/abi/event.go @@ -59,16 +59,19 @@ func (e Event) tupleUnpack(v interface{}, output []byte) error { var ( value = valueOf.Elem() typ = value.Type() + kind = value.Kind() ) - - if value.Kind() != reflect.Struct { - return fmt.Errorf("abi: cannot unmarshal tuple in to %v", typ) + if err := requireUnpackKind(value, typ, kind, e.Inputs, true); err != nil { + return err } + // `i` counts the nonindexed arguments. + // `j` counts the number of complex types. + // both `i` and `j` are used to to correctly compute `data` offset. i, j := -1, 0 for _, input := range e.Inputs { if input.Indexed { - // can't read, continue + // Indexed arguments are not packed into data continue } i++ @@ -83,7 +86,7 @@ func (e Event) tupleUnpack(v interface{}, output []byte) error { } reflectValue := reflect.ValueOf(marshalledValue) - switch value.Kind() { + switch kind { case reflect.Struct: for j := 0; j < typ.NumField(); j++ { field := typ.Field(j) @@ -95,19 +98,13 @@ func (e Event) tupleUnpack(v interface{}, output []byte) error { } } case reflect.Slice, reflect.Array: - if value.Len() < i { - return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", i, value.Len()) - } v := value.Index(i) - if v.Kind() != reflect.Ptr && v.Kind() != reflect.Interface { - return fmt.Errorf("abi: cannot unmarshal %v in to %v", v.Type(), reflectValue.Type()) + if err := requireAssignable(v, reflectValue); err != nil { + return err } - reflectValue := reflect.ValueOf(marshalledValue) if err := set(v.Elem(), reflectValue, input); err != nil { return err } - default: - return fmt.Errorf("abi: cannot unmarshal tuple in to %v", typ) } } return nil -- cgit From 95461e8b2289c1b8f6c588087a8de5f4f64a749c Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Fri, 10 Nov 2017 02:48:51 +0100 Subject: accounts/abi: satisfy most of the linter warnings + adding missing comments + small cleanups which won't significantly change function body. + unify Method receiver name --- accounts/abi/event.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'accounts/abi/event.go') diff --git a/accounts/abi/event.go b/accounts/abi/event.go index b67bc96a8..3d4e0b63c 100644 --- a/accounts/abi/event.go +++ b/accounts/abi/event.go @@ -120,7 +120,7 @@ func (e Event) singleUnpack(v interface{}, output []byte) error { } if e.Inputs[0].Indexed { - return fmt.Errorf("abi: attempting to unpack indexed variable into element.") + return fmt.Errorf("abi: attempting to unpack indexed variable into element") } value := valueOf.Elem() @@ -129,8 +129,5 @@ func (e Event) singleUnpack(v interface{}, output []byte) error { if err != nil { return err } - if err := set(value, reflect.ValueOf(marshalledValue), e.Inputs[0]); err != nil { - return err - } - return nil + return set(value, reflect.ValueOf(marshalledValue), e.Inputs[0]) } -- cgit From 73d4a57d47d3381faa0516b319fa5598e71681f9 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Thu, 21 Dec 2017 10:26:30 +0100 Subject: acounts/abi: refactor abi, generalize abi pack/unpack to Arguments --- accounts/abi/event.go | 89 +-------------------------------------------------- 1 file changed, 1 insertion(+), 88 deletions(-) (limited to 'accounts/abi/event.go') diff --git a/accounts/abi/event.go b/accounts/abi/event.go index 3d4e0b63c..726bac90e 100644 --- a/accounts/abi/event.go +++ b/accounts/abi/event.go @@ -18,7 +18,6 @@ package abi import ( "fmt" - "reflect" "strings" "github.com/ethereum/go-ethereum/common" @@ -31,7 +30,7 @@ import ( type Event struct { Name string Anonymous bool - Inputs []Argument + Inputs Arguments } // Id returns the canonical representation of the event's signature used by the @@ -45,89 +44,3 @@ func (e Event) Id() common.Hash { } return common.BytesToHash(crypto.Keccak256([]byte(fmt.Sprintf("%v(%v)", e.Name, strings.Join(types, ","))))) } - -// unpacks an event return tuple into a struct of corresponding go types -// -// Unpacking can be done into a struct or a slice/array. -func (e Event) tupleUnpack(v interface{}, output []byte) error { - // 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) - } - - var ( - value = valueOf.Elem() - typ = value.Type() - kind = value.Kind() - ) - if err := requireUnpackKind(value, typ, kind, e.Inputs, true); err != nil { - return err - } - - // `i` counts the nonindexed arguments. - // `j` counts the number of complex types. - // both `i` and `j` are used to to correctly compute `data` offset. - i, j := -1, 0 - for _, input := range e.Inputs { - if input.Indexed { - // Indexed arguments are not packed into data - continue - } - i++ - marshalledValue, err := toGoType((i+j)*32, input.Type, output) - if err != nil { - return err - } - if input.Type.T == ArrayTy { - // combined index ('i' + 'j') need to be adjusted only by size of array, thus - // we need to decrement 'j' because 'i' was incremented - j += input.Type.Size - 1 - } - reflectValue := reflect.ValueOf(marshalledValue) - - switch kind { - case reflect.Struct: - for j := 0; j < typ.NumField(); j++ { - field := typ.Field(j) - // TODO read tags: `abi:"fieldName"` - if field.Name == strings.ToUpper(input.Name[:1])+input.Name[1:] { - if err := set(value.Field(j), reflectValue, input); err != nil { - return err - } - } - } - case reflect.Slice, reflect.Array: - v := value.Index(i) - if err := requireAssignable(v, reflectValue); err != nil { - return err - } - if err := set(v.Elem(), reflectValue, input); err != nil { - return err - } - } - } - return nil -} - -func (e Event) isTupleReturn() bool { return len(e.Inputs) > 1 } - -func (e Event) singleUnpack(v interface{}, output []byte) error { - // 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) - } - - if e.Inputs[0].Indexed { - return fmt.Errorf("abi: attempting to unpack indexed variable into element") - } - - value := valueOf.Elem() - - marshalledValue, err := toGoType(0, e.Inputs[0].Type, output) - if err != nil { - return err - } - return set(value, reflect.ValueOf(marshalledValue), e.Inputs[0]) -} -- cgit