github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/accounts/abi/type.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:31</date>
    10  //</624450063220871168>
    11  
    12  
    13  package abi
    14  
    15  import (
    16  	"errors"
    17  	"fmt"
    18  	"reflect"
    19  	"regexp"
    20  	"strconv"
    21  	"strings"
    22  )
    23  
    24  //
    25  const (
    26  	IntTy byte = iota
    27  	UintTy
    28  	BoolTy
    29  	StringTy
    30  	SliceTy
    31  	ArrayTy
    32  	TupleTy
    33  	AddressTy
    34  	FixedBytesTy
    35  	BytesTy
    36  	HashTy
    37  	FixedPointTy
    38  	FunctionTy
    39  )
    40  
    41  //类型是受支持的参数类型的反射
    42  type Type struct {
    43  	Elem *Type
    44  	Kind reflect.Kind
    45  	Type reflect.Type
    46  	Size int
    47  T    byte //我们自己的类型检查
    48  
    49  stringKind string //保留用于派生签名的未分析字符串
    50  
    51  //元组相对字段
    52  TupleElems    []*Type  //所有元组字段的类型信息
    53  TupleRawNames []string //所有元组字段的原始字段名
    54  }
    55  
    56  var (
    57  //typeregex解析ABI子类型
    58  	typeRegex = regexp.MustCompile("([a-zA-Z]+)(([0-9]+)(x([0-9]+))?)?")
    59  )
    60  
    61  //new type创建在t中给定的abi类型的新反射类型。
    62  func NewType(t string, components []ArgumentMarshaling) (typ Type, err error) {
    63  //检查数组括号是否相等(如果存在)
    64  	if strings.Count(t, "[") != strings.Count(t, "]") {
    65  		return Type{}, fmt.Errorf("invalid arg type in abi")
    66  	}
    67  
    68  	typ.stringKind = t
    69  
    70  //如果有括号,准备进入切片/阵列模式
    71  //递归创建类型
    72  	if strings.Count(t, "[") != 0 {
    73  		i := strings.LastIndex(t, "[")
    74  //递归嵌入类型
    75  		embeddedType, err := NewType(t[:i], components)
    76  		if err != nil {
    77  			return Type{}, err
    78  		}
    79  //抓取最后一个单元格并从中创建类型
    80  		sliced := t[i:]
    81  //用regexp获取切片大小
    82  		re := regexp.MustCompile("[0-9]+")
    83  		intz := re.FindAllString(sliced, -1)
    84  
    85  		if len(intz) == 0 {
    86  //是一片
    87  			typ.T = SliceTy
    88  			typ.Kind = reflect.Slice
    89  			typ.Elem = &embeddedType
    90  			typ.Type = reflect.SliceOf(embeddedType.Type)
    91  			if embeddedType.T == TupleTy {
    92  				typ.stringKind = embeddedType.stringKind + sliced
    93  			}
    94  		} else if len(intz) == 1 {
    95  //是一个数组
    96  			typ.T = ArrayTy
    97  			typ.Kind = reflect.Array
    98  			typ.Elem = &embeddedType
    99  			typ.Size, err = strconv.Atoi(intz[0])
   100  			if err != nil {
   101  				return Type{}, fmt.Errorf("abi: error parsing variable size: %v", err)
   102  			}
   103  			typ.Type = reflect.ArrayOf(typ.Size, embeddedType.Type)
   104  			if embeddedType.T == TupleTy {
   105  				typ.stringKind = embeddedType.stringKind + sliced
   106  			}
   107  		} else {
   108  			return Type{}, fmt.Errorf("invalid formatting of array type")
   109  		}
   110  		return typ, err
   111  	}
   112  //分析ABI类型的类型和大小。
   113  	matches := typeRegex.FindAllStringSubmatch(t, -1)
   114  	if len(matches) == 0 {
   115  		return Type{}, fmt.Errorf("invalid type '%v'", t)
   116  	}
   117  	parsedType := matches[0]
   118  
   119  //varsize是变量的大小
   120  	var varSize int
   121  	if len(parsedType[3]) > 0 {
   122  		var err error
   123  		varSize, err = strconv.Atoi(parsedType[2])
   124  		if err != nil {
   125  			return Type{}, fmt.Errorf("abi: error parsing variable size: %v", err)
   126  		}
   127  	} else {
   128  		if parsedType[0] == "uint" || parsedType[0] == "int" {
   129  //这应该失败,因为这意味着
   130  //ABI类型(编译器应始终将其格式化为大小…始终)
   131  			return Type{}, fmt.Errorf("unsupported arg type: %s", t)
   132  		}
   133  	}
   134  //vartype是解析的abi类型
   135  	switch varType := parsedType[1]; varType {
   136  	case "int":
   137  		typ.Kind, typ.Type = reflectIntKindAndType(false, varSize)
   138  		typ.Size = varSize
   139  		typ.T = IntTy
   140  	case "uint":
   141  		typ.Kind, typ.Type = reflectIntKindAndType(true, varSize)
   142  		typ.Size = varSize
   143  		typ.T = UintTy
   144  	case "bool":
   145  		typ.Kind = reflect.Bool
   146  		typ.T = BoolTy
   147  		typ.Type = reflect.TypeOf(bool(false))
   148  	case "address":
   149  		typ.Kind = reflect.Array
   150  		typ.Type = addressT
   151  		typ.Size = 20
   152  		typ.T = AddressTy
   153  	case "string":
   154  		typ.Kind = reflect.String
   155  		typ.Type = reflect.TypeOf("")
   156  		typ.T = StringTy
   157  	case "bytes":
   158  		if varSize == 0 {
   159  			typ.T = BytesTy
   160  			typ.Kind = reflect.Slice
   161  			typ.Type = reflect.SliceOf(reflect.TypeOf(byte(0)))
   162  		} else {
   163  			typ.T = FixedBytesTy
   164  			typ.Kind = reflect.Array
   165  			typ.Size = varSize
   166  			typ.Type = reflect.ArrayOf(varSize, reflect.TypeOf(byte(0)))
   167  		}
   168  	case "tuple":
   169  		var (
   170  			fields     []reflect.StructField
   171  			elems      []*Type
   172  			names      []string
   173  expression string //规范参数表达式
   174  		)
   175  		expression += "("
   176  		for idx, c := range components {
   177  			cType, err := NewType(c.Type, c.Components)
   178  			if err != nil {
   179  				return Type{}, err
   180  			}
   181  			if ToCamelCase(c.Name) == "" {
   182  				return Type{}, errors.New("abi: purely anonymous or underscored field is not supported")
   183  			}
   184  			fields = append(fields, reflect.StructField{
   185  Name: ToCamelCase(c.Name), //reflect.structof将恐慌任何导出字段。
   186  				Type: cType.Type,
   187  			})
   188  			elems = append(elems, &cType)
   189  			names = append(names, c.Name)
   190  			expression += cType.stringKind
   191  			if idx != len(components)-1 {
   192  				expression += ","
   193  			}
   194  		}
   195  		expression += ")"
   196  		typ.Kind = reflect.Struct
   197  		typ.Type = reflect.StructOf(fields)
   198  		typ.TupleElems = elems
   199  		typ.TupleRawNames = names
   200  		typ.T = TupleTy
   201  		typ.stringKind = expression
   202  	case "function":
   203  		typ.Kind = reflect.Array
   204  		typ.T = FunctionTy
   205  		typ.Size = 24
   206  		typ.Type = reflect.ArrayOf(24, reflect.TypeOf(byte(0)))
   207  	default:
   208  		return Type{}, fmt.Errorf("unsupported arg type: %s", t)
   209  	}
   210  
   211  	return
   212  }
   213  
   214  //字符串实现字符串
   215  func (t Type) String() (out string) {
   216  	return t.stringKind
   217  }
   218  
   219  func (t Type) pack(v reflect.Value) ([]byte, error) {
   220  //如果指针是指针,则先取消引用指针
   221  	v = indirect(v)
   222  	if err := typeCheck(t, v); err != nil {
   223  		return nil, err
   224  	}
   225  
   226  	switch t.T {
   227  	case SliceTy, ArrayTy:
   228  		var ret []byte
   229  
   230  		if t.requiresLengthPrefix() {
   231  //追加长度
   232  			ret = append(ret, packNum(reflect.ValueOf(v.Len()))...)
   233  		}
   234  
   235  //计算偏移量(如果有)
   236  		offset := 0
   237  		offsetReq := isDynamicType(*t.Elem)
   238  		if offsetReq {
   239  			offset = getTypeSize(*t.Elem) * v.Len()
   240  		}
   241  		var tail []byte
   242  		for i := 0; i < v.Len(); i++ {
   243  			val, err := t.Elem.pack(v.Index(i))
   244  			if err != nil {
   245  				return nil, err
   246  			}
   247  			if !offsetReq {
   248  				ret = append(ret, val...)
   249  				continue
   250  			}
   251  			ret = append(ret, packNum(reflect.ValueOf(offset))...)
   252  			offset += len(val)
   253  			tail = append(tail, val...)
   254  		}
   255  		return append(ret, tail...), nil
   256  	case TupleTy:
   257  //(T1,…,Tk)对于k>=0和任何类型的T1,…,Tk
   258  //Enc(x)=Head(x(1))…头(x(k))尾(x(1))…尾部(x(k))
   259  //其中x=(x(1),…,x(k))和头部和尾部是为ti定义的静态
   260  //类型为
   261  //head(x(i))=enc(x(i)),tail(x(i))=“”(空字符串)
   262  //作为
   263  //头(x(i))=ENC(长度(头(x(1))..头(x(k))尾(x(1))…尾部(X(I-1))
   264  //尾(x(i))=enc(x(i))
   265  //否则,即,如果ti是动态类型。
   266  		fieldmap, err := mapArgNamesToStructFields(t.TupleRawNames, v)
   267  		if err != nil {
   268  			return nil, err
   269  		}
   270  //计算前缀占用的大小。
   271  		offset := 0
   272  		for _, elem := range t.TupleElems {
   273  			offset += getTypeSize(*elem)
   274  		}
   275  		var ret, tail []byte
   276  		for i, elem := range t.TupleElems {
   277  			field := v.FieldByName(fieldmap[t.TupleRawNames[i]])
   278  			if !field.IsValid() {
   279  				return nil, fmt.Errorf("field %s for tuple not found in the given struct", t.TupleRawNames[i])
   280  			}
   281  			val, err := elem.pack(field)
   282  			if err != nil {
   283  				return nil, err
   284  			}
   285  			if isDynamicType(*elem) {
   286  				ret = append(ret, packNum(reflect.ValueOf(offset))...)
   287  				tail = append(tail, val...)
   288  				offset += len(val)
   289  			} else {
   290  				ret = append(ret, val...)
   291  			}
   292  		}
   293  		return append(ret, tail...), nil
   294  
   295  	default:
   296  		return packElement(t, v), nil
   297  	}
   298  }
   299  
   300  //RequireLengthPrefix返回类型是否需要任何长度
   301  //前缀。
   302  func (t Type) requiresLengthPrefix() bool {
   303  	return t.T == StringTy || t.T == BytesTy || t.T == SliceTy
   304  }
   305  
   306  //如果类型是动态的,is dynamic type返回true。
   307  //以下类型称为“动态”类型:
   308  //*字节
   309  //*字符串
   310  //*t[]用于任何t
   311  //*t[k]对于任何动态t和任何k>=0
   312  //*(T1,…,Tk)如果Ti是动态的,则1<=i<=k
   313  func isDynamicType(t Type) bool {
   314  	if t.T == TupleTy {
   315  		for _, elem := range t.TupleElems {
   316  			if isDynamicType(*elem) {
   317  				return true
   318  			}
   319  		}
   320  		return false
   321  	}
   322  	return t.T == StringTy || t.T == BytesTy || t.T == SliceTy || (t.T == ArrayTy && isDynamicType(*t.Elem))
   323  }
   324  
   325  //GettypeSize返回此类型需要占用的大小。
   326  //我们区分静态和动态类型。静态类型就地编码
   327  //动态类型在
   328  //当前块。
   329  //因此对于静态变量,返回的大小表示
   330  //变量实际占用。
   331  //对于动态变量,返回的大小是固定的32字节,使用
   332  //存储实际值存储的位置引用。
   333  func getTypeSize(t Type) int {
   334  	if t.T == ArrayTy && !isDynamicType(*t.Elem) {
   335  //如果是嵌套数组,则递归计算类型大小
   336  		if t.Elem.T == ArrayTy {
   337  			return t.Size * getTypeSize(*t.Elem)
   338  		}
   339  		return t.Size * 32
   340  	} else if t.T == TupleTy && !isDynamicType(t) {
   341  		total := 0
   342  		for _, elem := range t.TupleElems {
   343  			total += getTypeSize(*elem)
   344  		}
   345  		return total
   346  	}
   347  	return 32
   348  }
   349