diff --git a/controllers/main.go b/controllers/main.go index 959fbe91..8c3572a7 100644 --- a/controllers/main.go +++ b/controllers/main.go @@ -34,9 +34,7 @@ import ( "github.com/gorilla/csrf" "github.com/zenazn/goji/web" - "google.golang.org/grpc" "google.golang.org/grpc/codes" - "google.golang.org/grpc/connectivity" ) const ( @@ -61,7 +59,7 @@ type MainController struct { closePoolMsg string enableStakepoold bool feeXpub *hdkeychain.ExtendedKey - grpcConnections []*grpc.ClientConn + StakepooldServers *stakepooldclient.StakepooldManager poolEmail string poolFees float64 poolLink string @@ -102,7 +100,7 @@ func getClientIP(r *http.Request, realIPHeader string) string { func NewMainController(params *chaincfg.Params, adminIPs []string, adminUserIDs []string, APISecret string, APIVersionsSupported []int, baseURL string, closePool bool, closePoolMsg string, enablestakepoold bool, - feeXpubStr string, grpcConnections []*grpc.ClientConn, poolFees float64, + feeXpubStr string, stakepooldConnMan *stakepooldclient.StakepooldManager, poolFees float64, poolEmail, poolLink string, emailSender email.Sender, walletHosts, walletCerts, walletUsers, walletPasswords []string, minServers int, realIPHeader, votingXpubStr string, maxVotedAge int64, description string, @@ -146,7 +144,7 @@ func NewMainController(params *chaincfg.Params, adminIPs []string, closePoolMsg: closePoolMsg, enableStakepoold: enablestakepoold, feeXpub: feeKey, - grpcConnections: grpcConnections, + StakepooldServers: stakepooldConnMan, poolEmail: poolEmail, poolFees: poolFees, poolLink: poolLink, @@ -303,13 +301,9 @@ func (controller *MainController) APIAddress(c web.C, r *http.Request) ([]string // Import the RedeemScript var importedHeight int64 - for i := range controller.grpcConnections { - importedHeight, err = stakepooldclient.StakepooldImportScript(controller.grpcConnections[i], serializedScript) - if err != nil { - log.Errorf("Error importing script on stakepoold rpc connection %d", i) - return nil, codes.Unavailable, "system error", errors.New("unable to process wallet commands") - } - log.Infof("Successfully imported script on stakepoold rpc connection %d", i) + importedHeight, err = controller.StakepooldServers.ImportScript(serializedScript) + if err != nil { + return nil, codes.Unavailable, "system error", errors.New("unable to process wallet commands") } userFeeAddr, err := controller.FeeAddressForUserID(int(user.Id)) @@ -472,25 +466,6 @@ func (controller *MainController) isAdmin(c web.C, r *http.Request) (bool, error return true, nil } -// StakepooldGetIgnoredLowFeeTickets performs a gRPC GetIgnoredLowFeeTickets -// request against all stakepoold instances and returns the first result fetched -// without errors -func (controller *MainController) StakepooldGetIgnoredLowFeeTickets() (map[chainhash.Hash]string, error) { - var err error - ignoredLowFeeTickets := make(map[chainhash.Hash]string) - - // TODO need some better code here - for i := range controller.grpcConnections { - ignoredLowFeeTickets, err = stakepooldclient.StakepooldGetIgnoredLowFeeTickets(controller.grpcConnections[i]) - // take the first non-error result - if err == nil { - return ignoredLowFeeTickets, err - } - } - - return ignoredLowFeeTickets, err -} - // StakepooldUpdateTickets attempts to trigger all connected stakepoold // instances to pull a data update of the specified kind. func (controller *MainController) StakepooldUpdateTickets(dbMap *gorp.DbMap) error { @@ -499,15 +474,10 @@ func (controller *MainController) StakepooldUpdateTickets(dbMap *gorp.DbMap) err return err } - for i := range controller.grpcConnections { - err := stakepooldclient.StakepooldSetAddedLowFeeTickets(controller.grpcConnections[i], votableLowFeeTickets) - if err != nil { - log.Errorf("stakepoold host %d unable to update manual "+ - "tickets grpc error: %v", i, err) - return err - } - log.Infof("Successfully triggered update tickets on stakepoold "+ - "host %d", i) + err = controller.StakepooldServers.SetAddedLowFeeTickets(votableLowFeeTickets) + if err != nil { + log.Errorf("error updating tickets on stakepoold: %v", err) + return err } return nil @@ -523,15 +493,10 @@ func (controller *MainController) StakepooldUpdateUsers(dbMap *gorp.DbMap) error return err } - for i := range controller.grpcConnections { - err := stakepooldclient.StakepooldSetUserVotingPrefs(controller.grpcConnections[i], allUsers) - if err != nil { - log.Errorf("stakepoold host %d unable to update voting config "+ - "grpc error: %v", i, err) - return err - } - log.Infof("successfully triggered update users on stakepoold "+ - "host %d", i) + err = controller.StakepooldServers.SetUserVotingPrefs(allUsers) + if err != nil { + log.Errorf("error updating users on stakepoold: %v", err) + return err } return nil @@ -855,13 +820,9 @@ func (controller *MainController) AddressPost(c web.C, r *http.Request) (string, // Import the RedeemScript var importedHeight int64 - for i := range controller.grpcConnections { - importedHeight, err = stakepooldclient.StakepooldImportScript(controller.grpcConnections[i], serializedScript) - if err != nil { - log.Errorf("Error importing script on stakepoold rpc connection %d", i) - return "/error", http.StatusSeeOther - } - log.Infof("Successfully imported script on stakepoold rpc connection %d", i) + importedHeight, err = controller.StakepooldServers.ImportScript(serializedScript) + if err != nil { + return "/error", http.StatusSeeOther } // Get the pool fees address for this user @@ -894,28 +855,16 @@ func (controller *MainController) AdminStatus(c web.C, r *http.Request) (string, } type stakepooldInfoPage struct { - Status string - } - - stakepooldPageInfo := make([]stakepooldInfoPage, len(controller.grpcConnections)) - - for i, conn := range controller.grpcConnections { - grpcStatus := "Unknown" - state := conn.GetState() - switch state { - case connectivity.Idle: - grpcStatus = "Idle" - case connectivity.Shutdown: - grpcStatus = "Shutdown" - case connectivity.Ready: - grpcStatus = "Ready" - case connectivity.Connecting: - grpcStatus = "Connecting" - case connectivity.TransientFailure: - grpcStatus = "TransientFailure" - } + RPCStatus string + } + + stakepooldRPCStatus := controller.StakepooldServers.RPCStatus() + + stakepooldPageInfo := make([]stakepooldInfoPage, len(stakepooldRPCStatus)) + + for i, grpcStatus := range stakepooldRPCStatus { stakepooldPageInfo[i] = stakepooldInfoPage{ - Status: grpcStatus, + RPCStatus: grpcStatus, } } @@ -1021,6 +970,12 @@ func (controller *MainController) AdminTickets(c web.C, r *http.Request) (string } } + ignoredLowFeeTickets, err := controller.StakepooldServers.GetIgnoredLowFeeTickets() + if err != nil { + log.Errorf("Could not retrieve ignored low fee tickets from stakepoold: %v", err) + session.AddFlash("Could not retrieve ignored low fee tickets from stakepoold", "adminTicketsError") + } + c.Env["Admin"] = isAdmin c.Env["IsAdminTickets"] = true c.Env["Network"] = controller.getNetworkName() @@ -1029,7 +984,8 @@ func (controller *MainController) AdminTickets(c web.C, r *http.Request) (string c.Env["FlashSuccess"] = session.Flashes("adminTicketsSuccess") c.Env["AddedLowFeeTickets"] = votableLowFeeTickets - c.Env["IgnoredLowFeeTickets"], _ = controller.StakepooldGetIgnoredLowFeeTickets() + c.Env["IgnoredLowFeeTickets"] = ignoredLowFeeTickets + widgets := controller.Parse(t, "admin/tickets", c.Env) c.Env["Title"] = "Decred Voting Service - Tickets (Admin)" @@ -1093,7 +1049,7 @@ func (controller *MainController) AdminTicketsPost(c web.C, r *http.Request) (st switch action { case "add": actionVerb = "added" - ignoredLowFeeTickets, err := controller.StakepooldGetIgnoredLowFeeTickets() + ignoredLowFeeTickets, err := controller.StakepooldServers.GetIgnoredLowFeeTickets() if err != nil { session.AddFlash("GetIgnoredLowFeeTickets error: "+err.Error(), "adminTicketsError") diff --git a/server.go b/server.go index 7dcb598f..55dd52c3 100644 --- a/server.go +++ b/server.go @@ -11,8 +11,6 @@ import ( "os" "strings" - "google.golang.org/grpc" - "github.com/gorilla/context" "github.com/gorilla/csrf" @@ -86,15 +84,13 @@ func runMain() int { // Supported API versions are advertised in the API stats result APIVersionsSupported := []int{1, 2} - grpcConnections := make([]*grpc.ClientConn, len(cfg.StakepooldHosts)) + var stakepooldConnMan *stakepooldclient.StakepooldManager if cfg.EnableStakepoold { - for i := range cfg.StakepooldHosts { - grpcConnections[i], err = stakepooldclient.ConnectStakepooldGRPC(cfg.StakepooldHosts, cfg.StakepooldCerts, i) - if err != nil { - log.Errorf("Failed to connect to stakepoold host %d: %v", i, err) - return 8 - } + stakepooldConnMan, err = stakepooldclient.ConnectStakepooldGRPC(cfg.StakepooldHosts, cfg.StakepooldCerts) + if err != nil { + log.Errorf("Failed to connect to stakepoold host: %v", err) + return 8 } } @@ -108,7 +104,7 @@ func runMain() int { controller, err := controllers.NewMainController(activeNetParams.Params, cfg.AdminIPs, cfg.AdminUserIDs, cfg.APISecret, APIVersionsSupported, cfg.BaseURL, cfg.ClosePool, cfg.ClosePoolMsg, cfg.EnableStakepoold, - cfg.ColdWalletExtPub, grpcConnections, cfg.PoolFees, cfg.PoolEmail, + cfg.ColdWalletExtPub, stakepooldConnMan, cfg.PoolFees, cfg.PoolEmail, cfg.PoolLink, sender, cfg.WalletHosts, cfg.WalletCerts, cfg.WalletUsers, cfg.WalletPasswords, cfg.MinServers, cfg.RealIPHeader, cfg.VotingWalletExtPub, cfg.MaxVotedAge, cfg.Description, cfg.Designation) @@ -143,25 +139,18 @@ func runMain() int { log.Errorf("StakepooldUpdateTickets failed: %v", err) return 9 } - for i := range grpcConnections { - addedLowFeeTickets, err := stakepooldclient.StakepooldGetAddedLowFeeTickets(grpcConnections[i]) - if err != nil { - log.Errorf("GetAddedLowFeeTickets failed on host %d: %v", i, err) - return 9 - } - ignoredLowFeeTickets, err := stakepooldclient.StakepooldGetIgnoredLowFeeTickets(grpcConnections[i]) - if err != nil { - log.Errorf("GetIgnoredLowFeeTickets failed on host %d: %v", i, err) - return 9 - } - liveTickets, err := stakepooldclient.StakepooldGetLiveTickets(grpcConnections[i]) - if err != nil { - log.Errorf("GetLiveTickets failed on host %d: %v", i, err) - return 9 - } - log.Infof("stakepoold %d reports ticket totals of AddedLowFee %v "+ - "IgnoredLowFee %v Live %v", i, len(addedLowFeeTickets), - len(ignoredLowFeeTickets), len(liveTickets)) + // Log the reported count of ignored/added/live tickets from each stakepoold + _, err = controller.StakepooldServers.GetIgnoredLowFeeTickets() + if err != nil { + return 9 + } + _, err = controller.StakepooldServers.GetAddedLowFeeTickets() + if err != nil { + return 9 + } + _, err = controller.StakepooldServers.GetLiveTickets() + if err != nil { + return 9 } } diff --git a/stakepooldclient/stakepooldclient.go b/stakepooldclient/stakepooldclient.go index dccce338..c968544d 100644 --- a/stakepooldclient/stakepooldclient.go +++ b/stakepooldclient/stakepooldclient.go @@ -1,9 +1,11 @@ package stakepooldclient import ( + "errors" "fmt" "google.golang.org/grpc" + "google.golang.org/grpc/connectivity" "google.golang.org/grpc/credentials" "github.com/decred/dcrd/chaincfg/chainhash" @@ -14,111 +16,134 @@ import ( var requiredStakepooldAPI = semver{major: 4, minor: 0, patch: 0} -func ConnectStakepooldGRPC(stakepooldHosts []string, stakepooldCerts []string, serverID int) (*grpc.ClientConn, error) { - log.Infof("Attempting to connect to stakepoold gRPC %s using "+ - "certificate located in %s", stakepooldHosts[serverID], - stakepooldCerts[serverID]) - creds, err := credentials.NewClientTLSFromFile(stakepooldCerts[serverID], "localhost") - if err != nil { - return nil, err - } - conn, err := grpc.Dial(stakepooldHosts[serverID], grpc.WithTransportCredentials(creds)) - if err != nil { - return nil, err - } - c := pb.NewVersionServiceClient(conn) +type StakepooldManager struct { + grpcConnections []*grpc.ClientConn +} - versionRequest := &pb.VersionRequest{} - versionResponse, err := c.Version(context.Background(), versionRequest) - if err != nil { - return nil, err - } +func ConnectStakepooldGRPC(stakepooldHosts []string, stakepooldCerts []string) (*StakepooldManager, error) { - var semverResponse = semver{ - major: versionResponse.Major, - minor: versionResponse.Minor, - patch: versionResponse.Patch, - } + conns := make([]*grpc.ClientConn, len(stakepooldHosts)) - if !semverCompatible(requiredStakepooldAPI, semverResponse) { - return nil, fmt.Errorf("Stakepoold gRPC server does not have "+ - "a compatible API version. Advertises %v but require %v", - versionResponse, requiredStakepooldAPI) - } + for serverID := range stakepooldHosts { + log.Infof("Attempting to connect to stakepoold gRPC %s using "+ + "certificate located in %s", stakepooldHosts[serverID], + stakepooldCerts[serverID]) + creds, err := credentials.NewClientTLSFromFile(stakepooldCerts[serverID], "localhost") + if err != nil { + return nil, err + } + conn, err := grpc.Dial(stakepooldHosts[serverID], grpc.WithTransportCredentials(creds)) + if err != nil { + return nil, err + } + c := pb.NewVersionServiceClient(conn) - log.Infof("Established connection to gRPC server %s", - stakepooldHosts[serverID]) + versionRequest := &pb.VersionRequest{} + versionResponse, err := c.Version(context.Background(), versionRequest) + if err != nil { + return nil, err + } - return conn, nil -} + var semverResponse = semver{ + major: versionResponse.Major, + minor: versionResponse.Minor, + patch: versionResponse.Patch, + } -func StakepooldGetAddedLowFeeTickets(conn *grpc.ClientConn) (map[chainhash.Hash]string, error) { - addedLowFeeTickets := make(map[chainhash.Hash]string) + if !semverCompatible(requiredStakepooldAPI, semverResponse) { + return nil, fmt.Errorf("Stakepoold gRPC server does not have "+ + "a compatible API version. Advertises %v but require %v", + versionResponse, requiredStakepooldAPI) + } - client := pb.NewStakepooldServiceClient(conn) - resp, err := client.GetAddedLowFeeTickets(context.Background(), &pb.GetAddedLowFeeTicketsRequest{}) - // return early if the list is empty - if resp == nil || err != nil { - return addedLowFeeTickets, err + log.Infof("Established connection to gRPC server %s", + stakepooldHosts[serverID]) + conns[serverID] = conn } - for _, ticket := range resp.Tickets { - hash, err := chainhash.NewHash(ticket.Hash) + return &StakepooldManager{conns}, nil +} + +// GetAddedLowFeeTickets performs gRPC GetAddedLowFeeTickets +// requests against all stakepoold instances and returns the first result fetched +// without errors. Returns an error if all RPC requests fail. +func (s *StakepooldManager) GetAddedLowFeeTickets() (map[chainhash.Hash]string, error) { + for i, conn := range s.grpcConnections { + client := pb.NewStakepooldServiceClient(conn) + resp, err := client.GetAddedLowFeeTickets(context.Background(), &pb.GetAddedLowFeeTicketsRequest{}) if err != nil { - log.Warnf("NewHash failed for %v: %v", ticket.Hash, err) + log.Warnf("GetAddedLowFeeTickets RPC failed on stakepoold instance %d: %v", i, err) continue } - addedLowFeeTickets[*hash] = ticket.Address + + addedLowFeeTickets := processTicketsResponse(resp.Tickets) + log.Infof("stakepoold %d reports %d AddedLowFee tickets", i, len(addedLowFeeTickets)) + return addedLowFeeTickets, err } - return addedLowFeeTickets, err + // All RPC requests failed + return nil, errors.New("GetAddedLowFeeTickets RPC failed on all stakepoold instances") } -func StakepooldGetIgnoredLowFeeTickets(conn *grpc.ClientConn) (map[chainhash.Hash]string, error) { - ignoredLowFeeTickets := make(map[chainhash.Hash]string) - - client := pb.NewStakepooldServiceClient(conn) - resp, err := client.GetIgnoredLowFeeTickets(context.Background(), &pb.GetIgnoredLowFeeTicketsRequest{}) - // return early if the list is empty - if resp == nil || err != nil { - return ignoredLowFeeTickets, err - } - - for _, ticket := range resp.Tickets { - hash, err := chainhash.NewHash(ticket.Hash) +// GetIgnoredLowFeeTickets performs gRPC GetIgnoredLowFeeTickets +// requests against all stakepoold instances and returns the first result fetched +// without errors. Returns an error if all RPC requests fail. +func (s *StakepooldManager) GetIgnoredLowFeeTickets() (map[chainhash.Hash]string, error) { + for i, conn := range s.grpcConnections { + client := pb.NewStakepooldServiceClient(conn) + resp, err := client.GetIgnoredLowFeeTickets(context.Background(), &pb.GetIgnoredLowFeeTicketsRequest{}) if err != nil { - log.Warnf("NewHash failed for %v: %v", ticket.Hash, err) + log.Warnf("GetIgnoredLowFeeTickets RPC failed on stakepoold instance %d: %v", i, err) continue } - ignoredLowFeeTickets[*hash] = ticket.Address + + ignoredLowFeeTickets := processTicketsResponse(resp.Tickets) + log.Infof("stakepoold %d reports %d IgnoredLowFee tickets", i, len(ignoredLowFeeTickets)) + return ignoredLowFeeTickets, nil } - return ignoredLowFeeTickets, err + // All RPC requests failed + return nil, errors.New("GetIgnoredLowFeeTickets RPC failed on all stakepoold instances") } -func StakepooldGetLiveTickets(conn *grpc.ClientConn) (map[chainhash.Hash]string, error) { - liveTickets := make(map[chainhash.Hash]string) +// GetLiveTickets performs gRPC GetLiveTickets +// requests against all stakepoold instances and returns the first result fetched +// without errors. Returns an error if all RPC requests fail. +func (s *StakepooldManager) GetLiveTickets() (map[chainhash.Hash]string, error) { + for i, conn := range s.grpcConnections { + client := pb.NewStakepooldServiceClient(conn) + resp, err := client.GetLiveTickets(context.Background(), &pb.GetLiveTicketsRequest{}) + if err != nil { + log.Warnf("GetLiveTickets RPC failed on stakepoold instance %d: %v", i, err) + continue + } - client := pb.NewStakepooldServiceClient(conn) - resp, err := client.GetLiveTickets(context.Background(), &pb.GetLiveTicketsRequest{}) - // return early if the list is empty - if resp == nil || err != nil { - return liveTickets, err + liveTickets := processTicketsResponse(resp.Tickets) + log.Infof("stakepoold %d reports %d Live Tickets", i, len(liveTickets)) + return liveTickets, nil } - for _, ticket := range resp.Tickets { + // All RPC requests failed + return nil, errors.New("GetLiveTickets RPC failed on all stakepoold instances") +} + +func processTicketsResponse(tickets []*pb.Ticket) map[chainhash.Hash]string { + processedTickets := make(map[chainhash.Hash]string) + for _, ticket := range tickets { hash, err := chainhash.NewHash(ticket.Hash) if err != nil { log.Warnf("NewHash failed for %v: %v", ticket.Hash, err) continue } - liveTickets[*hash] = ticket.Address + processedTickets[*hash] = ticket.Address } - return liveTickets, err + return processedTickets } -func StakepooldSetAddedLowFeeTickets(conn *grpc.ClientConn, dbTickets []models.LowFeeTicket) error { +// SetAddedLowFeeTickets performs gRPC SetAddedLowFeeTickets. It stops +// executing and returns an error if any RPC call fails +func (s *StakepooldManager) SetAddedLowFeeTickets(dbTickets []models.LowFeeTicket) error { var tickets []*pb.Ticket for _, ticket := range dbTickets { hash, err := chainhash.NewHashFromStr(ticket.TicketHash) @@ -132,17 +157,26 @@ func StakepooldSetAddedLowFeeTickets(conn *grpc.ClientConn, dbTickets []models.L }) } - client := pb.NewStakepooldServiceClient(conn) - setAddedTicketsReq := &pb.SetAddedLowFeeTicketsRequest{ - Tickets: tickets, + for i, conn := range s.grpcConnections { + client := pb.NewStakepooldServiceClient(conn) + setAddedTicketsReq := &pb.SetAddedLowFeeTicketsRequest{ + Tickets: tickets, + } + _, err := client.SetAddedLowFeeTickets(context.Background(), + setAddedTicketsReq) + if err != nil { + log.Errorf("SetAddedLowFeeTickets RPC failed on stakepoold instance %d: %v", i, err) + return err + } } - _, err := client.SetAddedLowFeeTickets(context.Background(), - setAddedTicketsReq) - return err + log.Info("SetAddedLowFeeTickets successful on all stakepoold instances") + return nil } -func StakepooldSetUserVotingPrefs(conn *grpc.ClientConn, dbUsers map[int64]*models.User) error { +// SetUserVotingPrefs performs gRPC SetUserVotingPrefs. It stops +// executing and returns an error if any RPC call fails +func (s *StakepooldManager) SetUserVotingPrefs(dbUsers map[int64]*models.User) error { var users []*pb.UserVotingConfigEntry for userid, data := range dbUsers { users = append(users, &pb.UserVotingConfigEntry{ @@ -153,24 +187,64 @@ func StakepooldSetUserVotingPrefs(conn *grpc.ClientConn, dbUsers map[int64]*mode }) } - client := pb.NewStakepooldServiceClient(conn) - setVotingConfigReq := &pb.SetUserVotingPrefsRequest{ - UserVotingConfig: users, + for i, conn := range s.grpcConnections { + client := pb.NewStakepooldServiceClient(conn) + setVotingConfigReq := &pb.SetUserVotingPrefsRequest{ + UserVotingConfig: users, + } + _, err := client.SetUserVotingPrefs(context.Background(), + setVotingConfigReq) + if err != nil { + log.Errorf("SetUserVotingPrefs RPC failed on stakepoold instance %d: %v", i, err) + return err + } } - _, err := client.SetUserVotingPrefs(context.Background(), - setVotingConfigReq) - return err + log.Info("SetUserVotingPrefs successful on all stakepoold instances") + return nil } -func StakepooldImportScript(conn *grpc.ClientConn, script []byte) (heightImported int64, err error) { - client := pb.NewStakepooldServiceClient(conn) - importScriptReq := &pb.ImportScriptRequest{ - Script: script, +// ImportScript calls ImportScript RPC on all stakepoold instances. It stops +// executing and returns an error if any RPC call fails +func (s *StakepooldManager) ImportScript(script []byte) (heightImported int64, err error) { + for i, conn := range s.grpcConnections { + client := pb.NewStakepooldServiceClient(conn) + req := &pb.ImportScriptRequest{ + Script: script, + } + resp, err := client.ImportScript(context.Background(), req) + if err != nil { + log.Errorf("ImportScript RPC failed on stakepoold instance %d: %v", i, err) + return -1, err + } + heightImported = resp.HeightImported } - importScriptResp, err := client.ImportScript(context.Background(), importScriptReq) - if err != nil { - return -1, err + + log.Info("ImportScript successful on all stakepoold instances") + return heightImported, err +} + +func (s *StakepooldManager) RPCStatus() []string { + stakepooldPageInfo := make([]string, len(s.grpcConnections)) + + for i, conn := range s.grpcConnections { + grpcStatus := "Unknown" + state := conn.GetState() + switch state { + case connectivity.Idle: + grpcStatus = "Idle" + case connectivity.Shutdown: + grpcStatus = "Shutdown" + case connectivity.Ready: + grpcStatus = "Ready" + case connectivity.Connecting: + grpcStatus = "Connecting" + case connectivity.TransientFailure: + grpcStatus = "TransientFailure" + } + + stakepooldPageInfo[i] = grpcStatus } - return importScriptResp.HeightImported, err + + return stakepooldPageInfo } diff --git a/views/admin/status.html b/views/admin/status.html index 414c7355..ed749a58 100644 --- a/views/admin/status.html +++ b/views/admin/status.html @@ -25,14 +25,14 @@

Stakepoold Number - GRPC Connection Number + RPC Status {{ range $i, $data := .StakepooldInfo }} {{$i}} - {{ $data.Status }} + {{ $data.RPCStatus }} {{end}}