code: func (lsi *LastSignedInfo) signVote(sign tmCryptoSigner, chainID string, vote *types.Vote) error {
  	height, round, step := vote.Height, vote.Round, voteToStep(vote)
  	signBytes := vote.SignBytes(chainID)
  
  	sameHRS, err := lsi.checkHRS(height, round, step)
  	if err != nil {
  		return err
  	}
  
  	// We might crash before writing to the wal,
  	// causing us to try to re-sign for the same HRS.
  	// If signbytes are the same, use the last signature.
  	// If they only differ by timestamp, use last timestamp and signature
  	// Otherwise, return error
  	if sameHRS {
  		if bytes.Equal(signBytes, lsi.SignBytes) {
  			vote.Signature = lsi.Signature
  		} else if timestamp, ok := checkVotesOnlyDifferByTimestamp(lsi.SignBytes, signBytes); ok {
  			vote.Timestamp = timestamp
  			vote.Signature = lsi.Signature
  		} else {
  			err = fmt.Errorf("Conflicting data")
  		}
  		return err
  	}
  
  	// It passed the checks. Sign the vote
  	sig := sign(signBytes)
  	lsi.saveSigned(height, round, step, signBytes, sig)
  	vote.Signature = sig
  	return nil
  }
docs: // signVote checks if the vote is good to sign and sets the vote signature.
  // It may need to set the timestamp as well if the vote is otherwise the same as
  // a previously signed vote (ie. we crashed after signing but before the vote hit the WAL).