From 4934d04c67f9cf9a0d2880839827081680cf994c Mon Sep 17 00:00:00 2001 From: Wisdom Arerosuoghene Date: Thu, 5 Sep 2019 00:13:47 +0100 Subject: [PATCH] refactor shared code into reusable method --- controllers/main.go | 230 ++++++++++++-------------------------------- 1 file changed, 64 insertions(+), 166 deletions(-) diff --git a/controllers/main.go b/controllers/main.go index 60562800..6e9bede0 100644 --- a/controllers/main.go +++ b/controllers/main.go @@ -300,66 +300,10 @@ func (controller *MainController) APIAddress(c web.C, r *http.Request) ([]string return nil, codes.InvalidArgument, "address error", err } - // Get the ticket address for this user - pooladdress, err := controller.TicketAddressForUserID(int(user.Id)) - if err != nil { - log.Errorf("unable to derive ticket address: %v", err) - return nil, codes.Unavailable, "system error", errors.New("unable to process wallet commands") - } - - poolValidateAddress, err := controller.Cfg.StakepooldServers.ValidateAddress(pooladdress) - if err != nil { - log.Errorf("unable to validate address: %v", err) - return nil, codes.Unavailable, "system error", errors.New("unable to process wallet commands") - } - if !poolValidateAddress.IsMine { - log.Errorf("unable to validate ismine for pool ticket address: %s", - pooladdress.String()) - return nil, codes.Unavailable, "system error", errors.New("unable to process wallet commands") - } - - poolPubKeyAddr := poolValidateAddress.PubKeyAddr - - if _, err = dcrutil.DecodeAddress(poolPubKeyAddr); err != nil { - return nil, codes.Unavailable, "system error", errors.New("unable to process wallet commands") - } - - createMultiSig, err := controller.Cfg.StakepooldServers.CreateMultisig([]string{poolPubKeyAddr, userPubKeyAddr}) - if err != nil { + if purchaseInfo := controller.generateTicketPurchaseInfo(dbMap, user, userPubKeyAddr); purchaseInfo == nil { return nil, codes.Unavailable, "system error", errors.New("unable to process wallet commands") } - // Serialize the redeem script (hex string -> []byte) - serializedScript, err := hex.DecodeString(createMultiSig.RedeemScript) - if err != nil { - return nil, codes.Unavailable, "system error", errors.New("unable to process wallet commands") - } - - // Import the redeem script - var importedHeight int64 - importedHeight, err = controller.Cfg.StakepooldServers.ImportScript(serializedScript) - if err != nil { - log.Warnf("unexpected error importing multisig redeem script: %v", err) - return nil, codes.Unavailable, "system error", errors.New("unable to process wallet commands") - } - - userFeeAddr, err := controller.FeeAddressForUserID(int(user.Id)) - if err != nil { - log.Warnf("unexpected error deriving pool addr: %s", err.Error()) - return nil, codes.Unavailable, "system error", errors.New("unable to process wallet commands") - } - - models.UpdateUserByID(dbMap, user.Id, createMultiSig.Address, - createMultiSig.RedeemScript, poolPubKeyAddr, userPubKeyAddr, - userFeeAddr.EncodeAddress(), importedHeight) - - log.Infof("successfully create multisigaddress for user %d", int(user.Id)) - - err = controller.StakepooldUpdateUsers(dbMap) - if err != nil { - log.Warnf("failure to update users: %v", err) - } - return nil, codes.OK, "address successfully imported", nil } @@ -405,76 +349,12 @@ func (controller *MainController) APIPurchaseTicket(c web.C, r *http.Request) (* // load saved user info from db to get the user id user = models.GetUserByEmail(dbMap, userPubKeyAddr) - userId := int(user.Id) - - // Get the ticket address for this user - pooladdress, err := controller.TicketAddressForUserID(int(user.Id)) - if err != nil { - log.Errorf("unable to derive ticket address: %v", err) - return nil, codes.Unavailable, "system error", errors.New("unable to process wallet commands") - } - - poolValidateAddress, err := controller.Cfg.StakepooldServers.ValidateAddress(pooladdress) - if err != nil { - log.Errorf("unable to validate address: %v", err) - return nil, codes.Unavailable, "system error", errors.New("unable to process wallet commands") - } - if !poolValidateAddress.IsMine { - log.Errorf("unable to validate ismine for pool ticket address: %s", - pooladdress.String()) - return nil, codes.Unavailable, "system error", errors.New("unable to process wallet commands") - } - - poolPubKeyAddr := poolValidateAddress.PubKeyAddr - - if _, err = dcrutil.DecodeAddress(poolPubKeyAddr); err != nil { - return nil, codes.Unavailable, "system error", errors.New("unable to process wallet commands") - } - - createMultiSig, err := controller.Cfg.StakepooldServers.CreateMultisig([]string{poolPubKeyAddr, userPubKeyAddr}) - if err != nil { - return nil, codes.Unavailable, "system error", errors.New("unable to process wallet commands") - } - - // Serialize the redeem script (hex string -> []byte) - serializedScript, err := hex.DecodeString(createMultiSig.RedeemScript) - if err != nil { - return nil, codes.Unavailable, "system error", errors.New("unable to process wallet commands") - } - - // Import the redeem script - var importedHeight int64 - importedHeight, err = controller.Cfg.StakepooldServers.ImportScript(serializedScript) - if err != nil { - log.Warnf("unexpected error importing multisig redeem script: %v", err) - return nil, codes.Unavailable, "system error", errors.New("unable to process wallet commands") - } - - userFeeAddr, err := controller.FeeAddressForUserID(int(user.Id)) - if err != nil { - log.Warnf("unexpected error deriving pool addr: %s", err.Error()) - return nil, codes.Unavailable, "system error", errors.New("unable to process wallet commands") - } - models.UpdateUserByID(dbMap, user.Id, createMultiSig.Address, - createMultiSig.RedeemScript, poolPubKeyAddr, userPubKeyAddr, - userFeeAddr.EncodeAddress(), importedHeight) - - log.Infof("successfully create multisigaddress for user %d", userId) - - err = controller.StakepooldUpdateUsers(dbMap) - if err != nil { - log.Warnf("failure to update users: %v", err) + if purchaseInfo := controller.generateTicketPurchaseInfo(dbMap, user, userPubKeyAddr); purchaseInfo != nil { + return purchaseInfo, codes.OK, "APIPurchaseTicket: purchaseinfo generated for userPubKeyAddr", nil } - purchaseInfo := &poolapi.PurchaseInfo{ - PoolAddress: userFeeAddr.EncodeAddress(), - PoolFees: controller.Cfg.PoolFees, - Script: createMultiSig.RedeemScript, - TicketAddress: createMultiSig.Address, - VoteBits: uint16(user.VoteBits), - } - return purchaseInfo, codes.OK, "APIPurchaseTicket: purchaseinfo generated for userPubKeyAddr", nil + return nil, codes.Unavailable, "system error", errors.New("unable to process wallet commands") } // APIPurchaseInfo fetches and returns the user's info or an error @@ -858,95 +738,113 @@ func validateUserPubKeyAddr(pubKeyAddr string) (dcrutil.Address, error) { return u, nil } -// AddressPost is address form submit route. -func (controller *MainController) AddressPost(c web.C, r *http.Request) (string, int) { - session := controller.GetSession(c) - c.Env[csrf.TemplateTag] = csrf.TemplateField(r) - remoteIP := getClientIP(r, controller.Cfg.RealIPHeader) - - if session.Values["UserId"] == nil { - return "/", http.StatusSeeOther - } - uid64 := session.Values["UserId"].(int64) - - // Only accept address if user does not already have a PubKeyAddr set. - dbMap := controller.GetDbMap(c) - user, _ := models.GetUserById(dbMap, session.Values["UserId"].(int64)) - if len(user.UserPubKeyAddr) > 0 { - session.AddFlash("The voting service is currently limited to one address per account", "address") - return controller.Address(c, r) - } - - userPubKeyAddr := r.FormValue("UserPubKeyAddr") - - log.Infof("Address POST from %v, pubkeyaddr %v", remoteIP, userPubKeyAddr) - - if _, err := validateUserPubKeyAddr(userPubKeyAddr); err != nil { - session.AddFlash(err.Error(), "address") - return controller.Address(c, r) - } +func (controller *MainController) generateTicketPurchaseInfo(dbMap *gorp.DbMap, user *models.User, + userPubKeyAddr string) *poolapi.PurchaseInfo { // Get the ticket address for this user - pooladdress, err := controller.TicketAddressForUserID(int(uid64)) + pooladdress, err := controller.TicketAddressForUserID(int(user.Id)) if err != nil { log.Errorf("unable to derive ticket address: %v", err) - session.AddFlash("Unable to derive ticket address", "address") - return controller.Address(c, r) + return nil } // From new address (pkh), get pubkey address poolValidateAddress, err := controller.Cfg.StakepooldServers.ValidateAddress(pooladdress) if err != nil { - return "/error", http.StatusSeeOther + log.Errorf("unable to validate address: %v", err) + return nil } if !poolValidateAddress.IsMine { log.Errorf("unable to validate ismine for pool ticket address: %s", pooladdress.String()) - session.AddFlash("Unable to validate pool ticket address", "address") - return controller.Address(c, r) + return nil } + poolPubKeyAddr := poolValidateAddress.PubKeyAddr // Get back Address from pool's new pubkey address if _, err = dcrutil.DecodeAddress(poolPubKeyAddr); err != nil { - return "/error", http.StatusSeeOther + return nil } // Create the the multisig script. Result includes a P2SH and redeem script. createMultiSig, err := controller.Cfg.StakepooldServers.CreateMultisig([]string{poolPubKeyAddr, userPubKeyAddr}) if err != nil { - return "/error", http.StatusSeeOther + return nil } // Serialize the redeem script (hex string -> []byte) serializedScript, err := hex.DecodeString(createMultiSig.RedeemScript) if err != nil { - return "/error", http.StatusSeeOther + return nil } // Import the redeem script var importedHeight int64 importedHeight, err = controller.Cfg.StakepooldServers.ImportScript(serializedScript) if err != nil { - return "/error", http.StatusSeeOther + log.Warnf("unexpected error importing multisig redeem script: %v", err) + return nil } // Get the pool fees address for this user - userFeeAddr, err := controller.FeeAddressForUserID(int(uid64)) + userFeeAddr, err := controller.FeeAddressForUserID(int(user.Id)) if err != nil { log.Errorf("unexpected error deriving fee addr: %s", err.Error()) - session.AddFlash("Unable to derive fee address", "address") - return controller.Address(c, r) + return nil } // Update the user's DB entry with multisig, user and pool pubkey // addresses, and the fee address - models.UpdateUserByID(dbMap, uid64, createMultiSig.Address, + models.UpdateUserByID(dbMap, user.Id, createMultiSig.Address, createMultiSig.RedeemScript, poolPubKeyAddr, userPubKeyAddr, userFeeAddr.EncodeAddress(), importedHeight) + log.Infof("successfully create multisigaddress for user %d", int(user.Id)) + if err = controller.StakepooldUpdateUsers(dbMap); err != nil { - log.Errorf("unable to update all: %v", err) + log.Errorf("unable to update users: %v", err) + } + + return &poolapi.PurchaseInfo{ + PoolAddress: userFeeAddr.EncodeAddress(), + PoolFees: controller.Cfg.PoolFees, + Script: createMultiSig.RedeemScript, + TicketAddress: createMultiSig.Address, + VoteBits: uint16(user.VoteBits), + } +} + +// AddressPost is address form submit route. +func (controller *MainController) AddressPost(c web.C, r *http.Request) (string, int) { + session := controller.GetSession(c) + c.Env[csrf.TemplateTag] = csrf.TemplateField(r) + remoteIP := getClientIP(r, controller.Cfg.RealIPHeader) + + if session.Values["UserId"] == nil { + return "/", http.StatusSeeOther + } + uid64 := session.Values["UserId"].(int64) + + // Only accept address if user does not already have a PubKeyAddr set. + dbMap := controller.GetDbMap(c) + user, _ := models.GetUserById(dbMap, uid64) + if len(user.UserPubKeyAddr) > 0 { + session.AddFlash("The voting service is currently limited to one address per account", "address") + return controller.Address(c, r) + } + + userPubKeyAddr := r.FormValue("UserPubKeyAddr") + + log.Infof("Address POST from %v, pubkeyaddr %v", remoteIP, userPubKeyAddr) + + if _, err := validateUserPubKeyAddr(userPubKeyAddr); err != nil { + session.AddFlash(err.Error(), "address") + return controller.Address(c, r) + } + + if purchaseInfo := controller.generateTicketPurchaseInfo(dbMap, user, userPubKeyAddr); purchaseInfo == nil { + return "/error", http.StatusSeeOther } return "/tickets", http.StatusSeeOther