github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/pss/protocol.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:44</date>
    10  //</624450116886990848>
    11  
    12  
    13  //+建设!NOPSS协议
    14  
    15  package pss
    16  
    17  import (
    18  	"bytes"
    19  	"fmt"
    20  	"sync"
    21  	"time"
    22  
    23  	"github.com/ethereum/go-ethereum/p2p"
    24  	"github.com/ethereum/go-ethereum/p2p/protocols"
    25  	"github.com/ethereum/go-ethereum/rlp"
    26  	"github.com/ethereum/go-ethereum/swarm/log"
    27  )
    28  
    29  const (
    30  	IsActiveProtocol = true
    31  )
    32  
    33  //用于通过PSS传输的devp2p协议消息的方便包装器
    34  type ProtocolMsg struct {
    35  	Code       uint64
    36  	Size       uint32
    37  	Payload    []byte
    38  	ReceivedAt time.Time
    39  }
    40  
    41  //创建protocolmsg
    42  func NewProtocolMsg(code uint64, msg interface{}) ([]byte, error) {
    43  
    44  	rlpdata, err := rlp.EncodeToBytes(msg)
    45  	if err != nil {
    46  		return nil, err
    47  	}
    48  
    49  //TODO验证嵌套结构不能在RLP中使用
    50  	smsg := &ProtocolMsg{
    51  		Code:    code,
    52  		Size:    uint32(len(rlpdata)),
    53  		Payload: rlpdata,
    54  	}
    55  
    56  	return rlp.EncodeToBytes(smsg)
    57  }
    58  
    59  //要传递到新协议实例的协议选项
    60  //
    61  //参数指定允许哪些加密方案
    62  type ProtocolParams struct {
    63  	Asymmetric bool
    64  	Symmetric  bool
    65  }
    66  
    67  //PSSReadWriter用devp2p协议发送/接收桥接PSS发送/接收
    68  //
    69  //实现p2p.msgreadwriter
    70  type PssReadWriter struct {
    71  	*Pss
    72  	LastActive time.Time
    73  	rw         chan p2p.Msg
    74  	spec       *protocols.Spec
    75  	topic      *Topic
    76  	sendFunc   func(string, Topic, []byte) error
    77  	key        string
    78  	closed     bool
    79  }
    80  
    81  //实现p2p.msgreader
    82  func (prw *PssReadWriter) ReadMsg() (p2p.Msg, error) {
    83  	msg := <-prw.rw
    84  	log.Trace(fmt.Sprintf("pssrw readmsg: %v", msg))
    85  	return msg, nil
    86  }
    87  
    88  //实现p2p.msgWriter
    89  func (prw *PssReadWriter) WriteMsg(msg p2p.Msg) error {
    90  	log.Trace("pssrw writemsg", "msg", msg)
    91  	if prw.closed {
    92  		return fmt.Errorf("connection closed")
    93  	}
    94  	rlpdata := make([]byte, msg.Size)
    95  	msg.Payload.Read(rlpdata)
    96  	pmsg, err := rlp.EncodeToBytes(ProtocolMsg{
    97  		Code:    msg.Code,
    98  		Size:    msg.Size,
    99  		Payload: rlpdata,
   100  	})
   101  	if err != nil {
   102  		return err
   103  	}
   104  	return prw.sendFunc(prw.key, *prw.topic, pmsg)
   105  }
   106  
   107  //将p2p.msg注入msgreadwriter,使其出现在关联的p2p.msgreader上
   108  func (prw *PssReadWriter) injectMsg(msg p2p.Msg) error {
   109  	log.Trace(fmt.Sprintf("pssrw injectmsg: %v", msg))
   110  	prw.rw <- msg
   111  	return nil
   112  }
   113  
   114  //PSS上仿真devp2p的方便对象
   115  type Protocol struct {
   116  	*Pss
   117  	proto        *p2p.Protocol
   118  	topic        *Topic
   119  	spec         *protocols.Spec
   120  	pubKeyRWPool map[string]p2p.MsgReadWriter
   121  	symKeyRWPool map[string]p2p.MsgReadWriter
   122  	Asymmetric   bool
   123  	Symmetric    bool
   124  	RWPoolMu     sync.Mutex
   125  }
   126  
   127  //在特定PSS主题上激活devp2p仿真
   128  //
   129  //必须指定一个或两个加密方案。如果
   130  //只指定了一个,协议将无效
   131  //对于另一个,并将使消息处理程序
   132  //返回错误
   133  func RegisterProtocol(ps *Pss, topic *Topic, spec *protocols.Spec, targetprotocol *p2p.Protocol, options *ProtocolParams) (*Protocol, error) {
   134  	if !options.Asymmetric && !options.Symmetric {
   135  		return nil, fmt.Errorf("specify at least one of asymmetric or symmetric messaging mode")
   136  	}
   137  	pp := &Protocol{
   138  		Pss:          ps,
   139  		proto:        targetprotocol,
   140  		topic:        topic,
   141  		spec:         spec,
   142  		pubKeyRWPool: make(map[string]p2p.MsgReadWriter),
   143  		symKeyRWPool: make(map[string]p2p.MsgReadWriter),
   144  		Asymmetric:   options.Asymmetric,
   145  		Symmetric:    options.Symmetric,
   146  	}
   147  	return pp, nil
   148  }
   149  
   150  //通过devp2p仿真接收消息的通用处理程序
   151  //
   152  //将传递给pss.register()。
   153  //
   154  //将在新的传入对等机上运行协议,前提是
   155  //消息的加密密钥在内部具有匹配项
   156  //PSS密钥池
   157  //
   158  //如果协议对消息加密方案无效,则失败,
   159  //如果添加新对等端失败,或者消息不是序列化的
   160  //p2p.msg(如果它是从这个对象发送的,它将一直是这样)。
   161  func (p *Protocol) Handle(msg []byte, peer *p2p.Peer, asymmetric bool, keyid string) error {
   162  	var vrw *PssReadWriter
   163  	if p.Asymmetric != asymmetric && p.Symmetric == !asymmetric {
   164  		return fmt.Errorf("invalid protocol encryption")
   165  	} else if (!p.isActiveSymKey(keyid, *p.topic) && !asymmetric) ||
   166  		(!p.isActiveAsymKey(keyid, *p.topic) && asymmetric) {
   167  
   168  		rw, err := p.AddPeer(peer, *p.topic, asymmetric, keyid)
   169  		if err != nil {
   170  			return err
   171  		} else if rw == nil {
   172  			return fmt.Errorf("handle called on nil MsgReadWriter for new key " + keyid)
   173  		}
   174  		vrw = rw.(*PssReadWriter)
   175  	}
   176  
   177  	pmsg, err := ToP2pMsg(msg)
   178  	if err != nil {
   179  		return fmt.Errorf("could not decode pssmsg")
   180  	}
   181  	if asymmetric {
   182  		if p.pubKeyRWPool[keyid] == nil {
   183  			return fmt.Errorf("handle called on nil MsgReadWriter for key " + keyid)
   184  		}
   185  		vrw = p.pubKeyRWPool[keyid].(*PssReadWriter)
   186  	} else {
   187  		if p.symKeyRWPool[keyid] == nil {
   188  			return fmt.Errorf("handle called on nil MsgReadWriter for key " + keyid)
   189  		}
   190  		vrw = p.symKeyRWPool[keyid].(*PssReadWriter)
   191  	}
   192  	vrw.injectMsg(pmsg)
   193  	return nil
   194  }
   195  
   196  //检查(对等)对称密钥当前是否已注册到此主题
   197  func (p *Protocol) isActiveSymKey(key string, topic Topic) bool {
   198  	return p.symKeyRWPool[key] != nil
   199  }
   200  
   201  //检查(对等)非对称密钥当前是否已注册到此主题
   202  func (p *Protocol) isActiveAsymKey(key string, topic Topic) bool {
   203  	return p.pubKeyRWPool[key] != nil
   204  }
   205  
   206  //创建p2p.msg的序列化(非缓冲)版本,用于专门的内部p2p.msgreadwriter实现
   207  func ToP2pMsg(msg []byte) (p2p.Msg, error) {
   208  	payload := &ProtocolMsg{}
   209  	if err := rlp.DecodeBytes(msg, payload); err != nil {
   210  		return p2p.Msg{}, fmt.Errorf("pss protocol handler unable to decode payload as p2p message: %v", err)
   211  	}
   212  
   213  	return p2p.Msg{
   214  		Code:       payload.Code,
   215  		Size:       uint32(len(payload.Payload)),
   216  		ReceivedAt: time.Now(),
   217  		Payload:    bytes.NewBuffer(payload.Payload),
   218  	}, nil
   219  }
   220  
   221  //在指定的对等机上运行模拟的PSS协议,
   222  //链接到特定主题
   223  //`key`和'asymmetric`指定什么加密密钥
   224  //将对等机链接到。
   225  //在添加对等机之前,密钥必须存在于PSS存储区中。
   226  func (p *Protocol) AddPeer(peer *p2p.Peer, topic Topic, asymmetric bool, key string) (p2p.MsgReadWriter, error) {
   227  	rw := &PssReadWriter{
   228  		Pss:   p.Pss,
   229  		rw:    make(chan p2p.Msg),
   230  		spec:  p.spec,
   231  		topic: p.topic,
   232  		key:   key,
   233  	}
   234  	if asymmetric {
   235  		rw.sendFunc = p.Pss.SendAsym
   236  	} else {
   237  		rw.sendFunc = p.Pss.SendSym
   238  	}
   239  	if asymmetric {
   240  		p.Pss.pubKeyPoolMu.Lock()
   241  		if _, ok := p.Pss.pubKeyPool[key]; !ok {
   242  			return nil, fmt.Errorf("asym key does not exist: %s", key)
   243  		}
   244  		p.Pss.pubKeyPoolMu.Unlock()
   245  		p.RWPoolMu.Lock()
   246  		p.pubKeyRWPool[key] = rw
   247  		p.RWPoolMu.Unlock()
   248  	} else {
   249  		p.Pss.symKeyPoolMu.Lock()
   250  		if _, ok := p.Pss.symKeyPool[key]; !ok {
   251  			return nil, fmt.Errorf("symkey does not exist: %s", key)
   252  		}
   253  		p.Pss.symKeyPoolMu.Unlock()
   254  		p.RWPoolMu.Lock()
   255  		p.symKeyRWPool[key] = rw
   256  		p.RWPoolMu.Unlock()
   257  	}
   258  	go func() {
   259  		err := p.proto.Run(peer, rw)
   260  		log.Warn(fmt.Sprintf("pss vprotocol quit on %v topic %v: %v", peer, topic, err))
   261  	}()
   262  	return rw, nil
   263  }
   264  
   265  func (p *Protocol) RemovePeer(asymmetric bool, key string) {
   266  	log.Debug("closing pss peer", "asym", asymmetric, "key", key)
   267  	p.RWPoolMu.Lock()
   268  	defer p.RWPoolMu.Unlock()
   269  	if asymmetric {
   270  		rw := p.pubKeyRWPool[key].(*PssReadWriter)
   271  		rw.closed = true
   272  		delete(p.pubKeyRWPool, key)
   273  	} else {
   274  		rw := p.symKeyRWPool[key].(*PssReadWriter)
   275  		rw.closed = true
   276  		delete(p.symKeyRWPool, key)
   277  	}
   278  }
   279  
   280  //协议说明符到主题的统一翻译
   281  func ProtocolTopic(spec *protocols.Spec) Topic {
   282  	return BytesToTopic([]byte(fmt.Sprintf("%s:%d", spec.Name, spec.Version)))
   283  }
   284