github.com/ylsGit/go-ethereum@v1.6.5/accounts/abi/abi.go (about) 1 // Copyright 2015 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 "encoding/binary" 21 "encoding/json" 22 "fmt" 23 "io" 24 "math/big" 25 "reflect" 26 "strings" 27 28 "github.com/ethereum/go-ethereum/common" 29 ) 30 31 // The ABI holds information about a contract's context and available 32 // invokable methods. It will allow you to type check function calls and 33 // packs data accordingly. 34 type ABI struct { 35 Constructor Method 36 Methods map[string]Method 37 Events map[string]Event 38 } 39 40 // JSON returns a parsed ABI interface and error if it failed. 41 func JSON(reader io.Reader) (ABI, error) { 42 dec := json.NewDecoder(reader) 43 44 var abi ABI 45 if err := dec.Decode(&abi); err != nil { 46 return ABI{}, err 47 } 48 49 return abi, nil 50 } 51 52 // Pack the given method name to conform the ABI. Method call's data 53 // will consist of method_id, args0, arg1, ... argN. Method id consists 54 // of 4 bytes and arguments are all 32 bytes. 55 // Method ids are created from the first 4 bytes of the hash of the 56 // methods string signature. (signature = baz(uint32,string32)) 57 func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) { 58 // Fetch the ABI of the requested method 59 var method Method 60 61 if name == "" { 62 method = abi.Constructor 63 } else { 64 m, exist := abi.Methods[name] 65 if !exist { 66 return nil, fmt.Errorf("method '%s' not found", name) 67 } 68 method = m 69 } 70 arguments, err := method.pack(method, args...) 71 if err != nil { 72 return nil, err 73 } 74 // Pack up the method ID too if not a constructor and return 75 if name == "" { 76 return arguments, nil 77 } 78 return append(method.Id(), arguments...), nil 79 } 80 81 // toGoSliceType parses the input and casts it to the proper slice defined by the ABI 82 // argument in T. 83 func toGoSlice(i int, t Argument, output []byte) (interface{}, error) { 84 index := i * 32 85 // The slice must, at very least be large enough for the index+32 which is exactly the size required 86 // for the [offset in output, size of offset]. 87 if index+32 > len(output) { 88 return nil, fmt.Errorf("abi: cannot marshal in to go slice: insufficient size output %d require %d", len(output), index+32) 89 } 90 elem := t.Type.Elem 91 92 // first we need to create a slice of the type 93 var refSlice reflect.Value 94 switch elem.T { 95 case IntTy, UintTy, BoolTy: 96 // create a new reference slice matching the element type 97 switch t.Type.Kind { 98 case reflect.Bool: 99 refSlice = reflect.ValueOf([]bool(nil)) 100 case reflect.Uint8: 101 refSlice = reflect.ValueOf([]uint8(nil)) 102 case reflect.Uint16: 103 refSlice = reflect.ValueOf([]uint16(nil)) 104 case reflect.Uint32: 105 refSlice = reflect.ValueOf([]uint32(nil)) 106 case reflect.Uint64: 107 refSlice = reflect.ValueOf([]uint64(nil)) 108 case reflect.Int8: 109 refSlice = reflect.ValueOf([]int8(nil)) 110 case reflect.Int16: 111 refSlice = reflect.ValueOf([]int16(nil)) 112 case reflect.Int32: 113 refSlice = reflect.ValueOf([]int32(nil)) 114 case reflect.Int64: 115 refSlice = reflect.ValueOf([]int64(nil)) 116 default: 117 refSlice = reflect.ValueOf([]*big.Int(nil)) 118 } 119 case AddressTy: // address must be of slice Address 120 refSlice = reflect.ValueOf([]common.Address(nil)) 121 case HashTy: // hash must be of slice hash 122 refSlice = reflect.ValueOf([]common.Hash(nil)) 123 case FixedBytesTy: 124 refSlice = reflect.ValueOf([][]byte(nil)) 125 default: // no other types are supported 126 return nil, fmt.Errorf("abi: unsupported slice type %v", elem.T) 127 } 128 129 var slice []byte 130 var size int 131 var offset int 132 if t.Type.IsSlice { 133 // get the offset which determines the start of this array ... 134 offset = int(binary.BigEndian.Uint64(output[index+24 : index+32])) 135 if offset+32 > len(output) { 136 return nil, fmt.Errorf("abi: cannot marshal in to go slice: offset %d would go over slice boundary (len=%d)", len(output), offset+32) 137 } 138 139 slice = output[offset:] 140 // ... starting with the size of the array in elements ... 141 size = int(binary.BigEndian.Uint64(slice[24:32])) 142 slice = slice[32:] 143 // ... and make sure that we've at the very least the amount of bytes 144 // available in the buffer. 145 if size*32 > len(slice) { 146 return nil, fmt.Errorf("abi: cannot marshal in to go slice: insufficient size output %d require %d", len(output), offset+32+size*32) 147 } 148 149 // reslice to match the required size 150 slice = slice[:size*32] 151 } else if t.Type.IsArray { 152 //get the number of elements in the array 153 size = t.Type.SliceSize 154 155 //check to make sure array size matches up 156 if index+32*size > len(output) { 157 return nil, fmt.Errorf("abi: cannot marshal in to go array: offset %d would go over slice boundary (len=%d)", len(output), index+32*size) 158 } 159 //slice is there for a fixed amount of times 160 slice = output[index : index+size*32] 161 } 162 163 for i := 0; i < size; i++ { 164 var ( 165 inter interface{} // interface type 166 returnOutput = slice[i*32 : i*32+32] // the return output 167 ) 168 // set inter to the correct type (cast) 169 switch elem.T { 170 case IntTy, UintTy: 171 inter = readInteger(t.Type.Kind, returnOutput) 172 case BoolTy: 173 inter = !allZero(returnOutput) 174 case AddressTy: 175 inter = common.BytesToAddress(returnOutput) 176 case HashTy: 177 inter = common.BytesToHash(returnOutput) 178 case FixedBytesTy: 179 inter = returnOutput 180 } 181 // append the item to our reflect slice 182 refSlice = reflect.Append(refSlice, reflect.ValueOf(inter)) 183 } 184 185 // return the interface 186 return refSlice.Interface(), nil 187 } 188 189 func readInteger(kind reflect.Kind, b []byte) interface{} { 190 switch kind { 191 case reflect.Uint8: 192 return uint8(b[len(b)-1]) 193 case reflect.Uint16: 194 return binary.BigEndian.Uint16(b[len(b)-2:]) 195 case reflect.Uint32: 196 return binary.BigEndian.Uint32(b[len(b)-4:]) 197 case reflect.Uint64: 198 return binary.BigEndian.Uint64(b[len(b)-8:]) 199 case reflect.Int8: 200 return int8(b[len(b)-1]) 201 case reflect.Int16: 202 return int16(binary.BigEndian.Uint16(b[len(b)-2:])) 203 case reflect.Int32: 204 return int32(binary.BigEndian.Uint32(b[len(b)-4:])) 205 case reflect.Int64: 206 return int64(binary.BigEndian.Uint64(b[len(b)-8:])) 207 default: 208 return new(big.Int).SetBytes(b) 209 } 210 } 211 212 func allZero(b []byte) bool { 213 for _, byte := range b { 214 if byte != 0 { 215 return false 216 } 217 } 218 return true 219 } 220 221 // toGoType parses the input and casts it to the proper type defined by the ABI 222 // argument in T. 223 func toGoType(i int, t Argument, output []byte) (interface{}, error) { 224 // we need to treat slices differently 225 if (t.Type.IsSlice || t.Type.IsArray) && t.Type.T != BytesTy && t.Type.T != StringTy && t.Type.T != FixedBytesTy && t.Type.T != FunctionTy { 226 return toGoSlice(i, t, output) 227 } 228 229 index := i * 32 230 if index+32 > len(output) { 231 return nil, fmt.Errorf("abi: cannot marshal in to go type: length insufficient %d require %d", len(output), index+32) 232 } 233 234 // Parse the given index output and check whether we need to read 235 // a different offset and length based on the type (i.e. string, bytes) 236 var returnOutput []byte 237 switch t.Type.T { 238 case StringTy, BytesTy: // variable arrays are written at the end of the return bytes 239 // parse offset from which we should start reading 240 offset := int(binary.BigEndian.Uint64(output[index+24 : index+32])) 241 if offset+32 > len(output) { 242 return nil, fmt.Errorf("abi: cannot marshal in to go type: length insufficient %d require %d", len(output), offset+32) 243 } 244 // parse the size up until we should be reading 245 size := int(binary.BigEndian.Uint64(output[offset+24 : offset+32])) 246 if offset+32+size > len(output) { 247 return nil, fmt.Errorf("abi: cannot marshal in to go type: length insufficient %d require %d", len(output), offset+32+size) 248 } 249 250 // get the bytes for this return value 251 returnOutput = output[offset+32 : offset+32+size] 252 default: 253 returnOutput = output[index : index+32] 254 } 255 256 // convert the bytes to whatever is specified by the ABI. 257 switch t.Type.T { 258 case IntTy, UintTy: 259 return readInteger(t.Type.Kind, returnOutput), nil 260 case BoolTy: 261 return !allZero(returnOutput), nil 262 case AddressTy: 263 return common.BytesToAddress(returnOutput), nil 264 case HashTy: 265 return common.BytesToHash(returnOutput), nil 266 case BytesTy, FixedBytesTy, FunctionTy: 267 return returnOutput, nil 268 case StringTy: 269 return string(returnOutput), nil 270 } 271 return nil, fmt.Errorf("abi: unknown type %v", t.Type.T) 272 } 273 274 // these variable are used to determine certain types during type assertion for 275 // assignment. 276 var ( 277 r_interSlice = reflect.TypeOf([]interface{}{}) 278 r_hash = reflect.TypeOf(common.Hash{}) 279 r_bytes = reflect.TypeOf([]byte{}) 280 r_byte = reflect.TypeOf(byte(0)) 281 ) 282 283 // Unpack output in v according to the abi specification 284 func (abi ABI) Unpack(v interface{}, name string, output []byte) error { 285 var method = abi.Methods[name] 286 287 if len(output) == 0 { 288 return fmt.Errorf("abi: unmarshalling empty output") 289 } 290 291 // make sure the passed value is a pointer 292 valueOf := reflect.ValueOf(v) 293 if reflect.Ptr != valueOf.Kind() { 294 return fmt.Errorf("abi: Unpack(non-pointer %T)", v) 295 } 296 297 var ( 298 value = valueOf.Elem() 299 typ = value.Type() 300 ) 301 302 if len(method.Outputs) > 1 { 303 switch value.Kind() { 304 // struct will match named return values to the struct's field 305 // names 306 case reflect.Struct: 307 for i := 0; i < len(method.Outputs); i++ { 308 marshalledValue, err := toGoType(i, method.Outputs[i], output) 309 if err != nil { 310 return err 311 } 312 reflectValue := reflect.ValueOf(marshalledValue) 313 314 for j := 0; j < typ.NumField(); j++ { 315 field := typ.Field(j) 316 // TODO read tags: `abi:"fieldName"` 317 if field.Name == strings.ToUpper(method.Outputs[i].Name[:1])+method.Outputs[i].Name[1:] { 318 if err := set(value.Field(j), reflectValue, method.Outputs[i]); err != nil { 319 return err 320 } 321 } 322 } 323 } 324 case reflect.Slice: 325 if !value.Type().AssignableTo(r_interSlice) { 326 return fmt.Errorf("abi: cannot marshal tuple in to slice %T (only []interface{} is supported)", v) 327 } 328 329 // if the slice already contains values, set those instead of the interface slice itself. 330 if value.Len() > 0 { 331 if len(method.Outputs) > value.Len() { 332 return fmt.Errorf("abi: cannot marshal in to slices of unequal size (require: %v, got: %v)", len(method.Outputs), value.Len()) 333 } 334 335 for i := 0; i < len(method.Outputs); i++ { 336 marshalledValue, err := toGoType(i, method.Outputs[i], output) 337 if err != nil { 338 return err 339 } 340 reflectValue := reflect.ValueOf(marshalledValue) 341 if err := set(value.Index(i).Elem(), reflectValue, method.Outputs[i]); err != nil { 342 return err 343 } 344 } 345 return nil 346 } 347 348 // create a new slice and start appending the unmarshalled 349 // values to the new interface slice. 350 z := reflect.MakeSlice(typ, 0, len(method.Outputs)) 351 for i := 0; i < len(method.Outputs); i++ { 352 marshalledValue, err := toGoType(i, method.Outputs[i], output) 353 if err != nil { 354 return err 355 } 356 z = reflect.Append(z, reflect.ValueOf(marshalledValue)) 357 } 358 value.Set(z) 359 default: 360 return fmt.Errorf("abi: cannot unmarshal tuple in to %v", typ) 361 } 362 363 } else { 364 marshalledValue, err := toGoType(0, method.Outputs[0], output) 365 if err != nil { 366 return err 367 } 368 if err := set(value, reflect.ValueOf(marshalledValue), method.Outputs[0]); err != nil { 369 return err 370 } 371 } 372 373 return nil 374 } 375 376 func (abi *ABI) UnmarshalJSON(data []byte) error { 377 var fields []struct { 378 Type string 379 Name string 380 Constant bool 381 Indexed bool 382 Anonymous bool 383 Inputs []Argument 384 Outputs []Argument 385 } 386 387 if err := json.Unmarshal(data, &fields); err != nil { 388 return err 389 } 390 391 abi.Methods = make(map[string]Method) 392 abi.Events = make(map[string]Event) 393 for _, field := range fields { 394 switch field.Type { 395 case "constructor": 396 abi.Constructor = Method{ 397 Inputs: field.Inputs, 398 } 399 // empty defaults to function according to the abi spec 400 case "function", "": 401 abi.Methods[field.Name] = Method{ 402 Name: field.Name, 403 Const: field.Constant, 404 Inputs: field.Inputs, 405 Outputs: field.Outputs, 406 } 407 case "event": 408 abi.Events[field.Name] = Event{ 409 Name: field.Name, 410 Anonymous: field.Anonymous, 411 Inputs: field.Inputs, 412 } 413 } 414 } 415 416 return nil 417 }