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  }