code: func (cacher *txSenderCacher) recover(signer types.Signer, txs []*types.Transaction) {
  	// If there's nothing to recover, abort
  	if len(txs) == 0 {
  		return
  	}
  	// Ensure we have meaningful task sizes and schedule the recoveries
  	tasks := cacher.threads
  	if len(txs) < tasks*4 {
  		tasks = (len(txs) + 3) / 4
  	}
  	for i := 0; i < tasks; i++ {
  		cacher.tasks <- &txSenderCacherRequest{
  			signer: signer,
  			txs:    txs[i:],
  			inc:    tasks,
  		}
  	}
  }
docs: // recover recovers the senders from a batch of transactions and caches them
  // back into the same data structures. There is no validation being done, nor
  // any reaction to invalid signatures. That is up to calling code later.