Skip to content

Commit

Permalink
refactor shared code into reusable method
Browse files Browse the repository at this point in the history
  • Loading branch information
itswisdomagain committed Sep 19, 2019
1 parent 5ffe4e8 commit 145a270
Showing 1 changed file with 65 additions and 168 deletions.
233 changes: 65 additions & 168 deletions controllers/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
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.ImportNewScript(serializedScript)
if err != nil {
log.Warnf("unexpected error importing multisig redeem script: %v", err)
if purchaseInfo := controller.generateTicketPurchaseInfo(dbMap, user, userPubKeyAddr); purchaseInfo == nil {
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
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -860,95 +740,112 @@ 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.ImportNewScript(serializedScript)
importedHeight, err := controller.Cfg.StakepooldServers.ImportNewScript(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
Expand Down

0 comments on commit 145a270

Please sign in to comment.