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