github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/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 12:09:26</date>
    10  //</624342582406680576>
    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  //unmashaljson实现json.unmasheler接口
    33  func (argument *Argument) UnmarshalJSON(data []byte) error {
    34  	var extarg struct {
    35  		Name    string
    36  		Type    string
    37  		Indexed bool
    38  	}
    39  	err := json.Unmarshal(data, &extarg)
    40  	if err != nil {
    41  		return fmt.Errorf("argument json err: %v", err)
    42  	}
    43  
    44  	argument.Type, err = NewType(extarg.Type)
    45  	if err != nil {
    46  		return err
    47  	}
    48  	argument.Name = extarg.Name
    49  	argument.Indexed = extarg.Indexed
    50  
    51  	return nil
    52  }
    53  
    54  //lengthnonindexed返回不计算“indexed”参数时的参数数。只有事件
    55  //不能有“indexed”参数,方法输入/输出的参数应始终为false
    56  func (arguments Arguments) LengthNonIndexed() int {
    57  	out := 0
    58  	for _, arg := range arguments {
    59  		if !arg.Indexed {
    60  			out++
    61  		}
    62  	}
    63  	return out
    64  }
    65  
    66  //无索引返回已筛选出索引参数的参数
    67  func (arguments Arguments) NonIndexed() Arguments {
    68  	var ret []Argument
    69  	for _, arg := range arguments {
    70  		if !arg.Indexed {
    71  			ret = append(ret, arg)
    72  		}
    73  	}
    74  	return ret
    75  }
    76  
    77  //Istuple为非原子结构返回true,如(uint、uint)或uint[]
    78  func (arguments Arguments) isTuple() bool {
    79  	return len(arguments) > 1
    80  }
    81  
    82  //unpack执行hexdata->go-format操作
    83  func (arguments Arguments) Unpack(v interface{}, data []byte) error {
    84  
    85  //确保传递的值是参数指针
    86  	if reflect.Ptr != reflect.ValueOf(v).Kind() {
    87  		return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
    88  	}
    89  	marshalledValues, err := arguments.UnpackValues(data)
    90  	if err != nil {
    91  		return err
    92  	}
    93  	if arguments.isTuple() {
    94  		return arguments.unpackTuple(v, marshalledValues)
    95  	}
    96  	return arguments.unpackAtomic(v, marshalledValues)
    97  }
    98  
    99  func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interface{}) error {
   100  
   101  	var (
   102  		value = reflect.ValueOf(v).Elem()
   103  		typ   = value.Type()
   104  		kind  = value.Kind()
   105  	)
   106  
   107  	if err := requireUnpackKind(value, typ, kind, arguments); err != nil {
   108  		return err
   109  	}
   110  
   111  //如果接口是结构,则获取abi->struct_字段映射
   112  
   113  	var abi2struct map[string]string
   114  	if kind == reflect.Struct {
   115  		var err error
   116  		abi2struct, err = mapAbiToStructFields(arguments, value)
   117  		if err != nil {
   118  			return err
   119  		}
   120  	}
   121  	for i, arg := range arguments.NonIndexed() {
   122  
   123  		reflectValue := reflect.ValueOf(marshalledValues[i])
   124  
   125  		switch kind {
   126  		case reflect.Struct:
   127  			if structField, ok := abi2struct[arg.Name]; ok {
   128  				if err := set(value.FieldByName(structField), reflectValue, arg); err != nil {
   129  					return err
   130  				}
   131  			}
   132  		case reflect.Slice, reflect.Array:
   133  			if value.Len() < i {
   134  				return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", len(arguments), value.Len())
   135  			}
   136  			v := value.Index(i)
   137  			if err := requireAssignable(v, reflectValue); err != nil {
   138  				return err
   139  			}
   140  
   141  			if err := set(v.Elem(), reflectValue, arg); err != nil {
   142  				return err
   143  			}
   144  		default:
   145  			return fmt.Errorf("abi:[2] cannot unmarshal tuple in to %v", typ)
   146  		}
   147  	}
   148  	return nil
   149  }
   150  
   151  //解包原子解包(hexdata->go)单个值
   152  func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues []interface{}) error {
   153  	if len(marshalledValues) != 1 {
   154  		return fmt.Errorf("abi: wrong length, expected single value, got %d", len(marshalledValues))
   155  	}
   156  
   157  	elem := reflect.ValueOf(v).Elem()
   158  	kind := elem.Kind()
   159  	reflectValue := reflect.ValueOf(marshalledValues[0])
   160  
   161  	var abi2struct map[string]string
   162  	if kind == reflect.Struct {
   163  		var err error
   164  		if abi2struct, err = mapAbiToStructFields(arguments, elem); err != nil {
   165  			return err
   166  		}
   167  		arg := arguments.NonIndexed()[0]
   168  		if structField, ok := abi2struct[arg.Name]; ok {
   169  			return set(elem.FieldByName(structField), reflectValue, arg)
   170  		}
   171  		return nil
   172  	}
   173  
   174  	return set(elem, reflectValue, arguments.NonIndexed()[0])
   175  
   176  }
   177  
   178  //计算数组的完整大小;
   179  //也就是说,对嵌套数组进行计数,这些数组将计入解包的大小。
   180  func getArraySize(arr *Type) int {
   181  	size := arr.Size
   182  //数组可以嵌套,每个元素的大小相同
   183  	arr = arr.Elem
   184  	for arr.T == ArrayTy {
   185  //当elem是数组时,继续乘以elem.size。
   186  		size *= arr.Size
   187  		arr = arr.Elem
   188  	}
   189  //现在我们有了完整的数组大小,包括它的子数组。
   190  	return size
   191  }
   192  
   193  //解包值可用于根据ABI规范解包ABI编码的十六进制数据。
   194  //不提供要解包的结构。相反,此方法返回一个包含
   195  //价值观。原子参数将是一个包含一个元素的列表。
   196  func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) {
   197  	retval := make([]interface{}, 0, arguments.LengthNonIndexed())
   198  	virtualArgs := 0
   199  	for index, arg := range arguments.NonIndexed() {
   200  		marshalledValue, err := toGoType((index+virtualArgs)*32, arg.Type, data)
   201  		if arg.Type.T == ArrayTy {
   202  //如果我们有一个静态数组,比如[3]uint256,那么这些数组被编码为
   203  //就像uint256、uint256、uint256一样。
   204  //这意味着当
   205  //我们从现在开始计算索引。
   206  //
   207  //嵌套多层深度的数组值也以内联方式编码:
   208  //[2][3]uint256:uint256、uint256、uint256、uint256、uint256、uint256、uint256
   209  //
   210  //计算完整的数组大小以获得下一个参数的正确偏移量。
   211  //将其减小1,因为仍应用正常索引增量。
   212  			virtualArgs += getArraySize(&arg.Type) - 1
   213  		}
   214  		if err != nil {
   215  			return nil, err
   216  		}
   217  		retval = append(retval, marshalledValue)
   218  	}
   219  	return retval, nil
   220  }
   221  
   222  //packvalues执行操作go format->hexdata
   223  //它在语义上与unpackvalues相反
   224  func (arguments Arguments) PackValues(args []interface{}) ([]byte, error) {
   225  	return arguments.Pack(args...)
   226  }
   227  
   228  //pack执行操作go format->hexdata
   229  func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
   230  //确保参数匹配并打包
   231  	abiArgs := arguments
   232  	if len(args) != len(abiArgs) {
   233  		return nil, fmt.Errorf("argument count mismatch: %d for %d", len(args), len(abiArgs))
   234  	}
   235  //变量输入是在压缩结束时附加的输出
   236  //输出。这用于字符串和字节类型输入。
   237  	var variableInput []byte
   238  
   239  //输入偏移量是压缩输出的字节偏移量
   240  	inputOffset := 0
   241  	for _, abiArg := range abiArgs {
   242  		if abiArg.Type.T == ArrayTy {
   243  			inputOffset += 32 * abiArg.Type.Size
   244  		} else {
   245  			inputOffset += 32
   246  		}
   247  	}
   248  	var ret []byte
   249  	for i, a := range args {
   250  		input := abiArgs[i]
   251  //打包输入
   252  		packed, err := input.Type.pack(reflect.ValueOf(a))
   253  		if err != nil {
   254  			return nil, err
   255  		}
   256  //检查切片类型(字符串、字节、切片)
   257  		if input.Type.requiresLengthPrefix() {
   258  //计算偏移量
   259  			offset := inputOffset + len(variableInput)
   260  //设置偏移量
   261  			ret = append(ret, packNum(reflect.ValueOf(offset))...)
   262  //将打包输出附加到变量输入。变量输入
   263  //将附加在输入的末尾。
   264  			variableInput = append(variableInput, packed...)
   265  		} else {
   266  //将压缩值追加到输入
   267  			ret = append(ret, packed...)
   268  		}
   269  	}
   270  //在压缩输入的末尾附加变量输入
   271  	ret = append(ret, variableInput...)
   272  
   273  	return ret, nil
   274  }
   275  
   276  //大写将字符串的第一个字符设为大写,同时删除
   277  //在变量名中添加下划线前缀。
   278  func capitalise(input string) string {
   279  	for len(input) > 0 && input[0] == '_' {
   280  		input = input[1:]
   281  	}
   282  	if len(input) == 0 {
   283  		return ""
   284  	}
   285  	return strings.ToUpper(input[:1]) + input[1:]
   286  }
   287