github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/accounts/abi/argument.go (about)

     1  package abi
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"reflect"
     7  	"strings"
     8  )
     9  
    10  // Argument holds the name of the argument and the corresponding type.
    11  // Types are used when packing and testing arguments.
    12  type Argument struct {
    13  	Name    string
    14  	Type    Type
    15  	Indexed bool // indexed is only used by events
    16  }
    17  
    18  type Arguments []Argument
    19  
    20  // UnmarshalJSON implements json.Unmarshaler interface
    21  func (argument *Argument) UnmarshalJSON(data []byte) error {
    22  	var extarg struct {
    23  		Name    string
    24  		Type    string
    25  		Indexed bool
    26  	}
    27  	err := json.Unmarshal(data, &extarg)
    28  	if err != nil {
    29  		return fmt.Errorf("argument json err: %v", err)
    30  	}
    31  
    32  	argument.Type, err = NewType(extarg.Type)
    33  	if err != nil {
    34  		return err
    35  	}
    36  	argument.Name = extarg.Name
    37  	argument.Indexed = extarg.Indexed
    38  
    39  	return nil
    40  }
    41  
    42  // LengthNonIndexed returns the number of arguments when not counting 'indexed' ones. Only events
    43  // can ever have 'indexed' arguments, it should always be false on arguments for method input/output
    44  func (arguments Arguments) LengthNonIndexed() int {
    45  	out := 0
    46  	for _, arg := range arguments {
    47  		if !arg.Indexed {
    48  			out++
    49  		}
    50  	}
    51  	return out
    52  }
    53  
    54  // NonIndexed returns the arguments with indexed arguments filtered out
    55  func (arguments Arguments) NonIndexed() Arguments {
    56  	var ret []Argument
    57  	for _, arg := range arguments {
    58  		if !arg.Indexed {
    59  			ret = append(ret, arg)
    60  		}
    61  	}
    62  	return ret
    63  }
    64  
    65  // isTuple returns true for non-atomic constructs, like (uint,uint) or uint[]
    66  func (arguments Arguments) isTuple() bool {
    67  	return len(arguments) > 1
    68  }
    69  
    70  // Unpack performs the operation hexdata -> Go format
    71  func (arguments Arguments) Unpack(v interface{}, data []byte) error {
    72  
    73  	// make sure the passed value is arguments pointer
    74  	if reflect.Ptr != reflect.ValueOf(v).Kind() {
    75  		return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
    76  	}
    77  	marshalledValues, err := arguments.UnpackValues(data)
    78  	if err != nil {
    79  		return err
    80  	}
    81  	if arguments.isTuple() {
    82  		return arguments.unpackTuple(v, marshalledValues)
    83  	}
    84  	return arguments.unpackAtomic(v, marshalledValues)
    85  }
    86  
    87  func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interface{}) error {
    88  
    89  	var (
    90  		value = reflect.ValueOf(v).Elem()
    91  		typ   = value.Type()
    92  		kind  = value.Kind()
    93  	)
    94  
    95  	if err := requireUnpackKind(value, typ, kind, arguments); err != nil {
    96  		return err
    97  	}
    98  	// If the output interface is a struct, make sure names don't collide
    99  	if kind == reflect.Struct {
   100  		if err := requireUniqueStructFieldNames(arguments); err != nil {
   101  			return err
   102  		}
   103  	}
   104  	for i, arg := range arguments.NonIndexed() {
   105  
   106  		reflectValue := reflect.ValueOf(marshalledValues[i])
   107  
   108  		switch kind {
   109  		case reflect.Struct:
   110  			err := unpackStruct(value, reflectValue, arg)
   111  			if err != nil {
   112  				return err
   113  			}
   114  		case reflect.Slice, reflect.Array:
   115  			if value.Len() < i {
   116  				return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", len(arguments), value.Len())
   117  			}
   118  			v := value.Index(i)
   119  			if err := requireAssignable(v, reflectValue); err != nil {
   120  				return err
   121  			}
   122  
   123  			if err := set(v.Elem(), reflectValue, arg); err != nil {
   124  				return err
   125  			}
   126  		default:
   127  			return fmt.Errorf("abi:[2] cannot unmarshal tuple in to %v", typ)
   128  		}
   129  	}
   130  	return nil
   131  }
   132  
   133  // unpackAtomic unpacks ( hexdata -> go ) a single value
   134  func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues []interface{}) error {
   135  	if len(marshalledValues) != 1 {
   136  		return fmt.Errorf("abi: wrong length, expected single value, got %d", len(marshalledValues))
   137  	}
   138  	elem := reflect.ValueOf(v).Elem()
   139  	kind := elem.Kind()
   140  	reflectValue := reflect.ValueOf(marshalledValues[0])
   141  
   142  	if kind == reflect.Struct {
   143  		//make sure names don't collide
   144  		if err := requireUniqueStructFieldNames(arguments); err != nil {
   145  			return err
   146  		}
   147  
   148  		return unpackStruct(elem, reflectValue, arguments[0])
   149  	}
   150  
   151  	return set(elem, reflectValue, arguments.NonIndexed()[0])
   152  
   153  }
   154  
   155  // Computes the full size of an array;
   156  // i.e. counting nested arrays, which count towards size for unpacking.
   157  func getArraySize(arr *Type) int {
   158  	size := arr.Size
   159  	// Arrays can be nested, with each element being the same size
   160  	arr = arr.Elem
   161  	for arr.T == ArrayTy {
   162  		// Keep multiplying by elem.Size while the elem is an array.
   163  		size *= arr.Size
   164  		arr = arr.Elem
   165  	}
   166  	// Now we have the full array size, including its children.
   167  	return size
   168  }
   169  
   170  // UnpackValues can be used to unpack ABI-encoded hexdata according to the ABI-specification,
   171  // without supplying a struct to unpack into. Instead, this method returns a list containing the
   172  // values. An atomic argument will be a list with one element.
   173  func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) {
   174  	retval := make([]interface{}, 0, arguments.LengthNonIndexed())
   175  	virtualArgs := 0
   176  	for index, arg := range arguments.NonIndexed() {
   177  		marshalledValue, err := toGoType((index+virtualArgs)*32, arg.Type, data)
   178  		if arg.Type.T == ArrayTy {
   179  			// If we have a static array, like [3]uint256, these are coded as
   180  			// just like uint256,uint256,uint256.
   181  			// This means that we need to add two 'virtual' arguments when
   182  			// we count the index from now on.
   183  			//
   184  			// Array values nested multiple levels deep are also encoded inline:
   185  			// [2][3]uint256: uint256,uint256,uint256,uint256,uint256,uint256
   186  			//
   187  			// Calculate the full array size to get the correct offset for the next argument.
   188  			// Decrement it by 1, as the normal index increment is still applied.
   189  			virtualArgs += getArraySize(&arg.Type) - 1
   190  		}
   191  		if err != nil {
   192  			return nil, err
   193  		}
   194  		retval = append(retval, marshalledValue)
   195  	}
   196  	return retval, nil
   197  }
   198  
   199  // PackValues performs the operation Go format -> Hexdata
   200  // It is the semantic opposite of UnpackValues
   201  func (arguments Arguments) PackValues(args []interface{}) ([]byte, error) {
   202  	return arguments.Pack(args...)
   203  }
   204  
   205  // Pack performs the operation Go format -> Hexdata
   206  func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
   207  	// Make sure arguments match up and pack them
   208  	abiArgs := arguments
   209  	if len(args) != len(abiArgs) {
   210  		return nil, fmt.Errorf("argument count mismatch: %d for %d", len(args), len(abiArgs))
   211  	}
   212  	// variable input is the output appended at the end of packed
   213  	// output. This is used for strings and bytes types input.
   214  	var variableInput []byte
   215  
   216  	// input offset is the bytes offset for packed output
   217  	inputOffset := 0
   218  	for _, abiArg := range abiArgs {
   219  		if abiArg.Type.T == ArrayTy {
   220  			inputOffset += 32 * abiArg.Type.Size
   221  		} else {
   222  			inputOffset += 32
   223  		}
   224  	}
   225  	var ret []byte
   226  	for i, a := range args {
   227  		input := abiArgs[i]
   228  		// pack the input
   229  		packed, err := input.Type.pack(reflect.ValueOf(a))
   230  		if err != nil {
   231  			return nil, err
   232  		}
   233  		// check for a slice type (string, bytes, slice)
   234  		if input.Type.requiresLengthPrefix() {
   235  			// calculate the offset
   236  			offset := inputOffset + len(variableInput)
   237  			// set the offset
   238  			ret = append(ret, packNum(reflect.ValueOf(offset))...)
   239  			// Append the packed output to the variable input. The variable input
   240  			// will be appended at the end of the input.
   241  			variableInput = append(variableInput, packed...)
   242  		} else {
   243  			// append the packed value to the input
   244  			ret = append(ret, packed...)
   245  		}
   246  	}
   247  	// append the variable input at the end of the packed input
   248  	ret = append(ret, variableInput...)
   249  
   250  	return ret, nil
   251  }
   252  
   253  // capitalise makes the first character of a string upper case, also removing any
   254  // prefixing underscores from the variable names.
   255  func capitalise(input string) string {
   256  	for len(input) > 0 && input[0] == '_' {
   257  		input = input[1:]
   258  	}
   259  	if len(input) == 0 {
   260  		return ""
   261  	}
   262  	return strings.ToUpper(input[:1]) + input[1:]
   263  }
   264  
   265  //unpackStruct extracts each argument into its corresponding struct field
   266  func unpackStruct(value, reflectValue reflect.Value, arg Argument) error {
   267  	name := capitalise(arg.Name)
   268  	typ := value.Type()
   269  	for j := 0; j < typ.NumField(); j++ {
   270  		// TODO read tags: `abi:"fieldName"`
   271  		if typ.Field(j).Name == name {
   272  			if err := set(value.Field(j), reflectValue, arg); err != nil {
   273  				return err
   274  			}
   275  		}
   276  	}
   277  	return nil
   278  }