github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/accounts/abi/unpack.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 //版权所有2017 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/binary" 29 "fmt" 30 "math/big" 31 "reflect" 32 33 "github.com/ethereum/go-ethereum/common" 34 ) 35 36 //根据整数的类型读取整数 37 func readInteger(kind reflect.Kind, b []byte) interface{} { 38 switch kind { 39 case reflect.Uint8: 40 return b[len(b)-1] 41 case reflect.Uint16: 42 return binary.BigEndian.Uint16(b[len(b)-2:]) 43 case reflect.Uint32: 44 return binary.BigEndian.Uint32(b[len(b)-4:]) 45 case reflect.Uint64: 46 return binary.BigEndian.Uint64(b[len(b)-8:]) 47 case reflect.Int8: 48 return int8(b[len(b)-1]) 49 case reflect.Int16: 50 return int16(binary.BigEndian.Uint16(b[len(b)-2:])) 51 case reflect.Int32: 52 return int32(binary.BigEndian.Uint32(b[len(b)-4:])) 53 case reflect.Int64: 54 return int64(binary.BigEndian.Uint64(b[len(b)-8:])) 55 default: 56 return new(big.Int).SetBytes(b) 57 } 58 } 59 60 //读BoL 61 func readBool(word []byte) (bool, error) { 62 for _, b := range word[:31] { 63 if b != 0 { 64 return false, errBadBool 65 } 66 } 67 switch word[31] { 68 case 0: 69 return false, nil 70 case 1: 71 return true, nil 72 default: 73 return false, errBadBool 74 } 75 } 76 77 //函数类型只是在末尾带有函数选择签名的地址。 78 //这通过始终将其显示为24个数组(address+sig=24字节)来强制执行该标准。 79 func readFunctionType(t Type, word []byte) (funcTy [24]byte, err error) { 80 if t.T != FunctionTy { 81 return [24]byte{}, fmt.Errorf("abi: invalid type in call to make function type byte array") 82 } 83 if garbage := binary.BigEndian.Uint64(word[24:32]); garbage != 0 { 84 err = fmt.Errorf("abi: got improperly encoded function type, got %v", word) 85 } else { 86 copy(funcTy[:], word[0:24]) 87 } 88 return 89 } 90 91 //通过反射,创建要从中读取的固定数组 92 func readFixedBytes(t Type, word []byte) (interface{}, error) { 93 if t.T != FixedBytesTy { 94 return nil, fmt.Errorf("abi: invalid type in call to make fixed byte array") 95 } 96 //转换 97 array := reflect.New(t.Type).Elem() 98 99 reflect.Copy(array, reflect.ValueOf(word[0:t.Size])) 100 return array.Interface(), nil 101 102 } 103 104 func getFullElemSize(elem *Type) int { 105 //所有其他元素都应计为32(切片有指向各个元素的指针) 106 size := 32 107 //数组将其包装,每个元素的大小相同 108 for elem.T == ArrayTy { 109 size *= elem.Size 110 elem = elem.Elem 111 } 112 return size 113 } 114 115 //迭代解包元素 116 func forEachUnpack(t Type, output []byte, start, size int) (interface{}, error) { 117 if size < 0 { 118 return nil, fmt.Errorf("cannot marshal input to array, size is negative (%d)", size) 119 } 120 if start+32*size > len(output) { 121 return nil, fmt.Errorf("abi: cannot marshal in to go array: offset %d would go over slice boundary (len=%d)", len(output), start+32*size) 122 } 123 124 //此值将成为切片或数组,具体取决于类型 125 var refSlice reflect.Value 126 127 if t.T == SliceTy { 128 //申报我们的切片 129 refSlice = reflect.MakeSlice(t.Type, size, size) 130 } else if t.T == ArrayTy { 131 //声明我们的数组 132 refSlice = reflect.New(t.Type).Elem() 133 } else { 134 return nil, fmt.Errorf("abi: invalid type in array/slice unpacking stage") 135 } 136 137 //数组具有压缩元素,从而导致较长的解包步骤。 138 //每个元素的切片只有32个字节(指向内容)。 139 elemSize := 32 140 if t.T == ArrayTy { 141 elemSize = getFullElemSize(t.Elem) 142 } 143 144 for i, j := start, 0; j < size; i, j = i+elemSize, j+1 { 145 146 inter, err := toGoType(i, *t.Elem, output) 147 if err != nil { 148 return nil, err 149 } 150 151 //将项目附加到反射切片 152 refSlice.Index(j).Set(reflect.ValueOf(inter)) 153 } 154 155 //返回接口 156 return refSlice.Interface(), nil 157 } 158 159 //togotype解析输出字节并递归地分配这些字节的值 160 //符合ABI规范的GO类型。 161 func toGoType(index int, t Type, output []byte) (interface{}, error) { 162 if index+32 > len(output) { 163 return nil, fmt.Errorf("abi: cannot marshal in to go type: length insufficient %d require %d", len(output), index+32) 164 } 165 166 var ( 167 returnOutput []byte 168 begin, end int 169 err error 170 ) 171 172 //如果需要长度前缀,请查找返回的起始单词和大小。 173 if t.requiresLengthPrefix() { 174 begin, end, err = lengthPrefixPointsTo(index, output) 175 if err != nil { 176 return nil, err 177 } 178 } else { 179 returnOutput = output[index : index+32] 180 } 181 182 switch t.T { 183 case SliceTy: 184 return forEachUnpack(t, output, begin, end) 185 case ArrayTy: 186 return forEachUnpack(t, output, index, t.Size) 187 case StringTy: //变量数组写在返回字节的末尾 188 return string(output[begin : begin+end]), nil 189 case IntTy, UintTy: 190 return readInteger(t.Kind, returnOutput), nil 191 case BoolTy: 192 return readBool(returnOutput) 193 case AddressTy: 194 return common.BytesToAddress(returnOutput), nil 195 case HashTy: 196 return common.BytesToHash(returnOutput), nil 197 case BytesTy: 198 return output[begin : begin+end], nil 199 case FixedBytesTy: 200 return readFixedBytes(t, returnOutput) 201 case FunctionTy: 202 return readFunctionType(t, returnOutput) 203 default: 204 return nil, fmt.Errorf("abi: unknown type %v", t.T) 205 } 206 } 207 208 //将一个32字节的切片解释为一个偏移量,然后确定要寻找哪一个指示来解码该类型。 209 func lengthPrefixPointsTo(index int, output []byte) (start int, length int, err error) { 210 bigOffsetEnd := big.NewInt(0).SetBytes(output[index : index+32]) 211 bigOffsetEnd.Add(bigOffsetEnd, common.Big32) 212 outputLength := big.NewInt(int64(len(output))) 213 214 if bigOffsetEnd.Cmp(outputLength) > 0 { 215 return 0, 0, fmt.Errorf("abi: cannot marshal in to go slice: offset %v would go over slice boundary (len=%v)", bigOffsetEnd, outputLength) 216 } 217 218 if bigOffsetEnd.BitLen() > 63 { 219 return 0, 0, fmt.Errorf("abi offset larger than int64: %v", bigOffsetEnd) 220 } 221 222 offsetEnd := int(bigOffsetEnd.Uint64()) 223 lengthBig := big.NewInt(0).SetBytes(output[offsetEnd-32 : offsetEnd]) 224 225 totalSize := big.NewInt(0) 226 totalSize.Add(totalSize, bigOffsetEnd) 227 totalSize.Add(totalSize, lengthBig) 228 if totalSize.BitLen() > 63 { 229 return 0, 0, fmt.Errorf("abi length larger than int64: %v", totalSize) 230 } 231 232 if totalSize.Cmp(outputLength) > 0 { 233 return 0, 0, fmt.Errorf("abi: cannot marshal in to go type: length insufficient %v require %v", outputLength, totalSize) 234 } 235 start = int(bigOffsetEnd.Uint64()) 236 length = int(lengthBig.Uint64()) 237 return 238 }