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