accounts/abi: multiple fixes to arguments

This commit is contained in:
Marius van der Wijden 2020-04-01 17:22:25 +02:00
parent ebf0efeeb2
commit f4b170a088
2 changed files with 28 additions and 41 deletions

View file

@ -92,9 +92,8 @@ func (arguments Arguments) Unpack(v interface{}, data []byte) error {
if len(data) == 0 { if len(data) == 0 {
if len(arguments) != 0 { if len(arguments) != 0 {
return fmt.Errorf("abi: attempting to unmarshall an empty string while arguments are expected") return fmt.Errorf("abi: attempting to unmarshall an empty string while arguments are expected")
} else {
return nil // Nothing to unmarshal, return
} }
return nil // Nothing to unmarshal, return
} }
// make sure the passed value is arguments pointer // make sure the passed value is arguments pointer
if reflect.Ptr != reflect.ValueOf(v).Kind() { if reflect.Ptr != reflect.ValueOf(v).Kind() {
@ -115,18 +114,24 @@ func (arguments Arguments) Unpack(v interface{}, data []byte) error {
// UnpackIntoMap performs the operation hexdata -> mapping of argument name to argument value // UnpackIntoMap performs the operation hexdata -> mapping of argument name to argument value
func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte) error { func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte) error {
// Make sure map is not nil
if v == nil {
return fmt.Errorf("abi: cannot unpack into a nil map")
}
if len(data) == 0 { if len(data) == 0 {
if len(arguments) != 0 { if len(arguments) != 0 {
return fmt.Errorf("abi: attempting to unmarshall an empty string while arguments are expected") return fmt.Errorf("abi: attempting to unmarshall an empty string while arguments are expected")
} else {
return nil // Nothing to unmarshal, return
} }
return nil // Nothing to unmarshal, return
} }
marshalledValues, err := arguments.UnpackValues(data) marshalledValues, err := arguments.UnpackValues(data)
if err != nil { if err != nil {
return err return err
} }
return arguments.unpackIntoMap(v, marshalledValues) for i, arg := range arguments.NonIndexed() {
v[arg.Name] = marshalledValues[i]
}
return nil
} }
// unpack sets the unmarshalled value to go format. // unpack sets the unmarshalled value to go format.
@ -198,19 +203,6 @@ func unpack(t *Type, dst interface{}, src interface{}) error {
return nil 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 // unpackAtomic unpacks ( hexdata -> go ) a single value
func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues interface{}) error { func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues interface{}) error {
if arguments.LengthNonIndexed() == 0 { if arguments.LengthNonIndexed() == 0 {
@ -236,30 +228,28 @@ func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues interfac
// unpackTuple unpacks ( hexdata -> go ) a batch of values. // unpackTuple unpacks ( hexdata -> go ) a batch of values.
func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interface{}) error { func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interface{}) error {
var ( var (
value = reflect.ValueOf(v).Elem() value = reflect.ValueOf(v).Elem()
typ = value.Type() typ = value.Type()
kind = value.Kind() kind = value.Kind()
nonIndexedArgs = arguments.NonIndexed()
) )
if err := requireUnpackKind(value, typ, kind, arguments); err != nil { if err := requireUnpackKind(value, len(nonIndexedArgs), arguments); err != nil {
return err return err
} }
// If the interface is a struct, get of abi->struct_field mapping // If the interface is a struct, get of abi->struct_field mapping
var abi2struct map[string]string var abi2struct map[string]string
if kind == reflect.Struct { if kind == reflect.Struct {
var ( argNames := make([]string, len(nonIndexedArgs))
argNames []string for i, arg := range nonIndexedArgs {
err error argNames[i] = arg.Name
)
for _, arg := range arguments.NonIndexed() {
argNames = append(argNames, arg.Name)
} }
abi2struct, err = mapArgNamesToStructFields(argNames, value) var err error
if err != nil { if abi2struct, err = mapArgNamesToStructFields(argNames, value); err != nil {
return err return err
} }
} }
for i, arg := range arguments.NonIndexed() { for i, arg := range nonIndexedArgs {
switch kind { switch kind {
case reflect.Struct: case reflect.Struct:
field := value.FieldByName(abi2struct[arg.Name]) field := value.FieldByName(abi2struct[arg.Name])

View file

@ -118,18 +118,16 @@ func requireAssignable(dst, src reflect.Value) error {
} }
// requireUnpackKind verifies preconditions for unpacking `args` into `kind` // requireUnpackKind verifies preconditions for unpacking `args` into `kind`
func requireUnpackKind(v reflect.Value, t reflect.Type, k reflect.Kind, func requireUnpackKind(v reflect.Value, minLength int, args Arguments) error {
args Arguments) error { switch v.Kind() {
switch k {
case reflect.Struct: case reflect.Struct:
case reflect.Slice, reflect.Array: case reflect.Slice, reflect.Array:
if minLen := args.LengthNonIndexed(); v.Len() < minLen { if v.Len() < minLength {
return fmt.Errorf("abi: insufficient number of elements in the list/array for unpack, want %d, got %d", return fmt.Errorf("abi: insufficient number of elements in the list/array for unpack, want %d, got %d",
minLen, v.Len()) minLength, v.Len())
} }
default: default:
return fmt.Errorf("abi: cannot unmarshal tuple into %v", t) return fmt.Errorf("abi: cannot unmarshal tuple into %v", v.Type())
} }
return nil return nil
} }
@ -156,9 +154,8 @@ func mapArgNamesToStructFields(argNames []string, value reflect.Value) (map[stri
continue continue
} }
// skip fields that have no abi:"" tag. // skip fields that have no abi:"" tag.
var ok bool tagName, ok := typ.Field(i).Tag.Lookup("abi")
var tagName string if !ok {
if tagName, ok = typ.Field(i).Tag.Lookup("abi"); !ok {
continue continue
} }
// check if tag is empty. // check if tag is empty.