github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/accounts/abi/argument.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:30</date>
    10  //</624450059492134912>
    11  
    12  
    13  package abi
    14  
    15  import (
    16  	"encoding/json"
    17  	"fmt"
    18  	"reflect"
    19  	"strings"
    20  )
    21  
    22  //参数包含参数的名称和相应的类型。
    23  //类型在打包和测试参数时使用。
    24  type Argument struct {
    25  	Name    string
    26  	Type    Type
    27  Indexed bool //索引仅由事件使用
    28  }
    29  
    30  type Arguments []Argument
    31  
    32  type ArgumentMarshaling struct {
    33  	Name       string
    34  	Type       string
    35  	Components []ArgumentMarshaling
    36  	Indexed    bool
    37  }
    38  
    39  //unmashaljson实现json.unmasheler接口
    40  func (argument *Argument) UnmarshalJSON(data []byte) error {
    41  	var arg ArgumentMarshaling
    42  	err := json.Unmarshal(data, &arg)
    43  	if err != nil {
    44  		return fmt.Errorf("argument json err: %v", err)
    45  	}
    46  
    47  	argument.Type, err = NewType(arg.Type, arg.Components)
    48  	if err != nil {
    49  		return err
    50  	}
    51  	argument.Name = arg.Name
    52  	argument.Indexed = arg.Indexed
    53  
    54  	return nil
    55  }
    56  
    57  //lengthnonindexed返回不计算“indexed”参数时的参数数。只有事件
    58  //不能有“indexed”参数,方法输入/输出的参数应始终为false
    59  func (arguments Arguments) LengthNonIndexed() int {
    60  	out := 0
    61  	for _, arg := range arguments {
    62  		if !arg.Indexed {
    63  			out++
    64  		}
    65  	}
    66  	return out
    67  }
    68  
    69  //无索引返回已筛选出索引参数的参数
    70  func (arguments Arguments) NonIndexed() Arguments {
    71  	var ret []Argument
    72  	for _, arg := range arguments {
    73  		if !arg.Indexed {
    74  			ret = append(ret, arg)
    75  		}
    76  	}
    77  	return ret
    78  }
    79  
    80  //Istuple为非原子结构返回true,如(uint、uint)或uint[]
    81  func (arguments Arguments) isTuple() bool {
    82  	return len(arguments) > 1
    83  }
    84  
    85  //unpack执行hexdata->go-format操作
    86  func (arguments Arguments) Unpack(v interface{}, data []byte) error {
    87  //确保传递的值是参数指针
    88  	if reflect.Ptr != reflect.ValueOf(v).Kind() {
    89  		return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
    90  	}
    91  	marshalledValues, err := arguments.UnpackValues(data)
    92  	if err != nil {
    93  		return err
    94  	}
    95  	if arguments.isTuple() {
    96  		return arguments.unpackTuple(v, marshalledValues)
    97  	}
    98  	return arguments.unpackAtomic(v, marshalledValues[0])
    99  }
   100  
   101  //unpack将未标记的值设置为go格式。
   102  //注意这里的DST必须是可设置的。
   103  func unpack(t *Type, dst interface{}, src interface{}) error {
   104  	var (
   105  		dstVal = reflect.ValueOf(dst).Elem()
   106  		srcVal = reflect.ValueOf(src)
   107  	)
   108  
   109  	if t.T != TupleTy && !((t.T == SliceTy || t.T == ArrayTy) && t.Elem.T == TupleTy) {
   110  		return set(dstVal, srcVal)
   111  	}
   112  
   113  	switch t.T {
   114  	case TupleTy:
   115  		if dstVal.Kind() != reflect.Struct {
   116  			return fmt.Errorf("abi: invalid dst value for unpack, want struct, got %s", dstVal.Kind())
   117  		}
   118  		fieldmap, err := mapArgNamesToStructFields(t.TupleRawNames, dstVal)
   119  		if err != nil {
   120  			return err
   121  		}
   122  		for i, elem := range t.TupleElems {
   123  			fname := fieldmap[t.TupleRawNames[i]]
   124  			field := dstVal.FieldByName(fname)
   125  			if !field.IsValid() {
   126  				return fmt.Errorf("abi: field %s can't found in the given value", t.TupleRawNames[i])
   127  			}
   128  			if err := unpack(elem, field.Addr().Interface(), srcVal.Field(i).Interface()); err != nil {
   129  				return err
   130  			}
   131  		}
   132  		return nil
   133  	case SliceTy:
   134  		if dstVal.Kind() != reflect.Slice {
   135  			return fmt.Errorf("abi: invalid dst value for unpack, want slice, got %s", dstVal.Kind())
   136  		}
   137  		slice := reflect.MakeSlice(dstVal.Type(), srcVal.Len(), srcVal.Len())
   138  		for i := 0; i < slice.Len(); i++ {
   139  			if err := unpack(t.Elem, slice.Index(i).Addr().Interface(), srcVal.Index(i).Interface()); err != nil {
   140  				return err
   141  			}
   142  		}
   143  		dstVal.Set(slice)
   144  	case ArrayTy:
   145  		if dstVal.Kind() != reflect.Array {
   146  			return fmt.Errorf("abi: invalid dst value for unpack, want array, got %s", dstVal.Kind())
   147  		}
   148  		array := reflect.New(dstVal.Type()).Elem()
   149  		for i := 0; i < array.Len(); i++ {
   150  			if err := unpack(t.Elem, array.Index(i).Addr().Interface(), srcVal.Index(i).Interface()); err != nil {
   151  				return err
   152  			}
   153  		}
   154  		dstVal.Set(array)
   155  	}
   156  	return nil
   157  }
   158  
   159  //解包原子解包(hexdata->go)单个值
   160  func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues interface{}) error {
   161  	if arguments.LengthNonIndexed() == 0 {
   162  		return nil
   163  	}
   164  	argument := arguments.NonIndexed()[0]
   165  	elem := reflect.ValueOf(v).Elem()
   166  
   167  	if elem.Kind() == reflect.Struct {
   168  		fieldmap, err := mapArgNamesToStructFields([]string{argument.Name}, elem)
   169  		if err != nil {
   170  			return err
   171  		}
   172  		field := elem.FieldByName(fieldmap[argument.Name])
   173  		if !field.IsValid() {
   174  			return fmt.Errorf("abi: field %s can't be found in the given value", argument.Name)
   175  		}
   176  		return unpack(&argument.Type, field.Addr().Interface(), marshalledValues)
   177  	}
   178  	return unpack(&argument.Type, elem.Addr().Interface(), marshalledValues)
   179  }
   180  
   181  //解包解包(hexdata->go)一批值。
   182  func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interface{}) error {
   183  	var (
   184  		value = reflect.ValueOf(v).Elem()
   185  		typ   = value.Type()
   186  		kind  = value.Kind()
   187  	)
   188  	if err := requireUnpackKind(value, typ, kind, arguments); err != nil {
   189  		return err
   190  	}
   191  
   192  //如果接口是结构,则获取abi->struct_字段映射
   193  	var abi2struct map[string]string
   194  	if kind == reflect.Struct {
   195  		var (
   196  			argNames []string
   197  			err      error
   198  		)
   199  		for _, arg := range arguments.NonIndexed() {
   200  			argNames = append(argNames, arg.Name)
   201  		}
   202  		abi2struct, err = mapArgNamesToStructFields(argNames, value)
   203  		if err != nil {
   204  			return err
   205  		}
   206  	}
   207  	for i, arg := range arguments.NonIndexed() {
   208  		switch kind {
   209  		case reflect.Struct:
   210  			field := value.FieldByName(abi2struct[arg.Name])
   211  			if !field.IsValid() {
   212  				return fmt.Errorf("abi: field %s can't be found in the given value", arg.Name)
   213  			}
   214  			if err := unpack(&arg.Type, field.Addr().Interface(), marshalledValues[i]); err != nil {
   215  				return err
   216  			}
   217  		case reflect.Slice, reflect.Array:
   218  			if value.Len() < i {
   219  				return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", len(arguments), value.Len())
   220  			}
   221  			v := value.Index(i)
   222  			if err := requireAssignable(v, reflect.ValueOf(marshalledValues[i])); err != nil {
   223  				return err
   224  			}
   225  			if err := unpack(&arg.Type, v.Addr().Interface(), marshalledValues[i]); err != nil {
   226  				return err
   227  			}
   228  		default:
   229  			return fmt.Errorf("abi:[2] cannot unmarshal tuple in to %v", typ)
   230  		}
   231  	}
   232  	return nil
   233  
   234  }
   235  
   236  //解包值可用于根据ABI规范解包ABI编码的十六进制数据。
   237  //不提供要解包的结构。相反,此方法返回一个包含
   238  //价值观。原子参数将是一个包含一个元素的列表。
   239  func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) {
   240  	retval := make([]interface{}, 0, arguments.LengthNonIndexed())
   241  	virtualArgs := 0
   242  	for index, arg := range arguments.NonIndexed() {
   243  		marshalledValue, err := toGoType((index+virtualArgs)*32, arg.Type, data)
   244  		if arg.Type.T == ArrayTy && !isDynamicType(arg.Type) {
   245  //如果我们有一个静态数组,比如[3]uint256,那么这些数组被编码为
   246  //就像uint256、uint256、uint256一样。
   247  //这意味着当
   248  //我们从现在开始计算索引。
   249  //
   250  //嵌套多层深度的数组值也以内联方式编码:
   251  //[2][3]uint256:uint256、uint256、uint256、uint256、uint256、uint256、uint256
   252  //
   253  //计算完整的数组大小以获得下一个参数的正确偏移量。
   254  //将其减小1,因为仍应用正常索引增量。
   255  			virtualArgs += getTypeSize(arg.Type)/32 - 1
   256  		} else if arg.Type.T == TupleTy && !isDynamicType(arg.Type) {
   257  //如果我们有一个静态元组,比如(uint256、bool、uint256),这些是
   258  //代码与uint256、bool、uint256相同
   259  			virtualArgs += getTypeSize(arg.Type)/32 - 1
   260  		}
   261  		if err != nil {
   262  			return nil, err
   263  		}
   264  		retval = append(retval, marshalledValue)
   265  	}
   266  	return retval, nil
   267  }
   268  
   269  //packvalues执行操作go format->hexdata
   270  //它在语义上与unpackvalues相反
   271  func (arguments Arguments) PackValues(args []interface{}) ([]byte, error) {
   272  	return arguments.Pack(args...)
   273  }
   274  
   275  //pack执行操作go format->hexdata
   276  func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
   277  //确保参数匹配并打包
   278  	abiArgs := arguments
   279  	if len(args) != len(abiArgs) {
   280  		return nil, fmt.Errorf("argument count mismatch: %d for %d", len(args), len(abiArgs))
   281  	}
   282  //变量输入是在压缩结束时附加的输出
   283  //输出。这用于字符串和字节类型输入。
   284  	var variableInput []byte
   285  
   286  //输入偏移量是压缩输出的字节偏移量
   287  	inputOffset := 0
   288  	for _, abiArg := range abiArgs {
   289  		inputOffset += getTypeSize(abiArg.Type)
   290  	}
   291  	var ret []byte
   292  	for i, a := range args {
   293  		input := abiArgs[i]
   294  //打包输入
   295  		packed, err := input.Type.pack(reflect.ValueOf(a))
   296  		if err != nil {
   297  			return nil, err
   298  		}
   299  //检查动态类型
   300  		if isDynamicType(input.Type) {
   301  //设置偏移量
   302  			ret = append(ret, packNum(reflect.ValueOf(inputOffset))...)
   303  //计算下一个偏移量
   304  			inputOffset += len(packed)
   305  //附加到变量输入
   306  			variableInput = append(variableInput, packed...)
   307  		} else {
   308  //将压缩值追加到输入
   309  			ret = append(ret, packed...)
   310  		}
   311  	}
   312  //在压缩输入的末尾附加变量输入
   313  	ret = append(ret, variableInput...)
   314  
   315  	return ret, nil
   316  }
   317  
   318  //to camel case将欠分数字符串转换为驼色大小写字符串
   319  func ToCamelCase(input string) string {
   320  	parts := strings.Split(input, "_")
   321  	for i, s := range parts {
   322  		if len(s) > 0 {
   323  			parts[i] = strings.ToUpper(s[:1]) + s[1:]
   324  		}
   325  	}
   326  	return strings.Join(parts, "")
   327  }
   328