github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/whisper/whisperv6/filter.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  //
    10  //
    11  //
    12  //
    13  //
    14  //
    15  //
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  
    25  package whisperv6
    26  
    27  import (
    28  	"crypto/ecdsa"
    29  	"fmt"
    30  	"sync"
    31  
    32  	"github.com/ethereum/go-ethereum/common"
    33  	"github.com/ethereum/go-ethereum/crypto"
    34  	"github.com/ethereum/go-ethereum/log"
    35  )
    36  
    37  //
    38  type Filter struct {
    39  Src        *ecdsa.PublicKey  //
    40  KeyAsym    *ecdsa.PrivateKey //
    41  KeySym     []byte            //
    42  Topics     [][]byte          //
    43  PoW        float64           //
    44  AllowP2P   bool              //
    45  SymKeyHash common.Hash       //
    46  id         string            //
    47  
    48  	Messages map[common.Hash]*ReceivedMessage
    49  	mutex    sync.RWMutex
    50  }
    51  
    52  //
    53  type Filters struct {
    54  	watchers map[string]*Filter
    55  
    56  topicMatcher     map[TopicType]map[*Filter]struct{} //
    57  allTopicsMatcher map[*Filter]struct{}               //
    58  
    59  	whisper *Whisper
    60  	mutex   sync.RWMutex
    61  }
    62  
    63  //
    64  func NewFilters(w *Whisper) *Filters {
    65  	return &Filters{
    66  		watchers:         make(map[string]*Filter),
    67  		topicMatcher:     make(map[TopicType]map[*Filter]struct{}),
    68  		allTopicsMatcher: make(map[*Filter]struct{}),
    69  		whisper:          w,
    70  	}
    71  }
    72  
    73  //
    74  func (fs *Filters) Install(watcher *Filter) (string, error) {
    75  	if watcher.KeySym != nil && watcher.KeyAsym != nil {
    76  		return "", fmt.Errorf("filters must choose between symmetric and asymmetric keys")
    77  	}
    78  
    79  	if watcher.Messages == nil {
    80  		watcher.Messages = make(map[common.Hash]*ReceivedMessage)
    81  	}
    82  
    83  	id, err := GenerateRandomID()
    84  	if err != nil {
    85  		return "", err
    86  	}
    87  
    88  	fs.mutex.Lock()
    89  	defer fs.mutex.Unlock()
    90  
    91  	if fs.watchers[id] != nil {
    92  		return "", fmt.Errorf("failed to generate unique ID")
    93  	}
    94  
    95  	if watcher.expectsSymmetricEncryption() {
    96  		watcher.SymKeyHash = crypto.Keccak256Hash(watcher.KeySym)
    97  	}
    98  
    99  	watcher.id = id
   100  	fs.watchers[id] = watcher
   101  	fs.addTopicMatcher(watcher)
   102  	return id, err
   103  }
   104  
   105  //
   106  //
   107  func (fs *Filters) Uninstall(id string) bool {
   108  	fs.mutex.Lock()
   109  	defer fs.mutex.Unlock()
   110  	if fs.watchers[id] != nil {
   111  		fs.removeFromTopicMatchers(fs.watchers[id])
   112  		delete(fs.watchers, id)
   113  		return true
   114  	}
   115  	return false
   116  }
   117  
   118  //
   119  //
   120  //
   121  func (fs *Filters) addTopicMatcher(watcher *Filter) {
   122  	if len(watcher.Topics) == 0 {
   123  		fs.allTopicsMatcher[watcher] = struct{}{}
   124  	} else {
   125  		for _, t := range watcher.Topics {
   126  			topic := BytesToTopic(t)
   127  			if fs.topicMatcher[topic] == nil {
   128  				fs.topicMatcher[topic] = make(map[*Filter]struct{})
   129  			}
   130  			fs.topicMatcher[topic][watcher] = struct{}{}
   131  		}
   132  	}
   133  }
   134  
   135  //
   136  func (fs *Filters) removeFromTopicMatchers(watcher *Filter) {
   137  	delete(fs.allTopicsMatcher, watcher)
   138  	for _, topic := range watcher.Topics {
   139  		delete(fs.topicMatcher[BytesToTopic(topic)], watcher)
   140  	}
   141  }
   142  
   143  //
   144  //
   145  func (fs *Filters) getWatchersByTopic(topic TopicType) []*Filter {
   146  	res := make([]*Filter, 0, len(fs.allTopicsMatcher))
   147  	for watcher := range fs.allTopicsMatcher {
   148  		res = append(res, watcher)
   149  	}
   150  	for watcher := range fs.topicMatcher[topic] {
   151  		res = append(res, watcher)
   152  	}
   153  	return res
   154  }
   155  
   156  //
   157  func (fs *Filters) Get(id string) *Filter {
   158  	fs.mutex.RLock()
   159  	defer fs.mutex.RUnlock()
   160  	return fs.watchers[id]
   161  }
   162  
   163  //
   164  //
   165  func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) {
   166  	var msg *ReceivedMessage
   167  
   168  	fs.mutex.RLock()
   169  	defer fs.mutex.RUnlock()
   170  
   171  	candidates := fs.getWatchersByTopic(env.Topic)
   172  	for _, watcher := range candidates {
   173  		if p2pMessage && !watcher.AllowP2P {
   174  			log.Trace(fmt.Sprintf("msg [%x], filter [%s]: p2p messages are not allowed", env.Hash(), watcher.id))
   175  			continue
   176  		}
   177  
   178  		var match bool
   179  		if msg != nil {
   180  			match = watcher.MatchMessage(msg)
   181  		} else {
   182  			match = watcher.MatchEnvelope(env)
   183  			if match {
   184  				msg = env.Open(watcher)
   185  				if msg == nil {
   186  					log.Trace("processing message: failed to open", "message", env.Hash().Hex(), "filter", watcher.id)
   187  				}
   188  			} else {
   189  				log.Trace("processing message: does not match", "message", env.Hash().Hex(), "filter", watcher.id)
   190  			}
   191  		}
   192  
   193  		if match && msg != nil {
   194  			log.Trace("processing message: decrypted", "hash", env.Hash().Hex())
   195  			if watcher.Src == nil || IsPubKeyEqual(msg.Src, watcher.Src) {
   196  				watcher.Trigger(msg)
   197  			}
   198  		}
   199  	}
   200  }
   201  
   202  func (f *Filter) expectsAsymmetricEncryption() bool {
   203  	return f.KeyAsym != nil
   204  }
   205  
   206  func (f *Filter) expectsSymmetricEncryption() bool {
   207  	return f.KeySym != nil
   208  }
   209  
   210  //
   211  //
   212  func (f *Filter) Trigger(msg *ReceivedMessage) {
   213  	f.mutex.Lock()
   214  	defer f.mutex.Unlock()
   215  
   216  	if _, exist := f.Messages[msg.EnvelopeHash]; !exist {
   217  		f.Messages[msg.EnvelopeHash] = msg
   218  	}
   219  }
   220  
   221  //
   222  //
   223  func (f *Filter) Retrieve() (all []*ReceivedMessage) {
   224  	f.mutex.Lock()
   225  	defer f.mutex.Unlock()
   226  
   227  	all = make([]*ReceivedMessage, 0, len(f.Messages))
   228  	for _, msg := range f.Messages {
   229  		all = append(all, msg)
   230  	}
   231  
   232  f.Messages = make(map[common.Hash]*ReceivedMessage) //
   233  	return all
   234  }
   235  
   236  //
   237  //
   238  //
   239  //
   240  func (f *Filter) MatchMessage(msg *ReceivedMessage) bool {
   241  	if f.PoW > 0 && msg.PoW < f.PoW {
   242  		return false
   243  	}
   244  
   245  	if f.expectsAsymmetricEncryption() && msg.isAsymmetricEncryption() {
   246  		return IsPubKeyEqual(&f.KeyAsym.PublicKey, msg.Dst)
   247  	} else if f.expectsSymmetricEncryption() && msg.isSymmetricEncryption() {
   248  		return f.SymKeyHash == msg.SymKeyHash
   249  	}
   250  	return false
   251  }
   252  
   253  //
   254  //
   255  //
   256  //
   257  func (f *Filter) MatchEnvelope(envelope *Envelope) bool {
   258  	return f.PoW <= 0 || envelope.pow >= f.PoW
   259  }
   260  
   261  //
   262  func IsPubKeyEqual(a, b *ecdsa.PublicKey) bool {
   263  	if !ValidatePublicKey(a) {
   264  		return false
   265  	} else if !ValidatePublicKey(b) {
   266  		return false
   267  	}
   268  //
   269  	return a.X.Cmp(b.X) == 0 && a.Y.Cmp(b.Y) == 0
   270  }