github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/pss/protocol.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  //
    26  
    27  package pss
    28  
    29  import (
    30  	"bytes"
    31  	"fmt"
    32  	"sync"
    33  	"time"
    34  
    35  	"github.com/ethereum/go-ethereum/p2p"
    36  	"github.com/ethereum/go-ethereum/p2p/protocols"
    37  	"github.com/ethereum/go-ethereum/rlp"
    38  	"github.com/ethereum/go-ethereum/swarm/log"
    39  )
    40  
    41  const (
    42  	IsActiveProtocol = true
    43  )
    44  
    45  //
    46  type ProtocolMsg struct {
    47  	Code       uint64
    48  	Size       uint32
    49  	Payload    []byte
    50  	ReceivedAt time.Time
    51  }
    52  
    53  //
    54  func NewProtocolMsg(code uint64, msg interface{}) ([]byte, error) {
    55  
    56  	rlpdata, err := rlp.EncodeToBytes(msg)
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  
    61  //
    62  	smsg := &ProtocolMsg{
    63  		Code:    code,
    64  		Size:    uint32(len(rlpdata)),
    65  		Payload: rlpdata,
    66  	}
    67  
    68  	return rlp.EncodeToBytes(smsg)
    69  }
    70  
    71  //
    72  //
    73  //
    74  type ProtocolParams struct {
    75  	Asymmetric bool
    76  	Symmetric  bool
    77  }
    78  
    79  //
    80  //
    81  //
    82  type PssReadWriter struct {
    83  	*Pss
    84  	LastActive time.Time
    85  	rw         chan p2p.Msg
    86  	spec       *protocols.Spec
    87  	topic      *Topic
    88  	sendFunc   func(string, Topic, []byte) error
    89  	key        string
    90  	closed     bool
    91  }
    92  
    93  //
    94  func (prw *PssReadWriter) ReadMsg() (p2p.Msg, error) {
    95  	msg := <-prw.rw
    96  	log.Trace(fmt.Sprintf("pssrw readmsg: %v", msg))
    97  	return msg, nil
    98  }
    99  
   100  //
   101  func (prw *PssReadWriter) WriteMsg(msg p2p.Msg) error {
   102  	log.Trace("pssrw writemsg", "msg", msg)
   103  	if prw.closed {
   104  		return fmt.Errorf("connection closed")
   105  	}
   106  	rlpdata := make([]byte, msg.Size)
   107  	msg.Payload.Read(rlpdata)
   108  	pmsg, err := rlp.EncodeToBytes(ProtocolMsg{
   109  		Code:    msg.Code,
   110  		Size:    msg.Size,
   111  		Payload: rlpdata,
   112  	})
   113  	if err != nil {
   114  		return err
   115  	}
   116  	return prw.sendFunc(prw.key, *prw.topic, pmsg)
   117  }
   118  
   119  //
   120  func (prw *PssReadWriter) injectMsg(msg p2p.Msg) error {
   121  	log.Trace(fmt.Sprintf("pssrw injectmsg: %v", msg))
   122  	prw.rw <- msg
   123  	return nil
   124  }
   125  
   126  //
   127  type Protocol struct {
   128  	*Pss
   129  	proto        *p2p.Protocol
   130  	topic        *Topic
   131  	spec         *protocols.Spec
   132  	pubKeyRWPool map[string]p2p.MsgReadWriter
   133  	symKeyRWPool map[string]p2p.MsgReadWriter
   134  	Asymmetric   bool
   135  	Symmetric    bool
   136  	RWPoolMu     sync.Mutex
   137  }
   138  
   139  //
   140  //
   141  //
   142  //
   143  //
   144  //
   145  func RegisterProtocol(ps *Pss, topic *Topic, spec *protocols.Spec, targetprotocol *p2p.Protocol, options *ProtocolParams) (*Protocol, error) {
   146  	if !options.Asymmetric && !options.Symmetric {
   147  		return nil, fmt.Errorf("specify at least one of asymmetric or symmetric messaging mode")
   148  	}
   149  	pp := &Protocol{
   150  		Pss:          ps,
   151  		proto:        targetprotocol,
   152  		topic:        topic,
   153  		spec:         spec,
   154  		pubKeyRWPool: make(map[string]p2p.MsgReadWriter),
   155  		symKeyRWPool: make(map[string]p2p.MsgReadWriter),
   156  		Asymmetric:   options.Asymmetric,
   157  		Symmetric:    options.Symmetric,
   158  	}
   159  	return pp, nil
   160  }
   161  
   162  //
   163  //
   164  //
   165  //
   166  //
   167  //
   168  //
   169  //
   170  //
   171  //
   172  //
   173  func (p *Protocol) Handle(msg []byte, peer *p2p.Peer, asymmetric bool, keyid string) error {
   174  	var vrw *PssReadWriter
   175  	if p.Asymmetric != asymmetric && p.Symmetric == !asymmetric {
   176  		return fmt.Errorf("invalid protocol encryption")
   177  	} else if (!p.isActiveSymKey(keyid, *p.topic) && !asymmetric) ||
   178  		(!p.isActiveAsymKey(keyid, *p.topic) && asymmetric) {
   179  
   180  		rw, err := p.AddPeer(peer, *p.topic, asymmetric, keyid)
   181  		if err != nil {
   182  			return err
   183  		} else if rw == nil {
   184  			return fmt.Errorf("handle called on nil MsgReadWriter for new key " + keyid)
   185  		}
   186  		vrw = rw.(*PssReadWriter)
   187  	}
   188  
   189  	pmsg, err := ToP2pMsg(msg)
   190  	if err != nil {
   191  		return fmt.Errorf("could not decode pssmsg")
   192  	}
   193  	if asymmetric {
   194  		if p.pubKeyRWPool[keyid] == nil {
   195  			return fmt.Errorf("handle called on nil MsgReadWriter for key " + keyid)
   196  		}
   197  		vrw = p.pubKeyRWPool[keyid].(*PssReadWriter)
   198  	} else {
   199  		if p.symKeyRWPool[keyid] == nil {
   200  			return fmt.Errorf("handle called on nil MsgReadWriter for key " + keyid)
   201  		}
   202  		vrw = p.symKeyRWPool[keyid].(*PssReadWriter)
   203  	}
   204  	vrw.injectMsg(pmsg)
   205  	return nil
   206  }
   207  
   208  //
   209  func (p *Protocol) isActiveSymKey(key string, topic Topic) bool {
   210  	return p.symKeyRWPool[key] != nil
   211  }
   212  
   213  //
   214  func (p *Protocol) isActiveAsymKey(key string, topic Topic) bool {
   215  	return p.pubKeyRWPool[key] != nil
   216  }
   217  
   218  //
   219  func ToP2pMsg(msg []byte) (p2p.Msg, error) {
   220  	payload := &ProtocolMsg{}
   221  	if err := rlp.DecodeBytes(msg, payload); err != nil {
   222  		return p2p.Msg{}, fmt.Errorf("pss protocol handler unable to decode payload as p2p message: %v", err)
   223  	}
   224  
   225  	return p2p.Msg{
   226  		Code:       payload.Code,
   227  		Size:       uint32(len(payload.Payload)),
   228  		ReceivedAt: time.Now(),
   229  		Payload:    bytes.NewBuffer(payload.Payload),
   230  	}, nil
   231  }
   232  
   233  //
   234  //
   235  //
   236  //
   237  //
   238  func (p *Protocol) AddPeer(peer *p2p.Peer, topic Topic, asymmetric bool, key string) (p2p.MsgReadWriter, error) {
   239  	rw := &PssReadWriter{
   240  		Pss:   p.Pss,
   241  		rw:    make(chan p2p.Msg),
   242  		spec:  p.spec,
   243  		topic: p.topic,
   244  		key:   key,
   245  	}
   246  	if asymmetric {
   247  		rw.sendFunc = p.Pss.SendAsym
   248  	} else {
   249  		rw.sendFunc = p.Pss.SendSym
   250  	}
   251  	if asymmetric {
   252  		p.Pss.pubKeyPoolMu.Lock()
   253  		if _, ok := p.Pss.pubKeyPool[key]; !ok {
   254  			return nil, fmt.Errorf("asym key does not exist: %s", key)
   255  		}
   256  		p.Pss.pubKeyPoolMu.Unlock()
   257  		p.RWPoolMu.Lock()
   258  		p.pubKeyRWPool[key] = rw
   259  		p.RWPoolMu.Unlock()
   260  	} else {
   261  		p.Pss.symKeyPoolMu.Lock()
   262  		if _, ok := p.Pss.symKeyPool[key]; !ok {
   263  			return nil, fmt.Errorf("symkey does not exist: %s", key)
   264  		}
   265  		p.Pss.symKeyPoolMu.Unlock()
   266  		p.RWPoolMu.Lock()
   267  		p.symKeyRWPool[key] = rw
   268  		p.RWPoolMu.Unlock()
   269  	}
   270  	go func() {
   271  		err := p.proto.Run(peer, rw)
   272  		log.Warn(fmt.Sprintf("pss vprotocol quit on %v topic %v: %v", peer, topic, err))
   273  	}()
   274  	return rw, nil
   275  }
   276  
   277  func (p *Protocol) RemovePeer(asymmetric bool, key string) {
   278  	log.Debug("closing pss peer", "asym", asymmetric, "key", key)
   279  	p.RWPoolMu.Lock()
   280  	defer p.RWPoolMu.Unlock()
   281  	if asymmetric {
   282  		rw := p.pubKeyRWPool[key].(*PssReadWriter)
   283  		rw.closed = true
   284  		delete(p.pubKeyRWPool, key)
   285  	} else {
   286  		rw := p.symKeyRWPool[key].(*PssReadWriter)
   287  		rw.closed = true
   288  		delete(p.symKeyRWPool, key)
   289  	}
   290  }
   291  
   292  //
   293  func ProtocolTopic(spec *protocols.Spec) Topic {
   294  	return BytesToTopic([]byte(fmt.Sprintf("%s:%d", spec.Name, spec.Version)))
   295  }