code: func (ks *KeyStore) processSym(envelope *whisper.Envelope) (*whisper.ReceivedMessage, string, PssAddress, error) {
  	metrics.GetOrRegisterCounter("pss.process.sym", nil).Inc(1)
  
  	for i := ks.symKeyDecryptCacheCursor; i > ks.symKeyDecryptCacheCursor-cap(ks.symKeyDecryptCache) && i > 0; i-- {
  		symkeyid := ks.symKeyDecryptCache[i%cap(ks.symKeyDecryptCache)]
  		symkey, err := ks.w.GetSymKey(*symkeyid)
  		if err != nil {
  			continue
  		}
  		recvmsg, err := envelope.OpenSymmetric(symkey)
  		if err != nil {
  			continue
  		}
  		if !recvmsg.ValidateAndParse() {
  			return nil, "", nil, errors.New("symmetrically encrypted message has invalid signature or is corrupt")
  		}
  		var from PssAddress
  		ks.mx.RLock()
  		if ks.symKeyPool[*symkeyid][Topic(envelope.Topic)] != nil {
  			from = ks.symKeyPool[*symkeyid][Topic(envelope.Topic)].address
  		}
  		ks.mx.RUnlock()
  		ks.symKeyDecryptCacheCursor++
  		ks.symKeyDecryptCache[ks.symKeyDecryptCacheCursor%cap(ks.symKeyDecryptCache)] = symkeyid
  		return recvmsg, *symkeyid, from, nil
  	}
  	return nil, "", nil, errors.New("could not decrypt message")
  }
docs: // Attempt to decrypt, validate and unpack a symmetrically encrypted message.
  // If successful, returns the unpacked whisper ReceivedMessage struct
  // encapsulating the decrypted message, and the whisper backend id
  // of the symmetric key used to decrypt the message.
  // It fails if decryption of the message fails or if the message is corrupted.