github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/accounts/abi/argument.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //版权所有2015 Go Ethereum作者
    10  //此文件是Go以太坊库的一部分。
    11  //
    12  //Go-Ethereum库是免费软件:您可以重新分发它和/或修改
    13  //根据GNU发布的较低通用公共许可证的条款
    14  //自由软件基金会,或者许可证的第3版,或者
    15  //(由您选择)任何更高版本。
    16  //
    17  //Go以太坊图书馆的发行目的是希望它会有用,
    18  //但没有任何保证;甚至没有
    19  //适销性或特定用途的适用性。见
    20  //GNU较低的通用公共许可证,了解更多详细信息。
    21  //
    22  //你应该收到一份GNU较低级别的公共许可证副本
    23  //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。
    24  
    25  package abi
    26  
    27  import (
    28  	"encoding/json"
    29  	"fmt"
    30  	"reflect"
    31  	"strings"
    32  )
    33  
    34  //参数包含参数的名称和相应的类型。
    35  //类型在打包和测试参数时使用。
    36  type Argument struct {
    37  	Name    string
    38  	Type    Type
    39  Indexed bool //索引仅由事件使用
    40  }
    41  
    42  type Arguments []Argument
    43  
    44  //unmashaljson实现json.unmasheler接口
    45  func (argument *Argument) UnmarshalJSON(data []byte) error {
    46  	var extarg struct {
    47  		Name    string
    48  		Type    string
    49  		Indexed bool
    50  	}
    51  	err := json.Unmarshal(data, &extarg)
    52  	if err != nil {
    53  		return fmt.Errorf("argument json err: %v", err)
    54  	}
    55  
    56  	argument.Type, err = NewType(extarg.Type)
    57  	if err != nil {
    58  		return err
    59  	}
    60  	argument.Name = extarg.Name
    61  	argument.Indexed = extarg.Indexed
    62  
    63  	return nil
    64  }
    65  
    66  //lengthnonindexed返回不计算“indexed”参数时的参数数。只有事件
    67  //不能有“indexed”参数,方法输入/输出的参数应始终为false
    68  func (arguments Arguments) LengthNonIndexed() int {
    69  	out := 0
    70  	for _, arg := range arguments {
    71  		if !arg.Indexed {
    72  			out++
    73  		}
    74  	}
    75  	return out
    76  }
    77  
    78  //无索引返回已筛选出索引参数的参数
    79  func (arguments Arguments) NonIndexed() Arguments {
    80  	var ret []Argument
    81  	for _, arg := range arguments {
    82  		if !arg.Indexed {
    83  			ret = append(ret, arg)
    84  		}
    85  	}
    86  	return ret
    87  }
    88  
    89  //Istuple为非原子结构返回true,如(uint、uint)或uint[]
    90  func (arguments Arguments) isTuple() bool {
    91  	return len(arguments) > 1
    92  }
    93  
    94  //unpack执行hexdata->go-format操作
    95  func (arguments Arguments) Unpack(v interface{}, data []byte) error {
    96  
    97  //确保传递的值是参数指针
    98  	if reflect.Ptr != reflect.ValueOf(v).Kind() {
    99  		return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
   100  	}
   101  	marshalledValues, err := arguments.UnpackValues(data)
   102  	if err != nil {
   103  		return err
   104  	}
   105  	if arguments.isTuple() {
   106  		return arguments.unpackTuple(v, marshalledValues)
   107  	}
   108  	return arguments.unpackAtomic(v, marshalledValues)
   109  }
   110  
   111  func (arguments Arguments) unpackTuple(v interface{}, marshalledValues []interface{}) error {
   112  
   113  	var (
   114  		value = reflect.ValueOf(v).Elem()
   115  		typ   = value.Type()
   116  		kind  = value.Kind()
   117  	)
   118  
   119  	if err := requireUnpackKind(value, typ, kind, arguments); err != nil {
   120  		return err
   121  	}
   122  
   123  //如果接口是结构,则获取abi->struct_字段映射
   124  
   125  	var abi2struct map[string]string
   126  	if kind == reflect.Struct {
   127  		var err error
   128  		abi2struct, err = mapAbiToStructFields(arguments, value)
   129  		if err != nil {
   130  			return err
   131  		}
   132  	}
   133  	for i, arg := range arguments.NonIndexed() {
   134  
   135  		reflectValue := reflect.ValueOf(marshalledValues[i])
   136  
   137  		switch kind {
   138  		case reflect.Struct:
   139  			if structField, ok := abi2struct[arg.Name]; ok {
   140  				if err := set(value.FieldByName(structField), reflectValue, arg); err != nil {
   141  					return err
   142  				}
   143  			}
   144  		case reflect.Slice, reflect.Array:
   145  			if value.Len() < i {
   146  				return fmt.Errorf("abi: insufficient number of arguments for unpack, want %d, got %d", len(arguments), value.Len())
   147  			}
   148  			v := value.Index(i)
   149  			if err := requireAssignable(v, reflectValue); err != nil {
   150  				return err
   151  			}
   152  
   153  			if err := set(v.Elem(), reflectValue, arg); err != nil {
   154  				return err
   155  			}
   156  		default:
   157  			return fmt.Errorf("abi:[2] cannot unmarshal tuple in to %v", typ)
   158  		}
   159  	}
   160  	return nil
   161  }
   162  
   163  //解包原子解包(hexdata->go)单个值
   164  func (arguments Arguments) unpackAtomic(v interface{}, marshalledValues []interface{}) error {
   165  	if len(marshalledValues) != 1 {
   166  		return fmt.Errorf("abi: wrong length, expected single value, got %d", len(marshalledValues))
   167  	}
   168  
   169  	elem := reflect.ValueOf(v).Elem()
   170  	kind := elem.Kind()
   171  	reflectValue := reflect.ValueOf(marshalledValues[0])
   172  
   173  	var abi2struct map[string]string
   174  	if kind == reflect.Struct {
   175  		var err error
   176  		if abi2struct, err = mapAbiToStructFields(arguments, elem); err != nil {
   177  			return err
   178  		}
   179  		arg := arguments.NonIndexed()[0]
   180  		if structField, ok := abi2struct[arg.Name]; ok {
   181  			return set(elem.FieldByName(structField), reflectValue, arg)
   182  		}
   183  		return nil
   184  	}
   185  
   186  	return set(elem, reflectValue, arguments.NonIndexed()[0])
   187  
   188  }
   189  
   190  //计算数组的完整大小;
   191  //也就是说,对嵌套数组进行计数,这些数组将计入解包的大小。
   192  func getArraySize(arr *Type) int {
   193  	size := arr.Size
   194  //数组可以嵌套,每个元素的大小相同
   195  	arr = arr.Elem
   196  	for arr.T == ArrayTy {
   197  //当elem是数组时,继续乘以elem.size。
   198  		size *= arr.Size
   199  		arr = arr.Elem
   200  	}
   201  //现在我们有了完整的数组大小,包括它的子数组。
   202  	return size
   203  }
   204  
   205  //解包值可用于根据ABI规范解包ABI编码的十六进制数据。
   206  //不提供要解包的结构。相反,此方法返回一个包含
   207  //价值观。原子参数将是一个包含一个元素的列表。
   208  func (arguments Arguments) UnpackValues(data []byte) ([]interface{}, error) {
   209  	retval := make([]interface{}, 0, arguments.LengthNonIndexed())
   210  	virtualArgs := 0
   211  	for index, arg := range arguments.NonIndexed() {
   212  		marshalledValue, err := toGoType((index+virtualArgs)*32, arg.Type, data)
   213  		if arg.Type.T == ArrayTy {
   214  //如果我们有一个静态数组,比如[3]uint256,那么这些数组被编码为
   215  //就像uint256、uint256、uint256一样。
   216  //这意味着当
   217  //我们从现在开始计算索引。
   218  //
   219  //嵌套多层深度的数组值也以内联方式编码:
   220  //[2][3]uint256:uint256、uint256、uint256、uint256、uint256、uint256、uint256
   221  //
   222  //计算完整的数组大小以获得下一个参数的正确偏移量。
   223  //将其减小1,因为仍应用正常索引增量。
   224  			virtualArgs += getArraySize(&arg.Type) - 1
   225  		}
   226  		if err != nil {
   227  			return nil, err
   228  		}
   229  		retval = append(retval, marshalledValue)
   230  	}
   231  	return retval, nil
   232  }
   233  
   234  //packvalues执行操作go format->hexdata
   235  //它在语义上与unpackvalues相反
   236  func (arguments Arguments) PackValues(args []interface{}) ([]byte, error) {
   237  	return arguments.Pack(args...)
   238  }
   239  
   240  //pack执行操作go format->hexdata
   241  func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
   242  //确保参数匹配并打包
   243  	abiArgs := arguments
   244  	if len(args) != len(abiArgs) {
   245  		return nil, fmt.Errorf("argument count mismatch: %d for %d", len(args), len(abiArgs))
   246  	}
   247  //变量输入是在压缩结束时附加的输出
   248  //输出。这用于字符串和字节类型输入。
   249  	var variableInput []byte
   250  
   251  //输入偏移量是压缩输出的字节偏移量
   252  	inputOffset := 0
   253  	for _, abiArg := range abiArgs {
   254  		if abiArg.Type.T == ArrayTy {
   255  			inputOffset += 32 * abiArg.Type.Size
   256  		} else {
   257  			inputOffset += 32
   258  		}
   259  	}
   260  	var ret []byte
   261  	for i, a := range args {
   262  		input := abiArgs[i]
   263  //打包输入
   264  		packed, err := input.Type.pack(reflect.ValueOf(a))
   265  		if err != nil {
   266  			return nil, err
   267  		}
   268  //检查切片类型(字符串、字节、切片)
   269  		if input.Type.requiresLengthPrefix() {
   270  //计算偏移量
   271  			offset := inputOffset + len(variableInput)
   272  //设置偏移量
   273  			ret = append(ret, packNum(reflect.ValueOf(offset))...)
   274  //将打包输出附加到变量输入。变量输入
   275  //将附加在输入的末尾。
   276  			variableInput = append(variableInput, packed...)
   277  		} else {
   278  //将压缩值追加到输入
   279  			ret = append(ret, packed...)
   280  		}
   281  	}
   282  //在压缩输入的末尾附加变量输入
   283  	ret = append(ret, variableInput...)
   284  
   285  	return ret, nil
   286  }
   287  
   288  //大写将字符串的第一个字符设为大写,同时删除
   289  //在变量名中添加下划线前缀。
   290  func capitalise(input string) string {
   291  	for len(input) > 0 && input[0] == '_' {
   292  		input = input[1:]
   293  	}
   294  	if len(input) == 0 {
   295  		return ""
   296  	}
   297  	return strings.ToUpper(input[:1]) + input[1:]
   298  }