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