github.com/aaa256/atlantis@v0.0.0-20210707112435-42ee889287a2/swarm/pss/pss.go (about)

     1  // Copyright 2018 The go-athereum Authors
     2  // This file is part of the go-athereum library.
     3  //
     4  // The go-athereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-athereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-athereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package pss
    18  
    19  import (
    20  	"bytes"
    21  	"crypto/ecdsa"
    22  	"crypto/rand"
    23  	"errors"
    24  	"fmt"
    25  	"sync"
    26  	"time"
    27  
    28  	"github.com/athereum/go-athereum/common"
    29  	"github.com/athereum/go-athereum/crypto"
    30  	"github.com/athereum/go-athereum/metrics"
    31  	"github.com/athereum/go-athereum/p2p"
    32  	"github.com/athereum/go-athereum/p2p/discover"
    33  	"github.com/athereum/go-athereum/p2p/protocols"
    34  	"github.com/athereum/go-athereum/rpc"
    35  	"github.com/athereum/go-athereum/swarm/log"
    36  	"github.com/athereum/go-athereum/swarm/network"
    37  	"github.com/athereum/go-athereum/swarm/pot"
    38  	"github.com/athereum/go-athereum/swarm/storage"
    39  	whisper "github.com/athereum/go-athereum/whisper/whisperv5"
    40  )
    41  
    42  const (
    43  	defaultPaddingByteSize     = 16
    44  	defaultMsgTTL              = time.Second * 120
    45  	defaultDigestCacheTTL      = time.Second * 10
    46  	defaultSymKeyCacheCapacity = 512
    47  	digestLength               = 32 // byte length of digest used for pss cache (currently same as swarm chunk hash)
    48  	defaultWhisperWorkTime     = 3
    49  	defaultWhisperPoW          = 0.0000000001
    50  	defaultMaxMsgSize          = 1024 * 1024
    51  	defaultCleanInterval       = time.Second * 60 * 10
    52  	defaultOutboxCapacity      = 100000
    53  	pssProtocolName            = "pss"
    54  	pssVersion                 = 2
    55  	hasherCount                = 8
    56  )
    57  
    58  var (
    59  	addressLength = len(pot.Address{})
    60  )
    61  
    62  // cache is used for preventing backwards routing
    63  // will also be instrumental in flood guard mechanism
    64  // and mailbox implementation
    65  type pssCacheEntry struct {
    66  	expiresAt time.Time
    67  }
    68  
    69  // abstraction to enable access to p2p.protocols.Peer.Send
    70  type senderPeer interface {
    71  	Info() *p2p.PeerInfo
    72  	ID() discover.NodeID
    73  	Address() []byte
    74  	Send(interface{}) error
    75  }
    76  
    77  // per-key peer related information
    78  // member `protected` prevents garbage collection of the instance
    79  type pssPeer struct {
    80  	lastSeen  time.Time
    81  	address   *PssAddress
    82  	protected bool
    83  }
    84  
    85  // Pss configuration parameters
    86  type PssParams struct {
    87  	MsgTTL              time.Duration
    88  	CacheTTL            time.Duration
    89  	privateKey          *ecdsa.PrivateKey
    90  	SymKeyCacheCapacity int
    91  	AllowRaw            bool // If true, enables sending and receiving messages without builtin pss encryption
    92  }
    93  
    94  // Sane defaults for Pss
    95  func NewPssParams() *PssParams {
    96  	return &PssParams{
    97  		MsgTTL:              defaultMsgTTL,
    98  		CacheTTL:            defaultDigestCacheTTL,
    99  		SymKeyCacheCapacity: defaultSymKeyCacheCapacity,
   100  	}
   101  }
   102  
   103  func (params *PssParams) WithPrivateKey(privatekey *ecdsa.PrivateKey) *PssParams {
   104  	params.privateKey = privatekey
   105  	return params
   106  }
   107  
   108  // Toplevel pss object, takes care of message sending, receiving, decryption and encryption, message handler dispatchers and message forwarding.
   109  //
   110  // Implements node.Service
   111  type Pss struct {
   112  	network.Overlay                   // we can get the overlayaddress from this
   113  	privateKey      *ecdsa.PrivateKey // pss can have it's own independent key
   114  	w               *whisper.Whisper  // key and encryption backend
   115  	auxAPIs         []rpc.API         // builtins (handshake, test) can add APIs
   116  
   117  	// sending and forwarding
   118  	fwdPool         map[string]*protocols.Peer // keep track of all peers sitting on the pssmsg routing layer
   119  	fwdPoolMu       sync.RWMutex
   120  	fwdCache        map[pssDigest]pssCacheEntry // checksum of unique fields from pssmsg mapped to expiry, cache to determine whather to drop msg
   121  	fwdCacheMu      sync.RWMutex
   122  	cacheTTL        time.Duration // how long to keep messages in fwdCache (not implemented)
   123  	msgTTL          time.Duration
   124  	paddingByteSize int
   125  	capstring       string
   126  	outbox          chan *PssMsg
   127  
   128  	// keys and peers
   129  	pubKeyPool                 map[string]map[Topic]*pssPeer // mapping of hex public keys to peer address by topic.
   130  	pubKeyPoolMu               sync.RWMutex
   131  	symKeyPool                 map[string]map[Topic]*pssPeer // mapping of symkeyids to peer address by topic.
   132  	symKeyPoolMu               sync.RWMutex
   133  	symKeyDecryptCache         []*string // fast lookup of symkeys recently used for decryption; last used is on top of stack
   134  	symKeyDecryptCacheCursor   int       // modular cursor pointing to last used, wraps on symKeyDecryptCache array
   135  	symKeyDecryptCacheCapacity int       // max amount of symkeys to keep.
   136  
   137  	// message handling
   138  	handlers   map[Topic]map[*Handler]bool // topic and version based pss payload handlers. See pss.Handle()
   139  	handlersMu sync.RWMutex
   140  	allowRaw   bool
   141  	hashPool   sync.Pool
   142  
   143  	// process
   144  	quitC chan struct{}
   145  }
   146  
   147  func (p *Pss) String() string {
   148  	return fmt.Sprintf("pss: addr %x, pubkey %v", p.BaseAddr(), common.ToHex(crypto.FromECDSAPub(&p.privateKey.PublicKey)))
   149  }
   150  
   151  // Creates a new Pss instance.
   152  //
   153  // In addition to params, it takes a swarm network overlay
   154  // and a FileStore storage for message cache storage.
   155  func NewPss(k network.Overlay, params *PssParams) (*Pss, error) {
   156  	if params.privateKey == nil {
   157  		return nil, errors.New("missing private key for pss")
   158  	}
   159  	cap := p2p.Cap{
   160  		Name:    pssProtocolName,
   161  		Version: pssVersion,
   162  	}
   163  	ps := &Pss{
   164  		Overlay:    k,
   165  		privateKey: params.privateKey,
   166  		w:          whisper.New(&whisper.DefaultConfig),
   167  		quitC:      make(chan struct{}),
   168  
   169  		fwdPool:         make(map[string]*protocols.Peer),
   170  		fwdCache:        make(map[pssDigest]pssCacheEntry),
   171  		cacheTTL:        params.CacheTTL,
   172  		msgTTL:          params.MsgTTL,
   173  		paddingByteSize: defaultPaddingByteSize,
   174  		capstring:       cap.String(),
   175  		outbox:          make(chan *PssMsg, defaultOutboxCapacity),
   176  
   177  		pubKeyPool:                 make(map[string]map[Topic]*pssPeer),
   178  		symKeyPool:                 make(map[string]map[Topic]*pssPeer),
   179  		symKeyDecryptCache:         make([]*string, params.SymKeyCacheCapacity),
   180  		symKeyDecryptCacheCapacity: params.SymKeyCacheCapacity,
   181  
   182  		handlers: make(map[Topic]map[*Handler]bool),
   183  		allowRaw: params.AllowRaw,
   184  		hashPool: sync.Pool{
   185  			New: func() interface{} {
   186  				return storage.MakeHashFunc(storage.DefaultHash)()
   187  			},
   188  		},
   189  	}
   190  
   191  	for i := 0; i < hasherCount; i++ {
   192  		hashfunc := storage.MakeHashFunc(storage.DefaultHash)()
   193  		ps.hashPool.Put(hashfunc)
   194  	}
   195  
   196  	return ps, nil
   197  }
   198  
   199  /////////////////////////////////////////////////////////////////////
   200  // SECTION: node.Service interface
   201  /////////////////////////////////////////////////////////////////////
   202  
   203  func (p *Pss) Start(srv *p2p.Server) error {
   204  	go func() {
   205  		ticker := time.NewTicker(defaultCleanInterval)
   206  		cacheTicker := time.NewTicker(p.cacheTTL)
   207  		defer ticker.Stop()
   208  		defer cacheTicker.Stop()
   209  		for {
   210  			select {
   211  			case <-cacheTicker.C:
   212  				p.cleanFwdCache()
   213  			case <-ticker.C:
   214  				p.cleanKeys()
   215  			case <-p.quitC:
   216  				return
   217  			}
   218  		}
   219  	}()
   220  	go func() {
   221  		for {
   222  			select {
   223  			case msg := <-p.outbox:
   224  				err := p.forward(msg)
   225  				if err != nil {
   226  					log.Error(err.Error())
   227  					metrics.GetOrRegisterCounter("pss.forward.err", nil).Inc(1)
   228  				}
   229  			case <-p.quitC:
   230  				return
   231  			}
   232  		}
   233  	}()
   234  	log.Debug("Started pss", "public key", common.ToHex(crypto.FromECDSAPub(p.PublicKey())))
   235  	return nil
   236  }
   237  
   238  func (p *Pss) Stop() error {
   239  	log.Info("pss shutting down")
   240  	close(p.quitC)
   241  	return nil
   242  }
   243  
   244  var pssSpec = &protocols.Spec{
   245  	Name:       pssProtocolName,
   246  	Version:    pssVersion,
   247  	MaxMsgSize: defaultMaxMsgSize,
   248  	Messages: []interface{}{
   249  		PssMsg{},
   250  	},
   251  }
   252  
   253  func (p *Pss) Protocols() []p2p.Protocol {
   254  	return []p2p.Protocol{
   255  		{
   256  			Name:    pssSpec.Name,
   257  			Version: pssSpec.Version,
   258  			Length:  pssSpec.Length(),
   259  			Run:     p.Run,
   260  		},
   261  	}
   262  }
   263  
   264  func (p *Pss) Run(peer *p2p.Peer, rw p2p.MsgReadWriter) error {
   265  	pp := protocols.NewPeer(peer, rw, pssSpec)
   266  	p.fwdPoolMu.Lock()
   267  	p.fwdPool[peer.Info().ID] = pp
   268  	p.fwdPoolMu.Unlock()
   269  	return pp.Run(p.handlePssMsg)
   270  }
   271  
   272  func (p *Pss) APIs() []rpc.API {
   273  	apis := []rpc.API{
   274  		{
   275  			Namespace: "pss",
   276  			Version:   "1.0",
   277  			Service:   NewAPI(p),
   278  			Public:    true,
   279  		},
   280  	}
   281  	apis = append(apis, p.auxAPIs...)
   282  	return apis
   283  }
   284  
   285  // add API methods to the pss API
   286  // must be run before node is started
   287  func (p *Pss) addAPI(api rpc.API) {
   288  	p.auxAPIs = append(p.auxAPIs, api)
   289  }
   290  
   291  // Returns the swarm overlay address of the pss node
   292  func (p *Pss) BaseAddr() []byte {
   293  	return p.Overlay.BaseAddr()
   294  }
   295  
   296  // Returns the pss node's public key
   297  func (p *Pss) PublicKey() *ecdsa.PublicKey {
   298  	return &p.privateKey.PublicKey
   299  }
   300  
   301  /////////////////////////////////////////////////////////////////////
   302  // SECTION: Message handling
   303  /////////////////////////////////////////////////////////////////////
   304  
   305  // Links a handler function to a Topic
   306  //
   307  // All incoming messages with an envelope Topic matching the
   308  // topic specified will be passed to the given Handler function.
   309  //
   310  // There may be an arbitrary number of handler functions per topic.
   311  //
   312  // Returns a deregister function which needs to be called to
   313  // deregister the handler,
   314  func (p *Pss) Register(topic *Topic, handler Handler) func() {
   315  	p.handlersMu.Lock()
   316  	defer p.handlersMu.Unlock()
   317  	handlers := p.handlers[*topic]
   318  	if handlers == nil {
   319  		handlers = make(map[*Handler]bool)
   320  		p.handlers[*topic] = handlers
   321  	}
   322  	handlers[&handler] = true
   323  	return func() { p.deregister(topic, &handler) }
   324  }
   325  func (p *Pss) deregister(topic *Topic, h *Handler) {
   326  	p.handlersMu.Lock()
   327  	defer p.handlersMu.Unlock()
   328  	handlers := p.handlers[*topic]
   329  	if len(handlers) == 1 {
   330  		delete(p.handlers, *topic)
   331  		return
   332  	}
   333  	delete(handlers, h)
   334  }
   335  
   336  // get all registered handlers for respective topics
   337  func (p *Pss) getHandlers(topic Topic) map[*Handler]bool {
   338  	p.handlersMu.RLock()
   339  	defer p.handlersMu.RUnlock()
   340  	return p.handlers[topic]
   341  }
   342  
   343  // Filters incoming messages for processing or forwarding.
   344  // Check if address partially matches
   345  // If yes, it CAN be for us, and we process it
   346  // Only passes error to pss protocol handler if payload is not valid pssmsg
   347  func (p *Pss) handlePssMsg(msg interface{}) error {
   348  	metrics.GetOrRegisterCounter("pss.handlepssmsg", nil).Inc(1)
   349  
   350  	pssmsg, ok := msg.(*PssMsg)
   351  
   352  	if !ok {
   353  		return fmt.Errorf("invalid message type. Expected *PssMsg, got %T ", msg)
   354  	}
   355  	if int64(pssmsg.Expire) < time.Now().Unix() {
   356  		metrics.GetOrRegisterCounter("pss.expire", nil).Inc(1)
   357  		log.Warn("pss filtered expired message", "from", fmt.Sprintf("%x", p.Overlay.BaseAddr()), "to", fmt.Sprintf("%x", common.ToHex(pssmsg.To)))
   358  		return nil
   359  	}
   360  	if p.checkFwdCache(pssmsg) {
   361  		log.Trace(fmt.Sprintf("pss relay block-cache match (process): FROM %x TO %x", p.Overlay.BaseAddr(), common.ToHex(pssmsg.To)))
   362  		return nil
   363  	}
   364  	p.addFwdCache(pssmsg)
   365  
   366  	if !p.isSelfPossibleRecipient(pssmsg) {
   367  		log.Trace("pss was for someone else :'( ... forwarding", "pss", common.ToHex(p.BaseAddr()))
   368  		return p.enqueue(pssmsg)
   369  	}
   370  
   371  	log.Trace("pss for us, yay! ... let's process!", "pss", common.ToHex(p.BaseAddr()))
   372  	if err := p.process(pssmsg); err != nil {
   373  		qerr := p.enqueue(pssmsg)
   374  		if qerr != nil {
   375  			return fmt.Errorf("process fail: processerr %v, queueerr: %v", err, qerr)
   376  		}
   377  	}
   378  	return nil
   379  
   380  }
   381  
   382  // Entry point to processing a message for which the current node can be the intended recipient.
   383  // Attempts symmetric and asymmetric decryption with stored keys.
   384  // Dispatches message to all handlers matching the message topic
   385  func (p *Pss) process(pssmsg *PssMsg) error {
   386  	metrics.GetOrRegisterCounter("pss.process", nil).Inc(1)
   387  
   388  	var err error
   389  	var recvmsg *whisper.ReceivedMessage
   390  	var payload []byte
   391  	var from *PssAddress
   392  	var asymmetric bool
   393  	var keyid string
   394  	var keyFunc func(envelope *whisper.Envelope) (*whisper.ReceivedMessage, string, *PssAddress, error)
   395  
   396  	envelope := pssmsg.Payload
   397  	psstopic := Topic(envelope.Topic)
   398  	if pssmsg.isRaw() {
   399  		if !p.allowRaw {
   400  			return errors.New("raw message support disabled")
   401  		}
   402  		payload = pssmsg.Payload.Data
   403  	} else {
   404  		if pssmsg.isSym() {
   405  			keyFunc = p.processSym
   406  		} else {
   407  			asymmetric = true
   408  			keyFunc = p.processAsym
   409  		}
   410  
   411  		recvmsg, keyid, from, err = keyFunc(envelope)
   412  		if err != nil {
   413  			return errors.New("Decryption failed")
   414  		}
   415  		payload = recvmsg.Payload
   416  	}
   417  
   418  	if len(pssmsg.To) < addressLength {
   419  		if err := p.enqueue(pssmsg); err != nil {
   420  			return err
   421  		}
   422  	}
   423  	p.executeHandlers(psstopic, payload, from, asymmetric, keyid)
   424  
   425  	return nil
   426  
   427  }
   428  
   429  func (p *Pss) executeHandlers(topic Topic, payload []byte, from *PssAddress, asymmetric bool, keyid string) {
   430  	handlers := p.getHandlers(topic)
   431  	nid, _ := discover.HexID("0x00") // this hack is needed to satisfy the p2p method
   432  	peer := p2p.NewPeer(nid, fmt.Sprintf("%x", from), []p2p.Cap{})
   433  	for f := range handlers {
   434  		err := (*f)(payload, peer, asymmetric, keyid)
   435  		if err != nil {
   436  			log.Warn("Pss handler %p failed: %v", f, err)
   437  		}
   438  	}
   439  }
   440  
   441  // will return false if using partial address
   442  func (p *Pss) isSelfRecipient(msg *PssMsg) bool {
   443  	return bytes.Equal(msg.To, p.Overlay.BaseAddr())
   444  }
   445  
   446  // test match of leftmost bytes in given message to node's overlay address
   447  func (p *Pss) isSelfPossibleRecipient(msg *PssMsg) bool {
   448  	local := p.Overlay.BaseAddr()
   449  	return bytes.Equal(msg.To[:], local[:len(msg.To)])
   450  }
   451  
   452  /////////////////////////////////////////////////////////////////////
   453  // SECTION: Encryption
   454  /////////////////////////////////////////////////////////////////////
   455  
   456  // Links a peer ECDSA public key to a topic
   457  //
   458  // This is required for asymmetric message exchange
   459  // on the given topic
   460  //
   461  // The value in `address` will be used as a routing hint for the
   462  // public key / topic association
   463  func (p *Pss) SetPeerPublicKey(pubkey *ecdsa.PublicKey, topic Topic, address *PssAddress) error {
   464  	pubkeybytes := crypto.FromECDSAPub(pubkey)
   465  	if len(pubkeybytes) == 0 {
   466  		return fmt.Errorf("invalid public key: %v", pubkey)
   467  	}
   468  	pubkeyid := common.ToHex(pubkeybytes)
   469  	psp := &pssPeer{
   470  		address: address,
   471  	}
   472  	p.pubKeyPoolMu.Lock()
   473  	if _, ok := p.pubKeyPool[pubkeyid]; !ok {
   474  		p.pubKeyPool[pubkeyid] = make(map[Topic]*pssPeer)
   475  	}
   476  	p.pubKeyPool[pubkeyid][topic] = psp
   477  	p.pubKeyPoolMu.Unlock()
   478  	log.Trace("added pubkey", "pubkeyid", pubkeyid, "topic", topic, "address", common.ToHex(*address))
   479  	return nil
   480  }
   481  
   482  // Automatically generate a new symkey for a topic and address hint
   483  func (p *Pss) generateSymmetricKey(topic Topic, address *PssAddress, addToCache bool) (string, error) {
   484  	keyid, err := p.w.GenerateSymKey()
   485  	if err != nil {
   486  		return "", err
   487  	}
   488  	p.addSymmetricKeyToPool(keyid, topic, address, addToCache, false)
   489  	return keyid, nil
   490  }
   491  
   492  // Links a peer symmetric key (arbitrary byte sequence) to a topic
   493  //
   494  // This is required for symmetrically encrypted message exchange
   495  // on the given topic
   496  //
   497  // The key is stored in the whisper backend.
   498  //
   499  // If addtocache is set to true, the key will be added to the cache of keys
   500  // used to attempt symmetric decryption of incoming messages.
   501  //
   502  // Returns a string id that can be used to retrieve the key bytes
   503  // from the whisper backend (see pss.GetSymmetricKey())
   504  func (p *Pss) SetSymmetricKey(key []byte, topic Topic, address *PssAddress, addtocache bool) (string, error) {
   505  	return p.setSymmetricKey(key, topic, address, addtocache, true)
   506  }
   507  
   508  func (p *Pss) setSymmetricKey(key []byte, topic Topic, address *PssAddress, addtocache bool, protected bool) (string, error) {
   509  	keyid, err := p.w.AddSymKeyDirect(key)
   510  	if err != nil {
   511  		return "", err
   512  	}
   513  	p.addSymmetricKeyToPool(keyid, topic, address, addtocache, protected)
   514  	return keyid, nil
   515  }
   516  
   517  // adds a symmetric key to the pss key pool, and optionally adds the key
   518  // to the collection of keys used to attempt symmetric decryption of
   519  // incoming messages
   520  func (p *Pss) addSymmetricKeyToPool(keyid string, topic Topic, address *PssAddress, addtocache bool, protected bool) {
   521  	psp := &pssPeer{
   522  		address:   address,
   523  		protected: protected,
   524  	}
   525  	p.symKeyPoolMu.Lock()
   526  	if _, ok := p.symKeyPool[keyid]; !ok {
   527  		p.symKeyPool[keyid] = make(map[Topic]*pssPeer)
   528  	}
   529  	p.symKeyPool[keyid][topic] = psp
   530  	p.symKeyPoolMu.Unlock()
   531  	if addtocache {
   532  		p.symKeyDecryptCacheCursor++
   533  		p.symKeyDecryptCache[p.symKeyDecryptCacheCursor%cap(p.symKeyDecryptCache)] = &keyid
   534  	}
   535  	key, _ := p.GetSymmetricKey(keyid)
   536  	log.Trace("added symkey", "symkeyid", keyid, "symkey", common.ToHex(key), "topic", topic, "address", fmt.Sprintf("%p", address), "cache", addtocache)
   537  }
   538  
   539  // Returns a symmetric key byte seqyence stored in the whisper backend
   540  // by its unique id
   541  //
   542  // Passes on the error value from the whisper backend
   543  func (p *Pss) GetSymmetricKey(symkeyid string) ([]byte, error) {
   544  	symkey, err := p.w.GetSymKey(symkeyid)
   545  	if err != nil {
   546  		return nil, err
   547  	}
   548  	return symkey, nil
   549  }
   550  
   551  // Returns all recorded topic and address combination for a specific public key
   552  func (p *Pss) GetPublickeyPeers(keyid string) (topic []Topic, address []PssAddress, err error) {
   553  	p.pubKeyPoolMu.RLock()
   554  	defer p.pubKeyPoolMu.RUnlock()
   555  	for t, peer := range p.pubKeyPool[keyid] {
   556  		topic = append(topic, t)
   557  		address = append(address, *peer.address)
   558  	}
   559  
   560  	return topic, address, nil
   561  }
   562  
   563  func (p *Pss) getPeerAddress(keyid string, topic Topic) (PssAddress, error) {
   564  	p.pubKeyPoolMu.RLock()
   565  	defer p.pubKeyPoolMu.RUnlock()
   566  	if peers, ok := p.pubKeyPool[keyid]; ok {
   567  		if t, ok := peers[topic]; ok {
   568  			return *t.address, nil
   569  		}
   570  	}
   571  	return nil, fmt.Errorf("peer with pubkey %s, topic %x not found", keyid, topic)
   572  }
   573  
   574  // Attempt to decrypt, validate and unpack a
   575  // symmetrically encrypted message
   576  // If successful, returns the unpacked whisper ReceivedMessage struct
   577  // encapsulating the decrypted message, and the whisper backend id
   578  // of the symmetric key used to decrypt the message.
   579  // It fails if decryption of the message fails or if the message is corrupted
   580  func (p *Pss) processSym(envelope *whisper.Envelope) (*whisper.ReceivedMessage, string, *PssAddress, error) {
   581  	metrics.GetOrRegisterCounter("pss.process.sym", nil).Inc(1)
   582  
   583  	for i := p.symKeyDecryptCacheCursor; i > p.symKeyDecryptCacheCursor-cap(p.symKeyDecryptCache) && i > 0; i-- {
   584  		symkeyid := p.symKeyDecryptCache[i%cap(p.symKeyDecryptCache)]
   585  		symkey, err := p.w.GetSymKey(*symkeyid)
   586  		if err != nil {
   587  			continue
   588  		}
   589  		recvmsg, err := envelope.OpenSymmetric(symkey)
   590  		if err != nil {
   591  			continue
   592  		}
   593  		if !recvmsg.Validate() {
   594  			return nil, "", nil, fmt.Errorf("symmetrically encrypted message has invalid signature or is corrupt")
   595  		}
   596  		p.symKeyPoolMu.Lock()
   597  		from := p.symKeyPool[*symkeyid][Topic(envelope.Topic)].address
   598  		p.symKeyPoolMu.Unlock()
   599  		p.symKeyDecryptCacheCursor++
   600  		p.symKeyDecryptCache[p.symKeyDecryptCacheCursor%cap(p.symKeyDecryptCache)] = symkeyid
   601  		return recvmsg, *symkeyid, from, nil
   602  	}
   603  	return nil, "", nil, fmt.Errorf("could not decrypt message")
   604  }
   605  
   606  // Attempt to decrypt, validate and unpack an
   607  // asymmetrically encrypted message
   608  // If successful, returns the unpacked whisper ReceivedMessage struct
   609  // encapsulating the decrypted message, and the byte representation of
   610  // the public key used to decrypt the message.
   611  // It fails if decryption of message fails, or if the message is corrupted
   612  func (p *Pss) processAsym(envelope *whisper.Envelope) (*whisper.ReceivedMessage, string, *PssAddress, error) {
   613  	metrics.GetOrRegisterCounter("pss.process.asym", nil).Inc(1)
   614  
   615  	recvmsg, err := envelope.OpenAsymmetric(p.privateKey)
   616  	if err != nil {
   617  		return nil, "", nil, fmt.Errorf("could not decrypt message: %s", err)
   618  	}
   619  	// check signature (if signed), strip padding
   620  	if !recvmsg.Validate() {
   621  		return nil, "", nil, fmt.Errorf("invalid message")
   622  	}
   623  	pubkeyid := common.ToHex(crypto.FromECDSAPub(recvmsg.Src))
   624  	var from *PssAddress
   625  	p.pubKeyPoolMu.Lock()
   626  	if p.pubKeyPool[pubkeyid][Topic(envelope.Topic)] != nil {
   627  		from = p.pubKeyPool[pubkeyid][Topic(envelope.Topic)].address
   628  	}
   629  	p.pubKeyPoolMu.Unlock()
   630  	return recvmsg, pubkeyid, from, nil
   631  }
   632  
   633  // Symkey garbage collection
   634  // a key is removed if:
   635  // - it is not marked as protected
   636  // - it is not in the incoming decryption cache
   637  func (p *Pss) cleanKeys() (count int) {
   638  	for keyid, peertopics := range p.symKeyPool {
   639  		var expiredtopics []Topic
   640  		for topic, psp := range peertopics {
   641  			if psp.protected {
   642  				continue
   643  			}
   644  
   645  			var match bool
   646  			for i := p.symKeyDecryptCacheCursor; i > p.symKeyDecryptCacheCursor-cap(p.symKeyDecryptCache) && i > 0; i-- {
   647  				cacheid := p.symKeyDecryptCache[i%cap(p.symKeyDecryptCache)]
   648  				if *cacheid == keyid {
   649  					match = true
   650  				}
   651  			}
   652  			if !match {
   653  				expiredtopics = append(expiredtopics, topic)
   654  			}
   655  		}
   656  		for _, topic := range expiredtopics {
   657  			p.symKeyPoolMu.Lock()
   658  			delete(p.symKeyPool[keyid], topic)
   659  			log.Trace("symkey cleanup deletion", "symkeyid", keyid, "topic", topic, "val", p.symKeyPool[keyid])
   660  			p.symKeyPoolMu.Unlock()
   661  			count++
   662  		}
   663  	}
   664  	return
   665  }
   666  
   667  /////////////////////////////////////////////////////////////////////
   668  // SECTION: Message sending
   669  /////////////////////////////////////////////////////////////////////
   670  
   671  func (p *Pss) enqueue(msg *PssMsg) error {
   672  	select {
   673  	case p.outbox <- msg:
   674  		return nil
   675  	default:
   676  	}
   677  
   678  	metrics.GetOrRegisterCounter("pss.enqueue.outbox.full", nil).Inc(1)
   679  	return errors.New("outbox full")
   680  }
   681  
   682  // Send a raw message (any encryption is responsibility of calling client)
   683  //
   684  // Will fail if raw messages are disallowed
   685  func (p *Pss) SendRaw(address PssAddress, topic Topic, msg []byte) error {
   686  	if !p.allowRaw {
   687  		return errors.New("Raw messages not enabled")
   688  	}
   689  	pssMsgParams := &msgParams{
   690  		raw: true,
   691  	}
   692  	payload := &whisper.Envelope{
   693  		Data:  msg,
   694  		Topic: whisper.TopicType(topic),
   695  	}
   696  	pssMsg := newPssMsg(pssMsgParams)
   697  	pssMsg.To = address
   698  	pssMsg.Expire = uint32(time.Now().Add(p.msgTTL).Unix())
   699  	pssMsg.Payload = payload
   700  	p.addFwdCache(pssMsg)
   701  	return p.enqueue(pssMsg)
   702  }
   703  
   704  // Send a message using symmetric encryption
   705  //
   706  // Fails if the key id does not match any of the stored symmetric keys
   707  func (p *Pss) SendSym(symkeyid string, topic Topic, msg []byte) error {
   708  	symkey, err := p.GetSymmetricKey(symkeyid)
   709  	if err != nil {
   710  		return fmt.Errorf("missing valid send symkey %s: %v", symkeyid, err)
   711  	}
   712  	p.symKeyPoolMu.Lock()
   713  	psp, ok := p.symKeyPool[symkeyid][topic]
   714  	p.symKeyPoolMu.Unlock()
   715  	if !ok {
   716  		return fmt.Errorf("invalid topic '%s' for symkey '%s'", topic.String(), symkeyid)
   717  	} else if psp.address == nil {
   718  		return fmt.Errorf("no address hint for topic '%s' symkey '%s'", topic.String(), symkeyid)
   719  	}
   720  	err = p.send(*psp.address, topic, msg, false, symkey)
   721  	return err
   722  }
   723  
   724  // Send a message using asymmetric encryption
   725  //
   726  // Fails if the key id does not match any in of the stored public keys
   727  func (p *Pss) SendAsym(pubkeyid string, topic Topic, msg []byte) error {
   728  	if _, err := crypto.UnmarshalPubkey(common.FromHex(pubkeyid)); err != nil {
   729  		return fmt.Errorf("Cannot unmarshal pubkey: %x", pubkeyid)
   730  	}
   731  	p.pubKeyPoolMu.Lock()
   732  	psp, ok := p.pubKeyPool[pubkeyid][topic]
   733  	p.pubKeyPoolMu.Unlock()
   734  	if !ok {
   735  		return fmt.Errorf("invalid topic '%s' for pubkey '%s'", topic.String(), pubkeyid)
   736  	} else if psp.address == nil {
   737  		return fmt.Errorf("no address hint for topic '%s' pubkey '%s'", topic.String(), pubkeyid)
   738  	}
   739  	go func() {
   740  		p.send(*psp.address, topic, msg, true, common.FromHex(pubkeyid))
   741  	}()
   742  	return nil
   743  }
   744  
   745  // Send is payload agnostic, and will accept any byte slice as payload
   746  // It generates an whisper envelope for the specified recipient and topic,
   747  // and wraps the message payload in it.
   748  // TODO: Implement proper message padding
   749  func (p *Pss) send(to []byte, topic Topic, msg []byte, asymmetric bool, key []byte) error {
   750  	metrics.GetOrRegisterCounter("pss.send", nil).Inc(1)
   751  
   752  	if key == nil || bytes.Equal(key, []byte{}) {
   753  		return fmt.Errorf("Zero length key passed to pss send")
   754  	}
   755  	padding := make([]byte, p.paddingByteSize)
   756  	c, err := rand.Read(padding)
   757  	if err != nil {
   758  		return err
   759  	} else if c < p.paddingByteSize {
   760  		return fmt.Errorf("invalid padding length: %d", c)
   761  	}
   762  	wparams := &whisper.MessageParams{
   763  		TTL:      defaultWhisperTTL,
   764  		Src:      p.privateKey,
   765  		Topic:    whisper.TopicType(topic),
   766  		WorkTime: defaultWhisperWorkTime,
   767  		PoW:      defaultWhisperPoW,
   768  		Payload:  msg,
   769  		Padding:  padding,
   770  	}
   771  	if asymmetric {
   772  		pk, err := crypto.UnmarshalPubkey(key)
   773  		if err != nil {
   774  			return fmt.Errorf("Cannot unmarshal pubkey: %x", key)
   775  		}
   776  		wparams.Dst = pk
   777  	} else {
   778  		wparams.KeySym = key
   779  	}
   780  	// set up outgoing message container, which does encryption and envelope wrapping
   781  	woutmsg, err := whisper.NewSentMessage(wparams)
   782  	if err != nil {
   783  		return fmt.Errorf("failed to generate whisper message encapsulation: %v", err)
   784  	}
   785  	// performs encryption.
   786  	// Does NOT perform / performs negligible PoW due to very low difficulty setting
   787  	// after this the message is ready for sending
   788  	envelope, err := woutmsg.Wrap(wparams)
   789  	if err != nil {
   790  		return fmt.Errorf("failed to perform whisper encryption: %v", err)
   791  	}
   792  	log.Trace("pssmsg whisper done", "env", envelope, "wparams payload", common.ToHex(wparams.Payload), "to", common.ToHex(to), "asym", asymmetric, "key", common.ToHex(key))
   793  
   794  	// prepare for devp2p transport
   795  	pssMsgParams := &msgParams{
   796  		sym: !asymmetric,
   797  	}
   798  	pssMsg := newPssMsg(pssMsgParams)
   799  	pssMsg.To = to
   800  	pssMsg.Expire = uint32(time.Now().Add(p.msgTTL).Unix())
   801  	pssMsg.Payload = envelope
   802  	return p.enqueue(pssMsg)
   803  }
   804  
   805  // Forwards a pss message to the peer(s) closest to the to recipient address in the PssMsg struct
   806  // The recipient address can be of any length, and the byte slice will be matched to the MSB slice
   807  // of the peer address of the equivalent length.
   808  func (p *Pss) forward(msg *PssMsg) error {
   809  	metrics.GetOrRegisterCounter("pss.forward", nil).Inc(1)
   810  
   811  	to := make([]byte, addressLength)
   812  	copy(to[:len(msg.To)], msg.To)
   813  
   814  	// send with kademlia
   815  	// find the closest peer to the recipient and attempt to send
   816  	sent := 0
   817  	p.Overlay.EachConn(to, 256, func(op network.OverlayConn, po int, isproxbin bool) bool {
   818  		// we need p2p.protocols.Peer.Send
   819  		// cast and resolve
   820  		sp, ok := op.(senderPeer)
   821  		if !ok {
   822  			log.Crit("Pss cannot use kademlia peer type")
   823  			return false
   824  		}
   825  		info := sp.Info()
   826  
   827  		// check if the peer is running pss
   828  		var ispss bool
   829  		for _, cap := range info.Caps {
   830  			if cap == p.capstring {
   831  				ispss = true
   832  				break
   833  			}
   834  		}
   835  		if !ispss {
   836  			log.Trace("peer doesn't have matching pss capabilities, skipping", "peer", info.Name, "caps", info.Caps)
   837  			return true
   838  		}
   839  
   840  		// get the protocol peer from the forwarding peer cache
   841  		sendMsg := fmt.Sprintf("MSG TO %x FROM %x VIA %x", to, p.BaseAddr(), op.Address())
   842  		p.fwdPoolMu.RLock()
   843  		pp := p.fwdPool[sp.Info().ID]
   844  		p.fwdPoolMu.RUnlock()
   845  
   846  		// attempt to send the message
   847  		err := pp.Send(msg)
   848  		if err != nil {
   849  			metrics.GetOrRegisterCounter("pss.pp.send.error", nil).Inc(1)
   850  			log.Error(err.Error())
   851  			return true
   852  		}
   853  		sent++
   854  		log.Trace(fmt.Sprintf("%v: successfully forwarded", sendMsg))
   855  
   856  		// continue forwarding if:
   857  		// - if the peer is end recipient but the full address has not been disclosed
   858  		// - if the peer address matches the partial address fully
   859  		// - if the peer is in proxbin
   860  		if len(msg.To) < addressLength && bytes.Equal(msg.To, op.Address()[:len(msg.To)]) {
   861  			log.Trace(fmt.Sprintf("Pss keep forwarding: Partial address + full partial match"))
   862  			return true
   863  		} else if isproxbin {
   864  			log.Trace(fmt.Sprintf("%x is in proxbin, keep forwarding", common.ToHex(op.Address())))
   865  			return true
   866  		}
   867  		// at this point we stop forwarding, and the state is as follows:
   868  		// - the peer is end recipient and we have full address
   869  		// - we are not in proxbin (directed routing)
   870  		// - partial addresses don't fully match
   871  		return false
   872  	})
   873  
   874  	if sent == 0 {
   875  		log.Debug("unable to forward to any peers")
   876  		if err := p.enqueue(msg); err != nil {
   877  			metrics.GetOrRegisterCounter("pss.forward.enqueue.error", nil).Inc(1)
   878  			log.Error(err.Error())
   879  			return err
   880  		}
   881  	}
   882  
   883  	// cache the message
   884  	p.addFwdCache(msg)
   885  	return nil
   886  }
   887  
   888  /////////////////////////////////////////////////////////////////////
   889  // SECTION: Caching
   890  /////////////////////////////////////////////////////////////////////
   891  
   892  // cleanFwdCache is used to periodically remove expired entries from the forward cache
   893  func (p *Pss) cleanFwdCache() {
   894  	metrics.GetOrRegisterCounter("pss.cleanfwdcache", nil).Inc(1)
   895  	p.fwdCacheMu.Lock()
   896  	defer p.fwdCacheMu.Unlock()
   897  	for k, v := range p.fwdCache {
   898  		if v.expiresAt.Before(time.Now()) {
   899  			delete(p.fwdCache, k)
   900  		}
   901  	}
   902  }
   903  
   904  // add a message to the cache
   905  func (p *Pss) addFwdCache(msg *PssMsg) error {
   906  	metrics.GetOrRegisterCounter("pss.addfwdcache", nil).Inc(1)
   907  
   908  	var entry pssCacheEntry
   909  	var ok bool
   910  
   911  	p.fwdCacheMu.Lock()
   912  	defer p.fwdCacheMu.Unlock()
   913  
   914  	digest := p.digest(msg)
   915  	if entry, ok = p.fwdCache[digest]; !ok {
   916  		entry = pssCacheEntry{}
   917  	}
   918  	entry.expiresAt = time.Now().Add(p.cacheTTL)
   919  	p.fwdCache[digest] = entry
   920  	return nil
   921  }
   922  
   923  // check if message is in the cache
   924  func (p *Pss) checkFwdCache(msg *PssMsg) bool {
   925  	p.fwdCacheMu.Lock()
   926  	defer p.fwdCacheMu.Unlock()
   927  
   928  	digest := p.digest(msg)
   929  	entry, ok := p.fwdCache[digest]
   930  	if ok {
   931  		if entry.expiresAt.After(time.Now()) {
   932  			log.Trace("unexpired cache", "digest", fmt.Sprintf("%x", digest))
   933  			metrics.GetOrRegisterCounter("pss.checkfwdcache.unexpired", nil).Inc(1)
   934  			return true
   935  		}
   936  		metrics.GetOrRegisterCounter("pss.checkfwdcache.expired", nil).Inc(1)
   937  	}
   938  	return false
   939  }
   940  
   941  // Digest of message
   942  func (p *Pss) digest(msg *PssMsg) pssDigest {
   943  	hasher := p.hashPool.Get().(storage.SwarmHash)
   944  	defer p.hashPool.Put(hasher)
   945  	hasher.Reset()
   946  	hasher.Write(msg.serialize())
   947  	digest := pssDigest{}
   948  	key := hasher.Sum(nil)
   949  	copy(digest[:], key[:digestLength])
   950  	return digest
   951  }