github.com/klaytn/klaytn@v1.10.2/accounts/abi/reflect.go (about) 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 17 package abi 18 19 import ( 20 "errors" 21 "fmt" 22 "math/big" 23 "reflect" 24 "strings" 25 ) 26 27 // indirect recursively dereferences the value until it either gets the value 28 // or finds a big.Int 29 func indirect(v reflect.Value) reflect.Value { 30 if v.Kind() == reflect.Ptr && v.Elem().Type() != reflect.TypeOf(big.Int{}) { 31 return indirect(v.Elem()) 32 } 33 return v 34 } 35 36 // reflectIntType returns the reflect using the given size and 37 // unsignedness. 38 func reflectIntType(unsigned bool, size int) reflect.Type { 39 if unsigned { 40 switch size { 41 case 8: 42 return reflect.TypeOf(uint8(0)) 43 case 16: 44 return reflect.TypeOf(uint16(0)) 45 case 32: 46 return reflect.TypeOf(uint32(0)) 47 case 64: 48 return reflect.TypeOf(uint64(0)) 49 } 50 } 51 switch size { 52 case 8: 53 return reflect.TypeOf(int8(0)) 54 case 16: 55 return reflect.TypeOf(int16(0)) 56 case 32: 57 return reflect.TypeOf(int32(0)) 58 case 64: 59 return reflect.TypeOf(int64(0)) 60 } 61 return reflect.TypeOf(&big.Int{}) 62 } 63 64 // mustArrayToBytesSlice creates a new byte slice with the exact same size as value 65 // and copies the bytes in value to the new slice. 66 func mustArrayToByteSlice(value reflect.Value) reflect.Value { 67 slice := reflect.MakeSlice(reflect.TypeOf([]byte{}), value.Len(), value.Len()) 68 reflect.Copy(slice, value) 69 return slice 70 } 71 72 // set attempts to assign src to dst by either setting, copying or otherwise. 73 // 74 // set is a bit more lenient when it comes to assignment and doesn't force an as 75 // strict ruleset as bare `reflect` does. 76 func set(dst, src reflect.Value) error { 77 dstType, srcType := dst.Type(), src.Type() 78 switch { 79 case dstType.Kind() == reflect.Interface && dst.Elem().IsValid(): 80 return set(dst.Elem(), src) 81 case dstType.Kind() == reflect.Ptr && dstType.Elem() != reflect.TypeOf(big.Int{}): 82 return set(dst.Elem(), src) 83 case srcType.AssignableTo(dstType) && dst.CanSet(): 84 dst.Set(src) 85 case dstType.Kind() == reflect.Slice && srcType.Kind() == reflect.Slice && dst.CanSet(): 86 return setSlice(dst, src) 87 case dstType.Kind() == reflect.Array: 88 return setArray(dst, src) 89 case dstType.Kind() == reflect.Struct: 90 return setStruct(dst, src) 91 default: 92 return fmt.Errorf("abi: cannot unmarshal %v in to %v", src.Type(), dst.Type()) 93 } 94 return nil 95 } 96 97 // setSlice attempts to assign src to dst when slices are not assignable by default 98 // e.g. src: [][]byte -> dst: [][15]byte 99 // setSlice ignores if we cannot copy all of src' elements. 100 func setSlice(dst, src reflect.Value) error { 101 slice := reflect.MakeSlice(dst.Type(), src.Len(), src.Len()) 102 for i := 0; i < src.Len(); i++ { 103 if src.Index(i).Kind() == reflect.Struct { 104 if err := set(slice.Index(i), src.Index(i)); err != nil { 105 return err 106 } 107 } else { 108 // e.g. [][32]uint8 to []common.Hash 109 if err := set(slice.Index(i), src.Index(i)); err != nil { 110 return err 111 } 112 } 113 } 114 if dst.CanSet() { 115 dst.Set(slice) 116 return nil 117 } 118 return errors.New("Cannot set slice, destination not settable") 119 } 120 121 func setArray(dst, src reflect.Value) error { 122 array := reflect.New(dst.Type()).Elem() 123 min := src.Len() 124 if src.Len() > dst.Len() { 125 min = dst.Len() 126 } 127 for i := 0; i < min; i++ { 128 if err := set(array.Index(i), src.Index(i)); err != nil { 129 return err 130 } 131 } 132 if dst.CanSet() { 133 dst.Set(array) 134 return nil 135 } 136 return errors.New("Cannot set array, destination not settable") 137 } 138 139 func setStruct(dst, src reflect.Value) error { 140 for i := 0; i < src.NumField(); i++ { 141 srcField := src.Field(i) 142 dstField := dst.Field(i) 143 if !dstField.IsValid() || !srcField.IsValid() { 144 return fmt.Errorf("Could not find src field: %v value: %v in destination", srcField.Type().Name(), srcField) 145 } 146 if err := set(dstField, srcField); err != nil { 147 return err 148 } 149 } 150 return nil 151 } 152 153 // mapArgNamesToStructFields maps a slice of argument names to struct fields. 154 // first round: for each Exportable field that contains a `abi:""` tag 155 // and this field name exists in the given argument name list, pair them together. 156 // second round: for each argument name that has not been already linked, 157 // find what variable is expected to be mapped into, if it exists and has not been 158 // used, pair them. 159 // Note this function assumes the given value is a struct value. 160 func mapArgNamesToStructFields(argNames []string, value reflect.Value) (map[string]string, error) { 161 typ := value.Type() 162 163 abi2struct := make(map[string]string) 164 struct2abi := make(map[string]string) 165 166 // first round ~~~ 167 for i := 0; i < typ.NumField(); i++ { 168 structFieldName := typ.Field(i).Name 169 170 // skip private struct fields. 171 if structFieldName[:1] != strings.ToUpper(structFieldName[:1]) { 172 continue 173 } 174 // skip fields that have no abi:"" tag. 175 tagName, ok := typ.Field(i).Tag.Lookup("abi") 176 if !ok { 177 continue 178 } 179 // check if tag is empty. 180 if tagName == "" { 181 return nil, fmt.Errorf("struct: abi tag in '%s' is empty", structFieldName) 182 } 183 // check which argument field matches with the abi tag. 184 found := false 185 for _, arg := range argNames { 186 if arg == tagName { 187 if abi2struct[arg] != "" { 188 return nil, fmt.Errorf("struct: abi tag in '%s' already mapped", structFieldName) 189 } 190 // pair them 191 abi2struct[arg] = structFieldName 192 struct2abi[structFieldName] = arg 193 found = true 194 } 195 } 196 // check if this tag has been mapped. 197 if !found { 198 return nil, fmt.Errorf("struct: abi tag '%s' defined but not found in abi", tagName) 199 } 200 } 201 202 // second round ~~~ 203 for _, argName := range argNames { 204 205 structFieldName := ToCamelCase(argName) 206 207 if structFieldName == "" { 208 return nil, fmt.Errorf("abi: purely underscored output cannot unpack to struct") 209 } 210 211 // this abi has already been paired, skip it... unless there exists another, yet unassigned 212 // struct field with the same field name. If so, raise an error: 213 // abi: [ { "name": "value" } ] 214 // struct { Value *big.Int , Value1 *big.Int `abi:"value"`} 215 if abi2struct[argName] != "" { 216 if abi2struct[argName] != structFieldName && 217 struct2abi[structFieldName] == "" && 218 value.FieldByName(structFieldName).IsValid() { 219 return nil, fmt.Errorf("abi: multiple variables maps to the same abi field '%s'", argName) 220 } 221 continue 222 } 223 224 // return an error if this struct field has already been paired. 225 if struct2abi[structFieldName] != "" { 226 return nil, fmt.Errorf("abi: multiple outputs mapping to the same struct field '%s'", structFieldName) 227 } 228 229 if value.FieldByName(structFieldName).IsValid() { 230 // pair them 231 abi2struct[argName] = structFieldName 232 struct2abi[structFieldName] = argName 233 } else { 234 // not paired, but annotate as used, to detect cases like 235 // abi : [ { "name": "value" }, { "name": "_value" } ] 236 // struct { Value *big.Int } 237 struct2abi[structFieldName] = argName 238 } 239 } 240 return abi2struct, nil 241 }