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