code: func (api *SignerAPI) sign(addr common.MixedcaseAddress, req *SignDataRequest, legacyV bool) (hexutil.Bytes, error) {
  
  	// We make the request prior to looking up if we actually have the account, to prevent
  	// account-enumeration via the API
  	res, err := api.UI.ApproveSignData(req)
  	if err != nil {
  		return nil, err
  	}
  	if !res.Approved {
  		return nil, ErrRequestDenied
  	}
  	// Look up the wallet containing the requested signer
  	account := accounts.Account{Address: addr.Address()}
  	wallet, err := api.am.Find(account)
  	if err != nil {
  		return nil, err
  	}
  	pw, err := api.lookupOrQueryPassword(account.Address,
  		"Password for signing",
  		fmt.Sprintf("Please enter password for signing data with account %s", account.Address.Hex()))
  	if err != nil {
  		return nil, err
  	}
  	// Sign the data with the wallet
  	signature, err := wallet.SignDataWithPassphrase(account, pw, req.ContentType, req.Rawdata)
  	if err != nil {
  		return nil, err
  	}
  	if legacyV {
  		signature[64] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper
  	}
  	return signature, nil
  }
docs: // sign receives a request and produces a signature
  // Note, the produced signature conforms to the secp256k1 curve R, S and V values,
  // where the V value will be 27 or 28 for legacy reasons, if legacyV==true.