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  }