github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/pss/notify/notify.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  package notify
    10  
    11  import (
    12  	"crypto/ecdsa"
    13  	"fmt"
    14  	"sync"
    15  
    16  	"github.com/ethereum/go-ethereum/common/hexutil"
    17  	"github.com/ethereum/go-ethereum/crypto"
    18  	"github.com/ethereum/go-ethereum/p2p"
    19  	"github.com/ethereum/go-ethereum/rlp"
    20  	"github.com/ethereum/go-ethereum/swarm/log"
    21  	"github.com/ethereum/go-ethereum/swarm/pss"
    22  )
    23  
    24  const (
    25  //
    26  	MsgCodeStart = iota
    27  
    28  //
    29  	MsgCodeNotifyWithKey
    30  
    31  //
    32  	MsgCodeNotify
    33  
    34  //
    35  	MsgCodeStop
    36  	MsgCodeMax
    37  )
    38  
    39  const (
    40  	DefaultAddressLength = 1
    41  symKeyLength         = 32 //
    42  )
    43  
    44  var (
    45  //
    46  	controlTopic = pss.Topic{0x00, 0x00, 0x00, 0x01}
    47  )
    48  
    49  //
    50  //
    51  //
    52  //
    53  type Msg struct {
    54  	Code       byte
    55  	Name       []byte
    56  	Payload    []byte
    57  	namestring string
    58  }
    59  
    60  //
    61  func NewMsg(code byte, name string, payload []byte) *Msg {
    62  	return &Msg{
    63  		Code:       code,
    64  		Name:       []byte(name),
    65  		Payload:    payload,
    66  		namestring: name,
    67  	}
    68  }
    69  
    70  //
    71  func NewMsgFromPayload(payload []byte) (*Msg, error) {
    72  	msg := &Msg{}
    73  	err := rlp.DecodeBytes(payload, msg)
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  	msg.namestring = string(msg.Name)
    78  	return msg, nil
    79  }
    80  
    81  //
    82  type sendBin struct {
    83  	address  pss.PssAddress
    84  	symKeyId string
    85  	count    int
    86  }
    87  
    88  //
    89  //
    90  type notifier struct {
    91  	bins      map[string]*sendBin
    92  topic     pss.Topic //
    93  threshold int       //
    94  	updateC   <-chan []byte
    95  	quitC     chan struct{}
    96  }
    97  
    98  func (n *notifier) removeSubscription() {
    99  	n.quitC <- struct{}{}
   100  }
   101  
   102  //
   103  type subscription struct {
   104  	pubkeyId string
   105  	address  pss.PssAddress
   106  	handler  func(string, []byte) error
   107  }
   108  
   109  //
   110  type Controller struct {
   111  	pss           *pss.Pss
   112  	notifiers     map[string]*notifier
   113  	subscriptions map[string]*subscription
   114  	mu            sync.Mutex
   115  }
   116  
   117  //
   118  func NewController(ps *pss.Pss) *Controller {
   119  	ctrl := &Controller{
   120  		pss:           ps,
   121  		notifiers:     make(map[string]*notifier),
   122  		subscriptions: make(map[string]*subscription),
   123  	}
   124  	ctrl.pss.Register(&controlTopic, ctrl.Handler)
   125  	return ctrl
   126  }
   127  
   128  //
   129  //
   130  func (c *Controller) IsActive(name string) bool {
   131  	c.mu.Lock()
   132  	defer c.mu.Unlock()
   133  	return c.isActive(name)
   134  }
   135  
   136  func (c *Controller) isActive(name string) bool {
   137  	_, ok := c.notifiers[name]
   138  	return ok
   139  }
   140  
   141  //
   142  //
   143  //
   144  //
   145  func (c *Controller) Subscribe(name string, pubkey *ecdsa.PublicKey, address pss.PssAddress, handler func(string, []byte) error) error {
   146  	c.mu.Lock()
   147  	defer c.mu.Unlock()
   148  	msg := NewMsg(MsgCodeStart, name, c.pss.BaseAddr())
   149  	c.pss.SetPeerPublicKey(pubkey, controlTopic, &address)
   150  	pubkeyId := hexutil.Encode(crypto.FromECDSAPub(pubkey))
   151  	smsg, err := rlp.EncodeToBytes(msg)
   152  	if err != nil {
   153  		return err
   154  	}
   155  	err = c.pss.SendAsym(pubkeyId, controlTopic, smsg)
   156  	if err != nil {
   157  		return err
   158  	}
   159  	c.subscriptions[name] = &subscription{
   160  		pubkeyId: pubkeyId,
   161  		address:  address,
   162  		handler:  handler,
   163  	}
   164  	return nil
   165  }
   166  
   167  //
   168  //
   169  func (c *Controller) Unsubscribe(name string) error {
   170  	c.mu.Lock()
   171  	defer c.mu.Unlock()
   172  	sub, ok := c.subscriptions[name]
   173  	if !ok {
   174  		return fmt.Errorf("Unknown subscription '%s'", name)
   175  	}
   176  	msg := NewMsg(MsgCodeStop, name, sub.address)
   177  	smsg, err := rlp.EncodeToBytes(msg)
   178  	if err != nil {
   179  		return err
   180  	}
   181  	err = c.pss.SendAsym(sub.pubkeyId, controlTopic, smsg)
   182  	if err != nil {
   183  		return err
   184  	}
   185  	delete(c.subscriptions, name)
   186  	return nil
   187  }
   188  
   189  //
   190  //
   191  //
   192  //
   193  //
   194  func (c *Controller) NewNotifier(name string, threshold int, updateC <-chan []byte) (func(), error) {
   195  	c.mu.Lock()
   196  	if c.isActive(name) {
   197  		c.mu.Unlock()
   198  		return nil, fmt.Errorf("Notification service %s already exists in controller", name)
   199  	}
   200  	quitC := make(chan struct{})
   201  	c.notifiers[name] = &notifier{
   202  		bins:      make(map[string]*sendBin),
   203  		topic:     pss.BytesToTopic([]byte(name)),
   204  		threshold: threshold,
   205  		updateC:   updateC,
   206  		quitC:     quitC,
   207  //
   208  	}
   209  	c.mu.Unlock()
   210  	go func() {
   211  		for {
   212  			select {
   213  			case <-quitC:
   214  				return
   215  			case data := <-updateC:
   216  				c.notify(name, data)
   217  			}
   218  		}
   219  	}()
   220  
   221  	return c.notifiers[name].removeSubscription, nil
   222  }
   223  
   224  //
   225  //
   226  func (c *Controller) RemoveNotifier(name string) error {
   227  	c.mu.Lock()
   228  	defer c.mu.Unlock()
   229  	currentNotifier, ok := c.notifiers[name]
   230  	if !ok {
   231  		return fmt.Errorf("Unknown notification service %s", name)
   232  	}
   233  	currentNotifier.removeSubscription()
   234  	delete(c.notifiers, name)
   235  	return nil
   236  }
   237  
   238  //
   239  //
   240  //
   241  //
   242  func (c *Controller) notify(name string, data []byte) error {
   243  	c.mu.Lock()
   244  	defer c.mu.Unlock()
   245  	if !c.isActive(name) {
   246  		return fmt.Errorf("Notification service %s doesn't exist", name)
   247  	}
   248  	msg := NewMsg(MsgCodeNotify, name, data)
   249  	smsg, err := rlp.EncodeToBytes(msg)
   250  	if err != nil {
   251  		return err
   252  	}
   253  	for _, m := range c.notifiers[name].bins {
   254  		log.Debug("sending pss notify", "name", name, "addr", fmt.Sprintf("%x", m.address), "topic", fmt.Sprintf("%x", c.notifiers[name].topic), "data", data)
   255  		go func(m *sendBin) {
   256  			err = c.pss.SendSym(m.symKeyId, c.notifiers[name].topic, smsg)
   257  			if err != nil {
   258  				log.Warn("Failed to send notify to addr %x: %v", m.address, err)
   259  			}
   260  		}(m)
   261  	}
   262  	return nil
   263  }
   264  
   265  //
   266  //
   267  //
   268  func (c *Controller) addToBin(ntfr *notifier, address []byte) (symKeyId string, pssAddress pss.PssAddress, err error) {
   269  
   270  //
   271  	if len(address) > ntfr.threshold {
   272  		address = address[:ntfr.threshold]
   273  	}
   274  
   275  	pssAddress = pss.PssAddress(address)
   276  	hexAddress := fmt.Sprintf("%x", address)
   277  	currentBin, ok := ntfr.bins[hexAddress]
   278  	if ok {
   279  		currentBin.count++
   280  		symKeyId = currentBin.symKeyId
   281  	} else {
   282  		symKeyId, err = c.pss.GenerateSymmetricKey(ntfr.topic, &pssAddress, false)
   283  		if err != nil {
   284  			return "", nil, err
   285  		}
   286  		ntfr.bins[hexAddress] = &sendBin{
   287  			address:  address,
   288  			symKeyId: symKeyId,
   289  			count:    1,
   290  		}
   291  	}
   292  	return symKeyId, pssAddress, nil
   293  }
   294  
   295  func (c *Controller) handleStartMsg(msg *Msg, keyid string) (err error) {
   296  
   297  	keyidbytes, err := hexutil.Decode(keyid)
   298  	if err != nil {
   299  		return err
   300  	}
   301  	pubkey, err := crypto.UnmarshalPubkey(keyidbytes)
   302  	if err != nil {
   303  		return err
   304  	}
   305  
   306  //
   307  	currentNotifier, ok := c.notifiers[msg.namestring]
   308  	if !ok {
   309  		return fmt.Errorf("Subscribe attempted on unknown resource '%s'", msg.namestring)
   310  	}
   311  
   312  //
   313  	symKeyId, pssAddress, err := c.addToBin(currentNotifier, msg.Payload)
   314  	if err != nil {
   315  		return err
   316  	}
   317  
   318  //
   319  	symkey, err := c.pss.GetSymmetricKey(symKeyId)
   320  	if err != nil {
   321  		return err
   322  	}
   323  	err = c.pss.SetPeerPublicKey(pubkey, controlTopic, &pssAddress)
   324  	if err != nil {
   325  		return err
   326  	}
   327  
   328  //
   329  	notify := []byte{}
   330  	replyMsg := NewMsg(MsgCodeNotifyWithKey, msg.namestring, make([]byte, len(notify)+symKeyLength))
   331  	copy(replyMsg.Payload, notify)
   332  	copy(replyMsg.Payload[len(notify):], symkey)
   333  	sReplyMsg, err := rlp.EncodeToBytes(replyMsg)
   334  	if err != nil {
   335  		return err
   336  	}
   337  	return c.pss.SendAsym(keyid, controlTopic, sReplyMsg)
   338  }
   339  
   340  func (c *Controller) handleNotifyWithKeyMsg(msg *Msg) error {
   341  	symkey := msg.Payload[len(msg.Payload)-symKeyLength:]
   342  	topic := pss.BytesToTopic(msg.Name)
   343  
   344  //
   345  	updaterAddr := pss.PssAddress([]byte{})
   346  	c.pss.SetSymmetricKey(symkey, topic, &updaterAddr, true)
   347  	c.pss.Register(&topic, c.Handler)
   348  	return c.subscriptions[msg.namestring].handler(msg.namestring, msg.Payload[:len(msg.Payload)-symKeyLength])
   349  }
   350  
   351  func (c *Controller) handleStopMsg(msg *Msg) error {
   352  //
   353  	currentNotifier, ok := c.notifiers[msg.namestring]
   354  	if !ok {
   355  		return fmt.Errorf("Unsubscribe attempted on unknown resource '%s'", msg.namestring)
   356  	}
   357  
   358  //
   359  	address := msg.Payload
   360  	if len(msg.Payload) > currentNotifier.threshold {
   361  		address = address[:currentNotifier.threshold]
   362  	}
   363  
   364  //
   365  	hexAddress := fmt.Sprintf("%x", address)
   366  	currentBin, ok := currentNotifier.bins[hexAddress]
   367  	if !ok {
   368  		return fmt.Errorf("found no active bin for address %s", hexAddress)
   369  	}
   370  	currentBin.count--
   371  if currentBin.count == 0 { //
   372  		delete(currentNotifier.bins, hexAddress)
   373  	}
   374  	return nil
   375  }
   376  
   377  //
   378  //
   379  func (c *Controller) Handler(smsg []byte, p *p2p.Peer, asymmetric bool, keyid string) error {
   380  	c.mu.Lock()
   381  	defer c.mu.Unlock()
   382  	log.Debug("notify controller handler", "keyid", keyid)
   383  
   384  //
   385  	msg, err := NewMsgFromPayload(smsg)
   386  	if err != nil {
   387  		return err
   388  	}
   389  
   390  	switch msg.Code {
   391  	case MsgCodeStart:
   392  		return c.handleStartMsg(msg, keyid)
   393  	case MsgCodeNotifyWithKey:
   394  		return c.handleNotifyWithKeyMsg(msg)
   395  	case MsgCodeNotify:
   396  		return c.subscriptions[msg.namestring].handler(msg.namestring, msg.Payload)
   397  	case MsgCodeStop:
   398  		return c.handleStopMsg(msg)
   399  	}
   400  
   401  	return fmt.Errorf("Invalid message code: %d", msg.Code)
   402  }