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