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