github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/accounts/abi/bind/topics.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 //版权所有2018 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 bind 26 27 import ( 28 "errors" 29 "fmt" 30 "math/big" 31 "reflect" 32 33 "github.com/ethereum/go-ethereum/accounts/abi" 34 "github.com/ethereum/go-ethereum/common" 35 "github.com/ethereum/go-ethereum/crypto" 36 ) 37 38 //maketopics将筛选器查询参数列表转换为筛选器主题集。 39 func makeTopics(query ...[]interface{}) ([][]common.Hash, error) { 40 topics := make([][]common.Hash, len(query)) 41 for i, filter := range query { 42 for _, rule := range filter { 43 var topic common.Hash 44 45 //尝试基于简单类型生成主题 46 switch rule := rule.(type) { 47 case common.Hash: 48 copy(topic[:], rule[:]) 49 case common.Address: 50 copy(topic[common.HashLength-common.AddressLength:], rule[:]) 51 case *big.Int: 52 blob := rule.Bytes() 53 copy(topic[common.HashLength-len(blob):], blob) 54 case bool: 55 if rule { 56 topic[common.HashLength-1] = 1 57 } 58 case int8: 59 blob := big.NewInt(int64(rule)).Bytes() 60 copy(topic[common.HashLength-len(blob):], blob) 61 case int16: 62 blob := big.NewInt(int64(rule)).Bytes() 63 copy(topic[common.HashLength-len(blob):], blob) 64 case int32: 65 blob := big.NewInt(int64(rule)).Bytes() 66 copy(topic[common.HashLength-len(blob):], blob) 67 case int64: 68 blob := big.NewInt(rule).Bytes() 69 copy(topic[common.HashLength-len(blob):], blob) 70 case uint8: 71 blob := new(big.Int).SetUint64(uint64(rule)).Bytes() 72 copy(topic[common.HashLength-len(blob):], blob) 73 case uint16: 74 blob := new(big.Int).SetUint64(uint64(rule)).Bytes() 75 copy(topic[common.HashLength-len(blob):], blob) 76 case uint32: 77 blob := new(big.Int).SetUint64(uint64(rule)).Bytes() 78 copy(topic[common.HashLength-len(blob):], blob) 79 case uint64: 80 blob := new(big.Int).SetUint64(rule).Bytes() 81 copy(topic[common.HashLength-len(blob):], blob) 82 case string: 83 hash := crypto.Keccak256Hash([]byte(rule)) 84 copy(topic[:], hash[:]) 85 case []byte: 86 hash := crypto.Keccak256Hash(rule) 87 copy(topic[:], hash[:]) 88 89 default: 90 //尝试从时髦类型生成主题 91 val := reflect.ValueOf(rule) 92 93 switch { 94 case val.Kind() == reflect.Array && reflect.TypeOf(rule).Elem().Kind() == reflect.Uint8: 95 reflect.Copy(reflect.ValueOf(topic[common.HashLength-val.Len():]), val) 96 97 default: 98 return nil, fmt.Errorf("unsupported indexed type: %T", rule) 99 } 100 } 101 topics[i] = append(topics[i], topic) 102 } 103 } 104 return topics, nil 105 } 106 107 //大批量的主题重构反射类型。 108 var ( 109 reflectHash = reflect.TypeOf(common.Hash{}) 110 reflectAddress = reflect.TypeOf(common.Address{}) 111 reflectBigInt = reflect.TypeOf(new(big.Int)) 112 ) 113 114 //ParseTopics将索引主题字段转换为实际的日志字段值。 115 // 116 //注意,动态类型无法重建,因为它们被映射到keccak256 117 //哈希值作为主题值! 118 func parseTopics(out interface{}, fields abi.Arguments, topics []common.Hash) error { 119 //健全性检查字段和主题是否匹配 120 if len(fields) != len(topics) { 121 return errors.New("topic/field count mismatch") 122 } 123 //遍历所有字段并从主题重新构造它们 124 for _, arg := range fields { 125 if !arg.Indexed { 126 return errors.New("non-indexed field in topic reconstruction") 127 } 128 field := reflect.ValueOf(out).Elem().FieldByName(capitalise(arg.Name)) 129 130 //尝试根据基元类型将主题解析回字段 131 switch field.Kind() { 132 case reflect.Bool: 133 if topics[0][common.HashLength-1] == 1 { 134 field.Set(reflect.ValueOf(true)) 135 } 136 case reflect.Int8: 137 num := new(big.Int).SetBytes(topics[0][:]) 138 field.Set(reflect.ValueOf(int8(num.Int64()))) 139 140 case reflect.Int16: 141 num := new(big.Int).SetBytes(topics[0][:]) 142 field.Set(reflect.ValueOf(int16(num.Int64()))) 143 144 case reflect.Int32: 145 num := new(big.Int).SetBytes(topics[0][:]) 146 field.Set(reflect.ValueOf(int32(num.Int64()))) 147 148 case reflect.Int64: 149 num := new(big.Int).SetBytes(topics[0][:]) 150 field.Set(reflect.ValueOf(num.Int64())) 151 152 case reflect.Uint8: 153 num := new(big.Int).SetBytes(topics[0][:]) 154 field.Set(reflect.ValueOf(uint8(num.Uint64()))) 155 156 case reflect.Uint16: 157 num := new(big.Int).SetBytes(topics[0][:]) 158 field.Set(reflect.ValueOf(uint16(num.Uint64()))) 159 160 case reflect.Uint32: 161 num := new(big.Int).SetBytes(topics[0][:]) 162 field.Set(reflect.ValueOf(uint32(num.Uint64()))) 163 164 case reflect.Uint64: 165 num := new(big.Int).SetBytes(topics[0][:]) 166 field.Set(reflect.ValueOf(num.Uint64())) 167 168 default: 169 // 170 switch field.Type() { 171 case reflectHash: //还包括所有动态类型 172 field.Set(reflect.ValueOf(topics[0])) 173 174 case reflectAddress: 175 var addr common.Address 176 copy(addr[:], topics[0][common.HashLength-common.AddressLength:]) 177 field.Set(reflect.ValueOf(addr)) 178 179 case reflectBigInt: 180 num := new(big.Int).SetBytes(topics[0][:]) 181 field.Set(reflect.ValueOf(num)) 182 183 default: 184 //没有自定义类型,请尝试疯狂 185 switch { 186 case arg.Type.T == abi.FixedBytesTy: 187 reflect.Copy(field, reflect.ValueOf(topics[0][common.HashLength-arg.Type.Size:])) 188 189 default: 190 return fmt.Errorf("unsupported indexed type: %v", arg.Type) 191 } 192 } 193 } 194 topics = topics[1:] 195 } 196 return nil 197 }