github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/chain/accounts/abi/argument.go (about) 1 package abi 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "reflect" 7 "strings" 8 ) 9 10 type Argument struct { 11 Name string 12 Type Type 13 Indexed bool 14 } 15 16 type Arguments []Argument 17 18 type ArgumentMarshaling struct { 19 Name string 20 Type string 21 InternalType string 22 Components []ArgumentMarshaling 23 Indexed bool 24 } 25 26 func (argument *Argument) UnmarshalJSON(data []byte) error { 27 var arg ArgumentMarshaling 28 err := json.Unmarshal(data, &arg) 29 if err != nil { 30 return fmt.Errorf("argument json err: %v", err) 31 } 32 33 argument.Type, err = NewType(arg.Type, arg.InternalType, arg.Components) 34 if err != nil { 35 return err 36 } 37 argument.Name = arg.Name 38 argument.Indexed = arg.Indexed 39 40 return nil 41 } 42 43 func (arguments Arguments) LengthNonIndexed() int { 44 out := 0 45 for _, arg := range arguments { 46 if !arg.Indexed { 47 out++ 48 } 49 } 50 return out 51 } 52 53 func (arguments Arguments) NonIndexed() Arguments { 54 var ret []Argument 55 for _, arg := range arguments { 56 if !arg.Indexed { 57 ret = append(ret, arg) 58 } 59 } 60 return ret 61 } 62 63 func (arguments Arguments) isTuple() bool { 64 return len(arguments) > 1 65 } 66 67 func (arguments Arguments) Unpack(v interface{}, data []byte) error { 68 if len(data) == 0 { 69 if len(arguments) != 0 { 70 return fmt.Errorf("abi: attempting to unmarshall an empty string while arguments are expected") 71 } else { 72 return nil 73 } 74 } 75 76 if reflect.Ptr != reflect.ValueOf(v).Kind() { 77 return fmt.Errorf("abi: Unpack(non-pointer %T)", v) 78 } 79 marshalledValues, err := arguments.UnpackValues(data) 80 81 if err != nil { 82 return err 83 } 84 if arguments.isTuple() { 85 return arguments.unpackTuple(v, marshalledValues) 86 } 87 return arguments.unpackAtomic(v, marshalledValues[0]) 88 } 89 90 func (arguments Arguments) UnpackForRevert(v interface{}, data []byte) ([]interface{}, error) { 91 if len(data) == 0 { 92 if len(arguments) != 0 { 93 return nil, fmt.Errorf("abi: attempting to unmarshall an empty string while arguments are expected") 94 } else { 95 return nil, nil 96 } 97 } 98 99 if reflect.Ptr != reflect.ValueOf(v).Kind() { 100 return nil, fmt.Errorf("abi: Unpack(non-pointer %T)", v) 101 } 102 return arguments.UnpackValues(data) 103 } 104 105 func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte) error { 106 if len(data) == 0 { 107 if len(arguments) != 0 { 108 return fmt.Errorf("abi: attempting to unmarshall an empty string while arguments are expected") 109 } else { 110 return nil 111 } 112 } 113 marshalledValues, err := arguments.UnpackValues(data) 114 if err != nil { 115 return err 116 } 117 return arguments.unpackIntoMap(v, marshalledValues) 118 } 119 120 func unpack(t *Type, dst interface{}, src interface{}) error { 121 var ( 122 dstVal = reflect.ValueOf(dst).Elem() 123 srcVal = reflect.ValueOf(src) 124 ) 125 tuple, typ := false, t 126 for { 127 if typ.T == SliceTy || typ.T == ArrayTy { 128 typ = typ.Elem 129 continue 130 } 131 tuple = typ.T == TupleTy 132 break 133 } 134 if !tuple { 135 return set(dstVal, srcVal) 136 } 137 138 dstVal = indirectInterfaceOrPtr(dstVal) 139 140 switch t.T { 141 case TupleTy: 142 if dstVal.Kind() != reflect.Struct { 143 return fmt.Errorf("abi: invalid dst value for unpack, want struct, got %s", dstVal.Kind()) 144 } 145 fieldmap, err := mapArgNamesToStructFields(t.TupleRawNames, dstVal) 146 if err != nil { 147 return err 148 } 149 for i, elem := range t.TupleElems { 150 fname := fieldmap[t.TupleRawNames[i]] 151 field := dstVal.FieldByName(fname) 152 if !field.IsValid() { 153 return fmt.Errorf("abi: field %s can't found in the given value", t.TupleRawNames[i]) 154 } 155 if err := unpack(elem, field.Addr().Interface(), srcVal.Field(i).Interface()); err != nil { 156 return err 157 } 158 } 159 return nil 160 case SliceTy: 161 if dstVal.Kind() != reflect.Slice { 162 return fmt.Errorf("abi: invalid dst value for unpack, want slice, got %s", dstVal.Kind()) 163 } 164 slice := reflect.MakeSlice(dstVal.Type(), srcVal.Len(), srcVal.Len()) 165 for i := 0; i < slice.Len(); i++ { 166 if err := unpack(t.Elem, slice.Index(i).Addr().Interface(), srcVal.Index(i).Interface()); err != nil { 167 return err 168 } 169 } 170 dstVal.Set(slice) 171 case ArrayTy: 172 if dstVal.Kind() != reflect.Array { 173 return fmt.Errorf("abi: invalid dst value for unpack, want array, got %s", dstVal.Kind()) 174 } 175 array := reflect.New(dstVal.Type()).Elem() 176 for i := 0; i < array.Len(); i++ { 177 if err := unpack(t.Elem, array.Index(i).Addr().Interface(), srcVal.Index(i).Interface()); err != nil { 178 return err 179 } 180 } 181 dstVal.Set(array) 182 } 183 return nil 184 } 185 186 func (arguments Arguments) unpackIntoMap(v map[string]interface{}, marshalledValues []interface{}) error { 187 188 if v == nil { 189 return fmt.Errorf("abi: cannot unpack into a nil map") 190 } 191 192 for i, arg := range arguments.NonIndexed() { 193 v[arg.Name] = marshalledValues[i] 194 } 195 return nil 196 } 197 198 func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues interface{}) error { 199 if arguments.LengthNonIndexed() == 0 { 200 return nil 201 } 202 argument := arguments.NonIndexed()[0] 203 elem := reflect.ValueOf(v).Elem() 204 205 if elem.Kind() == reflect.Struct && argument.Type.T != TupleTy { 206 fieldmap, err := mapArgNamesToStructFields([]string{argument.Name}, elem) 207 if err != nil { 208 return err 209 } 210 field := elem.FieldByName(fieldmap[argument.Name]) 211 if !field.IsValid() { 212 return fmt.Errorf("abi: field %s can't be found in the given value", argument.Name) 213 } 214 return unpack(&argument.Type, field.Addr().Interface(), marshalledValues) 215 } 216 return unpack(&argument.Type, elem.Addr().Interface(), marshalledValues) 217 } 218 219 func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interface{}) error { 220 var ( 221 value = reflect.ValueOf(v).Elem() 222 typ = value.Type() 223 kind = value.Kind() 224 ) 225 if err := requireUnpackKind(value, typ, kind, arguments); err != nil { 226 return err 227 } 228 229 var abi2struct map[string]string 230 if kind == reflect.Struct { 231 var ( 232 argNames []string 233 err error 234 ) 235 for _, arg := range arguments.NonIndexed() { 236 argNames = append(argNames, arg.Name) 237 } 238 abi2struct, err = mapArgNamesToStructFields(argNames, value) 239 if err != nil { 240 return err 241 } 242 } 243 for i, arg := range arguments.NonIndexed() { 244 switch kind { 245 case reflect.Struct: 246 field := value.FieldByName(abi2struct[arg.Name]) 247 if !field.IsValid() { 248 return fmt.Errorf("abi: field %s can't be found in the given value", arg.Name) 249 } 250 if err := unpack(&arg.Type, field.Addr().Interface(), marshalledValues[i]); err != nil { 251 return err 252 } 253 case reflect.Slice, reflect.Array: 254 if value.Len() < i { 255 return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", len(arguments), value.Len()) 256 } 257 v := value.Index(i) 258 if err := requireAssignable(v, reflect.ValueOf(marshalledValues[i])); err != nil { 259 return err 260 } 261 if err := unpack(&arg.Type, v.Addr().Interface(), marshalledValues[i]); err != nil { 262 return err 263 } 264 default: 265 return fmt.Errorf("abi:[2] cannot unmarshal tuple in to %v", typ) 266 } 267 } 268 return nil 269 270 } 271 272 func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) { 273 retval := make([]interface{}, 0, arguments.LengthNonIndexed()) 274 virtualArgs := 0 275 for index, arg := range arguments.NonIndexed() { 276 marshalledValue, err := toGoType((index+virtualArgs)*32, arg.Type, data) 277 if arg.Type.T == ArrayTy && !isDynamicType(arg.Type) { 278 279 virtualArgs += getTypeSize(arg.Type)/32 - 1 280 } else if arg.Type.T == TupleTy && !isDynamicType(arg.Type) { 281 282 virtualArgs += getTypeSize(arg.Type)/32 - 1 283 } 284 if err != nil { 285 return nil, err 286 } 287 retval = append(retval, marshalledValue) 288 } 289 return retval, nil 290 } 291 292 func (arguments Arguments) PackValues(args []interface{}) ([]byte, error) { 293 return arguments.Pack(args...) 294 } 295 296 func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) { 297 298 abiArgs := arguments 299 if len(args) != len(abiArgs) { 300 return nil, fmt.Errorf("argument count mismatch: %d for %d", len(args), len(abiArgs)) 301 } 302 303 var variableInput []byte 304 305 inputOffset := 0 306 for _, abiArg := range abiArgs { 307 inputOffset += getTypeSize(abiArg.Type) 308 } 309 var ret []byte 310 for i, a := range args { 311 input := abiArgs[i] 312 313 packed, err := input.Type.pack(reflect.ValueOf(a)) 314 if err != nil { 315 return nil, err 316 } 317 318 if isDynamicType(input.Type) { 319 320 ret = append(ret, packNum(reflect.ValueOf(inputOffset))...) 321 322 inputOffset += len(packed) 323 324 variableInput = append(variableInput, packed...) 325 } else { 326 327 ret = append(ret, packed...) 328 } 329 } 330 331 ret = append(ret, variableInput...) 332 333 return ret, nil 334 } 335 336 func ToCamelCase(input string) string { 337 parts := strings.Split(input, "_") 338 for i, s := range parts { 339 if len(s) > 0 { 340 parts[i] = strings.ToUpper(s[:1]) + s[1:] 341 } 342 } 343 return strings.Join(parts, "") 344 }