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