github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/whisper/whisperv5/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 19:16:46</date>
    10  //</624450124365434880>
    11  
    12  
    13  package whisperv5
    14  
    15  import (
    16  	"crypto/ecdsa"
    17  	"fmt"
    18  	"sync"
    19  
    20  	"github.com/ethereum/go-ethereum/common"
    21  	"github.com/ethereum/go-ethereum/crypto"
    22  	"github.com/ethereum/go-ethereum/log"
    23  )
    24  
    25  type Filter struct {
    26  Src        *ecdsa.PublicKey  //邮件的发件人
    27  KeyAsym    *ecdsa.PrivateKey //收件人的私钥
    28  KeySym     []byte            //与主题关联的键
    29  Topics     [][]byte          //筛选邮件的主题
    30  PoW        float64           //耳语规范中所述的工作证明
    31  AllowP2P   bool              //指示此筛选器是否对直接对等消息感兴趣
    32  SymKeyHash common.Hash       //优化所需的对称密钥的keccak256hash
    33  
    34  	Messages map[common.Hash]*ReceivedMessage
    35  	mutex    sync.RWMutex
    36  }
    37  
    38  type Filters struct {
    39  	watchers map[string]*Filter
    40  	whisper  *Whisper
    41  	mutex    sync.RWMutex
    42  }
    43  
    44  func NewFilters(w *Whisper) *Filters {
    45  	return &Filters{
    46  		watchers: make(map[string]*Filter),
    47  		whisper:  w,
    48  	}
    49  }
    50  
    51  func (fs *Filters) Install(watcher *Filter) (string, error) {
    52  	if watcher.Messages == nil {
    53  		watcher.Messages = make(map[common.Hash]*ReceivedMessage)
    54  	}
    55  
    56  	id, err := GenerateRandomID()
    57  	if err != nil {
    58  		return "", err
    59  	}
    60  
    61  	fs.mutex.Lock()
    62  	defer fs.mutex.Unlock()
    63  
    64  	if fs.watchers[id] != nil {
    65  		return "", fmt.Errorf("failed to generate unique ID")
    66  	}
    67  
    68  	if watcher.expectsSymmetricEncryption() {
    69  		watcher.SymKeyHash = crypto.Keccak256Hash(watcher.KeySym)
    70  	}
    71  
    72  	fs.watchers[id] = watcher
    73  	return id, err
    74  }
    75  
    76  func (fs *Filters) Uninstall(id string) bool {
    77  	fs.mutex.Lock()
    78  	defer fs.mutex.Unlock()
    79  	if fs.watchers[id] != nil {
    80  		delete(fs.watchers, id)
    81  		return true
    82  	}
    83  	return false
    84  }
    85  
    86  func (fs *Filters) Get(id string) *Filter {
    87  	fs.mutex.RLock()
    88  	defer fs.mutex.RUnlock()
    89  	return fs.watchers[id]
    90  }
    91  
    92  func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) {
    93  	var msg *ReceivedMessage
    94  
    95  	fs.mutex.RLock()
    96  	defer fs.mutex.RUnlock()
    97  
    98  i := -1 //仅用于日志信息
    99  	for _, watcher := range fs.watchers {
   100  		i++
   101  		if p2pMessage && !watcher.AllowP2P {
   102  			log.Trace(fmt.Sprintf("msg [%x], filter [%d]: p2p messages are not allowed", env.Hash(), i))
   103  			continue
   104  		}
   105  
   106  		var match bool
   107  		if msg != nil {
   108  			match = watcher.MatchMessage(msg)
   109  		} else {
   110  			match = watcher.MatchEnvelope(env)
   111  			if match {
   112  				msg = env.Open(watcher)
   113  				if msg == nil {
   114  					log.Trace("processing message: failed to open", "message", env.Hash().Hex(), "filter", i)
   115  				}
   116  			} else {
   117  				log.Trace("processing message: does not match", "message", env.Hash().Hex(), "filter", i)
   118  			}
   119  		}
   120  
   121  		if match && msg != nil {
   122  			log.Trace("processing message: decrypted", "hash", env.Hash().Hex())
   123  			if watcher.Src == nil || IsPubKeyEqual(msg.Src, watcher.Src) {
   124  				watcher.Trigger(msg)
   125  			}
   126  		}
   127  	}
   128  }
   129  
   130  func (f *Filter) processEnvelope(env *Envelope) *ReceivedMessage {
   131  	if f.MatchEnvelope(env) {
   132  		msg := env.Open(f)
   133  		if msg != nil {
   134  			return msg
   135  		} else {
   136  			log.Trace("processing envelope: failed to open", "hash", env.Hash().Hex())
   137  		}
   138  	} else {
   139  		log.Trace("processing envelope: does not match", "hash", env.Hash().Hex())
   140  	}
   141  	return nil
   142  }
   143  
   144  func (f *Filter) expectsAsymmetricEncryption() bool {
   145  	return f.KeyAsym != nil
   146  }
   147  
   148  func (f *Filter) expectsSymmetricEncryption() bool {
   149  	return f.KeySym != nil
   150  }
   151  
   152  func (f *Filter) Trigger(msg *ReceivedMessage) {
   153  	f.mutex.Lock()
   154  	defer f.mutex.Unlock()
   155  
   156  	if _, exist := f.Messages[msg.EnvelopeHash]; !exist {
   157  		f.Messages[msg.EnvelopeHash] = msg
   158  	}
   159  }
   160  
   161  func (f *Filter) Retrieve() (all []*ReceivedMessage) {
   162  	f.mutex.Lock()
   163  	defer f.mutex.Unlock()
   164  
   165  	all = make([]*ReceivedMessage, 0, len(f.Messages))
   166  	for _, msg := range f.Messages {
   167  		all = append(all, msg)
   168  	}
   169  
   170  f.Messages = make(map[common.Hash]*ReceivedMessage) //删除旧邮件
   171  	return all
   172  }
   173  
   174  func (f *Filter) MatchMessage(msg *ReceivedMessage) bool {
   175  	if f.PoW > 0 && msg.PoW < f.PoW {
   176  		return false
   177  	}
   178  
   179  	if f.expectsAsymmetricEncryption() && msg.isAsymmetricEncryption() {
   180  		return IsPubKeyEqual(&f.KeyAsym.PublicKey, msg.Dst) && f.MatchTopic(msg.Topic)
   181  	} else if f.expectsSymmetricEncryption() && msg.isSymmetricEncryption() {
   182  		return f.SymKeyHash == msg.SymKeyHash && f.MatchTopic(msg.Topic)
   183  	}
   184  	return false
   185  }
   186  
   187  func (f *Filter) MatchEnvelope(envelope *Envelope) bool {
   188  	if f.PoW > 0 && envelope.pow < f.PoW {
   189  		return false
   190  	}
   191  
   192  	if f.expectsAsymmetricEncryption() && envelope.isAsymmetric() {
   193  		return f.MatchTopic(envelope.Topic)
   194  	} else if f.expectsSymmetricEncryption() && envelope.IsSymmetric() {
   195  		return f.MatchTopic(envelope.Topic)
   196  	}
   197  	return false
   198  }
   199  
   200  func (f *Filter) MatchTopic(topic TopicType) bool {
   201  	if len(f.Topics) == 0 {
   202  //任何主题匹配
   203  		return true
   204  	}
   205  
   206  	for _, bt := range f.Topics {
   207  		if matchSingleTopic(topic, bt) {
   208  			return true
   209  		}
   210  	}
   211  	return false
   212  }
   213  
   214  func matchSingleTopic(topic TopicType, bt []byte) bool {
   215  	if len(bt) > TopicLength {
   216  		bt = bt[:TopicLength]
   217  	}
   218  
   219  	if len(bt) == 0 {
   220  		return false
   221  	}
   222  
   223  	for j, b := range bt {
   224  		if topic[j] != b {
   225  			return false
   226  		}
   227  	}
   228  	return true
   229  }
   230  
   231  func IsPubKeyEqual(a, b *ecdsa.PublicKey) bool {
   232  	if !ValidatePublicKey(a) {
   233  		return false
   234  	} else if !ValidatePublicKey(b) {
   235  		return false
   236  	}
   237  //曲线总是一样的,只要比较点
   238  	return a.X.Cmp(b.X) == 0 && a.Y.Cmp(b.Y) == 0
   239  }
   240