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 }