code: func (lsi *LastSignedInfo) signProposal(sign tmCryptoSigner, chainID string, proposal *types.Proposal) error {
  	height, round, step := proposal.Height, proposal.Round, stepPropose
  	signBytes := proposal.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) {
  			proposal.Signature = lsi.Signature
  		} else if timestamp, ok := checkProposalsOnlyDifferByTimestamp(lsi.SignBytes, signBytes); ok {
  			proposal.Timestamp = timestamp
  			proposal.Signature = lsi.Signature
  		} else {
  			err = fmt.Errorf("Conflicting data")
  		}
  		return err
  	}
  
  	// It passed the checks. Sign the proposal
  	sig := sign(signBytes)
  	lsi.saveSigned(height, round, step, signBytes, sig)
  	proposal.Signature = sig
  	return nil
  }
docs: // signProposal checks if the proposal is good to sign and sets the proposal signature.
  // It may need to set the timestamp as well if the proposal is otherwise the same as
  // a previously signed proposal ie. we crashed after signing but before the proposal hit the WAL).