1// Copyright 2016 The go-ethereum Authors
2// This file is part of the go-ethereum library.
3//
4// The go-ethereum library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU Lesser General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// The go-ethereum library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU Lesser General Public License for more details.
13//
14// You should have received a copy of the GNU Lesser General Public License
15// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
16
17package abi
18
19import (
20	"errors"
21	"fmt"
22	"math/big"
23	"reflect"
24	"strings"
25)
26
27// ConvertType converts an interface of a runtime type into a interface of the
28// given type
29// e.g. turn
30// var fields []reflect.StructField
31// fields = append(fields, reflect.StructField{
32// 		Name: "X",
33//		Type: reflect.TypeOf(new(big.Int)),
34//		Tag:  reflect.StructTag("json:\"" + "x" + "\""),
35// }
36// into
37// type TupleT struct { X *big.Int }
38func ConvertType(in interface{}, proto interface{}) interface{} {
39	protoType := reflect.TypeOf(proto)
40	if reflect.TypeOf(in).ConvertibleTo(protoType) {
41		return reflect.ValueOf(in).Convert(protoType).Interface()
42	}
43	// Use set as a last ditch effort
44	if err := set(reflect.ValueOf(proto), reflect.ValueOf(in)); err != nil {
45		panic(err)
46	}
47	return proto
48}
49
50// indirect recursively dereferences the value until it either gets the value
51// or finds a big.Int
52func indirect(v reflect.Value) reflect.Value {
53	if v.Kind() == reflect.Ptr && v.Elem().Type() != reflect.TypeOf(big.Int{}) {
54		return indirect(v.Elem())
55	}
56	return v
57}
58
59// reflectIntType returns the reflect using the given size and
60// unsignedness.
61func reflectIntType(unsigned bool, size int) reflect.Type {
62	if unsigned {
63		switch size {
64		case 8:
65			return reflect.TypeOf(uint8(0))
66		case 16:
67			return reflect.TypeOf(uint16(0))
68		case 32:
69			return reflect.TypeOf(uint32(0))
70		case 64:
71			return reflect.TypeOf(uint64(0))
72		}
73	}
74	switch size {
75	case 8:
76		return reflect.TypeOf(int8(0))
77	case 16:
78		return reflect.TypeOf(int16(0))
79	case 32:
80		return reflect.TypeOf(int32(0))
81	case 64:
82		return reflect.TypeOf(int64(0))
83	}
84	return reflect.TypeOf(&big.Int{})
85}
86
87// mustArrayToByteSlice creates a new byte slice with the exact same size as value
88// and copies the bytes in value to the new slice.
89func mustArrayToByteSlice(value reflect.Value) reflect.Value {
90	slice := reflect.MakeSlice(reflect.TypeOf([]byte{}), value.Len(), value.Len())
91	reflect.Copy(slice, value)
92	return slice
93}
94
95// set attempts to assign src to dst by either setting, copying or otherwise.
96//
97// set is a bit more lenient when it comes to assignment and doesn't force an as
98// strict ruleset as bare `reflect` does.
99func set(dst, src reflect.Value) error {
100	dstType, srcType := dst.Type(), src.Type()
101	switch {
102	case dstType.Kind() == reflect.Interface && dst.Elem().IsValid():
103		return set(dst.Elem(), src)
104	case dstType.Kind() == reflect.Ptr && dstType.Elem() != reflect.TypeOf(big.Int{}):
105		return set(dst.Elem(), src)
106	case srcType.AssignableTo(dstType) && dst.CanSet():
107		dst.Set(src)
108	case dstType.Kind() == reflect.Slice && srcType.Kind() == reflect.Slice && dst.CanSet():
109		return setSlice(dst, src)
110	case dstType.Kind() == reflect.Array:
111		return setArray(dst, src)
112	case dstType.Kind() == reflect.Struct:
113		return setStruct(dst, src)
114	default:
115		return fmt.Errorf("abi: cannot unmarshal %v in to %v", src.Type(), dst.Type())
116	}
117	return nil
118}
119
120// setSlice attempts to assign src to dst when slices are not assignable by default
121// e.g. src: [][]byte -> dst: [][15]byte
122// setSlice ignores if we cannot copy all of src' elements.
123func setSlice(dst, src reflect.Value) error {
124	slice := reflect.MakeSlice(dst.Type(), src.Len(), src.Len())
125	for i := 0; i < src.Len(); i++ {
126		if err := set(slice.Index(i), src.Index(i)); err != nil {
127			return err
128		}
129	}
130	if dst.CanSet() {
131		dst.Set(slice)
132		return nil
133	}
134	return errors.New("Cannot set slice, destination not settable")
135}
136
137func setArray(dst, src reflect.Value) error {
138	if src.Kind() == reflect.Ptr {
139		return set(dst, indirect(src))
140	}
141	array := reflect.New(dst.Type()).Elem()
142	min := src.Len()
143	if src.Len() > dst.Len() {
144		min = dst.Len()
145	}
146	for i := 0; i < min; i++ {
147		if err := set(array.Index(i), src.Index(i)); err != nil {
148			return err
149		}
150	}
151	if dst.CanSet() {
152		dst.Set(array)
153		return nil
154	}
155	return errors.New("Cannot set array, destination not settable")
156}
157
158func setStruct(dst, src reflect.Value) error {
159	for i := 0; i < src.NumField(); i++ {
160		srcField := src.Field(i)
161		dstField := dst.Field(i)
162		if !dstField.IsValid() || !srcField.IsValid() {
163			return fmt.Errorf("Could not find src field: %v value: %v in destination", srcField.Type().Name(), srcField)
164		}
165		if err := set(dstField, srcField); err != nil {
166			return err
167		}
168	}
169	return nil
170}
171
172// mapArgNamesToStructFields maps a slice of argument names to struct fields.
173// first round: for each Exportable field that contains a `abi:""` tag
174//   and this field name exists in the given argument name list, pair them together.
175// second round: for each argument name that has not been already linked,
176//   find what variable is expected to be mapped into, if it exists and has not been
177//   used, pair them.
178// Note this function assumes the given value is a struct value.
179func mapArgNamesToStructFields(argNames []string, value reflect.Value) (map[string]string, error) {
180	typ := value.Type()
181
182	abi2struct := make(map[string]string)
183	struct2abi := make(map[string]string)
184
185	// first round ~~~
186	for i := 0; i < typ.NumField(); i++ {
187		structFieldName := typ.Field(i).Name
188
189		// skip private struct fields.
190		if structFieldName[:1] != strings.ToUpper(structFieldName[:1]) {
191			continue
192		}
193		// skip fields that have no abi:"" tag.
194		tagName, ok := typ.Field(i).Tag.Lookup("abi")
195		if !ok {
196			continue
197		}
198		// check if tag is empty.
199		if tagName == "" {
200			return nil, fmt.Errorf("struct: abi tag in '%s' is empty", structFieldName)
201		}
202		// check which argument field matches with the abi tag.
203		found := false
204		for _, arg := range argNames {
205			if arg == tagName {
206				if abi2struct[arg] != "" {
207					return nil, fmt.Errorf("struct: abi tag in '%s' already mapped", structFieldName)
208				}
209				// pair them
210				abi2struct[arg] = structFieldName
211				struct2abi[structFieldName] = arg
212				found = true
213			}
214		}
215		// check if this tag has been mapped.
216		if !found {
217			return nil, fmt.Errorf("struct: abi tag '%s' defined but not found in abi", tagName)
218		}
219	}
220
221	// second round ~~~
222	for _, argName := range argNames {
223
224		structFieldName := ToCamelCase(argName)
225
226		if structFieldName == "" {
227			return nil, fmt.Errorf("abi: purely underscored output cannot unpack to struct")
228		}
229
230		// this abi has already been paired, skip it... unless there exists another, yet unassigned
231		// struct field with the same field name. If so, raise an error:
232		//    abi: [ { "name": "value" } ]
233		//    struct { Value  *big.Int , Value1 *big.Int `abi:"value"`}
234		if abi2struct[argName] != "" {
235			if abi2struct[argName] != structFieldName &&
236				struct2abi[structFieldName] == "" &&
237				value.FieldByName(structFieldName).IsValid() {
238				return nil, fmt.Errorf("abi: multiple variables maps to the same abi field '%s'", argName)
239			}
240			continue
241		}
242
243		// return an error if this struct field has already been paired.
244		if struct2abi[structFieldName] != "" {
245			return nil, fmt.Errorf("abi: multiple outputs mapping to the same struct field '%s'", structFieldName)
246		}
247
248		if value.FieldByName(structFieldName).IsValid() {
249			// pair them
250			abi2struct[argName] = structFieldName
251			struct2abi[structFieldName] = argName
252		} else {
253			// not paired, but annotate as used, to detect cases like
254			//   abi : [ { "name": "value" }, { "name": "_value" } ]
255			//   struct { Value *big.Int }
256			struct2abi[structFieldName] = argName
257		}
258	}
259	return abi2struct, nil
260}
261